From 68688dd528a8c907e1ed4b9f24b11bd1ade0f569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 19 Sep 2024 13:40:09 +0000 Subject: [PATCH] Revert "Merge branch 'revert-671bb6d5' into 'master'" This reverts merge request !732 --- .../unreleased/Feature-20240614-153236.yaml | 8 + .../unreleased/Feature-20240614-153537.yaml | 7 + .../unreleased/Feature-20240718-151233.yaml | 5 + .changes/v2.23.0.md | 10 +- .changes/v3.0.0.md | 5 + .changes/v3.1.0.md | 3 + .env | 94 ++ .env.test | 4 + .gitlab-ci.yml | 9 +- .php-cs-fixer.dist.php | 2 + CHANGELOG.md | 192 +-- MIGRATION.md | 117 ++ composer.json | 77 +- .../_static/code/exports/BirthdateFilter.php | 2 +- .../source/development/pagination/example.php | 5 +- .../controller-secured-for-person.php | 5 +- .../installation/enable-collabora-for-dev.rst | 125 ++ docs/source/installation/index.rst | 736 +++++----- package.json | 24 +- phpstan-baseline-2024-05.neon | 8 + ...an-baseline-deprecations-doctrine-orm.neon | 58 + phpstan-baseline-level-5.neon | 10 - phpstan-baseline.neon | 140 ++ phpstan-deprecations-sf54.neon | 153 +++ phpstan-deprecations.neon | 422 +----- phpstan.neon.dist | 2 + phpunit.rector.xml | 38 +- phpunit.xml.dist | 116 +- rector.php | 47 +- .../ChillActivityBundle.php | 4 +- .../Controller/ActivityController.php | 41 +- .../ActivityReasonCategoryController.php | 30 +- .../Controller/ActivityReasonController.php | 32 +- .../Controller/AdminController.php | 10 +- .../DataFixtures/ORM/LoadActivity.php | 2 +- .../ChillActivityBundle/Entity/Activity.php | 200 +-- .../Entity/ActivityPresence.php | 36 +- .../Entity/ActivityReason.php | 41 +- .../Entity/ActivityReasonCategory.php | 33 +- .../Entity/ActivityType.php | 216 +-- .../Entity/ActivityTypeCategory.php | 32 +- .../EntityListener/ActivityEntityListener.php | 4 +- .../ByActivityTypeAggregator.php | 3 +- .../BySocialActionAggregator.php | 4 +- .../BySocialIssueAggregator.php | 4 +- .../Aggregator/ActivityPresenceAggregator.php | 8 +- .../Aggregator/ActivityReasonAggregator.php | 3 +- .../Aggregator/ActivityTypeAggregator.php | 4 +- .../Aggregator/ActivityUserAggregator.php | 4 +- .../Aggregator/ActivityUsersAggregator.php | 4 +- .../Aggregator/ActivityUsersJobAggregator.php | 7 +- .../ActivityUsersScopeAggregator.php | 7 +- .../Export/Aggregator/ByCreatorAggregator.php | 4 +- .../Aggregator/ByThirdpartyAggregator.php | 4 +- .../Aggregator/CreatorJobAggregator.php | 7 +- .../Aggregator/CreatorScopeAggregator.php | 7 +- .../Aggregator/LocationTypeAggregator.php | 4 +- .../PersonAggregators/HouseholdAggregator.php | 99 ++ .../PersonAggregators/PersonAggregator.php | 4 +- .../Export/Aggregator/PersonsAggregator.php | 4 +- .../Aggregator/SentReceivedAggregator.php | 4 +- .../LinkedToACP/AvgActivityDuration.php | 4 +- .../Export/LinkedToACP/CountActivity.php | 4 +- .../LinkedToACP/CountHouseholdOnActivity.php | 4 +- .../LinkedToACP/CountPersonsOnActivity.php | 4 +- .../Export/LinkedToACP/ListActivity.php | 3 +- .../Export/LinkedToPerson/CountActivity.php | 4 +- .../CountHouseholdOnActivity.php | 4 +- .../Export/LinkedToPerson/ListActivity.php | 30 +- .../LinkedToPerson/StatActivityDuration.php | 4 +- .../Export/Export/ListActivityHelper.php | 9 +- .../Filter/ACPFilters/ActivityTypeFilter.php | 3 +- .../ACPFilters/BySocialActionFilter.php | 4 +- .../Filter/ACPFilters/BySocialIssueFilter.php | 4 +- ...PeriodHavingActivityBetweenDatesFilter.php | 3 +- .../Export/Filter/ActivityDateFilter.php | 4 +- .../Export/Filter/ActivityPresenceFilter.php | 3 +- .../Export/Filter/ActivityTypeFilter.php | 3 +- .../Export/Filter/ActivityUsersFilter.php | 4 +- .../Export/Filter/ByCreatorFilter.php | 4 +- .../Export/Filter/CreatorJobFilter.php | 3 +- .../Export/Filter/CreatorScopeFilter.php | 3 +- .../Export/Filter/EmergencyFilter.php | 4 +- .../Export/Filter/LocationTypeFilter.php | 4 +- .../PersonFilters/ActivityReasonFilter.php | 4 +- .../PersonHavingActivityBetweenDateFilter.php | 9 +- .../Export/Filter/PersonsFilter.php | 4 +- .../Export/Filter/SentReceivedFilter.php | 4 +- .../Export/Filter/UserFilter.php | 4 +- .../Export/Filter/UsersJobFilter.php | 3 +- .../Export/Filter/UsersScopeFilter.php | 3 +- .../Form/ActivityTypeType.php | 4 +- .../Form/Type/PickActivityReasonType.php | 3 +- ...TranslatableActivityReasonCategoryType.php | 4 +- .../Form/Type/TranslatableActivityType.php | 4 +- .../Menu/AccompanyingCourseMenuBuilder.php | 4 +- .../AccompanyingCourseQuickMenuBuilder.php | 4 +- .../Menu/AdminMenuBuilder.php | 4 +- .../Menu/PersonMenuBuilder.php | 4 +- .../ActivityNotificationHandler.php | 4 +- .../Repository/ActivityACLAwareRepository.php | 3 +- .../ActivityDocumentACLAwareRepository.php | 3 +- .../Repository/ActivityRepository.php | 16 +- .../Repository/ActivityTypeRepository.php | 4 +- .../ActivityStoredObjectVoter.php | 54 + .../Service/DocGenerator/ActivityContext.php | 3 +- ...tActivitiesByAccompanyingPeriodContext.php | 11 +- ...anyingPeriodActivityGenericDocProvider.php | 3 +- .../PersonActivityGenericDocProvider.php | 3 +- ...anyingPeriodActivityGenericDocRenderer.php | 4 +- .../ByActivityTypeAggregatorTest.php | 13 +- .../BySocialActionAggregatorTest.php | 9 +- .../BySocialIssueAggregatorTest.php | 9 +- .../ActivityPresenceAggregatorTest.php | 11 +- .../ActivityReasonAggregatorTest.php | 18 +- .../Aggregator/ActivityTypeAggregatorTest.php | 11 +- .../Aggregator/ActivityUserAggregatorTest.php | 11 +- .../Aggregator/ByThirdpartyAggregatorTest.php | 9 +- .../Aggregator/ByUserAggregatorTest.php | 9 +- .../Aggregator/CreatorJobAggregatorTest.php | 9 +- .../Aggregator/CreatorScopeAggregatorTest.php | 9 +- .../Export/Aggregator/DateAggregatorTest.php | 9 +- .../Aggregator/LocationTypeAggregatorTest.php | 9 +- .../PersonAggregatorTest.php | 9 +- .../Aggregator/PersonsAggregatorTest.php | 9 +- .../LinkedToACP/AvgActivityDurationTest.php | 6 +- .../AvgActivityVisitDurationTest.php | 6 +- .../Export/LinkedToACP/CountActivityTest.php | 6 +- .../CountHouseholdOnActivityTest.php | 6 +- .../CountPersonsOnActivityTest.php | 6 +- .../LinkedToACP/SumActivityDurationTest.php | 6 +- .../SumActivityVisitDurationTest.php | 8 +- .../LinkedToPerson/CountActivityTest.php | 6 +- .../CountHouseholdOnActivityTest.php | 6 +- .../LinkedToPerson/ListActivityTest.php | 14 +- .../StatActivityDurationTest.php | 6 +- .../ACPFilters/ActivityTypeFilterTest.php | 14 +- .../Filter/ACPFilters/ByCreatorFilterTest.php | 14 +- .../ACPFilters/BySocialActionFilterTest.php | 15 +- .../ACPFilters/BySocialIssueFilterTest.php | 14 +- .../Export/Filter/ActivityDateFilterTest.php | 11 +- .../Filter/ActivityPresenceFilterTest.php | 16 +- .../Filter/ActivityReasonFilterTest.php | 19 +- .../Export/Filter/ActivityTypeFilterTest.php | 17 +- .../Export/Filter/ByCreatorFilterTest.php | 14 +- .../Export/Filter/CreatorJobFilterTest.php | 12 +- .../Export/Filter/CreatorScopeFilterTest.php | 14 +- .../Export/Filter/EmergencyFilterTest.php | 9 +- .../Export/Filter/LocationTypeFilterTest.php | 14 +- .../ActivityReasonFilterTest.php | 14 +- ...sonHavingActivityBetweenDateFilterTest.php | 14 +- ...sonHavingActivityBetweenDateFilterTest.php | 20 +- .../Tests/Export/Filter/PersonsFilterTest.php | 15 +- .../Export/Filter/SentReceivedFilterTest.php | 9 +- .../Tests/Export/Filter/UserFilterTest.php | 14 +- .../Type/TranslatableActivityTypeTest.php | 2 +- .../ActivityACLAwareRepositoryTest.php | 10 +- ...ActivityDocumentACLAwareRepositoryTest.php | 8 +- ...ivitiesByAccompanyingPeriodContextTest.php | 8 +- .../Constraints/ActivityValidity.php | 4 +- .../config/services/export.yaml | 4 + .../translations/messages.fr.yml | 3 + .../src/ChillAsideActivityBundle.php | 4 +- .../src/Controller/AdminController.php | 4 +- .../Controller/AsideActivityController.php | 20 +- .../DataFixtures/ORM/LoadAsideActivity.php | 4 +- .../src/Entity/AsideActivity.php | 72 +- .../src/Entity/AsideActivityCategory.php | 45 +- .../Aggregator/ByActivityTypeAggregator.php | 3 +- .../Aggregator/ByLocationAggregator.php | 4 +- .../Export/Aggregator/ByUserJobAggregator.php | 7 +- .../Aggregator/ByUserScopeAggregator.php | 7 +- .../Export/AvgAsideActivityDuration.php | 8 +- .../src/Export/Export/CountAsideActivity.php | 8 +- .../src/Export/Export/ListAsideActivity.php | 7 +- .../Export/SumAsideActivityDuration.php | 8 +- .../Export/Filter/ByActivityTypeFilter.php | 3 +- .../src/Export/Filter/ByDateFilter.php | 4 +- .../src/Export/Filter/ByLocationFilter.php | 3 +- .../src/Export/Filter/ByUserFilter.php | 4 +- .../src/Export/Filter/ByUserJobFilter.php | 3 +- .../src/Export/Filter/ByUserScopeFilter.php | 3 +- .../src/Form/AsideActivityCategoryType.php | 4 +- .../Type/PickAsideActivityCategoryType.php | 4 +- .../src/Menu/AdminMenuBuilder.php | 4 +- .../src/Menu/SectionMenuBuilder.php | 4 +- .../src/Templating/Entity/CategoryRender.php | 4 +- .../AsideActivityControllerTest.php | 4 +- .../Export/Export/ListAsideActivityTest.php | 2 +- .../src/config/services/security.yaml | 1 - .../Controller/AbstractElementController.php | 21 +- .../Controller/Admin/AdminController.php | 4 +- .../Controller/ChargeController.php | 15 +- .../Controller/ElementController.php | 12 +- .../Controller/ResourceController.php | 18 +- .../Entity/AbstractElement.php | 55 +- .../ChillBudgetBundle/Entity/Charge.php | 29 +- .../ChillBudgetBundle/Entity/ChargeKind.php | 48 +- .../ChillBudgetBundle/Entity/Resource.php | 23 +- .../ChillBudgetBundle/Entity/ResourceKind.php | 51 +- .../ChillBudgetBundle/Form/ChargeType.php | 4 +- .../ChillBudgetBundle/Form/ResourceType.php | 4 +- .../Menu/AdminMenuBuilder.php | 4 +- .../Menu/HouseholdMenuBuilder.php | 24 +- .../Menu/PersonMenuBuilder.php | 4 +- .../Repository/ChargeKindRepository.php | 4 +- .../Repository/ResourceKindRepository.php | 4 +- .../Authorization/BudgetElementVoter.php | 4 +- .../Service/Summary/SummaryBudget.php | 4 +- .../Templating/BudgetElementTypeRender.php | 4 +- .../config/services/security.yaml | 4 +- .../AzureGrantAdminConsentAndAcquireToken.php | 4 +- .../MapAndSubscribeUserCalendarCommand.php | 5 +- .../SendShortMessageOnEligibleCalendar.php | 9 +- .../SendTestShortMessageOnCalendarCommand.php | 16 +- .../Controller/AdminController.php | 3 +- .../Controller/CalendarAPIController.php | 11 +- .../Controller/CalendarController.php | 43 +- .../Controller/CalendarDocController.php | 15 +- .../Controller/CalendarRangeAPIController.php | 11 +- .../Controller/InviteApiController.php | 7 +- .../RemoteCalendarConnectAzureController.php | 12 +- .../RemoteCalendarMSGraphSyncController.php | 9 +- .../RemoteCalendarProxyController.php | 8 +- .../DataFixtures/ORM/LoadCalendarRange.php | 4 +- .../ChillCalendarBundle/Entity/Calendar.php | 209 +-- .../Entity/CalendarDoc.php | 47 +- .../CalendarDoc/CalendarDocCreateDTO.php | 14 +- .../Entity/CalendarDoc/CalendarDocEditDTO.php | 11 +- .../Entity/CalendarRange.php | 71 +- .../Entity/CancelReason.php | 29 +- .../ChillCalendarBundle/Entity/Invite.php | 44 +- .../Entity/RemoteCalendarTrait.php | 8 +- .../Event/ListenToActivityCreate.php | 6 +- .../Export/Aggregator/AgentAggregator.php | 4 +- .../Aggregator/CancelReasonAggregator.php | 4 +- .../Export/Aggregator/JobAggregator.php | 7 +- .../Export/Aggregator/LocationAggregator.php | 4 +- .../Aggregator/LocationTypeAggregator.php | 4 +- .../Export/Aggregator/ScopeAggregator.php | 7 +- .../Export/Aggregator/UrgencyAggregator.php | 4 +- .../Export/Export/CountCalendars.php | 3 +- .../Export/Export/StatCalendarAvgDuration.php | 4 +- .../Export/Export/StatCalendarSumDuration.php | 4 +- .../Export/Filter/AgentFilter.php | 4 +- .../Export/Filter/BetweenDatesFilter.php | 4 +- .../Export/Filter/CalendarRangeFilter.php | 4 +- .../Export/Filter/JobFilter.php | 3 +- .../Export/Filter/ScopeFilter.php | 3 +- .../ChillCalendarBundle/Form/CalendarType.php | 3 +- .../Menu/AccompanyingCourseMenuBuilder.php | 4 +- .../AccompanyingCourseQuickMenuBuilder.php | 4 +- .../Menu/PersonMenuBuilder.php | 4 +- .../Menu/UserMenuBuilder.php | 4 +- .../Doctrine/CalendarEntityListener.php | 4 +- .../Doctrine/CalendarRangeEntityListener.php | 4 +- .../CalendarRangeRemoveToRemoteHandler.php | 4 +- .../Handler/CalendarRangeToRemoteHandler.php | 4 +- .../Handler/CalendarRemoveHandler.php | 4 +- .../Handler/CalendarToRemoteHandler.php | 4 +- .../Messenger/Handler/InviteUpdateHandler.php | 4 +- .../MSGraphChangeNotificationHandler.php | 4 +- .../MSGraphChangeNotificationMessage.php | 4 +- .../Connector/MSGraph/AddressConverter.php | 4 +- .../EventsOnUserSubscriptionCreator.php | 4 +- .../Connector/MSGraph/LocationConverter.php | 4 +- .../Connector/MSGraph/MSUserAbsenceReader.php | 3 +- .../Connector/MSGraph/MSUserAbsenceSync.php | 3 +- .../Connector/MSGraph/MachineTokenStorage.php | 4 +- .../Connector/MSGraph/MapCalendarToUser.php | 4 +- .../MSGraph/OnBehalfOfUserTokenStorage.php | 4 +- .../RemoteToLocalSync/CalendarRangeSyncer.php | 4 +- .../RemoteToLocalSync/CalendarSyncer.php | 4 +- .../MSGraphRemoteCalendarConnector.php | 4 +- .../Connector/NullRemoteCalendarConnector.php | 20 +- .../RemoteCalendar/Model/RemoteEvent.php | 23 +- .../Repository/CalendarACLAwareRepository.php | 4 +- .../Resources/public/vuejs/Calendar/App.vue | 2 +- .../Resources/public/vuejs/Calendar/i18n.js | 1 + .../Resources/views/Calendar/_list.html.twig | 12 +- .../Security/Voter/CalendarDocVoter.php | 31 +- .../Service/DocGenerator/CalendarContext.php | 3 +- .../DocGenerator/CalendarContextInterface.php | 4 +- ...anyingPeriodCalendarGenericDocProvider.php | 3 +- .../PersonCalendarGenericDocProvider.php | 3 +- ...anyingPeriodCalendarGenericDocRenderer.php | 4 +- .../BulkCalendarShortMessageSender.php | 4 +- .../CalendarForShortMessageProvider.php | 4 +- .../DefaultShortMessageForCalendarBuilder.php | 4 +- .../Controller/CalendarControllerTest.php | 4 +- ...emoteCalendarMSGraphSyncControllerTest.php | 2 +- .../Export/Aggregator/AgentAggregatorTest.php | 9 +- .../Aggregator/CancelReasonAggregatorTest.php | 9 +- .../Export/Aggregator/JobAggregatorTest.php | 9 +- .../Aggregator/LocationAggregatorTest.php | 9 +- .../Aggregator/LocationTypeAggregatorTest.php | 9 +- .../Aggregator/MonthYearAggregatorTest.php | 9 +- .../Export/Aggregator/ScopeAggregatorTest.php | 9 +- .../Tests/Export/Filter/AgentFilterTest.php | 21 +- .../Export/Filter/BetweenDatesFilterTest.php | 9 +- .../Tests/Export/Filter/JobFilterTest.php | 12 +- .../Tests/Export/Filter/ScopeFilterTest.php | 12 +- .../MSGraph/MSUserAbsenceReaderTest.php | 2 +- .../MSGraph/MSUserAbsenceSyncTest.php | 2 +- .../CalendarACLAwareRepositoryTest.php | 2 +- .../Normalizer/CalendarNormalizerTest.php | 2 +- .../DocGenerator/CalendarContextTest.php | 4 +- .../BulkCalendarShortMessageSenderTest.php | 4 +- .../DefaultRangeGeneratorTest.php | 2 +- .../Command/CreateFieldsOnGroupCommand.php | 4 +- .../Controller/AdminController.php | 4 +- .../Controller/CustomFieldController.php | 28 +- .../CustomFieldsGroupController.php | 47 +- .../CustomFields/CustomFieldChoice.php | 3 +- .../CustomFields/CustomFieldDate.php | 3 +- .../CustomFields/CustomFieldLongChoice.php | 3 +- .../CustomFields/CustomFieldNumber.php | 3 +- .../CustomFields/CustomFieldText.php | 3 +- .../CustomFields/CustomFieldTitle.php | 3 +- .../Entity/CustomField.php | 68 +- .../Entity/CustomFieldLongChoice/Option.php | 55 +- .../Entity/CustomFieldsDefaultGroup.php | 39 +- .../Entity/CustomFieldsGroup.php | 41 +- .../Form/CustomFieldType.php | 4 +- .../Form/CustomFieldsGroupType.php | 3 +- .../CustomFieldDataTransformer.php | 4 +- .../CustomFieldsGroupToIdTransformer.php | 4 +- .../Form/Type/CustomFieldsTitleType.php | 4 +- .../Form/Type/LinkedCustomFieldsType.php | 4 +- .../Service/CustomFieldsHelper.php | 4 +- .../Twig/CustomFieldRenderingTwig.php | 4 +- .../CustomFields/CustomFieldsChoiceTest.php | 4 +- .../config/services/controller.yaml | 1 - .../Context/ContextManager.php | 4 +- .../AdminDocGeneratorTemplateController.php | 8 +- .../DocGeneratorTemplateController.php | 41 +- .../ORM/LoadDocGeneratorTemplate.php | 13 +- .../ChillDocGeneratorExtension.php | 1 - .../Entity/DocGeneratorTemplate.php | 56 +- .../Form/DocGeneratorTemplateType.php | 4 +- .../GeneratorDriver/RelatorioDriver.php | 8 +- .../Menu/AdminMenuBuilder.php | 4 +- .../DocGeneratorTemplateRepository.php | 6 +- .../Helper/NormalizeNullValueHelper.php | 4 +- .../Service/Context/BaseContextData.php | 4 +- .../Service/Generator/Generator.php | 11 +- ...erMessageHandledClearStoredObjectCache.php | 3 +- .../Service/Messenger/OnGenerationFails.php | 3 +- .../Messenger/RequestGenerationHandler.php | 7 +- .../config/services.yaml | 1 + .../Serializer/Encoder/DocGenEncoderTest.php | 2 +- .../CollectionDocGenNormalizerTest.php | 2 +- .../Normalizer/DocGenObjectNormalizerTest.php | 33 +- .../Service/Context/BaseContextDataTest.php | 2 +- .../Context/Generator/GeneratorTest.php | 27 +- ...ConfigureOpenstackObjectStorageCommand.php | 91 ++ .../TempUrlOpenstackGenerator.php | 206 +++ .../Event/TempUrlGenerateEvent.php | 31 + .../Exception/BadCallToRemoteServer.php | 20 + .../Exception/TempUrlGeneratorException.php | 14 + .../TempUrlRemoteServerException.php | 20 + .../AsyncUpload/SignedUrl.php | 33 + .../AsyncUpload/SignedUrlPost.php | 37 + .../AsyncUpload/TempUrlGeneratorInterface.php | 24 + .../Templating/AsyncUploadExtension.php | 69 + .../Controller/AdminController.php | 6 +- .../Controller/AsyncUploadController.php | 121 ++ .../DocumentAccompanyingCourseController.php | 32 +- .../Controller/DocumentCategoryController.php | 41 +- .../Controller/DocumentPersonController.php | 37 +- ...ericDocForAccompanyingPeriodController.php | 6 +- .../Controller/GenericDocForPerson.php | 6 +- .../Controller/SignatureRequestController.php | 102 ++ .../Controller/StoredObjectApiController.php | 41 +- ...toredObjectRestoreVersionApiController.php | 47 + .../StoredObjectStatusApiController.php | 41 + .../StoredObjectVersionApiController.php | 69 + .../Controller/WebdavController.php | 36 +- .../Dav/Exception/ParseRequestException.php | 4 +- .../ChillDocStoreExtension.php | 31 +- .../DependencyInjection/Configuration.php | 64 +- .../Entity/AccompanyingCourseDocument.php | 24 +- .../ChillDocStoreBundle/Entity/Document.php | 58 +- .../Entity/DocumentCategory.php | 31 +- .../Entity/PersonDocument.php | 28 +- .../Entity/StoredObject.php | 264 ++-- .../Entity/StoredObjectPointInTime.php | 67 + .../StoredObjectPointInTimeReasonEnum.php | 18 + .../Entity/StoredObjectVersion.php | 229 +++ .../Form/AccompanyingCourseDocumentType.php | 3 +- .../DataMapper/StoredObjectDataMapper.php | 20 +- .../StoredObjectDataTransformer.php | 12 +- .../Form/DocumentCategoryType.php | 20 +- .../Form/PersonDocumentType.php | 4 +- .../Form/StoredObjectType.php | 3 +- .../Form/Type/AsyncUploaderType.php | 77 ++ .../GenericDoc/FetchQuery.php | 3 +- .../GenericDoc/GenericDocDTO.php | 3 +- ...anyingCourseDocumentGenericDocProvider.php | 3 +- .../PersonDocumentGenericDocProvider.php | 3 +- ...anyingCourseDocumentGenericDocRenderer.php | 3 +- .../Twig/GenericDocExtensionRuntime.php | 3 +- .../ChillDocStoreBundle/Menu/MenuBuilder.php | 4 +- .../Object/ObjectToAsyncFileTransformer.php | 47 - .../Object/PersistenceChecker.php | 40 - .../AccompanyingCourseDocumentRepository.php | 17 +- ...ssociatedEntityToStoredObjectInterface.php | 19 + .../PersonDocumentACLAwareRepository.php | 3 +- .../Repository/PersonDocumentRepository.php | 13 +- .../StoredObjectPointInTimeRepository.php | 27 + .../Repository/StoredObjectRepository.php | 16 + .../StoredObjectRepositoryInterface.php | 6 + .../StoredObjectVersionRepository.php | 94 ++ .../helper.ts => js/async-upload/uploader.ts} | 18 +- .../public/module/async_upload/index.ts | 14 +- .../document_action_buttons_group/index.ts | 3 +- .../Resources/public/types.ts | 150 +- .../vuejs/DocumentActionButtonsGroup.vue | 63 +- .../public/vuejs/DocumentSignature/App.vue | 634 +++++++++ .../public/vuejs/DocumentSignature/index.ts | 37 + .../public/vuejs/DropFileWidget/DropFile.vue | 60 +- .../vuejs/DropFileWidget/DropFileModal.vue | 69 + .../vuejs/DropFileWidget/DropFileWidget.vue | 14 +- .../Resources/public/vuejs/FileIcon.vue | 25 + .../StoredObjectButton/ConvertButton.vue | 4 +- .../StoredObjectButton/DesktopEditButton.vue | 3 + .../StoredObjectButton/DownloadButton.vue | 38 +- .../StoredObjectButton/HistoryButton.vue | 57 + .../HistoryButton/HistoryButtonList.vue | 68 + .../HistoryButton/HistoryButtonListItem.vue | 113 ++ .../HistoryButton/HistoryButtonModal.vue | 48 + .../HistoryButton/RestoreVersionButton.vue | 32 + .../StoredObjectButton/HistoryButton/api.ts | 12 + .../StoredObjectButton/WopiEditButton.vue | 5 +- .../vuejs/StoredObjectButton/helpers.ts | 53 +- .../vuejs/_components/AddAsyncUpload.vue | 174 --- .../_components/AddAsyncUploadDownloader.vue | 45 - .../_workflow.html.twig | 5 + .../Resources/views/List/list_item.html.twig | 4 +- .../views/PersonDocument/signature.html.twig | 38 + .../AccompanyingCourseDocumentVoter.php | 4 +- .../Authorization/AsyncUploadVoter.php | 49 + .../Authorization/StoredObjectVoter.php | 41 +- .../AbstractStoredObjectVoter.php | 69 + ...panyingCourseDocumentStoredObjectVoter.php | 54 + .../PersonDocumentStoredObjectVoter.php | 54 + .../StoredObjectVoterInterface.php | 22 + .../Security/Guard/DavOnUrlTokenExtractor.php | 3 +- .../Security/Guard/JWTDavTokenProvider.php | 3 +- .../Normalizer/StoredObjectDenormalizer.php | 62 +- .../Normalizer/StoredObjectNormalizer.php | 34 +- .../StoredObjectPointInTimeNormalizer.php | 38 + .../StoredObjectVersionNormalizer.php | 61 + .../Driver/BaseSigner/PdfSignedMessage.php | 24 + .../BaseSigner/PdfSignedMessageHandler.php | 61 + .../BaseSigner/PdfSignedMessageSerializer.php | 67 + .../BaseSigner/RequestPdfSignMessage.php | 29 + .../RequestPdfSignMessageSerializer.php | 105 ++ .../Service/Signature/PDFPage.php | 33 + .../Service/Signature/PDFSignatureZone.php | 43 + .../Signature/PDFSignatureZoneAvailable.php | 69 + .../Signature/PDFSignatureZoneParser.php | 60 + .../RemoveExpiredStoredObjectCronJob.php | 65 + .../RemoveOldVersionCronJob.php | 60 + .../RemoveOldVersionMessage.php | 19 + .../RemoveOldVersionMessageHandler.php | 78 ++ .../Service/StoredObjectManager.php | 169 ++- .../Service/StoredObjectManagerInterface.php | 54 +- .../Service/StoredObjectRestore.php | 38 + .../Service/StoredObjectRestoreInterface.php | 22 + .../Service/StoredObjectToPdfConverter.php | 75 + .../WorkflowStoredObjectPermissionHelper.php | 38 + .../WopiEditTwigExtensionRuntime.php | 9 +- ...igureOpenstackObjectStorageCommandTest.php | 65 + .../TempUrlOpenstackGeneratorTest.php | 254 ++++ .../OpenstackObjectStore/file-to-upload.txt | 1 + .../Templating/AsyncUploadExtensionTest.php | 77 ++ .../Controller/AsyncUploadControllerTest.php | 233 ++++ .../StoredObjectApiControllerTest.php | 55 + ...dObjectRestoreVersionApiControllerTest.php | 74 + .../StoredObjectVersionApiControllerTest.php | 77 ++ .../Tests/Controller/WebdavControllerTest.php | 66 +- .../Request/PropfindRequestAnalyzerTest.php | 2 +- .../Tests/Entity/StoredObjectTest.php | 48 +- .../Tests/Form/StoredObjectTypeTest.php | 67 +- .../Tests/GenericDoc/ManagerTest.php | 4 +- ...ngCourseDocumentGenericDocProviderTest.php | 4 +- .../PersonDocumentGenericDocProviderTest.php | 6 +- .../PersonDocumentACLAwareRepositoryTest.php | 13 +- .../AbstractStoredObjectVoterTest.php | 168 +++ .../Authorization/StoredObjectVoterTest.php | 133 +- .../Normalizer/SignedUrlNormalizerTest.php | 57 + .../SignedUrlPostNormalizerTest.php | 68 + .../StoredObjectDenormalizerTest.php | 144 ++ .../Normalizer/StoredObjectNormalizerTest.php | 98 ++ .../StoredObjectPointInTimeNormalizerTest.php | 64 + .../StoredObjectVersionNormalizerTest.php | 78 ++ .../StoredObjectVersionRepositoryTest.php | 43 + .../PdfSignedMessageHandlerTest.php | 100 ++ .../PdfSignedMessageSerializerTest.php | 64 + .../RequestPdfSignMessageSerializerTest.php | 137 ++ .../PDFSignatureZoneAvailableTest.php | 76 + .../Signature/PDFSignatureZoneParserTest.php | 79 ++ .../data/signature_2_signature_page_1.pdf | Bin 0 -> 16589 bytes .../RemoveExpiredStoredObjectCronJobTest.php | 113 ++ .../RemoveOldVersionCronJobTest.php | 102 ++ .../RemoveOldVersionMessageHandlerTest.php | 128 ++ .../Tests/Service/StoredObjectManagerTest.php | 239 +++- .../Tests/Service/StoredObjectRestoreTest.php | 53 + .../StoredObjectToPdfConverterTest.php | 61 + .../AsyncFileExistsValidatorTest.php | 77 ++ ...BeforeSignatureStepEventSubscriberTest.php | 208 +++ .../Validator/Constraints/AsyncFileExists.php | 39 + .../Constraints/AsyncFileExistsValidator.php | 53 + ...ompanyingCourseDocumentWorkflowHandler.php | 42 +- ...oPdfBeforeSignatureStepEventSubscriber.php | 75 + .../ChillDocStoreBundle/chill.api.specs.yaml | 184 ++- .../chill.webpack.config.js | 1 + .../ChillDocStoreBundle/config/services.yaml | 61 +- .../config/services/form.yaml | 13 +- .../config/services/media.yaml | 9 - .../config/services/security.yaml | 13 + .../migrations/Version20240709102730.php | 80 ++ .../migrations/Version20240910093735.php | 49 + .../migrations/Version20240918073234.php | 37 + .../ChillEventBundle/ChillEventBundle.php | 4 +- .../Controller/AdminController.php | 3 +- .../Controller/EventController.php | 121 +- .../Controller/EventListController.php | 7 +- .../Controller/EventTypeController.php | 38 +- .../Controller/ParticipationController.php | 53 +- .../Controller/RoleController.php | 37 +- .../Controller/StatusController.php | 38 +- src/Bundle/ChillEventBundle/Entity/Event.php | 91 +- .../ChillEventBundle/Entity/EventType.php | 44 +- .../ChillEventBundle/Entity/Participation.php | 53 +- src/Bundle/ChillEventBundle/Entity/Role.php | 36 +- src/Bundle/ChillEventBundle/Entity/Status.php | 36 +- .../Export/Aggregator/EventTypeAggregator.php | 4 +- .../Export/Aggregator/RoleAggregator.php | 4 +- .../Export/CountEventParticipations.php | 4 +- .../Export/Export/CountEvents.php | 6 +- .../Export/Filter/EventDateFilter.php | 4 +- .../Export/Filter/EventTypeFilter.php | 3 +- .../Export/Filter/RoleFilter.php | 3 +- .../Form/ChoiceLoader/EventChoiceLoader.php | 7 +- .../ChillEventBundle/Form/EventType.php | 8 +- .../Form/ParticipationType.php | 4 +- src/Bundle/ChillEventBundle/Form/RoleType.php | 4 +- .../Form/Type/PickEventType.php | 3 +- .../Form/Type/PickRoleType.php | 3 +- .../Form/Type/PickStatusType.php | 4 +- .../Menu/SectionMenuBuilder.php | 3 +- .../Repository/EventACLAwareRepository.php | 3 +- .../Repository/EventRepository.php | 58 +- .../_ignored_participations.html.twig | 2 +- .../ChillEventBundle/Search/EventSearch.php | 3 +- .../Authorization/EventStoredObjectVoter.php | 55 + .../Controller/EventListControllerTest.php | 4 +- .../ParticipationControllerTest.php | 4 +- .../Export/CountEventParticipationsTest.php | 2 +- .../Tests/Export/CountEventTest.php | 2 +- .../aggregators/EventDateAggregatorTest.php | 4 +- .../aggregators/EventTypeAggregatorTest.php | 4 +- .../Export/aggregators/RoleAggregatorTest.php | 4 +- .../Export/filters/EventDateFilterTest.php | 4 +- .../Export/filters/EventTypeFilterTest.php | 6 +- .../Tests/Export/filters/RoleFilterTest.php | 6 +- .../EventACLAwareRepositoryTest.php | 4 +- .../config/services/controller.yaml} | 0 .../translations/messages+intl-icu.fr.yml | 6 + .../translations/messages.fr.yml | 1 - .../src/ApiHelper/ApiWrapper.php | 84 ++ .../ApiHelper/PartenaireRomeAppellation.php | 113 ++ .../src/ApiHelper/ProcessRequestTrait.php | 100 ++ .../src/ChillFranceTravailApiBundle.php | 16 + .../src/Controller/RomeController.php | 56 + .../ChillFranceTravailApiExtension.php | 52 + .../src/DependencyInjection/Configuration.php | 34 + .../src/Resources/config/routing.yml | 3 + .../src/Resources/config/services.yml | 16 + .../src/Resources/views/.gitkeep | 1 + .../PartenaireRomeAppellationTest.php | 93 ++ .../Tests/Controller/RomeControllerTest.php | 29 + .../ChillJobBundle/src/ChillJobBundle.php | 16 + .../src/Controller/CSCrudReportController.php | 123 ++ .../src/Controller/CSPersonController.php | 150 ++ .../src/Controller/CSReportController.php | 73 + .../src/Controller/CVCrudController.php | 62 + .../src/Controller/FreinCrudController.php | 35 + .../Controller/ImmersionCrudController.php | 80 ++ .../ProjetProfessionnelCrudController.php | 57 + .../DependencyInjection/ChillJobExtension.php | 196 +++ .../src/DependencyInjection/Configuration.php | 35 + .../ChillJobBundle/src/Entity/CSPerson.php | 1224 +++++++++++++++++ src/Bundle/ChillJobBundle/src/Entity/CV.php | 303 ++++ .../src/Entity/CV/Experience.php | 205 +++ .../src/Entity/CV/Formation.php | 214 +++ .../ChillJobBundle/src/Entity/Frein.php | 192 +++ .../ChillJobBundle/src/Entity/Immersion.php | 1083 +++++++++++++++ .../src/Entity/ProjetProfessionnel.php | 407 ++++++ .../src/Entity/Rome/Appellation.php | 107 ++ .../ChillJobBundle/src/Entity/Rome/Metier.php | 100 ++ .../Export/AddCSPersonToPersonListHelper.php | 188 +++ .../ChillJobBundle/src/Export/ListCV.php | 395 ++++++ .../ChillJobBundle/src/Export/ListFrein.php | 497 +++++++ .../src/Export/ListProjetProfessionnel.php | 586 ++++++++ .../src/Form/CSPersonDispositifsType.php | 125 ++ .../Form/CSPersonPersonalSituationType.php | 256 ++++ .../src/Form/CV/ExperienceType.php | 70 + .../src/Form/CV/FormationType.php | 75 + src/Bundle/ChillJobBundle/src/Form/CVType.php | 91 ++ .../RomeAppellationChoiceLoader.php | 155 +++ .../ChillJobBundle/src/Form/FreinType.php | 66 + .../ChillJobBundle/src/Form/ImmersionType.php | 197 +++ .../src/Form/ProjetProfessionnelType.php | 108 ++ .../src/Form/Type/PickRomeAppellationType.php | 116 ++ .../ChillJobBundle/src/Menu/MenuBuilder.php | 72 + .../src/Repository/CSPersonRepository.php | 20 + .../Repository/CV/ExperienceRepository.php | 20 + .../src/Repository/CV/FormationRepository.php | 20 + .../src/Repository/CVRepository.php | 20 + .../src/Repository/FreinRepository.php | 20 + .../src/Repository/ImmersionRepository.php | 20 + .../ProjetProfessionnelRepository.php | 20 + .../Repository/Rome/AppellationRepository.php | 20 + .../src/Repository/Rome/MetierRepository.php | 20 + .../src/Resources/config/routing.yml | 3 + .../src/Resources/config/services.yml | 12 + .../Resources/config/services/3party_type.yml | 9 + .../Resources/config/services/controller.yml} | 6 +- .../src/Resources/config/services/export.yml | 20 + .../src/Resources/config/services/form.yml | 8 + .../src/Resources/config/services/menu.yml | 6 + .../Resources/config/services/security.yml | 13 + .../public/images/footer_bandeau.jpg | Bin 0 -> 39797 bytes .../src/Resources/public/images/index.js | 1 + .../Resources/public/module/cv_edit/index.js | 43 + .../public/module/dispositif_edit/index.js | 72 + .../public/module/immersion_edit/index.js | 20 + .../public/module/personal_situation/index.js | 103 ++ .../Resources/public/sass/csconnectes.scss | 19 + .../src/Resources/public/sass/index.js | 1 + .../Resources/translations/messages.fr.yml | 298 ++++ .../views/CSPerson/dispositifs_edit.html.twig | 96 ++ .../views/CSPerson/dispositifs_view.html.twig | 128 ++ .../personal_situation_edit.html.twig | 126 ++ .../personal_situation_view.html.twig | 285 ++++ .../src/Resources/views/CV/edit.html.twig | 61 + .../src/Resources/views/CV/new.html.twig | 61 + .../src/Resources/views/CV/view.html.twig | 144 ++ .../src/Resources/views/Frein/edit.html.twig | 20 + .../src/Resources/views/Frein/new.html.twig | 23 + .../src/Resources/views/Frein/view.html.twig | 58 + .../views/Immersion/edit-bilan.html.twig | 92 ++ .../Resources/views/Immersion/edit.html.twig | 71 + .../Resources/views/Immersion/new.html.twig | 75 + .../Resources/views/Immersion/view.html.twig | 222 +++ .../views/ProjetProfessionnel/edit.html.twig | 52 + .../views/ProjetProfessionnel/new.html.twig | 52 + .../views/ProjetProfessionnel/view.html.twig | 108 ++ .../Resources/views/Report/delete.html.twig | 16 + .../Resources/views/Report/index.html.twig | 253 ++++ .../Authorization/ExportsJobVoter.php | 122 ++ .../src/Security/Authorization/JobVoter.php | 119 ++ .../Controller/CSPersonControllerTest.php | 21 + .../Controller/CSReportControllerTest.php | 21 + .../src/ThirdParty/EntrepriseType.php | 25 + .../src/ThirdParty/PrescripteurType.php | 25 + .../src/chill.webpack.config.js | 20 + .../src/migrations/Version20240424095147.php | 158 +++ .../src/migrations/Version20240424140641.php | 46 + .../src/migrations/Version20240429111628.php | 41 + .../migrations/old/Version20191119172511.php | 114 ++ .../migrations/old/Version20191129112321.php | 60 + .../migrations/old/Version20200113104411.php | 53 + .../migrations/old/Version20200113142525.php | 43 + .../migrations/old/Version20200114081435.php | 44 + .../migrations/old/Version20200124130244.php | 36 + .../migrations/old/Version20200124132321.php | 36 + .../migrations/old/Version20200127132932.php | 36 + .../migrations/old/Version20200205132532.php | 83 ++ .../migrations/old/Version20200207224152.php | 38 + .../migrations/old/Version20200210105342.php | 36 + .../migrations/old/Version20200313124323.php | 87 ++ .../migrations/old/Version20200403114520.php | 35 + .../migrations/old/Version20200403123148.php | 32 + .../CRUDControllerCompilerPass.php | 6 + .../Controller/AbstractCRUDController.php | 23 +- .../CRUD/Controller/ApiController.php | 16 +- .../CRUD/Controller/CRUDController.php | 103 +- .../Exception/InvalidCrudConfiguration.php | 25 + .../CRUD/Form/CRUDDeleteEntityForm.php | 4 +- .../CRUD/Routing/CRUDRoutesLoader.php | 6 +- .../ChillMainBundle/ChillMainBundle.php | 6 +- .../Command/ChillImportUsersCommand.php | 9 +- .../ChillUserSendRenewPasswordCodeCommand.php | 4 +- .../Command/ExecuteCronJobCommand.php | 7 +- .../LoadAddressesBEFromBestAddressCommand.php | 7 +- .../LoadAddressesFRFromBANOCommand.php | 7 +- .../LoadAddressesLUFromBDAddressCommand.php | 2 +- .../Command/LoadAndUpdateLanguagesCommand.php | 4 +- .../Command/LoadCountriesCommand.php | 6 +- .../Command/LoadPostalCodeFR.php | 7 +- .../Command/LoadPostalCodesCommand.php | 17 +- .../Command/SetPasswordCommand.php | 8 +- .../SynchronizeEntityInfoViewsCommand.php | 10 +- .../Controller/AbsenceController.php | 27 +- .../Controller/AddressApiController.php | 8 +- .../AddressReferenceAPIController.php | 8 +- .../AddressToReferenceMatcherController.php | 15 +- .../Controller/AdminController.php | 20 +- .../Controller/CountryApiController.php | 16 + .../Controller/DashboardApiController.php | 6 +- .../Controller/DefaultController.php | 8 +- .../Controller/ExportController.php | 32 +- .../GeographicalUnitApiController.php | 16 + ...GeographicalUnitByAddressApiController.php | 8 +- .../Controller/LocationTypeController.php | 4 +- .../Controller/LoginController.php | 11 +- .../Controller/NewsItemApiController.php | 6 +- .../Controller/NewsItemHistoryController.php | 11 +- .../Controller/NotificationApiController.php | 20 +- .../Controller/NotificationController.php | 67 +- .../Controller/PasswordController.php | 90 +- .../Controller/PermissionApiController.php | 7 +- .../Controller/PermissionsGroupController.php | 33 +- .../Controller/PostalCodeAPIController.php | 8 +- .../Controller/PostalCodeController.php | 9 +- .../Controller/SavedExportController.php | 16 +- .../Controller/ScopeController.php | 86 +- .../Controller/SearchController.php | 24 +- .../Controller/TimelineCenterController.php | 11 +- .../Controller/UserApiController.php | 30 +- .../Controller/UserController.php | 49 +- .../Controller/UserExportController.php | 9 +- .../UserJobScopeHistoriesController.php | 7 +- .../Controller/UserProfileController.php | 20 +- .../WorkflowAddSignatureController.php | 79 ++ .../Controller/WorkflowApiController.php | 18 +- .../Controller/WorkflowController.php | 188 ++- .../Controller/WorkflowOnHoldController.php | 98 ++ .../ChillMainBundle/Cron/CronManager.php | 3 +- .../DataFixtures/ORM/LoadUsers.php | 3 +- .../ChillMainExtension.php | 4 + .../DependencyInjection/Configuration.php | 23 + .../RoleProvidersCompilerPass.php | 41 - .../Event/TrackCreateUpdateSubscriber.php | 4 +- .../ChillMainBundle/Doctrine/Model/Point.php | 4 +- .../Doctrine/Model/TrackCreationTrait.php | 18 +- .../Doctrine/Model/TrackUpdateTrait.php | 18 +- src/Bundle/ChillMainBundle/Entity/Address.php | 162 +-- .../Entity/AddressReference.php | 104 +- src/Bundle/ChillMainBundle/Entity/Center.php | 51 +- .../ChillMainBundle/Entity/Civility.php | 54 +- src/Bundle/ChillMainBundle/Entity/Country.php | 44 +- .../Entity/CronJobExecution.php | 31 +- .../Entity/DashboardConfigItem.php | 51 +- .../Entity/Embeddable/CommentEmbeddable.php | 21 +- .../Embeddable/PrivateCommentEmbeddable.php | 9 +- .../Entity/GeographicalUnit.php | 37 +- .../SimpleGeographicalUnitDTO.php | 15 +- .../Entity/GeographicalUnitLayer.php | 43 +- .../ChillMainBundle/Entity/GroupCenter.php | 47 +- .../ChillMainBundle/Entity/Language.php | 37 +- .../ChillMainBundle/Entity/Location.php | 121 +- .../ChillMainBundle/Entity/LocationType.php | 80 +- .../ChillMainBundle/Entity/NewsItem.php | 66 +- .../ChillMainBundle/Entity/Notification.php | 103 +- .../Entity/NotificationComment.php | 63 +- .../Entity/PermissionsGroup.php | 48 +- .../ChillMainBundle/Entity/PostalCode.php | 107 +- .../ChillMainBundle/Entity/Regroupment.php | 36 +- .../ChillMainBundle/Entity/RoleScope.php | 43 +- .../ChillMainBundle/Entity/SavedExport.php | 43 +- src/Bundle/ChillMainBundle/Entity/Scope.php | 51 +- src/Bundle/ChillMainBundle/Entity/User.php | 148 +- .../Entity/User/UserJobHistory.php | 34 +- .../Entity/User/UserScopeHistory.php | 35 +- src/Bundle/ChillMainBundle/Entity/UserJob.php | 38 +- .../Entity/Workflow/EntityWorkflow.php | 194 +-- .../Entity/Workflow/EntityWorkflowComment.php | 25 +- .../EntityWorkflowSignatureStateEnum.php | 20 + .../Entity/Workflow/EntityWorkflowStep.php | 156 ++- .../Workflow/EntityWorkflowStepHold.php | 54 + .../Workflow/EntityWorkflowStepSignature.php | 196 +++ .../Export/ExportFormHelper.php | 3 +- .../Export/Helper/DateTimeHelper.php | 4 +- .../Export/Helper/ExportAddressHelper.php | 4 +- .../TranslatableStringExportLabelHelper.php | 4 +- .../Export/Helper/UserHelper.php | 4 +- .../ChillMainBundle/Export/ListInterface.php | 4 +- .../Export/SortExportElement.php | 3 +- .../Form/DataMapper/AddressDataMapper.php | 4 +- .../DataMapper/ExportPickCenterDataMapper.php | 4 +- .../DataMapper/PrivateCommentDataMapper.php | 8 +- .../Form/DataMapper/RollingDateDataMapper.php | 4 +- .../Form/DataMapper/ScopePickerDataMapper.php | 8 +- .../Form/Event/CustomizeFormEvent.php | 4 +- .../ChillMainBundle/Form/LocationFormType.php | 4 +- .../AddressToIdDataTransformer.php | 4 +- .../DataTransformer/CenterTransformer.php | 4 +- .../EntityToJsonTransformer.php | 4 +- .../MultipleObjectsToIdTransformer.php | 4 +- .../DataTransformer/ObjectToIdTransformer.php | 4 +- .../PostalCodeToIdTransformer.php | 4 +- .../Type/DataTransformer/ScopeTransformer.php | 4 +- .../Form/Type/DateIntervalType.php | 1 - .../Form/Type/Export/ExportType.php | 4 +- .../Form/Type/Export/FilterType.php | 4 +- .../Form/Type/Export/PickCenterType.php | 3 +- .../Form/Type/PickAddressType.php | 4 +- .../Form/Type/PickCenterType.php | 4 +- .../Form/Type/PickCivilityType.php | 4 +- .../Form/Type/PickLocationTypeType.php | 4 +- .../Form/Type/PickPostalCodeType.php | 4 +- .../Form/Type/PickUserDynamicType.php | 4 +- .../Form/Type/PickUserLocationType.php | 4 +- .../Form/Type/PrivateCommentType.php | 4 +- .../Form/Type/ScopePickerType.php | 8 +- .../Form/Type/Select2CountryType.php | 4 +- .../Form/Type/Select2LanguageType.php | 4 +- .../ChillMainBundle/Form/UserPasswordType.php | 5 +- src/Bundle/ChillMainBundle/Form/UserType.php | 4 +- .../Form/WorkflowSignatureMetadataType.php | 62 + .../ChillMainBundle/Form/WorkflowStepType.php | 297 ++-- .../Counter/NotificationByUserCounter.php | 4 +- .../Notification/Email/NotificationMailer.php | 4 +- ...NotificationOnTerminateEventSubscriber.php | 6 +- .../Exception/NotificationHandlerNotFound.php | 4 +- .../ChillMainBundle/Notification/Mailer.php | 4 +- .../NotificationHandlerManager.php | 4 +- .../Notification/NotificationPresence.php | 4 +- .../NotificationTwigExtensionRuntime.php | 4 +- .../Pagination/PageGenerator.php | 4 +- .../ChillMainBundle/Pagination/Paginator.php | 3 +- .../Pagination/PaginatorFactory.php | 3 +- .../Phonenumber/Templating.php | 4 +- .../ChillMainBundle/Redis/ChillRedis.php | 4 +- .../Repository/AddressReferenceRepository.php | 6 +- .../Repository/AddressRepository.php | 4 +- .../Repository/CenterRepository.php | 4 +- .../Repository/CountryRepository.php | 4 +- .../GeographicalUnitLayerLayerRepository.php | 4 +- .../Repository/GeographicalUnitRepository.php | 4 +- .../Repository/GroupCenterRepository.php | 4 +- .../Repository/LanguageRepository.php | 4 +- .../Repository/PermissionsGroupRepository.php | 4 +- .../Repository/PostalCodeRepository.php | 6 +- .../Repository/RegroupmentRepository.php | 4 +- .../Repository/RoleScopeRepository.php | 4 +- .../Repository/ScopeRepository.php | 6 +- .../Repository/UserACLAwareRepository.php | 4 +- .../Workflow/EntityWorkflowRepository.php | 51 +- ...owSignatureACLAwareRepositoryInterface.php | 23 + .../EntityWorkflowStepHoldRepository.php | 79 ++ .../Workflow/EntityWorkflowStepRepository.php | 4 +- ...orkflowStepSignatureACLAwareRepository.php | 54 + .../EntityWorkflowStepSignatureRepository.php | 39 + .../Resources/public/chill/chillmain.scss | 3 + .../Resources/public/chill/js/date.ts | 4 + .../Resources/public/chill/scss/hover.scss | 11 + .../public/chill/scss/record_actions.scss | 4 + .../lib/download-report/download-report.js | 6 +- .../ckeditor5/{index.js => editor_config.ts} | 20 +- .../public/module/ckeditor5/index.ts | 15 + .../public/module/collection/index.ts | 9 +- .../public/module/pick-entity/index.js | 2 + .../public/page/export/download-export.js | 16 + .../public/page/workflow-show/index.js | 141 +- .../DashboardWidgets/NewsItem.vue | 2 +- .../vuejs/HomepageWidget/MyWorkflowsTable.vue | 5 +- .../public/vuejs/HomepageWidget/js/i18n.js | 1 + .../EntityWorkflow/ListWorkflow.vue | 6 +- .../views/CRUD/_edit_content.html.twig | 8 +- .../Resources/views/Dev/dev.assets.html.twig | 395 ++++++ .../views/Dev/dev.assets.test1.html.twig | 84 ++ .../views/Dev/dev.assets.test2.html.twig | 78 ++ .../views/Dev/swagger-ui/index.html.twig | 22 + .../Resources/views/Export/download.html.twig | 14 +- .../Resources/views/Menu/user.html.twig | 4 +- .../views/Workflow/_decision.html.twig | 35 +- .../views/Workflow/_history.html.twig | 14 +- .../views/Workflow/_signature.html.twig | 43 + .../Workflow/_signature_metadata.html.twig | 24 + .../views/Workflow/_signature_sign.html.twig | 35 + .../Resources/views/Workflow/index.html.twig | 27 +- .../Resources/views/Workflow/list.html.twig | 3 + .../views/Workflow/macro_breadcrumb.html.twig | 30 +- .../Workflow/person_signature_form.html.twig | 0 ...n_transition_completed_content.fr.txt.twig | 2 +- .../workflow_send_access_key.fr.txt.twig | 2 +- .../MenuBuilder/AdminNewsMenuBuilder.php | 4 +- .../MenuBuilder/SectionMenuBuilder.php | 4 +- .../Routing/MenuBuilder/UserMenuBuilder.php | 4 +- .../ChillMainBundle/Routing/MenuComposer.php | 4 +- .../ChillMainBundle/Routing/MenuTwig.php | 4 +- .../ChillMainBundle/Search/AbstractSearch.php | 6 +- .../Search/Entity/SearchUserApiProvider.php | 4 +- .../ChillMainBundle/Search/Model/Result.php | 3 +- .../Search/ParsingException.php | 4 +- .../ChillMainBundle/Search/SearchApi.php | 4 +- .../Search/SearchApiResult.php | 12 +- .../Search/Utils/SearchExtractionResult.php | 4 +- .../Authorization/AbstractChillVoter.php | 4 +- .../Authorization/AuthorizationHelper.php | 5 +- .../AuthorizationHelperForCurrentUser.php | 4 +- .../Authorization/ChillVoterInterface.php | 4 +- .../Authorization/DefaultVoterHelper.php | 3 +- .../DefaultVoterHelperFactory.php | 4 +- .../DefaultVoterHelperGenerator.php | 4 +- .../EntityWorkflowStepSignatureVoter.php | 41 + .../EntityWorkflowTransitionVoter.php | 88 ++ .../Authorization/EntityWorkflowVoter.php | 4 +- .../WorkflowEntityDeletionVoter.php | 9 +- .../Security/ChillSecurity.php | 54 + .../PasswordRecover/PasswordRecoverEvent.php | 3 +- .../PasswordRecover/RecoverPasswordHelper.php | 4 +- .../Security/ProvideRoleInterface.php | 4 +- .../Resolver/CenterResolverDispatcher.php | 4 +- .../Resolver/CenterResolverManager.php | 4 +- .../Resolver/ResolverTwigExtension.php | 4 +- .../Resolver/ScopeResolverDispatcher.php | 4 +- .../ChillMainBundle/Security/RoleProvider.php | 20 +- .../Security/UserProvider/UserProvider.php | 9 +- .../Serializer/Model/Collection.php | 4 +- .../Serializer/Model/Counter.php | 4 +- .../Normalizer/AddressNormalizer.php | 4 +- .../Normalizer/CenterNormalizer.php | 4 +- .../CommentEmbeddableDocGenNormalizer.php | 4 +- .../Serializer/Normalizer/DateNormalizer.php | 4 +- .../DoctrineExistingEntityNormalizer.php | 4 +- .../Normalizer/EntityWorkflowNormalizer.php | 5 +- .../EntityWorkflowStepNormalizer.php | 4 +- .../Normalizer/NotificationNormalizer.php | 4 +- .../PrivateCommentEmbeddableNormalizer.php | 4 +- .../Serializer/Normalizer/UserNormalizer.php | 4 +- ...ollateAddressWithReferenceOrPostalCode.php | 3 +- ...ddressWithReferenceOrPostalCodeCronJob.php | 3 +- ...eographicalUnitMaterializedViewCronJob.php | 3 +- .../EntityInfo/ViewEntityInfoManager.php | 3 +- .../AddressReferenceBEFromBestAddress.php | 6 +- .../Import/AddressReferenceBaseImporter.php | 4 +- .../Import/AddressReferenceFromBano.php | 4 +- .../Service/Import/AddressReferenceLU.php | 4 +- .../Import/AddressToReferenceMatcher.php | 4 +- .../Import/GeographicalUnitBaseImporter.php | 4 +- .../Import/PostalCodeBEFromBestAddress.php | 4 +- .../Service/Import/PostalCodeBaseImporter.php | 4 +- .../Import/PostalCodeFRFromOpenData.php | 4 +- .../Service/Mailer/ChillMailer.php | 4 +- .../Service/RollingDate/RollingDate.php | 3 +- .../ShortMessage/NullShortMessageSender.php | 4 +- .../Service/ShortMessage/ShortMessage.php | 4 +- .../ShortMessage/ShortMessageHandler.php | 4 +- .../ShortMessage/ShortMessageTransporter.php | 4 +- .../ShortMessageOvh/OvhShortMessageSender.php | 3 +- .../Workflow/CancelStaleWorkflowCronJob.php | 70 + .../Workflow/CancelStaleWorkflowHandler.php | 88 ++ .../Workflow/CancelStaleWorkflowMessage.php | 22 + .../Templating/Entity/AddressRender.php | 4 +- .../Entity/ChillEntityRenderExtension.php | 48 +- .../Entity/ChillEntityRenderInterface.php | 6 +- .../Entity/ChillEntityRenderManager.php | 56 + .../ChillEntityRenderManagerInterface.php | 19 + .../Templating/Entity/CommentRender.php | 4 +- .../Templating/Entity/UserRender.php | 3 +- .../FilterOrderGetActiveFilterHelper.php | 3 +- .../Templating/Listing/FilterOrderHelper.php | 5 +- .../Listing/FilterOrderHelperBuilder.php | 4 +- .../Listing/FilterOrderHelperFactory.php | 4 +- .../Templating/Listing/Templating.php | 3 +- .../Templating/TranslatableStringHelper.php | 6 +- .../Templating/TranslatableStringTwig.php | 4 +- .../ChillMainBundle/Test/DummyPaginator.php | 3 +- .../Test/Export/AbstractAggregatorTest.php | 42 +- .../Test/Export/AbstractExportTest.php | 22 +- .../Test/Export/AbstractFilterTest.php | 30 +- .../Test/PrepareCenterTrait.php | 2 +- .../Test/PrepareClientTrait.php | 37 +- .../Test/PrepareScopeTrait.php | 2 +- .../ChillMainBundle/Test/PrepareUserTrait.php | 2 +- .../EntityWorkflowTransitionVoterTest.php | 144 ++ .../Authorization/ParentRoleHelperTest.php | 2 +- .../Controller/AddressControllerTest.php | 4 +- .../AddressReferenceApiControllerTest.php | 4 +- ...ddressToReferenceMatcherControllerTest.php | 8 +- .../Tests/Controller/ExportControllerTest.php | 14 +- ...raphicalUnitByAddressApiControllerTest.php | 2 +- .../Tests/Controller/LoginControllerTest.php | 7 +- .../Controller/NewsItemControllerTest.php | 4 +- .../NewsItemsHistoryControllerTest.php | 4 +- .../NotificationApiControllerTest.php | 22 +- .../Tests/Controller/ScopeControllerTest.php | 9 +- .../Controller/SearchApiControllerTest.php | 2 +- .../Tests/Controller/SearchControllerTest.php | 21 +- .../Tests/Controller/UserControllerTest.php | 92 +- .../WorkflowAddSignatureControllerTest.php | 81 ++ .../WorkflowOnHoldControllerTest.php | 116 ++ .../Cron/CronJobDatabaseInteractionTest.php | 6 +- .../Tests/Cron/CronManagerTest.php | 4 +- .../Tests/Doctrine/DQL/AgeTest.php | 4 +- .../Tests/Doctrine/DQL/GreatestTest.php | 2 +- .../Doctrine/DQL/JsonBuildObjectTest.php | 4 +- .../Tests/Doctrine/DQL/JsonExtractTest.php | 4 +- .../Doctrine/DQL/JsonbExistsInArrayTest.php | 2 +- .../Tests/Doctrine/DQL/LeastTest.php | 2 +- .../Tests/Entity/NotificationTest.php | 8 +- .../EntityWorkflowStepSignatureTest.php | 69 + .../Entity/Workflow/EntityWorkflowTest.php | 105 +- .../AccompanyingCourseExportHelperTest.php | 4 +- .../Tests/Export/ExportManagerTest.php | 30 +- .../Tests/Export/SortExportElementTest.php | 30 +- .../Tests/Form/Type/ScopePickerTypeTest.php | 14 +- ...ficationOnTerminateEventSubscriberTest.php | 12 +- .../Tests/Pagination/PageTest.php | 4 +- .../Tests/Pagination/PaginatorTest.php | 8 +- .../Phonenumber/PhonenumberHelperTest.php | 2 +- .../Repository/NewsItemRepositoryTest.php | 2 +- .../Tests/Search/AbstractSearchTest.php | 6 +- .../Utils/ExtractDateFromPatternTest.php | 2 +- .../ExtractPhonenumberFromPatternTest.php | 2 +- .../Authorization/AuthorizationHelperTest.php | 34 +- .../PasswordRecover/TokenManagerTest.php | 6 +- .../Resolver/CenterResolverDispatcherTest.php | 2 +- .../Resolver/DefaultScopeResolverTest.php | 8 +- .../Resolver/ScopeResolverDispatcherTest.php | 4 +- .../Normalizer/DateNormalizerTest.php | 2 +- .../DoctrineExistingEntityNormalizerTest.php | 8 +- .../Normalizer/PhonenumberNormalizerTest.php | 2 +- .../Normalizer/UserNormalizerTest.php | 2 +- ...teAddressWithReferenceOrPostalCodeTest.php | 2 +- ...aphicalUnitMaterializedViewCronJobTest.php | 2 +- .../AddressReferenceBaseImporterTest.php | 8 +- .../Import/AddressToReferenceMatcherTest.php | 10 +- .../GeographicalUnitBaseImporterTest.php | 4 +- .../Import/PostalCodeBaseImporterTest.php | 8 +- .../Tests/Services/MenuComposerTest.php | 2 +- .../RollingDate/RollingDateConverterTest.php | 2 +- .../CancelStaleWorkflowCronJobTest.php | 104 ++ .../CancelStaleWorkflowHandlerTest.php | 161 +++ .../Templating/Entity/AddressRenderTest.php | 54 +- .../EntityWorkflowMarkingStoreTest.php | 71 + .../EntityWorkflowGuardTransitionTest.php | 178 +++ .../SignatureStepStateChangerTest.php | 146 ++ .../Timeline/TimelineBuilder.php | 4 +- .../Timeline/TimelineSingleQuery.php | 4 +- .../Constraint/PhonenumberConstraint.php | 12 +- .../Validator/RoleScopeScopePresence.php | 4 +- .../Validation/Validator/ValidPhonenumber.php | 4 +- .../Entity/UserCircleConsistency.php | 4 +- .../Counter/WorkflowByUserCounter.php | 4 +- .../EntityWorkflowHandlerInterface.php | 11 + .../Workflow/EntityWorkflowManager.php | 30 +- .../Workflow/EntityWorkflowMarkingStore.php | 53 + ...rkflowWithStoredObjectHandlerInterface.php | 27 + .../EntityWorkflowGuardTransition.php | 123 ++ ...ntityWorkflowTransitionEventSubscriber.php | 86 +- .../NotificationOnTransition.php | 15 +- .../SendAccessKeyEventSubscriber.php | 12 +- .../Exception/HandlerNotFoundException.php | 4 +- .../Workflow/Helper/MetadataExtractor.php | 4 +- .../WorkflowNotificationHandler.php | 4 +- .../Workflow/SignatureStepStateChanger.php | 112 ++ .../WorkflowTwigExtensionRuntime.php | 4 +- .../Validator/EntityWorkflowCreation.php | 3 +- .../EntityWorkflowCreationValidator.php | 4 +- .../Workflow/WorkflowTransitionContextDTO.php | 87 ++ .../ChillMainBundle/chill.webpack.config.js | 8 +- .../config/services/controller.yaml | 2 - .../ChillMainBundle/config/services/form.yaml | 15 +- .../config/services/security.yaml | 2 + .../config/services/templating.yaml | 9 +- .../migrations/Version20100000000000.php | 4 +- .../migrations/Version20220513151853.php | 4 +- .../migrations/Version20240628095159.php | 51 + .../migrations/Version20240807123801.php | 46 + .../translations/messages+intl-icu.fr.yaml | 3 + .../translations/messages.fr.yml | 23 + .../PersonAddressMoveEventSubscriber.php | 4 +- .../Events/UserRefEventSubscriber.php | 4 +- .../AccompanyingPeriodStepChangeCronjob.php | 3 +- ...mpanyingPeriodStepChangeMessageHandler.php | 3 +- .../AccompanyingPeriodStepChanger.php | 3 +- .../ChillPersonBundle/Actions/ActionEvent.php | 3 +- .../PersonMoveCenterHistoryHandler.php | 3 +- .../Actions/Remove/PersonMove.php | 3 +- .../Actions/Remove/PersonMoveManager.php | 3 +- .../Controller/EntityPersonCRUDController.php | 32 +- .../OneToOneEntityPersonCRUDController.php | 8 +- .../Command/ChillPersonMoveCommand.php | 5 +- .../Command/ImportSocialWorkMetadata.php | 1 - ...emoveOldDraftAccompanyingPeriodCommand.php | 5 +- .../Config/ConfigPersonAltNamesHelper.php | 3 +- .../AccompanyingCourseApiController.php | 30 +- .../AccompanyingCourseCommentController.php | 33 +- .../AccompanyingCourseController.php | 98 +- .../AccompanyingCourseWorkApiController.php | 24 +- .../AccompanyingCourseWorkController.php | 55 +- ...CourseWorkEvaluationDocumentController.php | 12 +- ...AccompanyingPeriodCommentApiController.php | 16 + .../AccompanyingPeriodController.php | 39 +- ...mpanyingPeriodRegulationListController.php | 8 +- ...ccompanyingPeriodResourceApiController.php | 16 + ...nyingPeriodWorkEvaluationApiController.php | 13 +- .../Controller/AdminController.php | 19 +- .../Controller/ClosingMotiveController.php | 4 +- .../Controller/HouseholdApiController.php | 22 +- .../HouseholdCompositionController.php | 18 +- .../Controller/HouseholdController.php | 78 +- .../Controller/HouseholdMemberController.php | 84 +- .../Controller/PersonAddressController.php | 40 +- .../Controller/PersonApiController.php | 23 +- .../Controller/PersonController.php | 23 +- .../Controller/PersonDuplicateController.php | 64 +- .../Controller/PersonResourceController.php | 25 +- .../Controller/PersonSignatureController.php | 60 + .../ReassignAccompanyingPeriodController.php | 8 +- .../Controller/RelationApiController.php | 16 + .../Controller/RelationshipApiController.php | 5 +- .../ResidentialAddressController.php | 28 +- .../SocialWorkEvaluationApiController.php | 12 +- .../SocialWorkGoalApiController.php | 4 +- .../SocialWorkResultApiController.php | 4 +- .../SocialWorkSocialActionApiController.php | 3 +- .../Controller/TimelinePersonController.php | 10 +- .../UserAccompanyingPeriodController.php | 12 +- .../ORM/LoadAccompanyingPeriodWork.php | 4 +- .../DataFixtures/ORM/LoadCustomFields.php | 3 +- .../DataFixtures/ORM/LoadRelationships.php | 4 +- .../ORM/LoadSocialWorkMetadata.php | 4 +- .../ChillPersonExtension.php | 6 + .../Entity/AccompanyingPeriod.php | 408 ++---- .../AccompanyingPeriodInfo.php | 36 +- .../AccompanyingPeriodLocationHistory.php | 37 +- .../AccompanyingPeriodStepHistory.php | 41 +- .../AccompanyingPeriodWork.php | 229 +-- .../AccompanyingPeriodWorkEvaluation.php | 160 +-- ...companyingPeriodWorkEvaluationDocument.php | 73 +- .../AccompanyingPeriodWorkGoal.php | 60 +- .../AccompanyingPeriodWorkReferrerHistory.php | 34 +- .../AccompanyingPeriod/ClosingMotive.php | 58 +- .../Entity/AccompanyingPeriod/Comment.php | 81 +- .../Entity/AccompanyingPeriod/Origin.php | 44 +- .../Entity/AccompanyingPeriod/Resource.php | 76 +- .../Entity/AccompanyingPeriod/UserHistory.php | 43 +- .../AccompanyingPeriodParticipation.php | 55 +- .../Entity/Household/Household.php | 151 +- .../Entity/Household/HouseholdComposition.php | 81 +- .../Household/HouseholdCompositionType.php | 41 +- .../Entity/Household/HouseholdMember.php | 105 +- .../Household/PersonHouseholdAddress.php | 44 +- .../Entity/Household/Position.php | 56 +- .../Entity/MaritalStatus.php | 20 +- .../ChillPersonBundle/Entity/Person.php | 357 ++--- .../Entity/Person/AbstractPersonResource.php | 198 +++ .../Entity/Person/PersonCenterCurrent.php | 29 +- .../Entity/Person/PersonCenterHistory.php | 35 +- .../Entity/Person/PersonCurrentAddress.php | 28 +- .../Entity/Person/PersonResource.php | 233 +--- .../Entity/Person/PersonResourceKind.php | 34 +- .../Entity/Person/ResidentialAddress.php | 75 +- .../Entity/PersonAltName.php | 37 +- .../Entity/PersonNotDuplicate.php | 34 +- .../ChillPersonBundle/Entity/PersonPhone.php | 46 +- .../Entity/Relationships/Relation.php | 52 +- .../Entity/Relationships/Relationship.php | 157 +-- .../Entity/SocialWork/Evaluation.php | 69 +- .../Entity/SocialWork/Goal.php | 55 +- .../Entity/SocialWork/Result.php | 63 +- .../Entity/SocialWork/SocialAction.php | 79 +- .../Entity/SocialWork/SocialIssue.php | 52 +- .../Event/Person/PersonAddressMoveEvent.php | 4 +- .../AccompanyingPeriodWorkEventListener.php | 4 +- .../AdministrativeLocationAggregator.php | 4 +- .../ClosingMotiveAggregator.php | 4 +- .../ConfidentialAggregator.php | 4 +- .../CreatorJobAggregator.php | 7 +- .../DurationAggregator.php | 4 +- .../EmergencyAggregator.php | 4 +- .../EvaluationAggregator.php | 4 +- .../GeographicalUnitStatAggregator.php | 7 +- .../IntensityAggregator.php | 4 +- .../JobWorkingOnCourseAggregator.php | 7 +- .../OriginAggregator.php | 6 +- .../PersonParticipatingAggregator.php | 3 +- .../ReferrerAggregator.php | 3 +- .../ReferrerScopeAggregator.php | 3 +- .../RequestorAggregator.php | 4 +- .../ScopeAggregator.php | 4 +- .../ScopeWorkingOnCourseAggregator.php | 7 +- .../SocialActionAggregator.php | 4 +- .../SocialIssueAggregator.php | 4 +- .../StepAggregator.php | 4 +- .../UserJobAggregator.php | 3 +- .../UserWorkingOnCourseAggregator.php | 3 +- .../ByClosingMotiveAggregator.php | 3 +- .../ByStepAggregator.php | 3 +- .../EvaluationTypeAggregator.php | 4 +- .../HavingEndDateAggregator.php | 4 +- .../ChildrenNumberAggregator.php | 4 +- .../CompositionAggregator.php | 4 +- .../PersonAggregators/AgeAggregator.php | 3 +- .../ByHouseholdCompositionAggregator.php | 4 +- .../PersonAggregators/CenterAggregator.php | 3 +- .../CountryOfBirthAggregator.php | 4 +- .../PersonAggregators/GenderAggregator.php | 8 +- .../GeographicalUnitAggregator.php | 4 +- .../HouseholdPositionAggregator.php | 4 +- .../MaritalStatusAggregator.php | 4 +- .../NationalityAggregator.php | 4 +- .../PostalCodeAggregator.php | 3 +- .../ActionTypeAggregator.php | 4 +- .../CreatorAggregator.php | 7 +- .../CreatorJobAggregator.php | 7 +- .../CreatorScopeAggregator.php | 7 +- .../CurrentActionAggregator.php | 4 +- .../SocialWorkAggregators/GoalAggregator.php | 4 +- .../GoalResultAggregator.php | 4 +- .../HandlingThirdPartyAggregator.php | 4 +- .../SocialWorkAggregators/JobAggregator.php | 7 +- .../ReferrerAggregator.php | 3 +- .../ResultAggregator.php | 4 +- .../SocialWorkAggregators/ScopeAggregator.php | 7 +- ...rkPersonAssociatedOnAccompanyingPeriod.php | 4 +- ...vgDurationAPWorkPersonAssociatedOnWork.php | 4 +- .../Export/Export/CountEvaluation.php | 4 +- .../Export/Export/ListAccompanyingPeriod.php | 3 +- ...orkAssociatePersonOnAccompanyingPeriod.php | 3 +- ...panyingPeriodWorkAssociatePersonOnWork.php | 3 +- .../Export/Export/ListEvaluation.php | 3 +- .../Export/Export/ListPerson.php | 4 +- .../Export/Export/ListPersonDuplicate.php | 4 +- ...istPersonWithAccompanyingPeriodDetails.php | 3 +- .../ActiveOnDateFilter.php | 4 +- .../ActiveOneDayBetweenDatesFilter.php | 4 +- .../AdministrativeLocationFilter.php | 4 +- .../ClosingMotiveFilter.php | 4 +- .../ConfidentialFilter.php | 4 +- .../CreatorJobFilter.php | 3 +- .../EmergencyFilter.php | 4 +- .../EvaluationFilter.php | 4 +- .../GeographicalUnitStatFilter.php | 3 +- .../HandlingThirdPartyFilter.php | 3 +- .../HasNoReferrerFilter.php | 4 +- .../HasTemporaryLocationFilter.php | 4 +- ...ccompanyingPeriodInfoWithinDatesFilter.php | 3 +- .../IntensityFilter.php | 4 +- .../JobWorkingOnCourseFilter.php | 3 +- ...tAssociatedWithAReferenceAddressFilter.php | 3 +- .../OpenBetweenDatesFilter.php | 4 +- .../OriginFilter.php | 4 +- .../ReferrerFilter.php | 4 +- .../ReferrerFilterBetweenDates.php | 3 +- .../RequestorFilter.php | 4 +- .../ScopeWorkingOnCourseFilter.php | 3 +- .../SocialActionFilter.php | 3 +- .../StepFilterBetweenDates.php | 4 +- .../StepFilterOnDate.php | 4 +- .../UserJobFilter.php | 3 +- .../UserScopeFilter.php | 3 +- .../UserWorkingOnCourseFilter.php | 3 +- .../ByDateFilter.php | 3 +- .../ByStepFilter.php | 3 +- .../EvaluationFilters/ByEndDateFilter.php | 4 +- .../EvaluationFilters/ByStartDateFilter.php | 4 +- .../EvaluationTypeFilter.php | 4 +- .../EvaluationFilters/MaxDateFilter.php | 4 +- .../HouseholdFilters/CompositionFilter.php | 3 +- .../PersonFilters/AddressRefStatusFilter.php | 4 +- .../Export/Filter/PersonFilters/AgeFilter.php | 4 +- .../Filter/PersonFilters/BirthdateFilter.php | 4 +- .../ByHouseholdCompositionFilter.php | 4 +- .../PersonFilters/DeadOrAliveFilter.php | 4 +- .../Filter/PersonFilters/DeathdateFilter.php | 4 +- .../PersonFilters/GeographicalUnitFilter.php | 4 +- .../PersonFilters/MaritalStatusFilter.php | 4 +- .../PersonFilters/NationalityFilter.php | 4 +- .../ResidentialAddressAtThirdpartyFilter.php | 4 +- .../ResidentialAddressAtUserFilter.php | 4 +- .../WithParticipationBetweenDatesFilter.php | 3 +- .../WithoutHouseholdComposition.php | 4 +- ...WithoutParticipationBetweenDatesFilter.php | 90 ++ ...yingPeriodWorkEndDateBetweenDateFilter.php | 3 +- ...ngPeriodWorkStartDateBetweenDateFilter.php | 3 +- ...odWorkWithEvaluationBetweenDatesFilter.php | 3 +- .../SocialWorkFilters/CreatorJobFilter.php | 3 +- .../SocialWorkFilters/CreatorScopeFilter.php | 3 +- .../Filter/SocialWorkFilters/JobFilter.php | 3 +- .../SocialWorkFilters/ReferrerFilter.php | 4 +- .../Filter/SocialWorkFilters/ScopeFilter.php | 3 +- .../SocialWorkTypeFilter.php | 4 +- .../Export/Helper/LabelPersonHelper.php | 4 +- .../Helper/ListAccompanyingPeriodHelper.php | 3 +- .../Export/Helper/ListPersonHelper.php | 3 +- .../Form/ClosingMotiveType.php | 4 +- .../DataMapper/PersonAltNameDataMapper.php | 8 +- .../Form/HouseholdCompositionType.php | 4 +- .../ChillPersonBundle/Form/HouseholdType.php | 1 + .../Form/PersonResourceType.php | 4 +- .../Form/SocialWork/SocialIssueType.php | 4 +- .../Form/Type/PersonAltNameType.php | 4 +- .../Form/Type/PersonPhoneType.php | 4 +- .../Form/Type/PickPersonDynamicType.php | 4 +- .../Form/Type/PickPersonType.php | 56 +- .../Form/Type/PickSocialActionType.php | 4 +- .../Form/Type/PickSocialIssueType.php | 4 +- .../Form/Type/Select2MaritalStatusType.php | 4 +- .../Household/MembersEditor.php | 3 +- .../Household/MembersEditorFactory.php | 4 +- .../Menu/PersonMenuBuilder.php | 17 + .../Menu/PersonQuickMenuBuilder.php | 4 +- .../Menu/SectionMenuBuilder.php | 4 +- .../AccompanyingPeriodNotificationHandler.php | 4 +- ...kEvaluationDocumentNotificationHandler.php | 4 +- ...ompanyingPeriodWorkNotificationHandler.php | 4 +- .../AccompanyingPeriodPrivacyEvent.php | 4 +- .../Privacy/PrivacyEvent.php | 4 +- .../Privacy/PrivacyEventSubscriber.php | 37 +- ...PeriodWorkEvaluationDocumentRepository.php | 21 +- .../AccompanyingPeriodWorkGoalRepository.php | 4 +- .../AccompanyingPeriod/CommentRepository.php | 4 +- .../AccompanyingPeriod/OriginRepository.php | 4 +- .../AccompanyingPeriod/ResourceRepository.php | 4 +- .../AccompanyingPeriodACLAwareRepository.php | 3 +- ...ompanyingPeriodParticipationRepository.php | 4 +- .../AccompanyingPeriodRepository.php | 4 +- .../Household/HouseholdACLAwareRepository.php | 4 +- .../HouseholdCompositionRepository.php | 4 +- .../HouseholdCompositionTypeRepository.php | 4 +- .../Household/HouseholdMembersRepository.php | 4 +- .../Household/HouseholdRepository.php | 6 +- .../PersonHouseholdAddressRepository.php | 4 +- .../Household/PositionRepository.php | 4 +- .../Person/PersonCenterHistoryInterface.php | 4 +- .../Repository/PersonACLAwareRepository.php | 4 +- .../Repository/PersonAltNameRepository.php | 4 +- .../PersonNotDuplicateRepository.php | 4 +- .../Repository/PersonResourceRepository.php | 4 +- .../SocialWork/EvaluationRepository.php | 4 +- .../Repository/SocialWork/GoalRepository.php | 4 +- .../SocialWork/ResultRepository.php | 4 +- .../SocialWork/SocialActionRepository.php | 4 +- .../SocialWork/SocialIssueRepository.php | 4 +- .../AccompanyingCourse/components/Comment.vue | 2 +- .../components/Resources/WriteComment.vue | 2 +- .../public/vuejs/AccompanyingCourse/index.js | 6 +- .../AccompanyingCourseWorkCreate/index.js | 4 +- .../vuejs/AccompanyingCourseWorkEdit/App.vue | 2 +- .../components/FormEvaluation.vue | 43 +- .../vuejs/AccompanyingCourseWorkEdit/index.js | 4 +- .../vuejs/AccompanyingCourseWorkEdit/store.js | 14 +- .../components/MemberDetails.vue | 2 +- .../components/PersonComment.vue | 2 +- .../vuejs/HouseholdMembersEditor/index.js | 4 +- .../Resources/public/vuejs/VisGraph/index.js | 5 +- .../public/vuejs/_js/{i18n.js => i18n.ts} | 2 +- .../Household/edit_member_metadata.html.twig | 2 +- .../views/Person/signature_list.html.twig | 44 + .../views/PersonResource/create.html.twig | 1 - .../_accompanying_period_work.html.twig | 5 + .../views/Workflow/_evaluation.html.twig | 5 + .../Workflow/_evaluation_document.html.twig | 5 + .../ChillPersonBundle/Search/PersonSearch.php | 4 +- .../Search/SearchHouseholdApiProvider.php | 4 +- .../Search/SearchPersonApiProvider.php | 4 +- .../AccompanyingPeriodCommentVoter.php | 4 +- .../AccompanyingPeriodResourceVoter.php | 4 +- ...nyingPeriodWorkEvaluationDocumentVoter.php | 16 +- .../AccompanyingPeriodWorkEvaluationVoter.php | 8 +- ...orkEvaluationDocumentStoredObjectVoter.php | 55 + .../AccompanyingPeriodDocGenNormalizer.php | 4 +- .../AccompanyingPeriodResourceNormalizer.php | 4 +- .../AccompanyingPeriodWorkDenormalizer.php | 4 +- ...PeriodWorkEvaluationDocumentNormalizer.php | 4 +- ...mpanyingPeriodWorkEvaluationNormalizer.php | 4 +- .../AccompanyingPeriodWorkNormalizer.php | 4 +- .../Normalizer/MembersEditorNormalizer.php | 4 +- .../Normalizer/PersonDocGenNormalizer.php | 4 +- .../Normalizer/PersonJsonNormalizer.php | 3 +- .../PersonJsonNormalizerInterface.php | 4 +- .../RelationshipDocGenNormalizer.php | 4 +- .../Normalizer/SocialActionNormalizer.php | 4 +- .../Normalizer/SocialIssueNormalizer.php | 4 +- .../Normalizer/WorkflowNormalizer.php | 4 +- .../OldDraftAccompanyingPeriodRemover.php | 4 +- .../AccompanyingPeriodContext.php | 3 +- .../AccompanyingPeriodWorkContext.php | 4 +- ...ccompanyingPeriodWorkEvaluationContext.php | 4 +- .../Service/DocGenerator/PersonContext.php | 30 +- .../PersonContextWithThirdParty.php | 3 +- ...companyingPeriodViewEntityInfoProvider.php | 3 +- ...PeriodWorkEvaluationGenericDocProvider.php | 3 +- ...PeriodWorkEvaluationGenericDocRenderer.php | 3 +- .../Service/Import/SocialWorkMetadata.php | 4 +- .../Import/SocialWorkMetadataInterface.php | 4 +- .../Templating/Entity/ClosingMotiveRender.php | 3 +- .../Templating/Entity/PersonRender.php | 4 +- .../Entity/PersonRenderInterface.php | 4 +- .../Templating/Entity/ResourceKindRender.php | 4 +- .../Templating/Entity/SocialActionRender.php | 4 +- .../Templating/Entity/SocialIssueRender.php | 4 +- .../AccompanyingPeriodConfidentialTest.php | 2 +- ...ccompanyingPeriodStepChangeCronjobTest.php | 2 +- ...cialIssueConsistencyEntityListenerTest.php | 4 +- .../Tests/Action/Remove/PersonMoveTest.php | 57 +- .../ConflictTest.php | 6 +- .../AccompanyingCourseApiControllerTest.php | 26 +- .../AccompanyingCourseControllerTest.php | 6 +- .../Controller/HouseholdApiControllerTest.php | 33 +- .../Controller/HouseholdControllerTest.php | 10 +- .../HouseholdMemberControllerTest.php | 10 +- .../Controller/PersonApiControllerTest.php | 8 +- .../Controller/PersonControllerCreateTest.php | 4 +- .../Controller/PersonControllerUpdateTest.php | 24 +- ...onControllerUpdateWithHiddenFieldsTest.php | 2 +- .../Controller/PersonControllerViewTest.php | 6 +- .../PersonDuplicateControllerViewTest.php | 6 +- .../RelationshipApiControllerTest.php | 22 +- .../SocialWorkEvaluationApiControllerTest.php | 25 +- .../EventListener/PersonCreateEventTest.php | 4 +- .../AdministrativeLocationAggregatorTest.php | 9 +- .../ClosingDateAggregatorTest.php | 20 +- .../ClosingMotiveAggregatorTest.php | 9 +- .../ConfidentialAggregatorTest.php | 9 +- .../DurationAggregatorTest.php | 9 +- .../EmergencyAggregatorTest.php | 9 +- .../EvaluationAggregatorTest.php | 9 +- .../GeographicalUnitStatAggregatorTest.php | 11 +- .../IntensityAggregatorTest.php | 9 +- .../OpeningDateAggregatorTest.php | 18 +- .../OriginAggregatorTest.php | 9 +- .../PersonParticipatingAggregatorTest.php | 9 +- .../ReferrerAggregatorTest.php | 11 +- .../ReferrerScopeAggregatorTest.php | 9 +- .../RequestorAggregatorTest.php | 9 +- .../ScopeAggregatorTest.php | 9 +- .../SocialActionAggregatorTest.php | 9 +- .../SocialIssueAggregatorTest.php | 9 +- .../StepAggregatorTest.php | 9 +- .../UserJobAggregatorTest.php | 11 +- .../ByClosingMotiveAggregatorTest.php | 11 +- .../ByDateAggregatorTest.php | 7 +- .../ByStepAggregatorTest.php | 7 +- .../EvaluationTypeAggregatorTest.php | 9 +- .../ChildrenNumberAggregatorTest.php | 9 +- .../CompositionAggregatorTest.php | 9 +- .../PersonAggregators/AgeAggregatorTest.php | 9 +- .../CountryOfBirthAggregatorTest.php | 9 +- .../GenderAggregatorTest.php | 9 +- .../HouseholdPositionAggregatorTest.php | 9 +- .../MaritalStatusAggregatorTest.php | 9 +- .../NationalityAggregatorTest.php | 9 +- .../PostalCodeAggregatorTest.php | 9 +- .../ActionTypeAggregatorTest.php | 9 +- .../CreatorAggregatorTest.php | 9 +- .../CreatorJobAggregatorTest.php | 9 +- .../CreatorScopeAggregatorTest.php | 9 +- .../GoalAggregatorTest.php | 9 +- .../GoalResultAggregatorTest.php | 9 +- .../HandlingThirdPartyAggregatorTest.php | 9 +- .../JobAggregatorTest.php | 9 +- .../ReferrerAggregatorTest.php | 9 +- .../ResultAggregatorTest.php | 9 +- .../ScopeAggregatorTest.php | 9 +- ...rsonAssociatedOnAccompanyingPeriodTest.php | 10 +- ...rationAPWorkPersonAssociatedOnWorkTest.php | 8 +- ...CountAccompanyingCourseStepHistoryTest.php | 6 +- .../Export/CountAccompanyingCourseTest.php | 6 +- ...ssociatePersonOnAccompanyingPeriodTest.php | 6 +- ...ingPeriodWorkAssociatePersonOnWorkTest.php | 6 +- .../Export/CountHouseholdInPeriodTest.php | 8 +- ...ingPeriodWorkAssociatePersonOnWorkTest.php | 6 +- .../Tests/Export/Export/CountPersonTest.php | 6 +- .../CountPersonWithAccompanyingCourseTest.php | 6 +- .../Export/ListAccompanyingPeriodTest.php | 14 +- ...ssociatePersonOnAccompanyingPeriodTest.php | 28 +- ...ingPeriodWorkAssociatePersonOnWorkTest.php | 28 +- .../Export/Export/ListEvaluationTest.php | 28 +- .../Export/ListHouseholdInPeriodTest.php | 14 +- ...ListPersonHavingAccompanyingPeriodTest.php | 10 +- .../Tests/Export/Export/ListPersonTest.php | 18 +- ...ersonWithAccompanyingPeriodDetailsTest.php | 12 +- .../StatAccompanyingCourseDurationTest.php | 10 +- .../ActiveOnDateFilterTest.php | 8 +- .../ActiveOneDayBetweenDatesFilterTest.php | 9 +- .../AdministrativeLocationFilterTest.php | 14 +- .../ClosingMotiveFilterTest.php | 14 +- .../ConfidentialFilterTest.php | 9 +- .../EmergencyFilterTest.php | 9 +- .../EvaluationFilterTest.php | 14 +- .../GeographicalUnitStatFilterTest.php | 12 +- .../HasTemporaryLocationFilterTest.php | 9 +- .../IntensityFilterTest.php | 9 +- ...ociatedWithAReferenceAddressFilterTest.php | 7 +- .../OpenBetweenDatesFilterTest.php | 9 +- .../OriginFilterTest.php | 14 +- .../ReferrerFilterBetweenDatesTest.php | 21 +- .../ReferrerFilterTest.php | 21 +- .../RequestorFilterTest.php | 9 +- .../SocialActionFilterTest.php | 12 +- .../SocialIssueFilterTest.php | 18 +- .../StepFilterTest.php | 15 +- .../UserJobFilterTest.php | 20 +- .../UserScopeFilterTest.php | 11 +- .../ByDateFilterTest.php | 9 +- .../ByStepFilterTest.php | 7 +- .../EvaluationTypeFilterTest.php | 14 +- .../EvaluationFilters/MaxDateFilterTest.php | 9 +- .../CompositionFilterTest.php | 16 +- .../Filter/PersonFilters/AgeFilterTest.php | 9 +- .../PersonFilters/BirthdateFilterTest.php | 9 +- .../PersonFilters/DeadOrAliveFilterTest.php | 9 +- .../PersonFilters/DeathdateFilterTest.php | 9 +- .../Filter/PersonFilters/GenderFilterTest.php | 9 +- .../PersonFilters/MaritalStatusFilterTest.php | 14 +- .../PersonFilters/NationalityFilterTest.php | 14 +- ...sidentialAddressAtThirdpartyFilterTest.php | 14 +- .../ResidentialAddressAtUserFilterTest.php | 9 +- ...ithParticipationBetweenDatesFilterTest.php | 9 +- ...outParticipationBetweenDatesFilterTest.php | 62 + .../SocialWorkFilters/CreatorFilterTest.php | 13 +- .../CreatorJobFilterTest.php | 12 +- .../CreatorScopeFilterTest.php | 12 +- .../HandlingThirdPartyFilterTest.php | 13 +- .../SocialWorkFilters/JobFilterTest.php | 12 +- .../SocialWorkFilters/ReferrerFilterTest.php | 14 +- .../SocialWorkFilters/ScopeFilterTest.php | 12 +- .../WithEvaluationBetweenDatesFilterTest.php | 8 +- ...FilterListAccompanyingPeriodHelperTest.php | 13 +- .../Tests/Form/Type/PickPersonTypeTest.php | 10 +- ...companyingPeriodACLAwareRepositoryTest.php | 95 +- .../PersonACLAwareRepositoryTest.php | 6 +- .../Tests/Repository/UserRepositoryTest.php | 2 +- .../Authorization/PersonVoterTest.php | 2 +- ...AccompanyingPeriodDocGenNormalizerTest.php | 2 +- ...AccompanyingPeriodOriginNormalizerTest.php | 2 +- ...companyingPeriodResourceNormalizerTest.php | 2 +- ...mpanyingPeriodWorkDocGenNormalizerTest.php | 2 +- .../Normalizer/HouseholdNormalizerTest.php | 4 +- .../Normalizer/PersonDocGenNormalizerTest.php | 20 +- .../Normalizer/PersonJsonNormalizerTest.php | 10 +- .../Normalizer/ResourceJsonNormalizerTest.php | 2 +- .../Normalizer/SocialActionNormalizerTest.php | 2 +- .../Normalizer/SocialIssueNormalizerTest.php | 2 +- .../AccompanyingPeriodContextTest.php | 24 +- .../DocGenerator/PersonContextTest.php | 20 +- ...ngPeriodCalendarGenericDocProviderTest.php | 18 +- ...odWorkEvaluationGenericDocProviderTest.php | 4 +- .../PersonCalendarGenericDocProviderTest.php | 11 +- .../Entity/ClosingMotiveRenderTest.php | 4 +- .../TimelineAccompanyingPeriodTest.php | 4 +- .../Tests/Validation/PersonValidationTest.php | 2 +- .../Household/MaxHolderValidatorTest.php | 2 +- .../Validator/Person/PersonValidationTest.php | 2 +- .../Workflows/AccompanyingPeriodLifecycle.php | 2 +- .../AbstractTimelineAccompanyingPeriod.php | 4 +- .../AccompanyingPeriodValidity.php | 4 +- .../AccompanyingPeriodValidityValidator.php | 4 +- .../ConfidentialCourseMustHaveReferrer.php | 4 +- .../AccompanyingPeriod/LocationValidity.php | 4 +- .../LocationValidityValidator.php | 4 +- .../ParticipationOverlap.php | 4 +- .../ParticipationOverlapValidator.php | 4 +- .../ResourceDuplicateCheck.php | 4 +- .../ResourceDuplicateCheckValidator.php | 4 +- .../HouseholdMembershipSequential.php | 4 +- ...HouseholdMembershipSequentialValidator.php | 4 +- .../Constraints/Household/MaxHolder.php | 4 +- .../Constraints/Person/Birthdate.php | 3 +- .../Constraints/Person/PersonHasCenter.php | 8 +- .../Relationship/RelationshipNoDuplicate.php | 4 +- .../RelationshipNoDuplicateValidator.php | 4 +- .../Widget/PersonListWidget.php | 4 +- ...dWorkEvaluationDocumentWorkflowHandler.php | 34 +- ...ingPeriodWorkEvaluationWorkflowHandler.php | 27 +- .../AccompanyingPeriodWorkWorkflowHandler.php | 27 +- .../config/services/controller.yaml | 9 +- .../config/services/exports_person.yaml | 4 + .../config/services/security.yaml | 2 - .../migrations/Version20160422000000.php | 4 +- .../migrations/Version20210419112619.php | 4 +- .../migrations/Version20231121070151.php | 4 +- .../translations/messages+intl-icu.fr.yaml | 3 + .../translations/messages.fr.yml | 16 +- .../ChillReportBundle/ChillReportBundle.php | 4 +- .../Controller/ReportController.php | 22 +- .../ChillReportBundle/Entity/Report.php | 49 +- .../Export/Export/ReportList.php | 4 +- .../Export/Filter/ReportDateFilter.php | 4 +- .../ChillReportBundle/Form/ReportType.php | 46 +- .../ChillReportBundle/Search/ReportSearch.php | 152 -- .../Export/Filter/ReportDateFilterTest.php | 9 +- .../Authorization/ReportVoterTest.php | 4 +- .../Timeline/TimelineReportProvider.php | 4 +- .../ChillReportBundle/config/services.yaml | 19 +- .../config/services/controller.yaml | 4 + .../Controller/SingleTaskController.php | 96 +- .../Controller/TaskController.php | 10 +- .../ChillTaskBundle/Entity/AbstractTask.php | 79 +- .../ChillTaskBundle/Entity/RecurringTask.php | 56 +- .../ChillTaskBundle/Entity/SingleTask.php | 110 +- .../Entity/Task/AbstractTaskPlaceEvent.php | 34 +- .../Entity/Task/SingleTaskPlaceEvent.php | 38 +- .../ChillTaskBundle/Form/SingleTaskType.php | 4 +- .../ChillTaskBundle/Menu/UserMenuBuilder.php | 39 +- .../Repository/AbstractTaskRepository.php | 4 +- .../Repository/RecurringTaskRepository.php | 4 +- .../SingleTaskAclAwareRepository.php | 4 +- .../Repository/SingleTaskStateRepository.php | 3 +- .../Authorization/AuthorizationEvent.php | 3 +- .../Tests/Controller/TaskControllerTest.php | 4 +- .../SingleTaskACLAwareRepositoryTest.php | 10 +- .../TaskLifeCycleEventTimelineProvider.php | 4 +- .../Workflow/TaskWorkflowDefinition.php | 4 +- .../config/services/controller.yaml | 2 +- .../config/services/security.yaml | 2 - .../Controller/AdminController.php | 3 +- .../Controller/ThirdPartyApiController.php | 16 + .../ChillThirdPartyExtension.php | 2 + .../Entity/ThirdParty.php | 220 +-- .../Entity/ThirdPartyCategory.php | 31 +- .../Entity/ThirdPartyProfession.php | 38 +- .../Export/Helper/LabelThirdPartyHelper.php | 4 +- .../Type/PickThirdPartyTypeCategoryType.php | 4 +- .../Form/Type/PickThirdpartyDynamicType.php | 4 +- .../ThirdPartyACLAwareRepository.php | 4 +- .../Search/ThirdPartyApiSearch.php | 8 +- .../Normalizer/ThirdPartyNormalizer.php | 4 +- .../Templating/Entity/ThirdPartyRender.php | 4 +- .../ThirdPartyDocGenNormalizerTest.php | 2 +- .../ThirdPartyJsonDenormalizerTest.php | 2 +- .../config/services/security.yaml | 1 - .../ChillWopiBundle/src/ChillWopiBundle.php | 4 +- .../src/Controller/Convert.php | 97 -- .../src/Controller/ConvertController.php | 57 + .../ChillWopiBundle/src/Controller/Editor.php | 4 +- .../src/Resources/config/routes/routes.php | 2 +- .../src/Resources/config/services.php | 5 - .../src/Service/Controller/Responder.php | 4 +- .../src/Service/Wopi/AuthorizationManager.php | 34 +- .../Service/Wopi/ChillDocumentLockManager.php | 3 +- .../src/Service/Wopi/ChillDocumentManager.php | 26 +- .../src/Service/Wopi/ChillWopi.php | 4 +- .../src/Service/Wopi/NullProofValidator.php | 28 + .../src/Service/Wopi/UserManager.php | 4 +- .../src/Service/WopiConverter.php | 69 + .../Controller/ConvertControllerTest.php | 93 ++ .../tests/Controller/ConvertTest.php | 105 -- .../Wopi/ChillDocumentLockManagerTest.php | 2 +- .../tests/Service/WopiConvertToPdfTest.php | 63 + .../tests/Service/fixtures/test-document.odt | Bin 0 -> 8918 bytes tests/Kernel.php | 38 +- tests/app/config/bootstrap.php | 2 +- tests/app/config/bundles.php | 3 - tests/app/config/packages/champs-libres.yaml | 14 - .../app/config/packages/chill_doc_store.yaml | 6 + tests/app/config/packages/framework.yaml | 23 +- tests/app/config/packages/messenger.yaml | 16 +- tests/app/config/packages/security.yaml | 48 +- tests/app/config/packages/test/framework.yaml | 6 - tests/app/config/packages/test/messenger.yaml | 7 - tests/app/config/packages/test/security.yaml | 7 +- tests/app/config/packages/wopi.yaml | 2 + tests/app/config/packages/workflow_chill.yaml | 294 ++++ tests/console | 39 +- tsconfig.json | 31 + ...aultDataOnExportFilterAggregatorRector.php | 7 +- ...rStaticForAbstractAggregatorTestRector.php | 96 ++ ...viderStaticForAbstractExportTestRector.php | 100 ++ ...viderStaticForAbstractFilterTestRector.php | 96 ++ ...DataOnExportFilterAggregatorRectorTest.php | 2 +- ...th-no-method-get-form-default-data.php.inc | 0 ...th-no-method-get-form-default-data.php.inc | 0 ...th-no-method-get-form-default-data.php.inc | 0 ...-default-data-with-chained-builder.php.inc | 0 ...le-reuse-data-on-form-default-data.php.inc | 0 .../Fixture/filter-no-data-on-builder.php.inc | 0 ...er-reuse-data-on-form-default-data.php.inc | 0 ...th-no-method-get-form-default-data.php.inc | 0 ...th-no-method-get-form-default-data.php.inc | 0 ...sting-get-form-default-data-method.php.inc | 0 .../config/config.php | 0 ...ticForAbstractAggregatorTestRectorTest.php | 40 + ...act-aggregator-test-already-static.php.inc | 54 + ...act-aggregator-test-to-make-static.php.inc | 112 ++ .../Fixture/not-an-aggregator.php.inc | 5 + .../Fixture/not-an-extends-class.php.inc | 5 + .../config/config.php | 14 + ...rStaticForAbstractExportTestRectorTest.php | 40 + ...bstract-export-test-already-static.php.inc | 51 + .../export-test-to-make-static.php.inc | 103 ++ .../Fixture/not-an-export.php.inc | 5 + .../Fixture/not-an-extends-class.php.inc | 5 + .../config/config.php | 14 + ...rStaticForAbstractFilterTestRectorTest.php | 40 + .../abstract-filter-test-simple.php.inc | 132 ++ ...r-test-with-already-static-methods.php.inc | 68 + .../Fixture/not-a-filter.php.inc | 5 + .../Fixture/not-an-extends-class.php.inc | 5 + .../config/config.php | 14 + 1701 files changed, 35022 insertions(+), 14546 deletions(-) create mode 100644 .changes/unreleased/Feature-20240614-153236.yaml create mode 100644 .changes/unreleased/Feature-20240614-153537.yaml create mode 100644 .changes/unreleased/Feature-20240718-151233.yaml create mode 100644 .changes/v3.0.0.md create mode 100644 .changes/v3.1.0.md create mode 100644 .env create mode 100644 MIGRATION.md create mode 100644 docs/source/installation/enable-collabora-for-dev.rst create mode 100644 phpstan-baseline-deprecations-doctrine-orm.neon create mode 100644 phpstan-deprecations-sf54.neon create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/HouseholdAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStoredObjectVoter.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Command/ConfigureOpenstackObjectStorageCommand.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Driver/OpenstackObjectStore/TempUrlOpenstackGenerator.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Event/TempUrlGenerateEvent.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Exception/BadCallToRemoteServer.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Exception/TempUrlGeneratorException.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Exception/TempUrlRemoteServerException.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/SignedUrl.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/SignedUrlPost.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/TempUrlGeneratorInterface.php create mode 100644 src/Bundle/ChillDocStoreBundle/AsyncUpload/Templating/AsyncUploadExtension.php create mode 100644 src/Bundle/ChillDocStoreBundle/Controller/AsyncUploadController.php create mode 100644 src/Bundle/ChillDocStoreBundle/Controller/SignatureRequestController.php create mode 100644 src/Bundle/ChillDocStoreBundle/Controller/StoredObjectRestoreVersionApiController.php create mode 100644 src/Bundle/ChillDocStoreBundle/Controller/StoredObjectStatusApiController.php create mode 100644 src/Bundle/ChillDocStoreBundle/Controller/StoredObjectVersionApiController.php create mode 100644 src/Bundle/ChillDocStoreBundle/Entity/StoredObjectPointInTime.php create mode 100644 src/Bundle/ChillDocStoreBundle/Entity/StoredObjectPointInTimeReasonEnum.php create mode 100644 src/Bundle/ChillDocStoreBundle/Entity/StoredObjectVersion.php create mode 100644 src/Bundle/ChillDocStoreBundle/Form/Type/AsyncUploaderType.php delete mode 100644 src/Bundle/ChillDocStoreBundle/Object/ObjectToAsyncFileTransformer.php delete mode 100644 src/Bundle/ChillDocStoreBundle/Object/PersistenceChecker.php create mode 100644 src/Bundle/ChillDocStoreBundle/Repository/AssociatedEntityToStoredObjectInterface.php create mode 100644 src/Bundle/ChillDocStoreBundle/Repository/StoredObjectPointInTimeRepository.php create mode 100644 src/Bundle/ChillDocStoreBundle/Repository/StoredObjectVersionRepository.php rename src/Bundle/ChillDocStoreBundle/Resources/public/{vuejs/_components/helper.ts => js/async-upload/uploader.ts} (75%) create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/index.ts create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileModal.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/FileIcon.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonListItem.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonModal.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/RestoreVersionButton.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/api.ts delete mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUpload.vue delete mode 100644 src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUploadDownloader.vue create mode 100644 src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/signature.html.twig create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authorization/AsyncUploadVoter.php create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AbstractStoredObjectVoter.php create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AccompanyingCourseDocumentStoredObjectVoter.php create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/PersonDocumentStoredObjectVoter.php create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoterInterface.php create mode 100644 src/Bundle/ChillDocStoreBundle/Serializer/Normalizer/StoredObjectPointInTimeNormalizer.php create mode 100644 src/Bundle/ChillDocStoreBundle/Serializer/Normalizer/StoredObjectVersionNormalizer.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessage.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandler.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessageSerializer.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/RequestPdfSignMessage.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/RequestPdfSignMessageSerializer.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/PDFPage.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZone.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZoneAvailable.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZoneParser.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveExpiredStoredObjectCronJob.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionCronJob.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionMessage.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionMessageHandler.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectRestore.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectRestoreInterface.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/StoredObjectToPdfConverter.php create mode 100644 src/Bundle/ChillDocStoreBundle/Service/WorkflowStoredObjectPermissionHelper.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/AsyncUpload/Command/ConfigureOpenstackObjectStorageCommandTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/AsyncUpload/Driver/OpenstackObjectStore/TempUrlOpenstackGeneratorTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/AsyncUpload/Driver/OpenstackObjectStore/file-to-upload.txt create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/AsyncUpload/Templating/AsyncUploadExtensionTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Controller/AsyncUploadControllerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectRestoreVersionApiControllerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectVersionApiControllerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Security/Authorization/AbstractStoredObjectVoterTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Serializer/Normalizer/SignedUrlNormalizerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Serializer/Normalizer/SignedUrlPostNormalizerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Serializer/Normalizer/StoredObjectDenormalizerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Serializer/Normalizer/StoredObjectNormalizerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Serializer/Normalizer/StoredObjectPointInTimeNormalizerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Serializer/Normalizer/StoredObjectVersionNormalizerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Repository/StoredObjectVersionRepositoryTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandlerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/PdfSignedMessageSerializerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/RequestPdfSignMessageSerializerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/PDFSignatureZoneAvailableTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/PDFSignatureZoneParserTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/data/signature_2_signature_page_1.pdf create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveExpiredStoredObjectCronJobTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveOldVersionCronJobTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveOldVersionMessageHandlerTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectRestoreTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectToPdfConverterTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Validator/Constraints/AsyncFileExistsValidatorTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriberTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Validator/Constraints/AsyncFileExists.php create mode 100644 src/Bundle/ChillDocStoreBundle/Validator/Constraints/AsyncFileExistsValidator.php create mode 100644 src/Bundle/ChillDocStoreBundle/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriber.php delete mode 100644 src/Bundle/ChillDocStoreBundle/config/services/media.yaml create mode 100644 src/Bundle/ChillDocStoreBundle/config/services/security.yaml create mode 100644 src/Bundle/ChillDocStoreBundle/migrations/Version20240709102730.php create mode 100644 src/Bundle/ChillDocStoreBundle/migrations/Version20240910093735.php create mode 100644 src/Bundle/ChillDocStoreBundle/migrations/Version20240918073234.php create mode 100644 src/Bundle/ChillEventBundle/Security/Authorization/EventStoredObjectVoter.php rename src/Bundle/{ChillPersonBundle/Tests/AccompanyingPeriod/Workflow/WorkflowEventSubscriberTest.php => ChillEventBundle/config/services/controller.yaml} (100%) create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/ApiWrapper.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/ProcessRequestTrait.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/ChillFranceTravailApiBundle.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/Controller/RomeController.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/DependencyInjection/ChillFranceTravailApiExtension.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/DependencyInjection/Configuration.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/Resources/config/routing.yml create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/Resources/config/services.yml create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/Resources/views/.gitkeep create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/Tests/ApiHelper/PartenaireRomeAppellationTest.php create mode 100644 src/Bundle/ChillFranceTravailApiBundle/src/Tests/Controller/RomeControllerTest.php create mode 100644 src/Bundle/ChillJobBundle/src/ChillJobBundle.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/CSCrudReportController.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/CSPersonController.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/CSReportController.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/CVCrudController.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/FreinCrudController.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/ImmersionCrudController.php create mode 100644 src/Bundle/ChillJobBundle/src/Controller/ProjetProfessionnelCrudController.php create mode 100644 src/Bundle/ChillJobBundle/src/DependencyInjection/ChillJobExtension.php create mode 100644 src/Bundle/ChillJobBundle/src/DependencyInjection/Configuration.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/CSPerson.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/CV.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/CV/Experience.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/CV/Formation.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/Frein.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/Immersion.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/ProjetProfessionnel.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/Rome/Appellation.php create mode 100644 src/Bundle/ChillJobBundle/src/Entity/Rome/Metier.php create mode 100644 src/Bundle/ChillJobBundle/src/Export/AddCSPersonToPersonListHelper.php create mode 100644 src/Bundle/ChillJobBundle/src/Export/ListCV.php create mode 100644 src/Bundle/ChillJobBundle/src/Export/ListFrein.php create mode 100644 src/Bundle/ChillJobBundle/src/Export/ListProjetProfessionnel.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/CSPersonDispositifsType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/CSPersonPersonalSituationType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/CV/ExperienceType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/CV/FormationType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/CVType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/FreinType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/ImmersionType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/ProjetProfessionnelType.php create mode 100644 src/Bundle/ChillJobBundle/src/Form/Type/PickRomeAppellationType.php create mode 100644 src/Bundle/ChillJobBundle/src/Menu/MenuBuilder.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/CSPersonRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/CV/ExperienceRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/CV/FormationRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/CVRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/FreinRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/ImmersionRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/ProjetProfessionnelRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/Rome/AppellationRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Repository/Rome/MetierRepository.php create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/routing.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/services.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/services/3party_type.yml rename src/Bundle/{ChillDocGeneratorBundle/config/services/controller.yaml => ChillJobBundle/src/Resources/config/services/controller.yml} (54%) create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/services/export.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/services/form.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/services/menu.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/config/services/security.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/images/footer_bandeau.jpg create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/images/index.js create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/module/cv_edit/index.js create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/module/dispositif_edit/index.js create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/module/immersion_edit/index.js create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/module/personal_situation/index.js create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/sass/csconnectes.scss create mode 100644 src/Bundle/ChillJobBundle/src/Resources/public/sass/index.js create mode 100644 src/Bundle/ChillJobBundle/src/Resources/translations/messages.fr.yml create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CSPerson/dispositifs_edit.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CSPerson/dispositifs_view.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CSPerson/personal_situation_edit.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CSPerson/personal_situation_view.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CV/edit.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CV/new.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/CV/view.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Frein/edit.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Frein/new.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Frein/view.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Immersion/edit-bilan.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Immersion/edit.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Immersion/new.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Immersion/view.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/ProjetProfessionnel/edit.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/ProjetProfessionnel/new.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/ProjetProfessionnel/view.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Report/delete.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Resources/views/Report/index.html.twig create mode 100644 src/Bundle/ChillJobBundle/src/Security/Authorization/ExportsJobVoter.php create mode 100644 src/Bundle/ChillJobBundle/src/Security/Authorization/JobVoter.php create mode 100644 src/Bundle/ChillJobBundle/src/Tests/Controller/CSPersonControllerTest.php create mode 100644 src/Bundle/ChillJobBundle/src/Tests/Controller/CSReportControllerTest.php create mode 100644 src/Bundle/ChillJobBundle/src/ThirdParty/EntrepriseType.php create mode 100644 src/Bundle/ChillJobBundle/src/ThirdParty/PrescripteurType.php create mode 100644 src/Bundle/ChillJobBundle/src/chill.webpack.config.js create mode 100644 src/Bundle/ChillJobBundle/src/migrations/Version20240424095147.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/Version20240424140641.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/Version20240429111628.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20191119172511.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20191129112321.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200113104411.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200113142525.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200114081435.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200124130244.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200124132321.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200127132932.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200205132532.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200207224152.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200210105342.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200313124323.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200403114520.php create mode 100644 src/Bundle/ChillJobBundle/src/migrations/old/Version20200403123148.php create mode 100644 src/Bundle/ChillMainBundle/CRUD/Exception/InvalidCrudConfiguration.php create mode 100644 src/Bundle/ChillMainBundle/Controller/CountryApiController.php create mode 100644 src/Bundle/ChillMainBundle/Controller/GeographicalUnitApiController.php create mode 100644 src/Bundle/ChillMainBundle/Controller/WorkflowAddSignatureController.php create mode 100644 src/Bundle/ChillMainBundle/Controller/WorkflowOnHoldController.php delete mode 100644 src/Bundle/ChillMainBundle/DependencyInjection/RoleProvidersCompilerPass.php create mode 100644 src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSignatureStateEnum.php create mode 100644 src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepHold.php create mode 100644 src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepSignature.php create mode 100644 src/Bundle/ChillMainBundle/Form/WorkflowSignatureMetadataType.php create mode 100644 src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowSignatureACLAwareRepositoryInterface.php create mode 100644 src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepHoldRepository.php create mode 100644 src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureACLAwareRepository.php create mode 100644 src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureRepository.php create mode 100644 src/Bundle/ChillMainBundle/Resources/public/chill/scss/hover.scss rename src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/{index.js => editor_config.ts} (72%) create mode 100644 src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.ts create mode 100644 src/Bundle/ChillMainBundle/Resources/public/page/export/download-export.js create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test1.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test2.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Dev/swagger-ui/index.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_metadata.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Workflow/person_signature_form.html.twig create mode 100644 src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowStepSignatureVoter.php create mode 100644 src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowTransitionVoter.php create mode 100644 src/Bundle/ChillMainBundle/Security/ChillSecurity.php create mode 100644 src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowCronJob.php create mode 100644 src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowHandler.php create mode 100644 src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowMessage.php create mode 100644 src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManager.php create mode 100644 src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManagerInterface.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Authorization/EntityWorkflowTransitionVoterTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Controller/WorkflowAddSignatureControllerTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Controller/WorkflowOnHoldControllerTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowStepSignatureTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowCronJobTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowHandlerTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowMarkingStoreTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Workflow/EventSubscriber/EntityWorkflowGuardTransitionTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Workflow/SignatureStepStateChangerTest.php create mode 100644 src/Bundle/ChillMainBundle/Workflow/EntityWorkflowMarkingStore.php create mode 100644 src/Bundle/ChillMainBundle/Workflow/EntityWorkflowWithStoredObjectHandlerInterface.php create mode 100644 src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowGuardTransition.php create mode 100644 src/Bundle/ChillMainBundle/Workflow/SignatureStepStateChanger.php create mode 100644 src/Bundle/ChillMainBundle/Workflow/WorkflowTransitionContextDTO.php create mode 100644 src/Bundle/ChillMainBundle/migrations/Version20240628095159.php create mode 100644 src/Bundle/ChillMainBundle/migrations/Version20240807123801.php create mode 100644 src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodCommentApiController.php create mode 100644 src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodResourceApiController.php create mode 100644 src/Bundle/ChillPersonBundle/Controller/PersonSignatureController.php create mode 100644 src/Bundle/ChillPersonBundle/Controller/RelationApiController.php create mode 100644 src/Bundle/ChillPersonBundle/Entity/Person/AbstractPersonResource.php create mode 100644 src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutParticipationBetweenDatesFilter.php rename src/Bundle/ChillPersonBundle/Resources/public/vuejs/_js/{i18n.js => i18n.ts} (96%) create mode 100644 src/Bundle/ChillPersonBundle/Resources/views/Person/signature_list.html.twig create mode 100644 src/Bundle/ChillPersonBundle/Security/Authorization/StoredObjectVoter/AccompanyingPeriodWorkEvaluationDocumentStoredObjectVoter.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/WithoutParticipationBetweenDatesFilterTest.php create mode 100644 src/Bundle/ChillThirdPartyBundle/Controller/ThirdPartyApiController.php delete mode 100644 src/Bundle/ChillWopiBundle/src/Controller/Convert.php create mode 100644 src/Bundle/ChillWopiBundle/src/Controller/ConvertController.php create mode 100644 src/Bundle/ChillWopiBundle/src/Service/Wopi/NullProofValidator.php create mode 100644 src/Bundle/ChillWopiBundle/src/Service/WopiConverter.php create mode 100644 src/Bundle/ChillWopiBundle/tests/Controller/ConvertControllerTest.php delete mode 100644 src/Bundle/ChillWopiBundle/tests/Controller/ConvertTest.php create mode 100644 src/Bundle/ChillWopiBundle/tests/Service/WopiConvertToPdfTest.php create mode 100644 src/Bundle/ChillWopiBundle/tests/Service/fixtures/test-document.odt delete mode 100644 tests/app/config/packages/champs-libres.yaml create mode 100644 tests/app/config/packages/chill_doc_store.yaml delete mode 100644 tests/app/config/packages/test/framework.yaml delete mode 100644 tests/app/config/packages/test/messenger.yaml create mode 100644 tests/app/config/packages/wopi.yaml create mode 100644 tests/app/config/packages/workflow_chill.yaml create mode 100644 tsconfig.json create mode 100644 utils/rector/src/Rector/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRector.php create mode 100644 utils/rector/src/Rector/ChillBundleMakeDataProviderStaticForAbstractExportTestRector.php create mode 100644 utils/rector/src/Rector/ChillBundleMakeDataProviderStaticForAbstractFilterTestRector.php rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/aggregator-with-no-method-get-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/direct-export-with-no-method-get-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/export-with-no-method-get-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/filter-multiple-reuse-data-on-form-default-data-with-chained-builder.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/filter-multiple-reuse-data-on-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/filter-no-data-on-builder.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/filter-reuse-data-on-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/filter-with-no-method-get-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/list-with-no-method-get-form-default-data.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/Fixture/skip-filter-existing-get-form-default-data-method.php.inc (100%) rename utils/rector/tests/{Rector => }/ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector/config/config.php (100%) create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest.php create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest/Fixture/abstract-aggregator-test-already-static.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest/Fixture/abstract-aggregator-test-to-make-static.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest/Fixture/not-an-aggregator.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest/Fixture/not-an-extends-class.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractAggregatorTestRectorTest/config/config.php create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest.php create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest/Fixture/abstract-export-test-already-static.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest/Fixture/export-test-to-make-static.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest/Fixture/not-an-export.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest/Fixture/not-an-extends-class.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractExportTestRectorTest/config/config.php create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractFilterTest/ChillBundleMakeDataProviderStaticForAbstractFilterTestRectorTest.php create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractFilterTest/Fixture/abstract-filter-test-simple.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractFilterTest/Fixture/abstract-filter-test-with-already-static-methods.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractFilterTest/Fixture/not-a-filter.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractFilterTest/Fixture/not-an-extends-class.php.inc create mode 100644 utils/rector/tests/ChillBundleMakeDataProviderStaticForAbstractFilterTest/config/config.php diff --git a/.changes/unreleased/Feature-20240614-153236.yaml b/.changes/unreleased/Feature-20240614-153236.yaml new file mode 100644 index 000000000..a29000cc1 --- /dev/null +++ b/.changes/unreleased/Feature-20240614-153236.yaml @@ -0,0 +1,8 @@ +kind: Feature +body: |- + Electronic signature + + Implementation of the electronic signature for documents within chill. +time: 2024-06-14T15:32:36.875891692+02:00 +custom: + Issue: "" diff --git a/.changes/unreleased/Feature-20240614-153537.yaml b/.changes/unreleased/Feature-20240614-153537.yaml new file mode 100644 index 000000000..c16d49b2d --- /dev/null +++ b/.changes/unreleased/Feature-20240614-153537.yaml @@ -0,0 +1,7 @@ +kind: Feature +body: The behavoir of the voters for stored objects is adjusted so as to limit edit + and delete possibilities to users related to the activity, social action or workflow + entity. +time: 2024-06-14T15:35:37.582159301+02:00 +custom: + Issue: "286" diff --git a/.changes/unreleased/Feature-20240718-151233.yaml b/.changes/unreleased/Feature-20240718-151233.yaml new file mode 100644 index 000000000..6e2666be8 --- /dev/null +++ b/.changes/unreleased/Feature-20240718-151233.yaml @@ -0,0 +1,5 @@ +kind: Feature +body: Metadata form added for person signatures +time: 2024-07-18T15:12:33.8134266+02:00 +custom: + Issue: "288" diff --git a/.changes/v2.23.0.md b/.changes/v2.23.0.md index 47f36fa51..5987b1ca8 100644 --- a/.changes/v2.23.0.md +++ b/.changes/v2.23.0.md @@ -1,5 +1,11 @@ -## v2.23.0 - 2024-07-19 +## v2.23.0 - 2024-07-23 & 2024-07-19 ### Feature +* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles +* Add job bundle (module emploi) +* Upgrade import of address list to the last version of compiled addresses of belgian-best-address + +* Upgrade CKEditor and refactor configuration with use of typescript + * ([#123](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/123)) Add a button to duplicate calendar ranges from a week to another one * [admin] filter users by active / inactive in the admin user's list * ([#273](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/273)) Add the possibility to mark all notifications as read @@ -9,6 +15,8 @@ * Do not update the "createdAt" column when importing postal code which does not change * Display filename on file upload within the UI interface ### Fixed +* Fix resolving of centers for an household, which will fix in turn the access control +* Resolved type hinting error in activity list export * ([#271](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/271)) Take into account the acp closing date in the acp works date filter ### Traduction française des principaux changements diff --git a/.changes/v3.0.0.md b/.changes/v3.0.0.md new file mode 100644 index 000000000..586e648da --- /dev/null +++ b/.changes/v3.0.0.md @@ -0,0 +1,5 @@ +## v3.0.0 - 2024-08-26 +### Fixed +* Fix delete action for accompanying periods in draft state +* Fix connection to azure when making an calendar event in chill +* CollectionType js fixes for remove button and adding multiple entries diff --git a/.changes/v3.1.0.md b/.changes/v3.1.0.md new file mode 100644 index 000000000..cb05f47fb --- /dev/null +++ b/.changes/v3.1.0.md @@ -0,0 +1,3 @@ +## v3.1.0 - 2024-08-30 +### Feature +* Add export aggregator to aggregate activities by household + filter persons that are not part of an accompanyingperiod during a certain timeframe. diff --git a/.env b/.env new file mode 100644 index 000000000..b2eecb78f --- /dev/null +++ b/.env @@ -0,0 +1,94 @@ +# * .env contains default values for the environment variables needed by the app +# * .env.local uncommitted file with local overrides +# * .env.$APP_ENV committed environment-specific defaults +# * .env.$APP_ENV.local uncommitted environment-specific overrides +# +# Real environment variables win over .env files. +# +# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# https://symfony.com/doc/current/configuration/secrets.html +# +# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). +# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration + +## Locale +LOCALE=fr + +###> symfony/framework-bundle ### +# this should be set in docker-compose.yml file +APP_ENV=prod +APP_SECRET=ChangeItf2b58287ef7f9976409d3f6c72529e99ChangeIt +TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 +TRUSTED_HOSTS='^(localhost|example\.com|nginx)$' +###< symfony/framework-bundle ### + +## Wopi server for editing documents online +EDITOR_SERVER=http://collabora:9980 + +# must be manually set in .env.local +# ADMIN_PASSWORD= + +###> symfony/mailer ### +# MAILER_DSN=null://null +###< symfony/mailer ### + +## Notifications +NOTIFICATION_HOST=localhost:8001 +NOTIFICATION_FROM_EMAIL=admin@chill.social +NOTIFICATION_FROM_NAME="Chill " + +## Pgadmin credential +PGADMIN_DEFAULT_EMAIL= +PGADMIN_DEFAULT_PASSWORD= + +## OVH OpenStack Storage Container +ASYNC_UPLOAD_TEMP_URL_KEY= +ASYNC_UPLOAD_TEMP_URL_BASE_PATH= +ASYNC_UPLOAD_TEMP_URL_CONTAINER= + +## Redis Cache +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} + +## Twilio +TWILIO_SID=~ +TWILIO_SECRET=~ +DEFAULT_CARRIER_CODE=BE + +ADD_ADDRESS_DEFAULT_COUNTRY=BE + +ADD_ADDRESS_MAP_CENTER_X=50.8443 +ADD_ADDRESS_MAP_CENTER_Y=4.3523 +ADD_ADDRESS_MAP_CENTER_Z=15 + +SHORT_MESSAGE_DSN=null://null + +## DOCKER IMAGES REGISTRY +#IMAGE_PHP= +#IMAGE_NGINX= + +## DOCKER IMAGES TAG +#VERSION=test +#VERSION=prod + +###> symfony/messenger ### +# Choose one of the transports below +# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages +# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages +MESSENGER_TRANSPORT_DSN=sync:// +MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 +###< symfony/messenger ### + +###> doctrine/doctrine-bundle ### +# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml +# +DATABASE_URL="postgresql://postgres:postgres@db:5432/postgres?serverVersion=14&charset=utf8" +###< doctrine/doctrine-bundle ### + +###> lexik/jwt-authentication-bundle ### +JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem +JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem +JWT_PASSPHRASE=2a30f6ba26521a2613821da35f28386e +###< lexik/jwt-authentication-bundle ### diff --git a/.env.test b/.env.test index 9245579c0..c78a1bc63 100644 --- a/.env.test +++ b/.env.test @@ -4,6 +4,8 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' +TRUSTED_HOSTS= + ADMIN_PASSWORD=password LOCALE=fr @@ -39,3 +41,5 @@ DATABASE_URL="postgresql://postgres:postgres@db:5432/test?serverVersion=14&chars ASYNC_UPLOAD_TEMP_URL_KEY= ASYNC_UPLOAD_TEMP_URL_BASE_PATH= ASYNC_UPLOAD_TEMP_URL_CONTAINER= + +EDITOR_SERVER=https://localhost:9980 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43f687649..c1fdebf43 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,6 +20,7 @@ services: # Set any variables we need variables: + APP_ENV: test GIT_DEPTH: 1 # Configure postgres environment variables (https://hub.docker.com/r/_/postgres/) POSTGRES_USER: postgres @@ -35,7 +36,7 @@ variables: # force a timezone TZ: Europe/Brussels # avoid direct deprecations (using symfony phpunit bridge: https://symfony.com/doc/4.x/components/phpunit_bridge.html#internal-deprecations - SYMFONY_DEPRECATIONS_HELPER: max[total]=99999999&max[self]=0&max[direct]=0&verbose=1 + SYMFONY_DEPRECATIONS_HELPER: max[total]=99999999&max[self]=0&max[direct]=45&verbose=0 stages: - Composer install @@ -120,8 +121,8 @@ unit_tests: - php tests/console doctrine:migrations:migrate -n --env=test - php tests/console chill:db:sync-views --env=test - php -d memory_limit=2G tests/console cache:clear --env=test - - php -d memory_limit=3G tests/console doctrine:fixtures:load -n - - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive + - php -d memory_limit=3G tests/console doctrine:fixtures:load -n --env=test + - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive,openstack-integration,collabora-integration artifacts: expire_in: 1 day paths: @@ -137,4 +138,4 @@ release: - echo "running release_job" release: tag_name: '$CI_COMMIT_TAG' - description: "./.changes/v$CI_COMMIT_TAG.md" + description: "./.changes/$CI_COMMIT_TAG.md" diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 9aae1c43f..4a70e81e7 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -27,6 +27,7 @@ $config ->setRiskyAllowed(true) ->setCacheFile('.cache/php-cs-fixer.cache') ->setUsingCache(true) + ->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()) ; $rules = $config->getRules(); @@ -112,6 +113,7 @@ $rules = array_merge( ], 'sort_algorithm' => 'alpha', ], + 'single_line_empty_body' => true, ], $rules, $riskyRules, diff --git a/CHANGELOG.md b/CHANGELOG.md index db735c10a..5272cd5a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,21 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and is generated by [Changie](https://github.com/miniscruff/changie). +## v3.1.0 - 2024-08-30 +### Feature +* Add export aggregator to aggregate activities by household + filter persons that are not part of an accompanyingperiod during a certain timeframe. + +## v3.0.0 - 2024-08-26 +### Fixed +* Fix delete action for accompanying periods in draft state +* Fix connection to azure when making an calendar event in chill +* CollectionType js fixes for remove button and adding multiple entries + ## v2.24.0 - 2024-09-11 ### Feature -* ([#306](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/306)) When a document is converted or downloaded in the browser, this document is removed from the browser memory after 45s. Future click on the button re-download the document. +* ([#306](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/306)) When a document is converted or downloaded in the browser, this document is removed from the browser memory after 45s. Future click on the button re-download the document. -## v2.23.0 - 2024-07-19 +## v2.23.0 - 2024-07-19 & 2024-07-23 ### Feature * ([#123](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/123)) Add a button to duplicate calendar ranges from a week to another one * [admin] filter users by active / inactive in the admin user's list @@ -33,15 +43,25 @@ and is generated by [Changie](https://github.com/miniscruff/changie). - Agrandit l'icône du type de fichier dans l'interface de dépôt de fichier; - correction: tient compte de la date de fermeture du parcours dans les filtres sur les actions d'accompagnement. +* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles +* Add job bundle (module emploi) +* Upgrade import of address list to the last version of compiled addresses of belgian-best-address + +* Upgrade CKEditor and refactor configuration with use of typescript + +### Fixed +* Fix resolving of centers for an household, which will fix in turn the access control +* Resolved type hinting error in activity list export + ## v2.22.2 - 2024-07-03 ### Fixed -* Remove scope required for event participation stats +* Remove scope required for event participation stats ## v2.22.1 - 2024-07-01 ### Fixed -* Remove debug word +* Remove debug word ### DX -* Add a command for reading official address DB from Luxembourg and update chill addresses +* Add a command for reading official address DB from Luxembourg and update chill addresses ## v2.22.0 - 2024-06-25 ### Feature @@ -84,7 +104,7 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.20.1 - 2024-06-05 ### Fixed -* Do not allow StoredObjectCreated for edit and convert buttons +* Do not allow StoredObjectCreated for edit and convert buttons ## v2.20.0 - 2024-06-05 ### Fixed @@ -131,96 +151,96 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.18.2 - 2024-04-12 ### Fixed -* ([#250](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/250)) Postal codes import : fix the source URL and the keys to handle each record +* ([#250](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/250)) Postal codes import : fix the source URL and the keys to handle each record ## v2.18.1 - 2024-03-26 ### Fixed -* Fix layout issue in document generation for admin (minor) +* Fix layout issue in document generation for admin (minor) ## v2.18.0 - 2024-03-26 ### Feature -* ([#268](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/268)) Improve admin UX to configure document templates for document generation +* ([#268](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/268)) Improve admin UX to configure document templates for document generation ### Fixed -* ([#267](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/267)) Fix the join between job and user in the user list (admin): show only the current user job +* ([#267](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/267)) Fix the join between job and user in the user list (admin): show only the current user job ## v2.17.0 - 2024-03-19 ### Feature -* ([#237](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/237)) New export filter for social actions with an evaluation created between two dates -* ([#258](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/258)) In the list of accompangying period, add the list of person's centers and the duration of the course -* ([#238](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/238)) Allow to customize list person with new fields +* ([#237](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/237)) New export filter for social actions with an evaluation created between two dates +* ([#258](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/258)) In the list of accompangying period, add the list of person's centers and the duration of the course +* ([#238](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/238)) Allow to customize list person with new fields * ([#159](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/159)) Admin can publish news on the homepage ### Fixed -* ([#264](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/264)) Fix languages: load the languages in all availables languages configured for Chill -* ([#259](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/259)) Keep a consistent behaviour between the filtering of activities within the document generation (model "accompanying period with activities"), and the same filter in the list of activities for an accompanying period +* ([#264](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/264)) Fix languages: load the languages in all availables languages configured for Chill +* ([#259](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/259)) Keep a consistent behaviour between the filtering of activities within the document generation (model "accompanying period with activities"), and the same filter in the list of activities for an accompanying period ## v2.16.3 - 2024-02-26 ### Fixed -* ([#236](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/236)) Fix translation of user job -> 'service' must be 'métier' +* ([#236](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/236)) Fix translation of user job -> 'service' must be 'métier' ### UX -* ([#232](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/232)) Order user jobs and services alphabetically in export filters +* ([#232](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/232)) Order user jobs and services alphabetically in export filters ## v2.16.2 - 2024-02-21 ### Fixed -* Check for null values in closing motive of parcours d'accompagnement for correct rendering of template +* Check for null values in closing motive of parcours d'accompagnement for correct rendering of template ## v2.16.1 - 2024-02-09 ### Fixed -* Force bootstrap version to avoid error in builds with newer version +* Force bootstrap version to avoid error in builds with newer version ## v2.16.0 - 2024-02-08 ### Feature -* ([#231](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/231)) Create new filter for persons having a participation in an accompanying period during a certain time span -* ([#241](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/241)) [Export][List of accompanyign period] Add two columns: the list of persons participating to the period, and their ids -* ([#244](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/244)) Add capability to generate export about change of steps of accompanying period, and generate exports for this -* ([#253](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/253)) Export: group accompanying period by person participating -* ([#243](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/243)) Export: add filter for courses not linked to a reference address -* ([#229](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/229)) Allow to group activities linked with accompanying period by reason -* ([#115](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/115)) Prevent social work to be saved when another user edited conccurently the social work -* Modernize the event bundle, with some new fields and multiple improvements +* ([#231](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/231)) Create new filter for persons having a participation in an accompanying period during a certain time span +* ([#241](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/241)) [Export][List of accompanyign period] Add two columns: the list of persons participating to the period, and their ids +* ([#244](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/244)) Add capability to generate export about change of steps of accompanying period, and generate exports for this +* ([#253](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/253)) Export: group accompanying period by person participating +* ([#243](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/243)) Export: add filter for courses not linked to a reference address +* ([#229](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/229)) Allow to group activities linked with accompanying period by reason +* ([#115](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/115)) Prevent social work to be saved when another user edited conccurently the social work +* Modernize the event bundle, with some new fields and multiple improvements ### Fixed -* ([#220](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/220)) Fix error in logs about wrong typing of eventArgs in onEditNotificationComment method -* ([#256](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/256)) Fix the conditions upon which social actions should be optional or required in relation to social issues within the activity creation form +* ([#220](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/220)) Fix error in logs about wrong typing of eventArgs in onEditNotificationComment method +* ([#256](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/256)) Fix the conditions upon which social actions should be optional or required in relation to social issues within the activity creation form ### UX -* ([#260](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/260)) Order list of centers alphabetically in dropdown 'user' section admin. +* ([#260](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/260)) Order list of centers alphabetically in dropdown 'user' section admin. ## v2.15.2 - 2024-01-11 ### Fixed -* Fix the id_seq used when creating a new accompanying period participation during fusion of two person files +* Fix the id_seq used when creating a new accompanying period participation during fusion of two person files ### DX -* Set placeholder to False for expanded EntityType form fields where required is set to False. +* Set placeholder to False for expanded EntityType form fields where required is set to False. ## v2.15.1 - 2023-12-20 ### Fixed -* Fix the household export query to exclude accompanying periods that are in draft state. +* Fix the household export query to exclude accompanying periods that are in draft state. ### DX -* ([#167](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/167)) Fixed readthedocs compilation by updating readthedocs config file and requirements for Sphinx +* ([#167](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/167)) Fixed readthedocs compilation by updating readthedocs config file and requirements for Sphinx ## v2.15.0 - 2023-12-11 ### Feature -* ([#191](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/191)) Add export "number of household associate with an exchange" -* ([#235](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/235)) Export: add dates on the filter "filter course by activity type" +* ([#191](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/191)) Add export "number of household associate with an exchange" +* ([#235](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/235)) Export: add dates on the filter "filter course by activity type" ### Fixed -* ([#214](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/214)) Fix error when posting an empty comment on an accompanying period. -* ([#233](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/233)) Fix "filter evaluation by evaluation type" (and add select2 to the list of evaluation types to pick) +* ([#214](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/214)) Fix error when posting an empty comment on an accompanying period. +* ([#233](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/233)) Fix "filter evaluation by evaluation type" (and add select2 to the list of evaluation types to pick) * ([#234](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/234)) Fix "filter aside activity by date" - -* ([#228](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/228)) Fix export of activity for people created before the introduction of the createdAt column on person (during v1) -* ([#246](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/246)) Do not show activities, evaluations and social work when associated to a confidential accompanying period, except for the users which are allowed to see them + +* ([#228](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/228)) Fix export of activity for people created before the introduction of the createdAt column on person (during v1) +* ([#246](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/246)) Do not show activities, evaluations and social work when associated to a confidential accompanying period, except for the users which are allowed to see them ## v2.14.1 - 2023-11-29 ### Fixed -* Export: fix list person with custom fields -* ([#100](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/100)) Add a paginator to budget elements (resource and charge types) in the admin -* Fix error in ListEvaluation when "handling agents" are alone +* Export: fix list person with custom fields +* ([#100](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/100)) Add a paginator to budget elements (resource and charge types) in the admin +* Fix error in ListEvaluation when "handling agents" are alone ## v2.14.0 - 2023-11-24 ### Feature -* ([#161](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/161)) Export: in filter "Filter accompanying period work (social action) by type, goal and result", order the items alphabetically or with the defined order +* ([#161](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/161)) Export: in filter "Filter accompanying period work (social action) by type, goal and result", order the items alphabetically or with the defined order ### Fixed -* ([#141](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/141)) Export: on filter "action by type goals, and results", restore the fields when editing a saved export -* ([#219](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/219)) Export: fix the list of accompanying period work, when the "calc date" is null -* ([#222](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/222)) Fix rendering of custom fields -* Fix various errors in custom fields administration +* ([#141](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/141)) Export: on filter "action by type goals, and results", restore the fields when editing a saved export +* ([#219](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/219)) Export: fix the list of accompanying period work, when the "calc date" is null +* ([#222](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/222)) Fix rendering of custom fields +* Fix various errors in custom fields administration ## v2.13.0 - 2023-11-21 ### Feature @@ -234,7 +254,7 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.12.1 - 2023-11-16 ### Fixed -* ([#208](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/208)) Export: fix loading of form for "filter action by type, goal and result" +* ([#208](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/208)) Export: fix loading of form for "filter action by type, goal and result" ## v2.12.0 - 2023-11-15 ### Feature @@ -265,36 +285,36 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.11.0 - 2023-11-07 ### Feature -* ([#194](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/194)) Export: add a filter "filter activity by creator job" +* ([#194](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/194)) Export: add a filter "filter activity by creator job" ### Fixed -* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix "group accompanying period by geographical unit": take into account the accompanying periods when the period is not located within an unit -* Fix "group activity by creator job" aggregator +* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix "group accompanying period by geographical unit": take into account the accompanying periods when the period is not located within an unit +* Fix "group activity by creator job" aggregator ## v2.10.6 - 2023-11-07 ### Fixed -* ([#182](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/182)) Fix merging of double person files. Adjustement relationship sql statement -* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix aggregator by geographical unit on person: avoid inconsistencies +* ([#182](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/182)) Fix merging of double person files. Adjustement relationship sql statement +* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix aggregator by geographical unit on person: avoid inconsistencies ## v2.10.5 - 2023-11-05 ### Fixed -* ([#183](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/183)) Fix "problem during download" on some filters, which used a wrong data type -* ([#184](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/184)) Fix filter "activity by date" +* ([#183](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/183)) Fix "problem during download" on some filters, which used a wrong data type +* ([#184](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/184)) Fix filter "activity by date" ## v2.10.4 - 2023-10-26 ### Fixed -* Fix null value constraint errors when merging relationships in doubles +* Fix null value constraint errors when merging relationships in doubles ## v2.10.3 - 2023-10-26 ### Fixed -* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Replace old method of getting translator with injection of translatorInterface +* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Replace old method of getting translator with injection of translatorInterface ## v2.10.2 - 2023-10-26 ### Fixed -* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Use injection of translator instead of ->get(). +* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Use injection of translator instead of ->get(). ## v2.10.1 - 2023-10-24 ### Fixed -* Fix export controller when generating an export without any data in session +* Fix export controller when generating an export without any data in session ## v2.10.0 - 2023-10-24 ### Feature @@ -319,11 +339,11 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.9.2 - 2023-10-17 ### Fixed -* Fix possible null values in string's entities +* Fix possible null values in string's entities ## v2.9.1 - 2023-10-17 ### Fixed -* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers +* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers ## v2.9.0 - 2023-10-17 ### Feature @@ -371,57 +391,57 @@ But if you do not need this any more, you must ensure that the configuration key ## v2.7.0 - 2023-09-27 ### Feature -* ([#155](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/155)) The regulation list load accompanying periods by exact postal code (address associated with postal code), and not by the content of the postal code (postal code with same code's string) +* ([#155](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/155)) The regulation list load accompanying periods by exact postal code (address associated with postal code), and not by the content of the postal code (postal code with same code's string) ### Fixed -* ([#142](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/142)) Fix the label of filter ActivityTypeFilter to a more obvious one -* ([#140](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/140)) [export] Fix association of filter "filter location by type" which did not appears on "list of activities" +* ([#142](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/142)) Fix the label of filter ActivityTypeFilter to a more obvious one +* ([#140](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/140)) [export] Fix association of filter "filter location by type" which did not appears on "list of activities" ## v2.6.3 - 2023-09-19 ### Fixed -* Remove id property from document -mappedsuperclass +* Remove id property from document +mappedsuperclass ## v2.6.2 - 2023-09-18 ### Fixed -* Fix doctrine mapping of AbstractTaskPlaceEvent and SingleTaskPlaceEvent: id property moved. +* Fix doctrine mapping of AbstractTaskPlaceEvent and SingleTaskPlaceEvent: id property moved. ## v2.6.1 - 2023-09-14 ### Fixed -* Filter out active centers in exports, which uses a different PickCenterType. +* Filter out active centers in exports, which uses a different PickCenterType. ## v2.6.0 - 2023-09-14 ### Feature -* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Add locations in Aside Activity. By default, suggest user location, otherwise a select with all locations. -* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Adapt Aside Activity exports: display location, filter by location, group by location -* Use the CRUD controller for center entity + add the isActive property to be able to mask instances of Center that are no longer in use. +* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Add locations in Aside Activity. By default, suggest user location, otherwise a select with all locations. +* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Adapt Aside Activity exports: display location, filter by location, group by location +* Use the CRUD controller for center entity + add the isActive property to be able to mask instances of Center that are no longer in use. ### Fixed -* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) reinstate the fusion of duplicate persons -* Missing translation in Work Actions exports -* Reimplement the mission type filter on tasks, only for instances that have a config parameter indicating true for this. -* ([#135](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/135)) Corrects a typing error in 2 filters, which caused an +* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) reinstate the fusion of duplicate persons +* Missing translation in Work Actions exports +* Reimplement the mission type filter on tasks, only for instances that have a config parameter indicating true for this. +* ([#135](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/135)) Corrects a typing error in 2 filters, which caused an error when trying to reedit a saved export - -* ([#136](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/136)) [household] when moving a person to a sharing position to a not-sharing position on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member. + +* ([#136](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/136)) [household] when moving a person to a sharing position to a not-sharing position on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member. * Add missing translation for comment field placeholder in repositionning household editor. - -* Do not send an email to creator twice when adding a comment to a notification -* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) Fix gestion doublon functionality to work with chill bundles v2 + +* Do not send an email to creator twice when adding a comment to a notification +* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) Fix gestion doublon functionality to work with chill bundles v2 ### UX * Uniformize badge-person in household banner (background, size) - + ## v2.5.3 - 2023-07-20 ### Fixed -* ([#132](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/132)) Rendez-vous documents created would appear in all documents lists of all persons with an accompanying period. Or statements are now added to the where clause to filter out documents that come from unrelated accompanying period/ or person rendez-vous. +* ([#132](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/132)) Rendez-vous documents created would appear in all documents lists of all persons with an accompanying period. Or statements are now added to the where clause to filter out documents that come from unrelated accompanying period/ or person rendez-vous. ## v2.5.2 - 2023-07-15 ### Fixed -* [Collate Address] when updating address point, do not use the point's address reference if the similarity is below the requirement for associating the address reference and the address (it uses the postcode's center instead) +* [Collate Address] when updating address point, do not use the point's address reference if the similarity is below the requirement for associating the address reference and the address (it uses the postcode's center instead) ## v2.5.1 - 2023-07-14 ### Fixed -* [collate addresses] block collating addresses to another address reference where the address reference is already the best match +* [collate addresses] block collating addresses to another address reference where the address reference is already the best match ## v2.5.0 - 2023-07-14 ### Feature diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 000000000..e823f0b22 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,117 @@ + +# Switch to symfony 5.0 + +- the tag `chill.role` is now renamed to `chill_main.provide_role`. + + **Note**: It is not necessary to apply this tag on service definition: the tag is automatically applyied if the + service implements `\Chill\MainBundle\Security\ProvideRoleInterface`. + +- those annotation can be converted to attribute: + + - `Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\AccompanyingPeriodValidity` + - `Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential` + - `Chill\PersonBundle\Validator\Constraints\Household\MaxHolder` + - `Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ConfidentialCourseMustHaveReferrer` + - `Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\LocationValidity` + - `Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ParticipationOverlap` + - `Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ResourceDuplicateCheck` + - `Chill\PersonBundle\Validator\Constraints\Person\Birthdate` + - `Chill\PersonBundle\Validator\Constraints\Person\PersonHasCenter` + - `Chill\PersonBundle\Validator\Constraints\Relationship\RelationshipNoDuplicate` + - `Chill\ActivityBundle\Validator\Constraints\ActivityValidity` + - `Chill\DocStoreBundle\Validator\Constraints\AsyncFileExists` + - `Chill\MainBundle\Validation\Constraint\PhonenumberConstraint` + - `Chill\MainBundle\Validator\Constraints\Entity\UserCircleConsistency` + - `Chill\MainBundle\Workflow\Validator\EntityWorkflowCreation` + + Here is the rector rule that can be used to switch attributes to annotations: + + ```php + $rectorConfig->ruleWithConfiguration(\Rector\Php80\Rector\Class_\AnnotationToAttributeRector::class, [ + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\AccompanyingPeriodValidity'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\Household\MaxHolder'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ConfidentialCourseMustHaveReferrer'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\LocationValidity'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ParticipationOverlap'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ResourceDuplicateCheck'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\Person\Birthdate'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\Person\PersonHasCenter'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\PersonBundle\Validator\Constraints\Relationship\RelationshipNoDuplicate'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\ActivityBundle\Validator\Constraints\ActivityValidity'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\DocStoreBundle\Validator\Constraints\AsyncFileExists'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\MainBundle\Validation\Constraint\PhonenumberConstraint'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\MainBundle\Validator\Constraints\Entity\UserCircleConsistency'), + new \Rector\Php80\ValueObject\AnnotationToAttribute('Chill\MainBundle\Workflow\Validator\EntityWorkflowCreation'), + ]); + ``` + +- to keep cleaner definition in container's dependency injection and framework bundle, the definition of crud or api + requires to define explicitly a controller. + + Before: + + ```php + $container->prependExtensionConfig('chill_main', [ + 'apis' => [ + [ + 'class' => ThirdParty::class, + 'name' => 'thirdparty', + 'base_path' => '/api/1.0/thirdparty/thirdparty', + 'actions' => [ + '_entity' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + Request::METHOD_POST => true, + Request::METHOD_PUT => true, + Request::METHOD_PATCH => true, + ], + 'roles' => [ + Request::METHOD_GET => ThirdPartyVoter::SHOW, + Request::METHOD_HEAD => ThirdPartyVoter::SHOW, + Request::METHOD_POST => ThirdPartyVoter::CREATE, + Request::METHOD_PUT => ThirdPartyVoter::CREATE, + Request::METHOD_PATCH => ThirdPartyVoter::CREATE, + ], + ], + ], + ], + ], + ]); + + After: + + ```php + $container->prependExtensionConfig('chill_main', [ + 'apis' => [ + [ + 'class' => ThirdParty::class, + 'controller' => ThirdPartyApiController::class, + 'name' => 'thirdparty', + 'base_path' => '/api/1.0/thirdparty/thirdparty', + 'actions' => [ + '_entity' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + Request::METHOD_POST => true, + Request::METHOD_PUT => true, + Request::METHOD_PATCH => true, + ], + 'roles' => [ + Request::METHOD_GET => ThirdPartyVoter::SHOW, + Request::METHOD_HEAD => ThirdPartyVoter::SHOW, + Request::METHOD_POST => ThirdPartyVoter::CREATE, + Request::METHOD_PUT => ThirdPartyVoter::CREATE, + Request::METHOD_PATCH => ThirdPartyVoter::CREATE, + ], + ], + ], + ], + ], + ]); + + ``` + + diff --git a/composer.json b/composer.json index f08f94677..b33314789 100644 --- a/composer.json +++ b/composer.json @@ -13,14 +13,12 @@ "ext-json": "*", "ext-openssl": "*", "ext-redis": "*", - "champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290", "champs-libres/wopi-bundle": "dev-master@dev", "champs-libres/wopi-lib": "dev-master@dev", "doctrine/doctrine-bundle": "^2.1", "doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/orm": "^2.13.0", "erusev/parsedown": "^1.7", - "graylog2/gelf-php": "^1.5", "knplabs/knp-menu-bundle": "^3.0", "knplabs/knp-time-bundle": "^1.12", "knpuniversity/oauth2-client-bundle": "^2.10", @@ -33,28 +31,50 @@ "phpoffice/phpspreadsheet": "^1.16", "ramsey/uuid-doctrine": "^1.7", "sensio/framework-extra-bundle": "^5.5", + "smalot/pdfparser": "^2.10", "spomky-labs/base64url": "^2.0", - "symfony/browser-kit": "^4.4", + "symfony/asset": "^5.4", + "symfony/browser-kit": "^5.4", + "symfony/cache": "^5.4", "symfony/clock": "^6.2", - "symfony/css-selector": "^4.4", - "symfony/expression-language": "^4.4", - "symfony/form": "^4.4", - "symfony/framework-bundle": "^4.4", - "symfony/http-client": "^4.4 || ^5", - "symfony/http-foundation": "^4.4", - "symfony/intl": "^4.4", + "symfony/config": "^5.4", + "symfony/console": "^5.4", + "symfony/css-selector": "^5.4", + "symfony/dom-crawler": "^5.4", + "symfony/error-handler": "^5.4", + "symfony/event-dispatcher": "^5.4", + "symfony/event-dispatcher-contracts": "^2.4", + "symfony/expression-language": "^5.4", + "symfony/filesystem": "^5.4", + "symfony/finder": "^5.4", + "symfony/form": "^5.4", + "symfony/framework-bundle": "^5.4", + "symfony/http-client": "^5.4", + "symfony/http-foundation": "^5.4", + "symfony/intl": "^5.4", "symfony/mailer": "^5.4", "symfony/messenger": "^5.4", "symfony/mime": "^5.4", "symfony/monolog-bundle": "^3.5", - "symfony/security-bundle": "^4.4", - "symfony/serializer": "^5.3", - "symfony/translation": "^4.4", - "symfony/twig-bundle": "^4.4", - "symfony/validator": "^4.4", + "symfony/options-resolver": "^5.4", + "symfony/process": "^5.4", + "symfony/property-access": "^5.4", + "symfony/property-info": "^5.4", + "symfony/routing": "^5.4", + "symfony/security-bundle": "^5.4", + "symfony/security-core": "^5.4", + "symfony/security-csrf": "^5.4", + "symfony/security-guard": "^5.4", + "symfony/security-http": "^5.4", + "symfony/serializer": "^5.4", + "symfony/string": "^5.4", + "symfony/templating": "^5.4", + "symfony/translation": "^5.4", + "symfony/twig-bundle": "^5.4", + "symfony/validator": "^5.4", "symfony/webpack-encore-bundle": "^1.11", - "symfony/workflow": "^4.4", - "symfony/yaml": "^4.4", + "symfony/workflow": "^5.4", + "symfony/yaml": "^5.4", "thenetworg/oauth2-azure": "^2.0", "twig/extra-bundle": "^3.0", "twig/intl-extra": "^3.0", @@ -73,17 +93,15 @@ "phpstan/phpstan": "^1.9", "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": ">= 7.5", - "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^4.0.2", - "rector/rector": "1.1.1", - "symfony/debug-bundle": "^5.1", - "symfony/dotenv": "^4.4", + "phpunit/phpunit": "^10.5.24", + "rector/rector": "^1.1.0", + "symfony/debug-bundle": "^5.4", + "symfony/dotenv": "^5.4", "symfony/maker-bundle": "^1.20", - "symfony/phpunit-bridge": "^4.4", - "symfony/stopwatch": "^4.4", - "symfony/var-dumper": "^4.4", - "vimeo/psalm": "^4.30.0" + "symfony/phpunit-bridge": "^7.1", + "symfony/runtime": "^5.4", + "symfony/stopwatch": "^5.4", + "symfony/var-dumper": "^5.4" }, "conflict": { "symfony/symfony": "*" @@ -98,6 +116,8 @@ "Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle", "Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle", "Chill\\EventBundle\\": "src/Bundle/ChillEventBundle", + "Chill\\FranceTravailApiBundle\\": "src/Bundle/ChillFranceTravailApiBundle/src", + "Chill\\JobBundle\\": "src/Bundle/ChillJobBundle/src", "Chill\\MainBundle\\": "src/Bundle/ChillMainBundle", "Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle", "Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle", @@ -132,6 +152,7 @@ "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd" - } + }, + "php-cs-fixer": "php-cs-fixer fix --config=./.php-cs-fixer.dist.php --show-progress=none" } } diff --git a/docs/source/_static/code/exports/BirthdateFilter.php b/docs/source/_static/code/exports/BirthdateFilter.php index e25d8b42f..fca768ab3 100644 --- a/docs/source/_static/code/exports/BirthdateFilter.php +++ b/docs/source/_static/code/exports/BirthdateFilter.php @@ -21,7 +21,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; class BirthdateFilter implements ExportElementValidatedInterface, FilterInterface { // add specific role for this filter - public function addRole() + public function addRole(): ?string { // we do not need any new role for this filter, so we return null return null; diff --git a/docs/source/development/pagination/example.php b/docs/source/development/pagination/example.php index 964da8764..ef565e941 100644 --- a/docs/source/development/pagination/example.php +++ b/docs/source/development/pagination/example.php @@ -15,9 +15,12 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; class example extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController { + public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) + { + } public function yourAction() { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); // first, get the number of total item are available $total = $em ->createQuery('SELECT COUNT (item.id) FROM ChillMyBundle:Item item') diff --git a/docs/source/development/useful-snippets/controller-secured-for-person.php b/docs/source/development/useful-snippets/controller-secured-for-person.php index da2078a7a..35028f524 100644 --- a/docs/source/development/useful-snippets/controller-secured-for-person.php +++ b/docs/source/development/useful-snippets/controller-secured-for-person.php @@ -18,6 +18,9 @@ use Symfony\Component\Security\Core\Role\Role; class ConsultationController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController { + public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) + { + } /** * @param int $id personId * @@ -48,7 +51,7 @@ class ConsultationController extends \Symfony\Bundle\FrameworkBundle\Controller\ ); // create a query which take circles into account - $consultations = $this->getDoctrine()->getManager() + $consultations = $this->managerRegistry->getManager() ->createQuery('SELECT c FROM ChillHealthBundle:Consultation c ' . 'WHERE c.patient = :person AND c.circle IN(:circles) ' . 'ORDER BY c.date DESC') diff --git a/docs/source/installation/enable-collabora-for-dev.rst b/docs/source/installation/enable-collabora-for-dev.rst new file mode 100644 index 000000000..17a9ae1cc --- /dev/null +++ b/docs/source/installation/enable-collabora-for-dev.rst @@ -0,0 +1,125 @@ + +Enable CODE for development +=========================== + +For editing a document, there must be a way to communicate between the collabora server and the symfony server, in +both direction. The domain name should also be the same for collabora server and for the browser which access to the +online editor. + +Using ngrok (or other http tunnel) +---------------------------------- + +One can configure a tunnel server to expose your local install to the web, and access to your local server using the +tunnel url. + +Start ngrok +^^^^^^^^^^^ + +This can be achieve using `ngrok `_. + +.. note:: + + The configuration of ngrok is outside of the scope of this document. Refers to the ngrok's documentation. + +.. code-block:: bash + + # ensuring that your server is running through http and port 8000 + ngrok http 8000 + # then open the link given by the ngrok utility and you should reach your app + +At this step, ensure that you can reach your local app using the ngrok url. + +Configure Collabora +^^^^^^^^^^^^^^^^^^^ + +The collabora server must be executed online and configure to access to your ngrok installation. Ensure that the aliasgroup +exists for your ngrok application (`See the CODE documentation: `_). + +Configure your app +^^^^^^^^^^^^^^^^^^ + +Set the :code:`EDITOR_SERVER` variable to point to your collabora server, this should be done in your :code:`.env.local` file. + +At this point, everything must be fine. In case of errors, watch the log from your collabora server, use the `profiler `_ +to debug the requests. + +.. note:: + + In case of error while validating proof (you'll see those message in the collabora's logs), you can temporarily disable + the proof validation adding this code snippet in `config/services.yaml`: + + .. code-block:: yaml + + when@dev: + # add only in dev environment, to avoid security problems + services: + ChampsLibres\WopiLib\Contract\Service\ProofValidatorInterface: + # this class will always validate proof + alias: Chill\WopiBundle\Service\Wopi\NullProofValidator + +With a local CODE image +----------------------- + +.. warning:: + + This configuration is not sure, and must be refined. The documentation does not seems to be entirely valid. + +Use a local domain name and https for your app +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Use the proxy feature from embedded symfony server to run your app. `See the dedicated doc ` + +Configure also the `https certificate `_ + +In this example, your local domain name will be :code:`my-domain` and the url will be :code:`https://my-domain.wip`. + +Ensure that the proxy is running. + +Create a certificate database for collabora +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Collabora must validate your certificate generated by symfony console. For that, you need `to create a NSS database ` +and configure collabora to use it. + +At first, export the certificate for symfony development. Use the graphical interface from your browser to get the +certificate as a PEM file. + +.. code-block:: bash + + # create your database in a custom directory + mkdir /path/to/your/directory + certutil -N -d /path/to/your/directory + cat /path/to/your/ca.crt | certutil -d . -A symfony -t -t C,P,C,u,w -a + +Launch CODE properly configured + +.. code-block:: yaml + + collabora: + image: collabora/code:latest + environment: + - SLEEPFORDEBUGGER=0 + - DONT_GEN_SSL_CERT="True" + # add path to the database + - extra_params=--o:ssl.enable=false --o:ssl.termination=false --o:logging.level=7 -o:certificates.database_path=/etc/custom-certificates/nss-database + - username=admin + - password=admin + - dictionaries=en_US + - aliasgroup1=https://my-domain.wip + ports: + - "127.0.0.1:9980:9980" + volumes: + - "/path/to/your/directory/nss-database:/etc/custom-certificates/nss-database" + extra_hosts: + - "my-domain.wip:host-gateway" + +Configure your app +^^^^^^^^^^^^^^^^^^ + +Into your :code:`.env.local` file: + +.. code-block:: env + + EDITOR_SERVER=http://${COLLABORA_HOST}:${COLLABORA_PORT} + +At this step, you should be able to edit a document through collabora. diff --git a/docs/source/installation/index.rst b/docs/source/installation/index.rst index 67a0b6ec6..a9a4ea0c6 100644 --- a/docs/source/installation/index.rst +++ b/docs/source/installation/index.rst @@ -14,6 +14,359 @@ Installation & Usage #################### + +You will learn here how to install a new symfony project with chill, and configure it. + +Requirements +============ + +The installation is tested on a Debian-like linux distribution. The installation on other operating systems is not documented. + +You have to install the following tools on your computer: + +- `PHP `_, version 8.3+, with the following extensions: pdo_pgsql, intl, mbstring, zip, bcmath, exif, sockets, redis, ast, gd; +- `composer `_; +- `symfony cli `_; +- `node, we encourage you to use nvm to configure the correct version `_. The project contains an + :code:`.nvmrc` file which selects automatically the required version of node (if present). +- `yarn `_. We use the version 1.22+ for now. +- `docker and the plugin compose `_ to run the database + +Chill needs a redis server and a postgresql database, and a few other things like a "relatorio service" which will +generate documents from templates. **All these things are available through docker using the plugin compose**. We do not provide +information on how to run this without docker compose. + + +Install a new project +===================== + +Initialize project and dependencies +*********************************** + +.. code-block:: bash + + symfony new --version=5.4 my_chill_project + cd my_chill_project + +We strongly encourage you to initialize a git repository at this step, to track further changes. + +.. code-block:: bash + + # add the flex endpoints required for custom recipes + cat <<< "$(jq '.extra.symfony += {"endpoint": ["flex://defaults", "https://gitlab.com/api/v4/projects/57371968/repository/files/index.json/raw?ref=main"]}' composer.json)" > composer.json + # install chill and some dependencies + # TODO fix the suffix "alpha1" and replace by ^3.0.0 when version 3.0.0 will be released + symfony composer require chill-project/chill-bundles v3.0.0-RC3 champs-libres/wopi-lib dev-master@dev champs-libres/wopi-bundle dev-master@dev + +We encourage you to accept the inclusion of the "Docker configuration from recipes": this is the documented way to run the database. +You must also accept to configure recipes from the contrib repository, unless you want to configure the bundles manually). + +.. code-block:: bash + + # fix some configuration + ./post-install-chill.sh + # install node dependencies + yarn install + # and compile assets + yarn run encore production + +.. note:: + + If you encounter this error during assets compilation (:code:`yarn run encore production`) (repeated multiple times): + + .. code-block:: txt + + [tsl] ERROR in /tmp/chill/v1/public/bundles/chillcalendar/types.ts(2,65) + TS2307: Cannot find module '../../../ChillMainBundle/Resources/public/types' or its corresponding type declarations. + + run: + + .. code-block:: bash + + rm -rf public/bundles/* + + Then restart the compilation of assets (:code:```yarn run encore production```) + +Configure your project +********************** + +You should read the configuration files in :code:`chill/config/packages` carefully, especially if you have +custom developments. But most of the time, this should be fine. + +You have to configure some local variables, which are described in the :code:`.env` file. The secrets should not be stored +in this :code:`.env` file, but instead using the `secrets management tool `_ +or in the :code:`.env.local` file, which should not be committed to the git repository. + +You do not need to set variables for the smtp server, redis server and relatorio server, as they are generated automatically +by the symfony server, from the docker compose services. + +The only required variable is the :code:`ADMIN_PASSWORD`. You can generate a hashed and salted admin password using the command +:code:`symfony console security:hash-password 'Symfony\Component\Security\Core\User\User'`. Then, +you can either: + +- add this password to the :code:`.env.local` file, you must escape the character :code:`$`: if the generated password + is :code:`$2y$13$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm`, your :code:`.env.local` file will be: + + .. code-block:: env + + ADMIN_PASSWORD=\$2y\$13\$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm + # note: if you copy-paste the line above, the password will be "admin". + +- add the generated password to the secrets manager (**note**: you must add the generated hashed password to the secrets env, + not the password in clear text). + +- set up the jwt authentication bundle + +Some environment variables are available for the JWT authentication bundle in the :code:`.env` file. + +Prepare migrations and other tools +********************************** + +To continue the installation process, you will have to run migrations: + +.. code-block:: bash + + # start databases and other services + docker compose up -d + # the first start, it may last some seconds, you can check with docker compose ps + # run migrations + symfony console doctrine:migrations:migrate + # setup messenger + symfony console messenger:setup-transports + # prepare some views + symfony console chill:db:sync-views + # generate jwt token, required for some api features (webdav access, ...) + symfony console lexik:jwt:generate-keypair + +.. warning:: + + If you encounter an error while running :code:`symfony console messenger:setup-transports`, you can set up the messenger + transport to redis, by adding this in the :code:`.env.local` or :code:`.env` file: + + .. code-block:: env + + MESSENGER_TRANSPORT_DSN=redis://${REDIS_HOST}:${REDIS_PORT}/messages + +Start your web server locally +***************************** + +At this step, Chill will be ready to be served locally, but without any configuration. You can run the project +locally using the `local symfony server `_: + +.. code-block:: bash + + # see the whole possibilities at https://symfony.com/doc/current/setup/symfony_server.html + symfony server:start -d + + +If you need to test the instance with accounts and some basic configuration, please install the fixtures (see below). + + +Add capabilities for dev +======================== + +If you need to add custom bundles, you can develop them in the `src/` directory, like for any other symfony project. You +can rely on the whole chill framework, meaning there is no need to add them to the original `chill-bundles`. + +You will require some bundles to have the following development tools: + +- add fixtures +- add profiler and debug bundle + +Install fixtures +**************** + +.. code-block:: bash + + # generate fixtures for chill + symfony composer require --dev doctrine/doctrine-fixtures-bundle nelmio/alice + # now, you can generate fixtures (this will reset your database) + symfony console doctrine:fixtures:load + +This will generate user accounts, centers, and some basic configuration. + +The accounts created are: :code:`center a_social`, :code:`center b_social`, :code:`center a_direction`, ... The full list is +visible in the "users" table: :code:`docker compose exec database psql -U app -c "SELECT username FROM users"`. + +The password is always :code:`password`. + +.. warning:: + + The fixtures are not fully functional. See the `corresponding issue `_. + +Add web profiler and debugger +***************************** + +.. code-block:: bash + + symfony composer require --dev symfony/web-profiler-bundle symfony/debug-bundle + +Working on chill bundles +************************ + +If you plan to improve the chill-bundles repository, that's great! + +You will have to download chill-bundles as a git repository (and not as an archive, which is barely editable). + +In your :code:`composer.json` file, add these lines: + +.. code-block:: diff + + { + "config": { + + "preferred-install": { + + "chill-project/chill-bundles": "source", + "*": "dist" + + } + } + +Then, run :code:`symfony composer reinstall chill-project/chill-bundles` to re-install the package from source. + +Code style, code quality and other tools +**************************************** + +For development, you will also have to install: + +- `php-cs-fixer `_ + +We also encourage you to use tools like `phpstan `_ and `rector `_. + +Commit and share your project +============================= + +If multiple developers work on a project, you can commit your symfony project and share it with other people. + +When another developer clones your project, they will have to: + +- run :code:`symfony composer install` and :code:`yarn install` to install the same dependencies as the initial developer; +- run :code:`yarn run encore production` to compile assets; +- copy any possible variables from the :code:`.env.local` files; +- start the docker compose stack, using :code:`docker compose`, and run migrations, set up transports, and prepare chill db views + (see the corresponding command above) + +Update +====== + +In order to update your app, you must update dependencies: + +- for chill-bundles, you can `set the last version `_ manually + in the :code:`composer.json` file, or set the version to `^3.0.0` and run :code:`symfony composer update` regularly +- run :code:`composer update` and :code:`yarn update` to maintain your dependencies up-to-date. + +After each update, you must update your database schema: + +.. code-block:: bash + + symfony console doctrine:migrations:migrate + symfony console chill:db:sync-views + +Operations +========== + +Build assets +************ + +run those commands: + +.. code-block:: bash + + # for production (or in dev, when you don't need to work on your assets and need some speed) + yarn run encore production + # in dev, when you wan't to reload the assets on each changes + yarn run encore dev --watch + +How to execute the console ? +**************************** + +.. code-block:: bash + + # start the console with all required variables + symfony console + # you can add your command after that: + symfony console list + +How to generate documents +************************* + +Documents are generated asynchronously by `"consuming messages" `_. + +You must generate them using a dedicated process: + +.. code-block:: bash + + symfony console messenger:consume async priority + +To avoid memory issues, we encourage you to also use the :code:`--limit` parameter of the command. + +How to read emails sent by the program ? +******************************************* + +In development, there is a built-in "mail catcher". Open it with :code:`symfony open:local:webmail` + +How to run cron-jobs ? +********************** + +Some commands must be executed in :ref:`cron jobs `. To execute them: + +.. code-block:: bash + + symfony console chill:cron-job:execute + +What about materialized views ? +******************************* + +There are some materialized views in chill, to speed up some complex computations in the database. + +In order to refresh them, run a cron job or refresh them manually in your database. + +How to run tests for chill-bundles +********************************** + +Tests reside inside the installed bundles. You must `cd` into that directory, download the required packages, and execute them from this place. + +**Note**: some bundles require the fixtures to be executed. See the dedicated _how-tos_. + +Example, for running a unit test inside `main` bundle: + +.. code-block:: bash + + # cd into main directory + cd vendor/chill-project/chill-bundles + composer install + # run tests + bin/phpunit src/Bundle/path/to/your/test + +Or for running tests to check code style and php conventions with csfixer and phpstan: + +Troubleshooting +=============== + +Error `An exception has been thrown during the rendering of a template ("Asset manifest file "/var/www/app/web/build/manifest.json" does not exist.").` on first run +******************************************************************************************************************************************************************** + +Build assets, see above. + +Running in production +===================== + +Currently, to run this software in production, the *state of the art* is the following : + +1. Run the software locally and tweak the configuration to your needs ; +2. Build the image and store it in a private container registry. + +.. warning:: + + In production, you **must** set these variables: + + * ``APP_ENV`` to ``prod`` + * ``APP_DEBUG`` to ``false`` + + There are security issues if you keep the same variables as for production. + + +Going further +============= + .. toctree:: :maxdepth: 2 @@ -21,386 +374,3 @@ Installation & Usage load-addresses.rst prod-calendar-sms-sending.rst msgraph-configure.rst - - -Requirements -************ - -- This project use `docker `_ to be run. As a developer, use `docker-compose `_ to bootstrap a dev environment in a glance. You do not need any other dependencies ; -- Make is used to automate scripts. - -Installation -************ - -If you plan to run chill in production: - -1. install it locally first, and check if everything is ok on your local machine; -2. once ready, build the image from your local machine, and deploy them. - -If you want to develop some bundles, the first step is sufficient (until you deploy on production). - - -1. Get the code -=============== - -Clone or download the chill-skeleton project and `cd` into the main directory. - - -.. code-block:: bash - - git clone https://gitea.champs-libres.be/Chill-project/chill-skeleton-basic.git - cd chill-skeleton-basic - - -As a developer, the code will stay on your computer and will be executed in docker container. To avoid permission problem, the code should be run with the same uid/gid from your current user. This is why we get your current user id with the command ``id -u`` in each following scripts. - -2. Prepare composer to download the sources -=========================================== - -As you are running in dev, you must configure an auth token for getting the source code. - -.. warning - - If you skip this part, the code will be downloaded from dist instead of source (with git repository). You will probably replace the source manually, but the next time you will run ```composer update```, your repository will be replaced and you might loose something. - -1. Create a personal access token from https://gitlab.com/-/profile/personal_access_tokens, with the `read_api` scope. -2. add a file called ```.composer/auth.json``` with this content: - - .. code-block:: json - - { - "gitlab-token": { - "gitlab.com": "glXXX-XXXXXXXXXXXXXXXXXXXX" - } - } - -2. Prepare your variables and environment -========================================= - -Copy ```docker-compose.override.dev.yml``` into ```docker-compose.override.yml``` - -.. code-block:: bash - - cp docker-compose.override.dev.template.yml docker-compose.override.yml - -2. Prepare your variables and docker-compose -============================================ - -Have a look at the variable in ``.env`` and check if you need to adapt them. If they do not adapt with your need, or if some are missing: - -1. copy the file as ``.env.local``: ``cp .env .env.local`` -2. you may replace some variables inside ``.env`` - -Prepare also you docker-compose installation, and adapt it to your needs: - -1. If you plan to deploy on dev, copy the file ``docker-compose.override.dev.template.yml`` to ``docker-compose.override.yml``. -2. adapt to your needs. - - -**Note**: If you intend to use the bundle ``Chill-Doc-Store``, you will need to configure and install an openstack object storage container with temporary url middleware. You will have to configure `secret keys `_. - -3. Run the bootstrap script -=========================== - -This script can be run using `make` - -.. code-block:: bash - - make init - -This script will : - -1. force docker-compose to, eventually, pull the base images and build the image used by this project ; -2. run an install script to download `composer `_ ; -3. install the php dependencies -4. build assets - -.. warning:: - - The script will work only if the binary ``docker-compose`` is located into your ``PATH``. If you use ``compose`` as a docker plugin, - you can simulate this binary by creating this file at (for instance), ``/usr/local/bin/docker-compose`` (and run ``chmod +x /usr/local/bin/docker-compose``): - - .. code-block:: bash - - #!/bin/bash - - /usr/bin/docker compose "$@" - - -.. note:: - - In some cases it can happen that an old image (chill_base_php82 or chill_php82) stored in the docker cache will make the script fail. To solve this problem you have to delete the image and the container, before the make init : - - .. code-block:: bash - - docker-compose images php - docker rmi -f chill_php82:prod - docker-compose rm php - - -4. Start the project -==================== - -.. code-block:: bash - - docker-compose up - -**On the first run** (and after each upgrade), you must execute *post update commands* and run database migrations. With a container up and running, execute the following commands: - -.. code-block:: bash - - # mount into to container - ./docker-php.sh - bin/console chill:db:sync-views - # and load fixtures - bin/console doctrine:migrations:migrate - - -Chill will be available at ``http://localhost:8001.`` Currently, there isn't any user or data. To add fixtures, run - -.. code-block:: bash - - # mount into to container - ./docker-php.sh - # and load fixtures (do not this for production) - bin/console doctrine:fixtures:load --purge-with-truncate - -There are several users available: - -- ``center a_social`` -- ``center b_social`` - -The password is always ``password``. - -Now, read `Operations` below. For running in production, read `prod_`. - - -Operations -********** - -Build assets -============ - -run those commands: - -.. code-block:: bash - - make build-assets - -How to execute the console ? -============================ - -.. code-block:: bash - - # if a container is running - ./docker-php.sh - # if not - docker-compose run --user $(id -u) php bin/console - -How to create the database schema (= run migrations) ? -====================================================== - -.. code-block:: bash - - # if a container is running - ./docker-php.sh - bin/console doctrine:migrations:migrate - bin/console chill:db:sync-views - # if not - docker-compose run --user $(id -u) php bin/console doctrine:migrations:migrate - docker-compose run --user $(id -u) php bin/console chill:db:sync-views - - -How to read the email sent by the program ? -=========================================== - -Go at ``http://localhost:8005`` and you should have access to mailcatcher. - -In case of you should click on a link in the email, be aware that you should remove the "s" from https. - -How to load fixtures ? (development mode only) -============================================== - -.. code-block:: bash - - # if a container is running - ./docker-php.sh - bin/console doctrine:fixtures:load - # if not - docker-compose run --user $(id -u) php bin/console doctrine:fixtures:load - -How to open a terminal in the project -===================================== - -.. code-block:: bash - - # if a container is running - ./docker-php.sh - # if not - docker-compose run --user $(id -u) php /bin/bash - -How to run cron-jobs ? -====================== - -Some command must be executed in :ref:`cron jobs `. To execute them: - -.. code-block:: bash - - # if a container is running - ./docker-php.sh - bin/console chill:cron-job:execute - # some of them are executed only during the night. So, we have to force the execution during the day: - bin/console chill:cron-job:execute 'name-of-the-cron' - # if not - docker-compose run --user $(id -u) php bin/console chill:cron-job:execute - # some of them are executed only during the night. So, we have to force the execution during the day: - docker-compose run --user $(id -u) php bin/console chill:cron-job:execute 'name-of-the-cron' - -How to run composer ? -===================== - -.. code-block:: bash - - # if a container is running - ./docker-php.sh - composer - # if not - docker-compose run --user $(id -u) php composer - -How to access to PGADMIN ? -========================== - -Pgadmin is installed with docker-compose, and is available **only if you uncomment the appropriate lines into ``docker-compose.override.yml``. - -You can access it at ``http://localhost:8002``. - -Credentials: - -- login: from the variable you set into ``docker-composer.override.yml`` -- password: same :-) - -How to run tests ? -================== - -Tests reside inside the installed bundles. You must `cd` into that directory, download the required packages, and execute them from this place. - -**Note**: some bundle require the fixture to be executed. See the dedicated _how-tos_. - -Exemple, for running unit test inside `main` bundle: - -.. code-block:: bash - - # mount into the php image - ./docker-php.sh - # cd into main directory - cd vendor/chill-project/chill-bundles - # download deps - git submodule init - git submodule update - composer install - # run tests - bin/phpunit src/Bundle/path/to/your/test - -Or for running tests to check code style and php conventions with csfixer and phpstan: - -.. code-block:: bash - - # run code style fixer - bin/grumphp run --tasks=phpcsfixer - # run phpstan - bin/grumphp run --tasks=phpstan - - -.. note:: - - To avoid phpstan block your commits: - - .. code-block:: bash - - git commit -n ... - - To avoid phpstan block your commits permanently: - - .. code-block:: bash - - ./bin/grumphp git:deinit - -How to run webpack interactively -================================ - -Executing :code:`bash docker-node.sh` will open a terminal in a node container, with volumes mounted. - -How to switch the branch for chill-bundles, and get new dependencies -==================================================================== - -During development, you will switch to new branches for chill-bundles. As long as the dependencies are equals, this does not cause any problem. But sometimes, a new branch introduces a new dependency, and you must download it. - -.. warning:: - - Ensure that you have gitlab-token ready before updating your branches. See above. - -In order to do that without pain, use those steps: - -0. Ensuire you have a token, set -1. at the app's root, update the ``composer.json`` to your current branch: - -.. code-block:: json - - { - "require": { - "chill-bundles": "dev-@dev" - } - -2. mount into the php container (``./docker-php.sh``), and run ``composer update`` - -Error `An exception has been thrown during the rendering of a template ("Asset manifest file "/var/www/app/web/build/manifest.json" does not exist.").` on first run -==================================================================================================================================================================== - -Run :code:`make build-assets` - -Running in production -********************* - -Currently, to run this software in production, the *state of the art* is the following : - -1. Run the software locally and tweak the configuration to your needs ; -2. Build the image and store them into a private container registry. This can be done using :code:`make build-and-push-image`. - - To be sure to target the correct container registry, you have to adapt the image names into your ``docker-compose.override.yml`` file. -3. Push the image on your registry, or upload them to the destination machine using ``docker image save`` and ``docker image load``. -3. Run the image on your production server, using docker-compose or eventually docker stack. You have to customize the variable set in docker-compose. - - See also the :ref:`running-production-tips-and-tricks` below. - -.. warning:: - - In production, you **must** set those variables: - - * ``APP_ENV`` to ``prod`` - * ``APP_DEBUG`` to ``false`` - - There are security issues if you keep the same variable than for production. - - -.. _running-production-tips-and-tricks: - -Tips and tricks -=============== - -Operation on database (backups, running custom sql, replication) are easier to set when run outside of a container. If you run into a container, take care of the volume where data are stored. - -The PHP sessions are stored inside redis. This is useful if you distribute the traffic amongst different php server: they will share same sessions if a request goes into a different instance of the container. - -When the PHP servers are shared across multiple instances, take care that some data is stored into redis: the same redis server should be reachable by all instances. - -It is worth having an eye on the configuration of logstash container. - - -Design principles -***************** - -Why the DB URL is also set in environment, and not in .env file ? -================================================================= - -Because, at startup, a script does check the db is up and, if not, wait for a couple of seconds before running ``entrypoint.sh``. For avoiding double configuration, the configuration of the PHP app takes his configuration from environment also (and it will be standard in future releases, with symfony 4.0). - diff --git a/package.json b/package.json index 17c7064a7..05750d5c9 100644 --- a/package.json +++ b/package.json @@ -6,29 +6,33 @@ "@apidevtools/swagger-cli": "^4.0.4", "@babel/core": "^7.20.5", "@babel/preset-env": "^7.20.2", - "@ckeditor/ckeditor5-build-classic": "^35.3.2", - "@ckeditor/ckeditor5-dev-utils": "^31.1.13", + "@ckeditor/ckeditor5-build-classic": "^41.4.2", + "@ckeditor/ckeditor5-dev-utils": "^40.2.0", "@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13", - "@ckeditor/ckeditor5-markdown-gfm": "^35.3.2", - "@ckeditor/ckeditor5-theme-lark": "^35.3.2", - "@ckeditor/ckeditor5-vue": "^4.0.1", + "@ckeditor/ckeditor5-dev-translations": "^40.2.0", + "@ckeditor/ckeditor5-markdown-gfm": "^41.4.2", + "@ckeditor/ckeditor5-theme-lark": "^41.4.2", + "@ckeditor/ckeditor5-vue": "^5.1.0", "@symfony/webpack-encore": "^4.1.0", "@tsconfig/node14": "^1.0.1", + "@types/dompurify": "^3.0.5", "bindings": "^1.5.0", "bootstrap": "5.2.3", "chokidar": "^3.5.1", + "dompurify": "^3.1.0", "fork-awesome": "^1.1.7", "jquery": "^3.6.0", "node-sass": "^8.0.0", + "marked": "^12.0.1", "popper.js": "^1.16.1", "postcss-loader": "^7.0.2", "raw-loader": "^4.0.2", - "sass-loader": "^13.0.0", + "sass-loader": "^14.0.0", "select2": "^4.0.13", "select2-bootstrap-theme": "0.1.0-beta.10", "style-loader": "^3.3.1", "ts-loader": "^9.3.1", - "typescript": "^4.7.2", + "typescript": "^5.4.5", "vue-loader": "^17.0.0", "webpack": "^5.75.0", "webpack-cli": "^5.0.1" @@ -49,12 +53,12 @@ "marked": "^12.0.2", "masonry-layout": "^4.2.2", "mime": "^4.0.0", - "swagger-ui": "^4.15.5", + "pdfjs-dist": "^4.3.136", "vis-network": "^9.1.0", - "vue": "^3.2.37", + "vue": "^3.5.6", "vue-i18n": "^9.1.6", "vue-multiselect": "3.0.0-alpha.2", - "vue-toast-notification": "^2.0", + "vue-toast-notification": "^3.1.2", "vuex": "^4.0.0" }, "browserslist": [ diff --git a/phpstan-baseline-2024-05.neon b/phpstan-baseline-2024-05.neon index 728ec4edc..12cb03856 100644 --- a/phpstan-baseline-2024-05.neon +++ b/phpstan-baseline-2024-05.neon @@ -4,3 +4,11 @@ parameters: message: "#^Parameter \\#1 \\$records of method League\\\\Csv\\\\Writer\\:\\:insertAll\\(\\) expects iterable\\\\>, iterable\\\\> given\\.$#" count: 1 path: src/Bundle/ChillMainBundle/Controller/UserExportController.php + + - + message: """ + #^Fetching deprecated class constant ASC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Ascending instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php diff --git a/phpstan-baseline-deprecations-doctrine-orm.neon b/phpstan-baseline-deprecations-doctrine-orm.neon new file mode 100644 index 000000000..824c0371f --- /dev/null +++ b/phpstan-baseline-deprecations-doctrine-orm.neon @@ -0,0 +1,58 @@ +# See https://github.com/doctrine/orm/issues/11313 for a follow-up +parameters: + ignoreErrors: + - + message: """ + #^Fetching deprecated class constant ASC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Ascending instead$# + """ + count: 1 + path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php + + - + message: """ + #^Fetching deprecated class constant ASC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Ascending instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Entity/Notification.php + + - + message: """ + #^Fetching deprecated class constant DESC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Descending instead$# + """ + count: 1 + path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php + + - + message: """ + #^Fetching deprecated class constant DESC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Descending instead$# + """ + count: 1 + path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php + + - + message: """ + #^Fetching deprecated class constant DESC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Descending instead$# + """ + count: 2 + path: src/Bundle/ChillPersonBundle/Entity/Household/Household.php + + - + message: """ + #^Fetching deprecated class constant DESC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Descending instead$# + """ + count: 2 + path: src/Bundle/ChillPersonBundle/Entity/Person.php + + - + message: """ + #^Fetching deprecated class constant DESC of class Doctrine\\\\Common\\\\Collections\\\\Criteria\\: + use Order\\:\\:Descending instead$# + """ + count: 1 + path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php diff --git a/phpstan-baseline-level-5.neon b/phpstan-baseline-level-5.neon index 23321ba68..34e2825a3 100644 --- a/phpstan-baseline-level-5.neon +++ b/phpstan-baseline-level-5.neon @@ -100,11 +100,6 @@ parameters: count: 1 path: src/Bundle/ChillEventBundle/Controller/EventController.php - - - message: "#^Parameter \\#1 \\$name of method Symfony\\\\Component\\\\Form\\\\FormFactoryInterface\\:\\:createNamedBuilder\\(\\) expects string, null given\\.$#" - count: 1 - path: src/Bundle/ChillEventBundle/Controller/EventController.php - - message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, Chill\\\\MainBundle\\\\Entity\\\\Center given\\.$#" count: 1 @@ -165,11 +160,6 @@ parameters: count: 1 path: src/Bundle/ChillMainBundle/Controller/ExportController.php - - - message: "#^Parameter \\#1 \\$name of method Symfony\\\\Component\\\\Form\\\\FormFactoryInterface\\:\\:createNamedBuilder\\(\\) expects string, null given\\.$#" - count: 1 - path: src/Bundle/ChillMainBundle/Controller/ExportController.php - - message: "#^Parameter \\#3 \\$alias of method Chill\\\\MainBundle\\\\Controller\\\\ExportController\\:\\:exportFormStep\\(\\) expects string, Symfony\\\\Component\\\\HttpFoundation\\\\Request given\\.$#" count: 1 diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a89386f29..641bb5dcd 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5,6 +5,26 @@ parameters: count: 1 path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php + - + message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" + count: 1 + path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php + + - + message: "#^Property Chill\\\\CustomFieldsBundle\\\\Entity\\\\CustomField\\:\\:\\$required \\(false\\) does not accept bool\\.$#" + count: 1 + path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php + + - + message: "#^Parameter \\#1 \\$user of method Chill\\\\DocStoreBundle\\\\Entity\\\\Document\\:\\:setUser\\(\\) expects Chill\\\\MainBundle\\\\Entity\\\\User\\|null, Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\UserInterface\\|null given\\.$#" + count: 2 + path: src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php + + - + message: "#^Parameter \\#1 \\$user of method Chill\\\\DocStoreBundle\\\\Entity\\\\Document\\:\\:setUser\\(\\) expects Chill\\\\MainBundle\\\\Entity\\\\User\\|null, Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\UserInterface\\|null given\\.$#" + count: 2 + path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php + - message: "#^Variable \\$participation might not be defined\\.$#" count: 3 @@ -15,6 +35,106 @@ parameters: count: 1 path: src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php + - + message: "#^Comparison operation \"\\>\" between \\(bool\\|int\\|Redis\\) and 0 results in an error\\.$#" + count: 1 + path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/ApiWrapper.php + + - + message: "#^Variable \\$response might not be defined\\.$#" + count: 1 + path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/ApiWrapper.php + + - + message: "#^Function GuzzleHttp\\\\Psr7\\\\get not found\\.$#" + count: 1 + path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php + + - + message: "#^Function GuzzleHttp\\\\Psr7\\\\str not found\\.$#" + count: 2 + path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php + + - + message: "#^Parameter \\#1 \\$seconds of function sleep expects int, string given\\.$#" + count: 1 + path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Controller/CSPersonController.php + + - + message: "#^Parameter \\#1 \\$interval of method DateTimeImmutable\\:\\:add\\(\\) expects DateInterval, string\\|null given\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Entity/Immersion.php + + - + message: "#^Parameter \\#1 \\$object of static method DateTimeImmutable\\:\\:createFromMutable\\(\\) expects DateTime, DateTimeInterface given\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Entity/Immersion.php + + - + message: "#^Property Chill\\\\JobBundle\\\\Entity\\\\Rome\\\\Metier\\:\\:\\$appellations is never read, only written\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Entity/Rome/Metier.php + + - + message: "#^Method Chill\\\\JobBundle\\\\Export\\\\ListCSPerson\\:\\:splitArrayToColumns\\(\\) never returns Closure so it can be removed from the return type\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php + + - + message: "#^Variable \\$f might not be defined\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php + + - + message: "#^Method Chill\\\\JobBundle\\\\Export\\\\ListFrein\\:\\:splitArrayToColumns\\(\\) never returns Closure so it can be removed from the return type\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Export/ListFrein.php + + - + message: "#^Method Chill\\\\JobBundle\\\\Export\\\\ListProjetProfessionnel\\:\\:splitArrayToColumns\\(\\) never returns Closure so it can be removed from the return type\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Export/ListProjetProfessionnel.php + + - + message: "#^Property Chill\\\\JobBundle\\\\Form\\\\ChoiceLoader\\\\RomeAppellationChoiceLoader\\:\\:\\$appellationRepository \\(Chill\\\\JobBundle\\\\Repository\\\\Rome\\\\AppellationRepository\\) does not accept Doctrine\\\\ORM\\\\EntityRepository\\\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php + + - + message: "#^Result of && is always false\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php + + - + message: "#^Strict comparison using \\=\\=\\= between array\\{\\} and Symfony\\\\Component\\\\Validator\\\\ConstraintViolationListInterface will always evaluate to false\\.$#" + count: 2 + path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php + + - + message: "#^Strict comparison using \\=\\=\\= between null and string will always evaluate to false\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php + + - + message: "#^Variable \\$metier might not be defined\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php + + - + message: "#^Parameter \\#1 \\$interval of method DateTimeImmutable\\:\\:add\\(\\) expects DateInterval, string\\|null given\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Security/Authorization/CSConnectesVoter.php + + - + message: "#^Parameter \\#1 \\$object of static method DateTimeImmutable\\:\\:createFromMutable\\(\\) expects DateTime, DateTimeInterface given\\.$#" + count: 1 + path: src/Bundle/ChillJobBundle/src/Security/Authorization/CSConnectesVoter.php + - message: "#^Cannot unset offset '_token' on array\\{formatter\\: mixed, export\\: mixed, centers\\: mixed, alias\\: string\\}\\.$#" count: 1 @@ -40,11 +160,31 @@ parameters: count: 1 path: src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php + - + message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" + count: 2 + path: src/Bundle/ChillMainBundle/Repository/NotificationRepository.php + + - + message: "#^Parameter \\#1 \\$user of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:userHasAccessForCenter\\(\\) expects Chill\\\\MainBundle\\\\Entity\\\\User, Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\UserInterface given\\.$#" + count: 1 + path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php + + - + message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" + count: 1 + path: src/Bundle/ChillMainBundle/Templating/ChillTwigRoutingHelper.php + - message: "#^Foreach overwrites \\$value with its value variable\\.$#" count: 1 path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php + - + message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" + count: 1 + path: src/Bundle/ChillPersonBundle/Form/PersonType.php + - message: "#^Foreach overwrites \\$value with its value variable\\.$#" count: 1 diff --git a/phpstan-deprecations-sf54.neon b/phpstan-deprecations-sf54.neon new file mode 100644 index 000000000..e2e5e85a6 --- /dev/null +++ b/phpstan-deprecations-sf54.neon @@ -0,0 +1,153 @@ +parameters: + ignoreErrors: + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 2 + path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 3 + path: src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 2 + path: src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php + + - + message: """ + #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Encoder\\\\EncoderFactory\\: + since Symfony 5\\.3, use \\{@link PasswordHasherFactory\\} instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Command/SetPasswordCommand.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Controller/MenuController.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Controller/SearchController.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Controller/UserController.php + + - + message: """ + #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Encoder\\\\EncoderFactory\\: + since Symfony 5\\.3, use \\{@link PasswordHasherFactory\\} instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 2 + path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 3 + path: src/Bundle/ChillMainBundle/Validation/Validator/UserUniqueEmailAndUsername.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 1 + path: src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistencyValidator.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 13 + path: src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 4 + path: src/Bundle/ChillPersonBundle/Controller/PersonController.php + + - + message: """ + #^Call to deprecated method get\\(\\) of class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController\\: + since Symfony 5\\.4, use method or constructor injection in your controller instead$# + """ + count: 7 + path: src/Bundle/ChillReportBundle/Controller/ReportController.php + + - + message: """ + #^Call to deprecated method getUsername\\(\\) of class Chill\\\\MainBundle\\\\Entity\\\\User\\: + since Symfony 5\\.3, use getUserIdentifier\\(\\) instead$# + """ + count: 1 + path: src/Bundle/ChillTaskBundle/Form/SingleTaskListType.php diff --git a/phpstan-deprecations.neon b/phpstan-deprecations.neon index c83feeb59..7f47e9c71 100644 --- a/phpstan-deprecations.neon +++ b/phpstan-deprecations.neon @@ -1,36 +1,5 @@ parameters: ignoreErrors: - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 2 - path: src/Bundle/ChillActivityBundle/Controller/ActivityController.php - - - - message: "#^Call to deprecated method setType\\(\\) of class Chill\\\\ActivityBundle\\\\Entity\\\\Activity\\.$#" - count: 1 - path: src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivity.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: src/Bundle/ChillActivityBundle/Entity/ActivityReason.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillActivityBundle/Form/ActivityType.php - - message: """ @@ -40,201 +9,10 @@ parameters: count: 1 path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php - - - - message: """ - #^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldChoice\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bridge\\\\Twig\\\\TwigEngine\\: - since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$# - """ - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php - - - - message: "#^Used function LogicException not found\\.$#" - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php - - - - message: """ - #^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldDate\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\: - since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$# - """ - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php - - - - message: """ - #^Parameter \\$twigEngine of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldLongChoice\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bridge\\\\Twig\\\\TwigEngine\\: - since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$# - """ - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php - - - - message: """ - #^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldNumber\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\: - since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$# - """ - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php - - - - message: """ - #^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldText\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\: - since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$# - """ - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php - - - - message: """ - #^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldTitle\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\: - since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$# - """ - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldTitle.php - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" count: 1 - path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 6 - path: src/Bundle/ChillEventBundle/Controller/EventController.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillEventBundle/Form/EventType.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillEventBundle/Form/Type/PickEventType.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php - - - - message: """ - #^Parameter \\$role of method Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\CRUDController\\:\\:getReachableCenters\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php - - - - message: """ - #^Call to deprecated method getLanguageBundle\\(\\) of class Symfony\\\\Component\\\\Intl\\\\Intl\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use \\{@see Languages\\} or \\{@see Scripts\\} instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php - - - - message: """ - #^Call to deprecated method getRegionBundle\\(\\) of class Symfony\\\\Component\\\\Intl\\\\Intl\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use \\{@see Countries\\} instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php - - - - message: """ - #^Parameter \\$role of anonymous function has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php - - - - message: """ - #^Call to deprecated method getLanguageBundle\\(\\) of class Symfony\\\\Component\\\\Intl\\\\Intl\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use \\{@see Languages\\} or \\{@see Scripts\\} instead\\.$# - """ - count: 2 - path: src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php - - - - message: """ - #^Return type of method Chill\\\\MainBundle\\\\Entity\\\\User\\:\\:getRoles\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Entity/User.php - - - - message: """ - #^Class Chill\\\\MainBundle\\\\Form\\\\Event\\\\CustomizeFormEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Form/Event/CustomizeFormEvent.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Form/Type/UserPickerType.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 2 - path: src/Bundle/ChillMainBundle/Repository/NotificationRepository.php - - - - message: """ - #^Parameter \\$attribute of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:userHasAccess\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php + path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php - message: """ @@ -244,14 +22,6 @@ parameters: count: 1 path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php - - - message: """ - #^Parameter \\$role of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:getReachableCircles\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php - - message: """ #^Parameter \\$centerResolverDispatcher of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\DefaultVoterHelper\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\: @@ -276,14 +46,6 @@ parameters: count: 1 path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperGenerator.php - - - message: """ - #^Class Chill\\\\MainBundle\\\\Security\\\\PasswordRecover\\\\PasswordRecoverEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php - - message: """ #^Class Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcher implements deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\: @@ -292,35 +54,6 @@ parameters: count: 1 path: src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: src/Bundle/ChillMainBundle/Templating/ChillTwigRoutingHelper.php - - - - message: """ - #^Class Chill\\\\MainBundle\\\\Templating\\\\Events\\\\DelegatedBlockRenderingEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillMainBundle/Templating/Events/DelegatedBlockRenderingEvent.php - - - - message: """ - #^Class Chill\\\\PersonBundle\\\\Actions\\\\ActionEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Actions/ActionEvent.php - - - - message: """ - #^Class Chill\\\\PersonBundle\\\\Controller\\\\AccompanyingCourseController extends deprecated class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\: - since Symfony 4\\.2, use "Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController" instead\\.$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php - - message: """ #^Call to deprecated method getCurrentAccompanyingPeriod\\(\\) of class Chill\\\\PersonBundle\\\\Entity\\\\Person\\: @@ -329,56 +62,10 @@ parameters: count: 1 path: src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php - - - message: """ - #^Class Chill\\\\PersonBundle\\\\Controller\\\\PersonDuplicateController extends deprecated class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\: - since Symfony 4\\.2, use "Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController" instead\\.$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php - - message: "#^Access to deprecated property \\$proxyAccompanyingPeriodOpenState of class Chill\\\\PersonBundle\\\\Entity\\\\Person\\.$#" count: 2 path: src/Bundle/ChillPersonBundle/Entity/Person.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Form/AccompanyingPeriodType.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Form/PersonType.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php - - - - message: """ - #^Class Chill\\\\PersonBundle\\\\Privacy\\\\AccompanyingPeriodPrivacyEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Privacy/AccompanyingPeriodPrivacyEvent.php - - - - message: """ - #^Class Chill\\\\PersonBundle\\\\Privacy\\\\PrivacyEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php - - message: """ #^Parameter \\$centerResolverDispatcher of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriodACLAwareRepository\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\: @@ -387,48 +74,6 @@ parameters: count: 1 path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillPersonBundle/Widget/PersonListWidget.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 3 - path: src/Bundle/ChillReportBundle/Controller/ReportController.php - - - - - message: """ - #^Parameter \\$role of method Chill\\\\ReportBundle\\\\Form\\\\ReportType\\:\\:appendScopeChoices\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillReportBundle/Form/ReportType.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillReportBundle/Search/ReportSearch.php - - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 2 - path: src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php - - message: """ #^Parameter \\$centerResolverDispatcher of method Chill\\\\TaskBundle\\\\Controller\\\\SingleTaskController\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\: @@ -437,46 +82,6 @@ parameters: count: 1 path: src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php - - - message: """ - #^Parameter \\$role of method Chill\\\\TaskBundle\\\\Controller\\\\SingleTaskController\\:\\:setCreateForm\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php - - - - message: """ - #^Class Chill\\\\TaskBundle\\\\Event\\\\TaskEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillTaskBundle/Event/TaskEvent.php - - - - message: """ - #^Class Chill\\\\TaskBundle\\\\Event\\\\UI\\\\UIEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillTaskBundle/Event/UI/UIEvent.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 4 - path: src/Bundle/ChillTaskBundle/Form/SingleTaskListType.php - - - - message: """ - #^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillTaskBundle/Form/SingleTaskType.php - - message: """ #^Parameter \\$centerResolverDispatcher of method Chill\\\\TaskBundle\\\\Form\\\\SingleTaskType\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\: @@ -484,28 +89,3 @@ parameters: """ count: 1 path: src/Bundle/ChillTaskBundle/Form/SingleTaskType.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 1 - path: src/Bundle/ChillTaskBundle/Repository/SingleTaskRepository.php - - - - message: """ - #^Class Chill\\\\TaskBundle\\\\Security\\\\Authorization\\\\AuthorizationEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\: - since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$# - """ - count: 1 - path: src/Bundle/ChillTaskBundle/Security/Authorization/AuthorizationEvent.php - - - - message: """ - #^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\: - since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$# - """ - count: 3 - path: src/Bundle/ChillTaskBundle/Timeline/TaskLifeCycleEventTimelineProvider.php - diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 4e6745469..ec4045858 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -31,5 +31,7 @@ includes: - phpstan-baseline-level-3.neon - phpstan-baseline-level-4.neon - phpstan-baseline-level-5.neon + - phpstan-deprecations-sf54.neon + - phpstan-baseline-deprecations-doctrine-orm.neon - phpstan-baseline-2024-05.neon diff --git a/phpunit.rector.xml b/phpunit.rector.xml index f8d9d3a11..25e0d25aa 100644 --- a/phpunit.rector.xml +++ b/phpunit.rector.xml @@ -1,29 +1,13 @@ - - - - utils/rector/tests - - - - - - utils/rector/src - - + + + + utils/rector/tests + + + + + utils/rector/src + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index aa519e376..336877a0c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,85 +1,73 @@ - - - - - - - - - - - - - - src/Bundle/ChillAsideActivityBundle/src/Tests/ - - - src/Bundle/ChillBudgetBundle/Tests/ - - - src/Bundle/ChillCalendarBundle/Tests/ - - - - src/Bundle/ChillDocGeneratorBundle/tests/ - - - src/Bundle/ChillDocStoreBundle/Tests/ - - + + src/Bundle/ChillDocGeneratorBundle/tests/ + + + src/Bundle/ChillDocStoreBundle/Tests/ + + - - src/Bundle/ChillMainBundle/Tests/ - - - src/Bundle/ChillPersonBundle/Tests/ - - src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingPeriodControllerTest.php - - src/Bundle/ChillPersonBundle/Tests/Controller/PersonAddressControllerTest.php - - src/Bundle/ChillPersonBundle/Tests/Controller/PersonControllerUpdateWithHiddenFieldsTest.php - - src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php - - + src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingPeriodControllerTest.php + + src/Bundle/ChillPersonBundle/Tests/Controller/PersonAddressControllerTest.php + + src/Bundle/ChillPersonBundle/Tests/Controller/PersonControllerUpdateWithHiddenFieldsTest.php + + src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php + + - - - src/Bundle/ChillThirdPartyBundle/Tests - - - src/Bundle/ChillWopiBundle/tests/ - - - - - - - - - + +

Projets professionnels

+ + {% if projet_professionnels|length == 0 %} +

{{ null|chill_print_or_message("Aucun rapport enregistré") }}

+ {% else %} + + + + + + + + + + + {% for pr in projet_professionnels %} + + + + + + + + {% endfor %} + +
Date de créationProjet validé ou souhaitéType de contrat 
{{ pr.reportDate|format_date('short') }} + {% set romes = [] %} + {% if pr.valide|length > 0 %} +

Projet validé :

+ {% set romes = pr.valide %} + {% elseif pr.souhait|length > 0 %} +

Projet souhaité :

+ {% set romes = pr.souhait %} + {% else %} +

Aucun souhait rempli

+ {% endif %} + +
    + {% for a in romes %} +
  • {{ a.libelle }} ({{ a.metier.code }} - {{ a.metier.libelle }})
  • + {% endfor %} +
+
+
    + {% for type in pr.typeContrat %} +
  • {{ ('projet_prof.type_contrat.' ~ type)|trans }}
  • + {% endfor %} +
+
+
    +
  • + +
  • +
  • + +
  • + {% if is_granted('CHILL_JOB_REPORT_DELETE', pr) %} +
  • + +
  • + {% endif %} +
+
+ {% endif %} + + + {% endif %} + + +{% endblock %} diff --git a/src/Bundle/ChillJobBundle/src/Security/Authorization/ExportsJobVoter.php b/src/Bundle/ChillJobBundle/src/Security/Authorization/ExportsJobVoter.php new file mode 100644 index 000000000..af4935893 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/Security/Authorization/ExportsJobVoter.php @@ -0,0 +1,122 @@ +authorizationHelper = $authorizationHelper; + } + + /** + * @return bool + */ + protected function supports($attribute, $subject) + { + if ($subject instanceof Center) { + return self::EXPORT === $attribute; + } + if (null === $subject) { + return self::EXPORT === $attribute; + } + + return false; + } + + /** + * @return bool + */ + protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + { + $user = $token->getUser(); + + if (!$user instanceof User) { + return false; + } + + $centers = $this->authorizationHelper->getReachableCenters($user, $attribute); + + if (null === $subject) { + return count($centers) > 0; + } + + return $this->authorizationHelper->userHasAccess($user, $subject, $attribute); + } + + /** + * Return an array of roles, where keys are the hierarchy, and values + * an array of roles. + * + * Example: + * + * ``` + * [ 'Title' => [ 'CHILL_FOO_SEE', 'CHILL_FOO_UPDATE' ] ] + * ``` + */ + public function getRolesWithHierarchy(): array + { + return ['JobBundle' => $this->getRoles()]; + } + + /** + * return an array of role provided by the object. + * + * @return string[] array of roles (as string) + */ + public function getRoles(): array + { + return $this->getAttributes(); + } + + /** + * return roles which doesn't need. + * + * @return string[] array of roles without scopes + */ + public function getRolesWithoutScope(): array + { + return $this->getAttributes(); + } + + /** + * @return array + */ + private function getAttributes() + { + return [self::EXPORT]; + } +} diff --git a/src/Bundle/ChillJobBundle/src/Security/Authorization/JobVoter.php b/src/Bundle/ChillJobBundle/src/Security/Authorization/JobVoter.php new file mode 100644 index 000000000..54de180f5 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/Security/Authorization/JobVoter.php @@ -0,0 +1,119 @@ +date15DaysAgo = new \DateTime('-15 days'); + $this->authorizationHelper = $authorizationHelper; + } + + protected function supports($attribute, $subject) + { + if (!\in_array($attribute, self::ALL, true)) { + return false; + } + + if ($subject instanceof Frein + || $subject instanceof CV + || $subject instanceof Immersion + || $subject instanceof ProjetProfessionnel + || $subject instanceof Person) { + return true; + } + + return false; + } + + protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + { + if ($subject instanceof Person) { + $center = $subject->getCenter(); + } else { + $center = $subject->getPerson()->getCenter(); + } + + switch ($attribute) { + case self::REPORT_NEW: + return $this->authorizationHelper->userHasAccess($token->getUser(), $center, $attribute); + + case self::REPORT_CV: + if (! ($subject instanceof CV || $subject instanceof Person)) { + return false; + } + + return $this->authorizationHelper->userHasAccess($token->getUser(), $center, $attribute); + + case self::REPORT_DELETE: + if ($subject instanceof Immersion) { + $date = \DateTimeImmutable::createFromMutable($subject->getDebutDate())->add($subject->getDuration()); + } else { + $date = $subject->getReportDate(); + } + + if (!$this->authorizationHelper->userHasAccess($token->getUser(), $center, $attribute)) { + return false; + } + + return $this->date15DaysAgo < $date; + } + + return true; + } + + public function getRoles(): array + { + return self::ALL; + } + + public function getRolesWithHierarchy(): array + { + return ['JobBundle' => $this->getRoles()]; + } + + public function getRolesWithoutScope(): array + { + return $this->getRoles(); + } +} diff --git a/src/Bundle/ChillJobBundle/src/Tests/Controller/CSPersonControllerTest.php b/src/Bundle/ChillJobBundle/src/Tests/Controller/CSPersonControllerTest.php new file mode 100644 index 000000000..a6b19e648 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/Tests/Controller/CSPersonControllerTest.php @@ -0,0 +1,21 @@ +addSql('CREATE SCHEMA chill_job'); + $this->addSql('CREATE SEQUENCE chill_job.cv_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.cv_experience_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.cv_formation_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.frein_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.immersion_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.projet_professionnel_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.rome_appellation_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_job.rome_metier_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_job.cs_person (id INT NOT NULL, person_id INT DEFAULT NULL, prescripteur_id INT DEFAULT NULL, situationLogement VARCHAR(255) DEFAULT NULL, situationLogementPrecision TEXT DEFAULT NULL, enfantACharge INT DEFAULT NULL, niveauMaitriseLangue JSONB DEFAULT NULL, vehiculePersonnel BOOLEAN DEFAULT NULL, permisConduire JSONB DEFAULT NULL, situationProfessionnelle VARCHAR(255) DEFAULT NULL, dateFinDernierEmploi DATE DEFAULT NULL, typeContrat JSONB DEFAULT NULL, typeContratAide TEXT DEFAULT NULL, ressources JSONB DEFAULT NULL, ressourcesComment TEXT DEFAULT NULL, ressourceDate1Versement DATE DEFAULT NULL, CPFMontant NUMERIC(10, 2) DEFAULT NULL, acomptedif NUMERIC(10, 2) DEFAULT NULL, accompagnement JSONB DEFAULT NULL, accompagnementRQTHDate DATE DEFAULT NULL, accompagnementComment VARCHAR(255) DEFAULT NULL, poleEmploiId VARCHAR(255) DEFAULT NULL, poleEmploiInscriptionDate DATE DEFAULT NULL, cafId VARCHAR(255) DEFAULT NULL, cafInscriptionDate DATE DEFAULT NULL, CERInscriptionDate DATE DEFAULT NULL, PPAEInscriptionDate DATE DEFAULT NULL, CERSignataire TEXT DEFAULT NULL, PPAESignataire TEXT DEFAULT NULL, NEETEligibilite VARCHAR(255) DEFAULT NULL, NEETCommissionDate DATE DEFAULT NULL, FSEMaDemarcheCode TEXT DEFAULT NULL, datecontratIEJ DATE DEFAULT NULL, dateavenantIEJ DATE DEFAULT NULL, dispositifs_notes TEXT DEFAULT NULL, handicap BOOLEAN DEFAULT NULL, handicapnotes TEXT DEFAULT NULL, handicapRecommandation VARCHAR(50) DEFAULT NULL, mobilitemoyentransport JSONB DEFAULT NULL, mobilitenotes TEXT DEFAULT NULL, handicapAccompagnement_id INT DEFAULT NULL, documentCV_id INT DEFAULT NULL, documentAgrementIAE_id INT DEFAULT NULL, documentRQTH_id INT DEFAULT NULL, documentAttestationNEET_id INT DEFAULT NULL, documentCI_id INT DEFAULT NULL, documentTitreSejour_id INT DEFAULT NULL, documentAttestationFiscale_id INT DEFAULT NULL, documentPermis_id INT DEFAULT NULL, documentAttestationCAAF_id INT DEFAULT NULL, documentContraTravail_id INT DEFAULT NULL, documentAttestationFormation_id INT DEFAULT NULL, documentQuittanceLoyer_id INT DEFAULT NULL, documentFactureElectricite_id INT DEFAULT NULL, documentAttestationSecuriteSociale_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_10864F31217BBB47 ON chill_job.cs_person (person_id)'); + $this->addSql('CREATE INDEX IDX_10864F312654B57D ON chill_job.cs_person (handicapAccompagnement_id)'); + $this->addSql('CREATE INDEX IDX_10864F3154866550 ON chill_job.cs_person (documentCV_id)'); + $this->addSql('CREATE INDEX IDX_10864F318825E118 ON chill_job.cs_person (documentAgrementIAE_id)'); + $this->addSql('CREATE INDEX IDX_10864F31A396AFAC ON chill_job.cs_person (documentRQTH_id)'); + $this->addSql('CREATE INDEX IDX_10864F3187541764 ON chill_job.cs_person (documentAttestationNEET_id)'); + $this->addSql('CREATE INDEX IDX_10864F315CFC2299 ON chill_job.cs_person (documentCI_id)'); + $this->addSql('CREATE INDEX IDX_10864F3134FDF11D ON chill_job.cs_person (documentTitreSejour_id)'); + $this->addSql('CREATE INDEX IDX_10864F315742C99D ON chill_job.cs_person (documentAttestationFiscale_id)'); + $this->addSql('CREATE INDEX IDX_10864F31166494D4 ON chill_job.cs_person (documentPermis_id)'); + $this->addSql('CREATE INDEX IDX_10864F3172820D66 ON chill_job.cs_person (documentAttestationCAAF_id)'); + $this->addSql('CREATE INDEX IDX_10864F31AFA5E636 ON chill_job.cs_person (documentContraTravail_id)'); + $this->addSql('CREATE INDEX IDX_10864F3161E05C22 ON chill_job.cs_person (documentAttestationFormation_id)'); + $this->addSql('CREATE INDEX IDX_10864F316F744BB0 ON chill_job.cs_person (documentQuittanceLoyer_id)'); + $this->addSql('CREATE INDEX IDX_10864F31AC39B1B ON chill_job.cs_person (documentFactureElectricite_id)'); + $this->addSql('CREATE INDEX IDX_10864F3172A75B6D ON chill_job.cs_person (documentAttestationSecuriteSociale_id)'); + $this->addSql('CREATE INDEX IDX_10864F31D486E642 ON chill_job.cs_person (prescripteur_id)'); + $this->addSql('CREATE TABLE chill_job.cv (id INT NOT NULL, person_id INT DEFAULT NULL, reportDate DATE NOT NULL, formationLevel VARCHAR(255) DEFAULT NULL, formationType VARCHAR(255) DEFAULT NULL, spokenLanguages JSONB DEFAULT NULL, notes TEXT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_3F24F812217BBB47 ON chill_job.cv (person_id)'); + $this->addSql('CREATE TABLE chill_job.cv_experience (id INT NOT NULL, poste TEXT DEFAULT NULL, structure TEXT DEFAULT NULL, startDate DATE DEFAULT NULL, endDate DATE DEFAULT NULL, contratType VARCHAR(100) NOT NULL, notes TEXT DEFAULT NULL, CV_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_102A1262AE1799D8 ON chill_job.cv_experience (CV_id)'); + $this->addSql('CREATE TABLE chill_job.cv_formation (id INT NOT NULL, title TEXT NOT NULL, startDate DATE DEFAULT NULL, endDate DATE DEFAULT NULL, diplomaObtained VARCHAR(255) DEFAULT NULL, diplomaReconnue VARCHAR(50) DEFAULT NULL, organisme TEXT DEFAULT NULL, CV_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_20BE09E2AE1799D8 ON chill_job.cv_formation (CV_id)'); + $this->addSql('CREATE TABLE chill_job.frein (id INT NOT NULL, reportDate DATE NOT NULL, freinsPerso JSONB NOT NULL, notesPerso TEXT NOT NULL, freinsEmploi JSONB NOT NULL, notesEmploi TEXT NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE chill_job.immersion (id INT NOT NULL, entreprise_id INT DEFAULT NULL, referent_id INT DEFAULT NULL, domaineActivite TEXT DEFAULT NULL, tuteurName TEXT DEFAULT NULL, tuteurFonction TEXT DEFAULT NULL, tuteurPhoneNumber TEXT DEFAULT NULL, structureAccName TEXT DEFAULT NULL, structureAccPhonenumber TEXT DEFAULT NULL, structureAccEmail TEXT DEFAULT NULL, posteDescriptif TEXT DEFAULT NULL, posteTitle TEXT DEFAULT NULL, posteLieu TEXT DEFAULT NULL, debutDate DATE DEFAULT NULL, duration INTERVAL DEFAULT NULL, horaire TEXT DEFAULT NULL, objectifs JSONB DEFAULT NULL, objectifsAutre TEXT DEFAULT NULL, is_bilan_fullfilled BOOLEAN DEFAULT false NOT NULL, savoirEtre JSONB DEFAULT NULL, savoirEtreNote TEXT DEFAULT NULL, noteimmersion TEXT, principalesActivites TEXT DEFAULT NULL, competencesAcquises TEXT DEFAULT NULL, competencesADevelopper TEXT DEFAULT NULL, noteBilan TEXT DEFAULT NULL, ponctualite_salarie TEXT DEFAULT NULL, ponctualite_salarie_note TEXT DEFAULT NULL, assiduite TEXT DEFAULT NULL, assiduite_note TEXT DEFAULT NULL, interet_activite TEXT DEFAULT NULL, interet_activite_note TEXT DEFAULT NULL, integre_regle TEXT DEFAULT NULL, integre_regle_note TEXT DEFAULT NULL, esprit_initiative TEXT DEFAULT NULL, esprit_initiative_note TEXT DEFAULT NULL, organisation TEXT DEFAULT NULL, organisation_note TEXT DEFAULT NULL, capacite_travail_equipe TEXT DEFAULT NULL, capacite_travail_equipe_note TEXT DEFAULT NULL, style_vestimentaire TEXT DEFAULT NULL, style_vestimentaire_note TEXT DEFAULT NULL, langage_prof TEXT DEFAULT NULL, langage_prof_note TEXT DEFAULT NULL, applique_consigne TEXT DEFAULT NULL, applique_consigne_note TEXT DEFAULT NULL, respect_hierarchie TEXT DEFAULT NULL, respect_hierarchie_note TEXT DEFAULT NULL, structureAccAddress_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_FBB3CBB4A4AEAFEA ON chill_job.immersion (entreprise_id)'); + $this->addSql('CREATE INDEX IDX_FBB3CBB435E47E35 ON chill_job.immersion (referent_id)'); + $this->addSql('CREATE INDEX IDX_FBB3CBB4B5E04267 ON chill_job.immersion (structureAccAddress_id)'); + $this->addSql('COMMENT ON COLUMN chill_job.immersion.duration IS \'(DC2Type:dateinterval)\''); + $this->addSql('CREATE TABLE chill_job.projet_professionnel (id INT NOT NULL, reportDate DATE NOT NULL, domaineActiviteSouhait TEXT DEFAULT NULL, typeContrat JSONB DEFAULT NULL, typeContratNotes TEXT DEFAULT NULL, volumeHoraire JSONB DEFAULT NULL, volumeHoraireNotes TEXT DEFAULT NULL, idee TEXT DEFAULT NULL, enCoursConstruction TEXT DEFAULT NULL, domaineActiviteValide TEXT DEFAULT NULL, valideNotes TEXT DEFAULT NULL, projetProfessionnelNote TEXT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE chill_job.projetprofessionnel_souhait (projetprofessionnel_id INT NOT NULL, appellation_id INT NOT NULL, PRIMARY KEY(projetprofessionnel_id, appellation_id))'); + $this->addSql('CREATE INDEX IDX_3280B96DB87BF7B5 ON chill_job.projetprofessionnel_souhait (projetprofessionnel_id)'); + $this->addSql('CREATE INDEX IDX_3280B96D7CDE30DD ON chill_job.projetprofessionnel_souhait (appellation_id)'); + $this->addSql('CREATE TABLE chill_job.projetprofessionnel_valide (projetprofessionnel_id INT NOT NULL, appellation_id INT NOT NULL, PRIMARY KEY(projetprofessionnel_id, appellation_id))'); + $this->addSql('CREATE INDEX IDX_E0501BE0B87BF7B5 ON chill_job.projetprofessionnel_valide (projetprofessionnel_id)'); + $this->addSql('CREATE INDEX IDX_E0501BE07CDE30DD ON chill_job.projetprofessionnel_valide (appellation_id)'); + $this->addSql('CREATE TABLE chill_job.rome_appellation (id INT NOT NULL, metier_id INT DEFAULT NULL, code VARCHAR(40) NOT NULL, libelle TEXT NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_D9E9CABC77153098 ON chill_job.rome_appellation (code)'); + $this->addSql('CREATE INDEX IDX_D9E9CABCED16FA20 ON chill_job.rome_appellation (metier_id)'); + $this->addSql('CREATE TABLE chill_job.rome_metier (id INT NOT NULL, libelle TEXT NOT NULL, code VARCHAR(20) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_3274952577153098 ON chill_job.rome_metier (code)'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F31217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F312654B57D FOREIGN KEY (handicapAccompagnement_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F3154866550 FOREIGN KEY (documentCV_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F318825E118 FOREIGN KEY (documentAgrementIAE_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F31A396AFAC FOREIGN KEY (documentRQTH_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F3187541764 FOREIGN KEY (documentAttestationNEET_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F315CFC2299 FOREIGN KEY (documentCI_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F3134FDF11D FOREIGN KEY (documentTitreSejour_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F315742C99D FOREIGN KEY (documentAttestationFiscale_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F31166494D4 FOREIGN KEY (documentPermis_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F3172820D66 FOREIGN KEY (documentAttestationCAAF_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F31AFA5E636 FOREIGN KEY (documentContraTravail_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F3161E05C22 FOREIGN KEY (documentAttestationFormation_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F316F744BB0 FOREIGN KEY (documentQuittanceLoyer_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F31AC39B1B FOREIGN KEY (documentFactureElectricite_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F3172A75B6D FOREIGN KEY (documentAttestationSecuriteSociale_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cs_person ADD CONSTRAINT FK_10864F31D486E642 FOREIGN KEY (prescripteur_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cv ADD CONSTRAINT FK_3F24F812217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cv_experience ADD CONSTRAINT FK_102A1262AE1799D8 FOREIGN KEY (CV_id) REFERENCES chill_job.cv (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.cv_formation ADD CONSTRAINT FK_20BE09E2AE1799D8 FOREIGN KEY (CV_id) REFERENCES chill_job.cv (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.immersion ADD CONSTRAINT FK_FBB3CBB4A4AEAFEA FOREIGN KEY (entreprise_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.immersion ADD CONSTRAINT FK_FBB3CBB435E47E35 FOREIGN KEY (referent_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.immersion ADD CONSTRAINT FK_FBB3CBB4B5E04267 FOREIGN KEY (structureAccAddress_id) REFERENCES chill_main_address (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_souhait ADD CONSTRAINT FK_3280B96DB87BF7B5 FOREIGN KEY (projetprofessionnel_id) REFERENCES chill_job.projet_professionnel (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_souhait ADD CONSTRAINT FK_3280B96D7CDE30DD FOREIGN KEY (appellation_id) REFERENCES chill_job.rome_appellation (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_valide ADD CONSTRAINT FK_E0501BE0B87BF7B5 FOREIGN KEY (projetprofessionnel_id) REFERENCES chill_job.projet_professionnel (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_valide ADD CONSTRAINT FK_E0501BE07CDE30DD FOREIGN KEY (appellation_id) REFERENCES chill_job.rome_appellation (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_job.rome_appellation ADD CONSTRAINT FK_D9E9CABCED16FA20 FOREIGN KEY (metier_id) REFERENCES chill_job.rome_metier (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_job.cv_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.cv_experience_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.cv_formation_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.frein_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.immersion_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.projet_professionnel_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.rome_appellation_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_job.rome_metier_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F31217BBB47'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F312654B57D'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F3154866550'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F318825E118'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F31A396AFAC'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F3187541764'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F315CFC2299'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F3134FDF11D'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F315742C99D'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F31166494D4'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F3172820D66'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F31AFA5E636'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F3161E05C22'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F316F744BB0'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F31AC39B1B'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F3172A75B6D'); + $this->addSql('ALTER TABLE chill_job.cs_person DROP CONSTRAINT FK_10864F31D486E642'); + $this->addSql('ALTER TABLE chill_job.cv DROP CONSTRAINT FK_3F24F812217BBB47'); + $this->addSql('ALTER TABLE chill_job.cv_experience DROP CONSTRAINT FK_102A1262AE1799D8'); + $this->addSql('ALTER TABLE chill_job.cv_formation DROP CONSTRAINT FK_20BE09E2AE1799D8'); + $this->addSql('ALTER TABLE chill_job.immersion DROP CONSTRAINT FK_FBB3CBB4A4AEAFEA'); + $this->addSql('ALTER TABLE chill_job.immersion DROP CONSTRAINT FK_FBB3CBB435E47E35'); + $this->addSql('ALTER TABLE chill_job.immersion DROP CONSTRAINT FK_FBB3CBB4B5E04267'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_souhait DROP CONSTRAINT FK_3280B96DB87BF7B5'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_souhait DROP CONSTRAINT FK_3280B96D7CDE30DD'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_valide DROP CONSTRAINT FK_E0501BE0B87BF7B5'); + $this->addSql('ALTER TABLE chill_job.projetprofessionnel_valide DROP CONSTRAINT FK_E0501BE07CDE30DD'); + $this->addSql('ALTER TABLE chill_job.rome_appellation DROP CONSTRAINT FK_D9E9CABCED16FA20'); + $this->addSql('DROP TABLE chill_job.cs_person'); + $this->addSql('DROP TABLE chill_job.cv'); + $this->addSql('DROP TABLE chill_job.cv_experience'); + $this->addSql('DROP TABLE chill_job.cv_formation'); + $this->addSql('DROP TABLE chill_job.frein'); + $this->addSql('DROP TABLE chill_job.immersion'); + $this->addSql('DROP TABLE chill_job.projet_professionnel'); + $this->addSql('DROP TABLE chill_job.projetprofessionnel_souhait'); + $this->addSql('DROP TABLE chill_job.projetprofessionnel_valide'); + $this->addSql('DROP TABLE chill_job.rome_appellation'); + $this->addSql('DROP TABLE chill_job.rome_metier'); + $this->addSql('DROP SCHEMA chill_job'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/Version20240424140641.php b/src/Bundle/ChillJobBundle/src/migrations/Version20240424140641.php new file mode 100644 index 000000000..87c9d3623 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/Version20240424140641.php @@ -0,0 +1,46 @@ +addSql('ALTER TABLE chill_job.frein ADD person_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_job.frein ADD CONSTRAINT FK_172EAC0A217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_172EAC0A217BBB47 ON chill_job.frein (person_id)'); + $this->addSql('ALTER TABLE chill_job.immersion ADD person_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_job.immersion ADD CONSTRAINT FK_FBB3CBB4217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_FBB3CBB4217BBB47 ON chill_job.immersion (person_id)'); + $this->addSql('ALTER TABLE chill_job.projet_professionnel ADD person_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_job.projet_professionnel ADD CONSTRAINT FK_12E4FFBF217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_12E4FFBF217BBB47 ON chill_job.projet_professionnel (person_id)'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_job.projet_professionnel DROP CONSTRAINT FK_12E4FFBF217BBB47'); + $this->addSql('ALTER TABLE chill_job.projet_professionnel DROP person_id'); + $this->addSql('ALTER TABLE chill_job.immersion DROP CONSTRAINT FK_FBB3CBB4217BBB47'); + $this->addSql('ALTER TABLE chill_job.immersion DROP person_id'); + $this->addSql('ALTER TABLE chill_job.frein DROP CONSTRAINT FK_172EAC0A217BBB47'); + $this->addSql('ALTER TABLE chill_job.frein DROP person_id'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/Version20240429111628.php b/src/Bundle/ChillJobBundle/src/migrations/Version20240429111628.php new file mode 100644 index 000000000..e12318d7c --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/Version20240429111628.php @@ -0,0 +1,41 @@ +addSql('ALTER TABLE chill_job.immersion ALTER tuteurphonenumber TYPE VARCHAR(35)'); + $this->addSql('COMMENT ON COLUMN chill_job.immersion.tuteurPhoneNumber IS \'(DC2Type:phone_number)\''); + + $this->addSql('ALTER TABLE chill_job.immersion ALTER structureAccPhonenumber TYPE VARCHAR(35)'); + $this->addSql('COMMENT ON COLUMN chill_job.immersion.structureAccPhonenumber IS \'(DC2Type:phone_number)\''); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_job.immersion ALTER tuteurPhoneNumber TYPE TEXT'); + $this->addSql('COMMENT ON COLUMN chill_job.immersion.tuteurphonenumber IS NULL'); + + $this->addSql('ALTER TABLE chill_job.immersion ALTER structureAccPhonenumber TYPE TEXT'); + $this->addSql('COMMENT ON COLUMN chill_job.immersion.structureAccPhonenumber IS NULL'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20191119172511.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20191119172511.php new file mode 100644 index 000000000..6dccbec42 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20191119172511.php @@ -0,0 +1,114 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('CREATE SCHEMA chill_csconnectes'); + $this->addSql('CREATE TABLE chill_csconnectes.cs_person ( + id INT NOT NULL, + person_id INT NOT NULL, + prescripteur_id INT DEFAULT NULL, + situationLogement VARCHAR(255) DEFAULT NULL, + enfantACharge INT DEFAULT NULL, + niveauMaitriseLangue JSONB DEFAULT NULL, + vehiculePersonnel BOOLEAN DEFAULT NULL, + permisConduire JSONB DEFAULT NULL, + situationProfessionnelle VARCHAR(255) DEFAULT NULL, + dateFinDernierEmploi DATE DEFAULT NULL, + typeContrat JSONB DEFAULT NULL, + ressources JSONB DEFAULT NULL, + ressourcesComment TEXT DEFAULT NULL, + ressourceDate1Versement DATE DEFAULT NULL, + CPFNombreHeures INT DEFAULT NULL, + accompagnement JSONB DEFAULT NULL, + accompagnementRQTHDate DATE DEFAULT NULL, + accompagnementComment VARCHAR(255) DEFAULT NULL, + poleEmploiId VARCHAR(255) DEFAULT NULL, + poleEmploiInscriptionDate DATE DEFAULT NULL, + cafId VARCHAR(255) DEFAULT NULL, + cafInscriptionDate DATE DEFAULT NULL, + CERInscriptionDate DATE DEFAULT NULL, + PPAEInscriptionDate DATE DEFAULT NULL, + NEETEligibilite BOOLEAN DEFAULT NULL, + NEETCommissionDate DATE DEFAULT NULL, + FSEMaDemarcheCode TEXT DEFAULT NULL, + documentCV_id INT DEFAULT NULL, + documentAgrementIAE_id INT DEFAULT NULL, + documentRQTH_id INT DEFAULT NULL, + documentAttestationNEET_id INT DEFAULT NULL, + documentCI_id INT DEFAULT NULL, + documentTitreSejour_id INT DEFAULT NULL, + documentAttestationFiscale_id INT DEFAULT NULL, + documentPermis_id INT DEFAULT NULL, + documentAttestationCAAF_id INT DEFAULT NULL, + documentContraTravail_id INT DEFAULT NULL, + documentAttestationFormation_id INT DEFAULT NULL, + documentQuittanceLoyer_id INT DEFAULT NULL, + documentFactureElectricite_id INT DEFAULT NULL, + PRIMARY KEY(id, person_id))'); + $this->addSql('CREATE INDEX IDX_10864F31217BBB47 ON chill_csconnectes.cs_person (person_id)'); + $this->addSql('CREATE INDEX IDX_10864F3154866550 ON chill_csconnectes.cs_person (documentCV_id)'); + $this->addSql('CREATE INDEX IDX_10864F318825E118 ON chill_csconnectes.cs_person (documentAgrementIAE_id)'); + $this->addSql('CREATE INDEX IDX_10864F31A396AFAC ON chill_csconnectes.cs_person (documentRQTH_id)'); + $this->addSql('CREATE INDEX IDX_10864F3187541764 ON chill_csconnectes.cs_person (documentAttestationNEET_id)'); + $this->addSql('CREATE INDEX IDX_10864F315CFC2299 ON chill_csconnectes.cs_person (documentCI_id)'); + $this->addSql('CREATE INDEX IDX_10864F3134FDF11D ON chill_csconnectes.cs_person (documentTitreSejour_id)'); + $this->addSql('CREATE INDEX IDX_10864F315742C99D ON chill_csconnectes.cs_person (documentAttestationFiscale_id)'); + $this->addSql('CREATE INDEX IDX_10864F31166494D4 ON chill_csconnectes.cs_person (documentPermis_id)'); + $this->addSql('CREATE INDEX IDX_10864F3172820D66 ON chill_csconnectes.cs_person (documentAttestationCAAF_id)'); + $this->addSql('CREATE INDEX IDX_10864F31AFA5E636 ON chill_csconnectes.cs_person (documentContraTravail_id)'); + $this->addSql('CREATE INDEX IDX_10864F3161E05C22 ON chill_csconnectes.cs_person (documentAttestationFormation_id)'); + $this->addSql('CREATE INDEX IDX_10864F316F744BB0 ON chill_csconnectes.cs_person (documentQuittanceLoyer_id)'); + $this->addSql('CREATE INDEX IDX_10864F31AC39B1B ON chill_csconnectes.cs_person (documentFactureElectricite_id)'); + $this->addSql('CREATE INDEX IDX_10864F31D486E642 ON chill_csconnectes.cs_person (prescripteur_id)'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F31217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F3154866550 FOREIGN KEY (documentCV_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F318825E118 FOREIGN KEY (documentAgrementIAE_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F31A396AFAC FOREIGN KEY (documentRQTH_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F3187541764 FOREIGN KEY (documentAttestationNEET_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F315CFC2299 FOREIGN KEY (documentCI_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F3134FDF11D FOREIGN KEY (documentTitreSejour_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F315742C99D FOREIGN KEY (documentAttestationFiscale_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F31166494D4 FOREIGN KEY (documentPermis_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F3172820D66 FOREIGN KEY (documentAttestationCAAF_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F31AFA5E636 FOREIGN KEY (documentContraTravail_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F3161E05C22 FOREIGN KEY (documentAttestationFormation_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F316F744BB0 FOREIGN KEY (documentQuittanceLoyer_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F31AC39B1B FOREIGN KEY (documentFactureElectricite_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CONSTRAINT FK_10864F31D486E642 FOREIGN KEY (prescripteur_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.niveauMaitriseLangue IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.permisConduire IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.typeContrat IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.ressources IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.accompagnement IS NULL'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('DROP TABLE chill_csconnectes.cs_person'); + $this->addSql('DROP SCHEMA chill_csconnectes CASCADE'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20191129112321.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20191129112321.php new file mode 100644 index 000000000..85ca4e137 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20191129112321.php @@ -0,0 +1,60 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('DROP INDEX chill_csconnectes.IDX_10864f31217bbb47'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD CERSignataire TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD PPAESignataire TEXT DEFAULT NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.niveauMaitriseLangue IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.permisConduire IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.typeContrat IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.ressources IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.accompagnement IS NULL'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_10864F31217BBB47 ON chill_csconnectes.cs_person (person_id)'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person DROP CONSTRAINT cs_person_pkey'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD PRIMARY KEY (id)'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ALTER person_id DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->throwIrreversibleMigrationException('this migration is not reversible (' + .'actions on primary keys)'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('DROP INDEX UNIQ_10864F31217BBB47'); + $this->addSql('DROP INDEX cs_person_pkey'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person DROP CERSignataire'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person DROP PPAESignataire'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ALTER person_id SET NOT NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.niveaumaitriselangue IS \'(DC2Type:json_array)\''); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.permisconduire IS \'(DC2Type:json_array)\''); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.typecontrat IS \'(DC2Type:json_array)\''); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.ressources IS \'(DC2Type:json_array)\''); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.cs_person.accompagnement IS \'(DC2Type:json_array)\''); + $this->addSql('CREATE INDEX idx_10864f31217bbb47 ON chill_csconnectes.cs_person (person_id)'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD PRIMARY KEY (id, person_id)'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200113104411.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200113104411.php new file mode 100644 index 000000000..1fb74f5f0 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200113104411.php @@ -0,0 +1,53 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('CREATE SEQUENCE chill_csconnectes.immersion_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_csconnectes.immersion (id INT NOT NULL, person_id INT DEFAULT NULL, entreprise_id INT DEFAULT NULL, referent_id INT DEFAULT NULL, domaineActivite TEXT DEFAULT NULL, tuteurName TEXT DEFAULT NULL, tuteurFonction TEXT DEFAULT NULL, tuteurPhoneNumber TEXT DEFAULT NULL, structureAccName TEXT DEFAULT NULL, structureAccPhonenumber TEXT DEFAULT NULL, posteDescriptif TEXT DEFAULT NULL, posteTitle TEXT DEFAULT NULL, posteLieu TEXT DEFAULT NULL, debutDate DATE DEFAULT NULL, duration INTERVAL DEFAULT NULL, horaire TEXT DEFAULT NULL, objectifs JSONB DEFAULT NULL, savoirEtre JSONB DEFAULT NULL, noteimmersion TEXT NOT NULL, principalesActivites TEXT DEFAULT NULL, competencesAcquises TEXT DEFAULT NULL, competencesADevelopper TEXT DEFAULT NULL, noteBilan TEXT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_FBB3CBB4217BBB47 ON chill_csconnectes.immersion (person_id)'); + $this->addSql('CREATE INDEX IDX_FBB3CBB4A4AEAFEA ON chill_csconnectes.immersion (entreprise_id)'); + $this->addSql('CREATE INDEX IDX_FBB3CBB435E47E35 ON chill_csconnectes.immersion (referent_id)'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.immersion.duration IS \'(DC2Type:dateinterval)\''); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD CONSTRAINT FK_FBB3CBB4217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD CONSTRAINT FK_FBB3CBB4A4AEAFEA FOREIGN KEY (entreprise_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD CONSTRAINT FK_FBB3CBB435E47E35 FOREIGN KEY (referent_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + $this->addSql('CREATE TABLE chill_csconnectes.cv_formation (id INT NOT NULL, title TEXT NOT NULL, startDate DATE DEFAULT NULL, endDate DATE DEFAULT NULL, diplomaObtained VARCHAR(255) DEFAULT NULL, diplomaReconnue VARCHAR(50) DEFAULT NULL, organisme TEXT DEFAULT NULL, CV_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_20BE09E2AE1799D8 ON chill_csconnectes.cv_formation (CV_id)'); + $this->addSql('ALTER TABLE chill_csconnectes.cv_formation ADD CONSTRAINT FK_20BE09E2AE1799D8 FOREIGN KEY (CV_id) REFERENCES chill_csconnectes.cv (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('DROP SEQUENCE chill_csconnectes.immersion_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_csconnectes.immersion'); + + $this->addSql('DROP SEQUENCE chill_csconnectes.cv_formation_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_csconnectes.cv_formation DROP CONSTRAINT FK_20BE09E2AE1799D8'); + $this->addSql('DROP TABLE chill_csconnectes.cv_formation'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200113142525.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200113142525.php new file mode 100644 index 000000000..cabc97d59 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200113142525.php @@ -0,0 +1,43 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD structureAccEmail TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD structureAccAddress_id INT DEFAULT NULL'); + $this->addSql('CREATE INDEX IDX_FBB3CBB4B5E04267 ON chill_csconnectes.immersion (structureAccAddress_id)'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP structureAccEmail'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP structureAccAddress_id'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200114081435.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200114081435.php new file mode 100644 index 000000000..a03263bf3 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200114081435.php @@ -0,0 +1,44 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD is_bilan_fullfilled BOOLEAN DEFAULT \'false\' NOT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD savoirEtreNote TEXT DEFAULT NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.immersion.savoirEtre IS NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD CONSTRAINT FK_FBB3CBB4B5E04267 FOREIGN KEY (structureAccAddress_id) REFERENCES chill_main_address (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP CONSTRAINT FK_FBB3CBB4B5E04267'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP is_bilan_fullfilled'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP savoirEtreNote'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200124130244.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200124130244.php new file mode 100644 index 000000000..dd1e669ae --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200124130244.php @@ -0,0 +1,36 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD datecontratIEJ DATE DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.cs_person DROP datecontratIEJ'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200124132321.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200124132321.php new file mode 100644 index 000000000..3cf1b3019 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200124132321.php @@ -0,0 +1,36 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD typeContratAide TEXT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.cs_person DROP typeContratAide'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200127132932.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200127132932.php new file mode 100644 index 000000000..2907c2155 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200127132932.php @@ -0,0 +1,36 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD objectifsAutre TEXT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP objectifsAutre'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200205132532.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200205132532.php new file mode 100644 index 000000000..1372aa308 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200205132532.php @@ -0,0 +1,83 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + // $this->addSql('DROP SEQUENCE report_id_seq CASCADE'); + $this->addSql('CREATE SEQUENCE chill_csconnectes.rome_appellation_id_seq ' + .'INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_csconnectes.rome_metier_id_seq ' + .'INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_csconnectes.projet_professionnel_id_seq ' + .'INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_csconnectes.cv_formation_id_seq ' + .'INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_csconnectes.rome_appellation (' + .'id INT NOT NULL, metier_id INT DEFAULT NULL, code VARCHAR(40) NOT NULL, ' + .'libelle TEXT NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_D9E9CABCED16FA20 ON chill_csconnectes.rome_appellation (metier_id)'); + $this->addSql('CREATE TABLE chill_csconnectes.rome_metier (id INT NOT NULL, ' + .'libelle TEXT NOT NULL, code VARCHAR(20) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE chill_csconnectes.projet_professionnel (id INT NOT NULL, ' + .'person_id INT DEFAULT NULL, reportDate DATE NOT NULL, ' + .'typeContrat JSONB DEFAULT NULL, typeContratNotes TEXT DEFAULT NULL, ' + .'volumeHoraire JSONB DEFAULT NULL, volumeHoraireNotes TEXT DEFAULT NULL, ' + .'idee TEXT DEFAULT NULL, enCoursConstruction TEXT DEFAULT NULL, ' + .'valideNotes TEXT DEFAULT NULL, projetProfessionnelNote TEXT DEFAULT NULL, ' + .'PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_12E4FFBF217BBB47 ON chill_csconnectes.projet_professionnel (person_id)'); + $this->addSql('CREATE TABLE chill_csconnectes.projetprofessionnel_souhait (projetprofessionnel_id INT NOT NULL, appellation_id INT NOT NULL, PRIMARY KEY(projetprofessionnel_id, appellation_id))'); + $this->addSql('CREATE INDEX IDX_3280B96DB87BF7B5 ON chill_csconnectes.projetprofessionnel_souhait (projetprofessionnel_id)'); + $this->addSql('CREATE INDEX IDX_3280B96D7CDE30DD ON chill_csconnectes.projetprofessionnel_souhait (appellation_id)'); + $this->addSql('CREATE TABLE chill_csconnectes.projetprofessionnel_valide (projetprofessionnel_id INT NOT NULL, appellation_id INT NOT NULL, PRIMARY KEY(projetprofessionnel_id, appellation_id))'); + $this->addSql('CREATE INDEX IDX_E0501BE0B87BF7B5 ON chill_csconnectes.projetprofessionnel_valide (projetprofessionnel_id)'); + $this->addSql('CREATE INDEX IDX_E0501BE07CDE30DD ON chill_csconnectes.projetprofessionnel_valide (appellation_id)'); + $this->addSql('ALTER TABLE chill_csconnectes.rome_appellation ADD CONSTRAINT FK_D9E9CABCED16FA20 FOREIGN KEY (metier_id) REFERENCES chill_csconnectes.rome_metier (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.projet_professionnel ADD CONSTRAINT FK_12E4FFBF217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_souhait ADD CONSTRAINT FK_3280B96DB87BF7B5 FOREIGN KEY (projetprofessionnel_id) REFERENCES chill_csconnectes.projet_professionnel (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_souhait ADD CONSTRAINT FK_3280B96D7CDE30DD FOREIGN KEY (appellation_id) REFERENCES chill_csconnectes.rome_appellation (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_valide ADD CONSTRAINT FK_E0501BE0B87BF7B5 FOREIGN KEY (projetprofessionnel_id) REFERENCES chill_csconnectes.projet_professionnel (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_valide ADD CONSTRAINT FK_E0501BE07CDE30DD FOREIGN KEY (appellation_id) REFERENCES chill_csconnectes.rome_appellation (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_souhait DROP CONSTRAINT FK_3280B96D7CDE30DD'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_valide DROP CONSTRAINT FK_E0501BE07CDE30DD'); + $this->addSql('ALTER TABLE chill_csconnectes.rome_appellation DROP CONSTRAINT FK_D9E9CABCED16FA20'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_souhait DROP CONSTRAINT FK_3280B96DB87BF7B5'); + $this->addSql('ALTER TABLE chill_csconnectes.projetprofessionnel_valide DROP CONSTRAINT FK_E0501BE0B87BF7B5'); + $this->addSql('DROP SEQUENCE chill_csconnectes.rome_appellation_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_csconnectes.rome_metier_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_csconnectes.projet_professionnel_id_seq CASCADE'); + + $this->addSql('DROP TABLE chill_csconnectes.rome_appellation'); + $this->addSql('DROP TABLE chill_csconnectes.rome_metier'); + $this->addSql('DROP TABLE chill_csconnectes.projet_professionnel'); + $this->addSql('DROP TABLE chill_csconnectes.projetprofessionnel_souhait'); + $this->addSql('DROP TABLE chill_csconnectes.projetprofessionnel_valide'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200207224152.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200207224152.php new file mode 100644 index 000000000..6fecfda82 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200207224152.php @@ -0,0 +1,38 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('CREATE INDEX code_appellation_idx ON chill_csconnectes.rome_appellation (code)'); + $this->addSql('CREATE INDEX code_metier_idx ON chill_csconnectes.rome_metier (code)'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('DROP INDEX code_appellation_idx ON chill_csconnectes.rome_appellation'); + $this->addSql('DROP INDEX code_metier_idx ON chill_csconnectes.rome_metier'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200210105342.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200210105342.php new file mode 100644 index 000000000..53d88ec2b --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200210105342.php @@ -0,0 +1,36 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_D9E9CABC77153098 ON chill_csconnectes.rome_appellation (code);'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_3274952577153098 ON chill_csconnectes.rome_metier (code);'); + $this->addSql('DROP INDEX IF EXISTS chill_csconnectes.code_metier_idx '); + $this->addSql('DROP INDEX IF EXISTS chill_csconnectes.code_appellation_idx '); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP INDEX chill_csconnectes.UNIQ_D9E9CABC77153098'); + $this->addSql('DROP INDEX chill_csconnectes.UNIQ_3274952577153098'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200313124323.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200313124323.php new file mode 100644 index 000000000..1c3ef3be4 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200313124323.php @@ -0,0 +1,87 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + $this->addSql('ALTER TABLE chill_csconnectes.cv_formation ALTER diplomaobtained TYPE VARCHAR(255)'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD ponctualite_salarie TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD ponctualite_salarie_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD assiduite TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD assiduite_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD interet_activite TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD interet_activite_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD integre_regle TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD integre_regle_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD esprit_initiative TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD esprit_initiative_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD organisation TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD organisation_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD capacite_travail_equipe TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD capacite_travail_equipe_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD style_vestimentaire TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD style_vestimentaire_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD langage_prof TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD langage_prof_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD applique_consigne TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD applique_consigne_note TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD respect_hierarchie TEXT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion ADD respect_hierarchie_note TEXT DEFAULT NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.immersion.objectifs IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.immersion.savoirEtre IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.frein.freinsPerso IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.frein.freinsEmploi IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.projet_professionnel.typeContrat IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.projet_professionnel.volumeHoraire IS NULL'); + $this->addSql('COMMENT ON COLUMN chill_3party.third_party.types IS NULL'); + } + + public function down(Schema $schema): void + { + $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP ponctualite_salarie'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP ponctualite_salarie_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP assiduite'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP assiduite_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP interet_activite'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP interet_activite_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP integre_regle'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP integre_regle_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP esprit_initiative'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP esprit_initiative_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP organisation'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP organisation_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP capacite_travail_equipe'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP capacite_travail_equipe_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP style_vestimentaire'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP style_vestimentaire_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP langage_prof'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP langage_prof_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP applique_consigne'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP applique_consigne_note'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP respect_hierarchie'); + $this->addSql('ALTER TABLE chill_csconnectes.immersion DROP respect_hierarchie_note'); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.immersion.objectifs IS \'(DC2Type:json_array)\''); + $this->addSql('COMMENT ON COLUMN chill_csconnectes.immersion.savoiretre IS \'(DC2Type:json_array)\''); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200403114520.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200403114520.php new file mode 100644 index 000000000..ab80c48d7 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200403114520.php @@ -0,0 +1,35 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->addSql('ALTER TABLE chill_csconnectes.projet_professionnel ADD domaineActiviteSouhait TEXT DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_csconnectes.projet_professionnel ADD domaineActiviteValide TEXT DEFAULT NULL;'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_csconnectes.projet_professionnel DROP domaineActiviteSouhait'); + $this->addSql('ALTER TABLE chill_csconnectes.projet_professionnel DROP domaineActiviteValide'); + } +} diff --git a/src/Bundle/ChillJobBundle/src/migrations/old/Version20200403123148.php b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200403123148.php new file mode 100644 index 000000000..307cd14c7 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/migrations/old/Version20200403123148.php @@ -0,0 +1,32 @@ +skipIf(true, 'Skipping this old migration. Replaced by migration Version20240424095147'); + $this->addSql('ALTER TABLE chill_csconnectes.cs_person ADD dateavenantIEJ DATE DEFAULT NULL;'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_csconnectes.cs_person DROP dateavenantIEJ'); + } +} diff --git a/src/Bundle/ChillMainBundle/CRUD/CompilerPass/CRUDControllerCompilerPass.php b/src/Bundle/ChillMainBundle/CRUD/CompilerPass/CRUDControllerCompilerPass.php index c3c7b9dc1..601dc9833 100644 --- a/src/Bundle/ChillMainBundle/CRUD/CompilerPass/CRUDControllerCompilerPass.php +++ b/src/Bundle/ChillMainBundle/CRUD/CompilerPass/CRUDControllerCompilerPass.php @@ -11,6 +11,9 @@ declare(strict_types=1); namespace Chill\MainBundle\CRUD\CompilerPass; +use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\MainBundle\CRUD\Controller\CRUDController; +use Chill\MainBundle\CRUD\Exception\InvalidCrudConfiguration; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -38,6 +41,9 @@ class CRUDControllerCompilerPass implements CompilerPassInterface private function configureCrudController(ContainerBuilder $container, array $crudEntry, string $apiOrCrud): void { $controllerClass = $crudEntry['controller']; + if (ApiController::class === $controllerClass || CRUDController::class === $controllerClass) { + throw InvalidCrudConfiguration::configurationRequiresControllerDefinition($crudEntry['class'], $apiOrCrud); + } $controllerServiceName = 'cs'.$apiOrCrud.'_'.$crudEntry['name'].'_controller'; // create config parameter in container diff --git a/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php b/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php index 9ee0d9e19..ea5e55a69 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php +++ b/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php @@ -18,10 +18,13 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Doctrine\DBAL\LockMode; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\OptimisticLockException; +use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\ConflictHttpException; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; @@ -60,7 +63,7 @@ abstract class AbstractCRUDController extends AbstractController parent::getSubscribedServices(), [ 'chill_main.paginator_factory' => PaginatorFactory::class, - + ManagerRegistry::class => ManagerRegistry::class, 'translator' => TranslatorInterface::class, AuthorizationHelper::class => AuthorizationHelper::class, EventDispatcherInterface::class => EventDispatcherInterface::class, @@ -95,7 +98,7 @@ abstract class AbstractCRUDController extends AbstractController */ protected function buildQueryEntities(string $action, Request $request) { - $qb = $this->getDoctrine()->getManager() + $qb = $this->getManagerRegistry()->getManager() ->createQueryBuilder() ->select('e') ->from($this->getEntityClass(), 'e'); @@ -116,7 +119,7 @@ abstract class AbstractCRUDController extends AbstractController * * @param mixed|null $entity * - * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedHttpException + * @throws AccessDeniedHttpException */ protected function checkACL(string $action, Request $request, string $_format, $entity = null) { @@ -145,9 +148,7 @@ abstract class AbstractCRUDController extends AbstractController return new $class(); } - protected function customizeQuery(string $action, Request $request, $query): void - { - } + protected function customizeQuery(string $action, Request $request, $query): void {} protected function getActionConfig(string $action) { @@ -169,8 +170,7 @@ abstract class AbstractCRUDController extends AbstractController */ protected function getEntity(mixed $action, string $id, Request $request): object { - $e = $this - ->getDoctrine() + $e = $this->getManagerRegistry() ->getRepository($this->getEntityClass()) ->find($id); @@ -181,7 +181,7 @@ abstract class AbstractCRUDController extends AbstractController $expectedVersion = $request->query->getInt('entity_version'); try { - $manager = $this->getDoctrine()->getManagerForClass($this->getEntityClass()); + $manager = $this->getManagerRegistry()->getManagerForClass($this->getEntityClass()); if ($manager instanceof EntityManagerInterface) { $manager->lock($e, LockMode::OPTIMISTIC, $expectedVersion); @@ -211,6 +211,11 @@ abstract class AbstractCRUDController extends AbstractController return $this->container->get('chill_main.paginator_factory'); } + protected function getManagerRegistry(): ManagerRegistry + { + return $this->container->get(ManagerRegistry::class); + } + /** * Get the result of the query. */ diff --git a/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php b/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php index a6675424e..6533da243 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php +++ b/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php @@ -80,8 +80,8 @@ class ApiController extends AbstractCRUDController return $response; } - $this->getDoctrine()->getManager()->remove($entity); - $this->getDoctrine()->getManager()->flush(); + $this->getManagerRegistry()->getManager()->remove($entity); + $this->getManagerRegistry()->getManager()->flush(); $response = $this->onAfterFlush($action, $request, $_format, $entity, $errors); @@ -153,7 +153,7 @@ class ApiController extends AbstractCRUDController return $response; } - $this->getDoctrine()->getManagerForClass($this->getEntityClass())->flush(); + $this->getManagerRegistry()->getManagerForClass($this->getEntityClass())->flush(); $response = $this->onAfterFlush($action, $request, $_format, $entity, $errors); @@ -269,10 +269,10 @@ class ApiController extends AbstractCRUDController } if ($forcePersist && Request::METHOD_POST === $request->getMethod()) { - $this->getDoctrine()->getManager()->persist($postedData); + $this->getManagerRegistry()->getManager()->persist($postedData); } - $this->getDoctrine()->getManager()->flush(); + $this->getManagerRegistry()->getManager()->flush(); $response = $this->onAfterFlush($action, $request, $_format, $entity, $errors, [$postedData]); @@ -373,7 +373,7 @@ class ApiController extends AbstractCRUDController try { $entity = $this->deserialize($action, $request, $_format, $entity); } catch (NotEncodableValueException $e) { - throw new BadRequestHttpException('invalid json', 400, $e); + throw new BadRequestHttpException('invalid json', $e, 400); } $errors = $this->validate($action, $request, $_format, $entity); @@ -403,8 +403,8 @@ class ApiController extends AbstractCRUDController return $response; } - $this->getDoctrine()->getManager()->persist($entity); - $this->getDoctrine()->getManager()->flush(); + $this->getManagerRegistry()->getManager()->persist($entity); + $this->getManagerRegistry()->getManager()->flush(); $response = $this->onAfterFlush($action, $request, $_format, $entity, $errors); diff --git a/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php b/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php index 951b7b875..19e9014da 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php +++ b/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php @@ -19,16 +19,40 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Templating\Listing\FilterOrderHelper; use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface; use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Contracts\Translation\TranslatorInterface; +/** + * The CRUDController class is an abstract class that provides basic CRUD (Create, Read, Update, Delete) functionality for entities in a Symfony application. It extends the Abstract + *Controller class. + * + * For the class \Chill\MainBundle\CRUD\Controller\CRUDController, the dependency injection system does not work as in + * the usual way, where dependencies are provided via the constructor method. Instead, it utilizes the capabilities + * provided by the \Symfony\Contracts\Service\ServiceSubscriberInterface. + * + * The \Symfony\Contracts\Service\ServiceSubscriberInterface is an interface that is used by objects needing explicit + * service references. It means this class has a direct dependency on the Symfony service container, allowing it to + * request specific services it needs for execution. + * + * By implementing the ServiceSubscriberInterface, this class effectively defines a method called getSubscribedServices, + * which returns an array mapping service IDs to their classes or interfaces. Symfony's service container uses this + * method to preconfigure the services required, optimizing the dependency injection process. + * + * This model can be used to keep the class itself concise by preventing the need to define a constructor and inject + * services through method calls. This approach also allows for more flexible service usage, as services can be fetched + * as and when required, rather than all services being loaded whether they are used or not. This makes for a more + * efficient and maintainable solution especially when dealing with larger services. + * + * For more details about how this works, you can refer to Symfony's Documentation + * on Service Subscribers & Service Locators: https://symfony.com/doc/current/service_container/service_subscribers_locators.html + */ class CRUDController extends AbstractController { /** @@ -78,6 +102,7 @@ class CRUDController extends AbstractController Resolver::class => Resolver::class, SerializerInterface::class => SerializerInterface::class, FilterOrderHelperFactoryInterface::class => FilterOrderHelperFactoryInterface::class, + ManagerRegistry::class => ManagerRegistry::class, ] ); } @@ -150,8 +175,7 @@ class CRUDController extends AbstractController */ protected function buildQueryEntities(string $action, Request $request) { - $query = $this - ->getDoctrine() + $query = $this->getManagerRegistry() ->getManager() ->createQueryBuilder() ->select('e') @@ -224,13 +248,9 @@ class CRUDController extends AbstractController /** * Customize the form created by createFormFor. */ - protected function customizeForm(string $action, FormInterface $form) - { - } + protected function customizeForm(string $action, FormInterface $form) {} - protected function customizeQuery(string $action, Request $request, $query): void - { - } + protected function customizeQuery(string $action, Request $request, $query): void {} /** * @param null $formClass @@ -269,7 +289,7 @@ class CRUDController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $this->onFormValid($action, $entity, $form, $request); - $em = $this->getDoctrine()->getManager(); + $em = $this->getManagerRegistry()->getManager(); $this->onPreRemove($action, $entity, $form, $request); $this->removeEntity($action, $entity, $form, $request); @@ -314,7 +334,7 @@ class CRUDController extends AbstractController $id = $request->query->get('duplicate_id', 0); $originalEntity = $this->getEntity($action, $id, $request); - $this->getDoctrine()->getManager() + $this->getManagerRegistry()->getManager() ->detach($originalEntity); return $originalEntity; @@ -386,7 +406,7 @@ class CRUDController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $this->onFormValid($action, $entity, $form, $request); - $em = $this->getDoctrine()->getManager(); + $em = $this->getManagerRegistry()->getManager(); $this->onPrePersist($action, $entity, $form, $request); $em->persist($entity); @@ -489,7 +509,7 @@ class CRUDController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $this->onFormValid($action, $entity, $form, $request); - $em = $this->getDoctrine()->getManager(); + $em = $this->getManagerRegistry()->getManager(); $this->onPreFlush($action, $entity, $form, $request); $em->flush(); @@ -603,7 +623,7 @@ class CRUDController extends AbstractController */ protected function getEntity(mixed $action, $id, Request $request): ?object { - return $this->getDoctrine() + return $this->getManagerRegistry() ->getRepository($this->getEntityClass()) ->find($id); } @@ -652,6 +672,11 @@ class CRUDController extends AbstractController return $this->container->get('chill_main.paginator_factory'); } + protected function getManagerRegistry(): ManagerRegistry + { + return $this->container->get(ManagerRegistry::class); + } + /** * Get the result of the query. */ @@ -843,9 +868,7 @@ class CRUDController extends AbstractController }; } - protected function onFormValid(string $action, object $entity, FormInterface $form, Request $request) - { - } + protected function onFormValid(string $action, object $entity, FormInterface $form, Request $request) {} protected function onPostCheckACL($action, Request $request, $entity): ?Response { @@ -857,58 +880,36 @@ class CRUDController extends AbstractController return null; } - protected function onPostFlush(string $action, $entity, FormInterface $form, Request $request) - { - } + protected function onPostFlush(string $action, $entity, FormInterface $form, Request $request) {} /** * method used by indexAction. */ - protected function onPostIndexBuildQuery(string $action, Request $request, int $totalItems, PaginatorInterface $paginator, mixed $query) - { - } + protected function onPostIndexBuildQuery(string $action, Request $request, int $totalItems, PaginatorInterface $paginator, mixed $query) {} /** * method used by indexAction. */ - protected function onPostIndexFetchQuery(string $action, Request $request, int $totalItems, PaginatorInterface $paginator, mixed $entities) - { - } + protected function onPostIndexFetchQuery(string $action, Request $request, int $totalItems, PaginatorInterface $paginator, mixed $entities) {} - protected function onPostPersist(string $action, $entity, FormInterface $form, Request $request) - { - } + protected function onPostPersist(string $action, $entity, FormInterface $form, Request $request) {} - protected function onPostRemove(string $action, $entity, FormInterface $form, Request $request) - { - } + protected function onPostRemove(string $action, $entity, FormInterface $form, Request $request) {} - protected function onPreDelete(string $action, Request $request) - { - } + protected function onPreDelete(string $action, Request $request) {} - protected function onPreFlush(string $action, $entity, FormInterface $form, Request $request) - { - } + protected function onPreFlush(string $action, $entity, FormInterface $form, Request $request) {} - protected function onPreIndex(string $action, Request $request) - { - } + protected function onPreIndex(string $action, Request $request) {} /** * method used by indexAction. */ - protected function onPreIndexBuildQuery(string $action, Request $request, int $totalItems, PaginatorInterface $paginator) - { - } + protected function onPreIndexBuildQuery(string $action, Request $request, int $totalItems, PaginatorInterface $paginator) {} - protected function onPrePersist(string $action, $entity, FormInterface $form, Request $request) - { - } + protected function onPrePersist(string $action, $entity, FormInterface $form, Request $request) {} - protected function onPreRemove(string $action, $entity, FormInterface $form, Request $request) - { - } + protected function onPreRemove(string $action, $entity, FormInterface $form, Request $request) {} /** * Add ordering fields in the query build by self::queryEntities. @@ -945,7 +946,7 @@ class CRUDController extends AbstractController protected function removeEntity(string $action, $entity, FormInterface $form, Request $request) { - $this->getDoctrine() + $this->getManagerRegistry() ->getManager() ->remove($entity); } diff --git a/src/Bundle/ChillMainBundle/CRUD/Exception/InvalidCrudConfiguration.php b/src/Bundle/ChillMainBundle/CRUD/Exception/InvalidCrudConfiguration.php new file mode 100644 index 000000000..350eced43 --- /dev/null +++ b/src/Bundle/ChillMainBundle/CRUD/Exception/InvalidCrudConfiguration.php @@ -0,0 +1,25 @@ + $controller.':'.($action['controller_action'] ?? $controllerAction), + '_controller' => $controller.'::'.($action['controller_action'] ?? $controllerAction), ]; // path are rewritten diff --git a/src/Bundle/ChillMainBundle/ChillMainBundle.php b/src/Bundle/ChillMainBundle/ChillMainBundle.php index b7cf4e289..ff721784a 100644 --- a/src/Bundle/ChillMainBundle/ChillMainBundle.php +++ b/src/Bundle/ChillMainBundle/ChillMainBundle.php @@ -22,7 +22,6 @@ use Chill\MainBundle\DependencyInjection\CompilerPass\ShortMessageCompilerPass; use Chill\MainBundle\DependencyInjection\CompilerPass\TimelineCompilerClass; use Chill\MainBundle\DependencyInjection\CompilerPass\WidgetsCompilerPass; use Chill\MainBundle\DependencyInjection\ConfigConsistencyCompilerPass; -use Chill\MainBundle\DependencyInjection\RoleProvidersCompilerPass; use Chill\MainBundle\Notification\NotificationHandlerInterface; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\MainBundle\Search\SearchApiInterface; @@ -44,8 +43,6 @@ class ChillMainBundle extends Bundle $container->registerForAutoconfiguration(LocalMenuBuilderInterface::class) ->addTag('chill.menu_builder'); - $container->registerForAutoconfiguration(ProvideRoleInterface::class) - ->addTag('chill.role'); $container->registerForAutoconfiguration(CenterResolverInterface::class) ->addTag('chill_main.center_resolver'); $container->registerForAutoconfiguration(ScopeResolverInterface::class) @@ -64,11 +61,12 @@ class ChillMainBundle extends Bundle ->addTag('chill_main.cron_job'); $container->registerForAutoconfiguration(ViewEntityInfoProviderInterface::class) ->addTag('chill_main.entity_info_provider'); + $container->registerForAutoconfiguration(ProvideRoleInterface::class) + ->addTag('chill_main.provide_role'); $container->addCompilerPass(new SearchableServicesCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new ConfigConsistencyCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new TimelineCompilerClass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); - $container->addCompilerPass(new RoleProvidersCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new ExportsCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new WidgetsCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new NotificationCounterCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); diff --git a/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php b/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php index cb984c100..44a86cb24 100644 --- a/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php +++ b/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php @@ -27,12 +27,12 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; class ChillImportUsersCommand extends Command { + protected static $defaultDescription = 'Import users from csv file'; /** * Centers and aliases. * @@ -55,7 +55,7 @@ class ChillImportUsersCommand extends Command public function __construct( protected EntityManagerInterface $em, protected LoggerInterface $logger, - protected UserPasswordEncoderInterface $passwordEncoder, + protected \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface $passwordEncoder, protected ValidatorInterface $validator, protected UserRepository $userRepository, ) { @@ -86,7 +86,6 @@ class ChillImportUsersCommand extends Command protected function configure() { $this - ->setDescription('Import users from csv file') ->setHelp("Import users from a csv file. Users are added to centers contained in the file. Headers are used to detect columns. Adding to multiple centers can be done by using a `grouping centers` file, which will group multiple centers into a signle alias, used in 'centers' column.") ->addArgument('csvfile', InputArgument::REQUIRED, 'Path to the csv file. Columns are: `username`, `email`, `center` (can contain alias), `permission group`') ->addOption('grouping-centers', null, InputOption::VALUE_OPTIONAL, 'Path to a csv file to aggregate multiple centers into a single alias') @@ -130,7 +129,7 @@ class ChillImportUsersCommand extends Command ->setEmail(\trim((string) $data['email'])) ->setUsername(\trim((string) $data['username'])) ->setEnabled(true) - ->setPassword($this->passwordEncoder->encodePassword( + ->setPassword($this->passwordEncoder->hashPassword( $user, \bin2hex(\random_bytes(32)) )); @@ -207,7 +206,7 @@ class ChillImportUsersCommand extends Command throw $e; } - return 0; + return Command::SUCCESS; } /** diff --git a/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php b/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php index b6aa1596f..c4d835dbd 100644 --- a/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php +++ b/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php @@ -29,6 +29,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; */ class ChillUserSendRenewPasswordCodeCommand extends Command { + protected static $defaultDescription = 'Send a message with code to recover password'; /** * @var EntityManagerInterface */ @@ -82,7 +83,6 @@ class ChillUserSendRenewPasswordCodeCommand extends Command { $this ->setName('chill:user:send-password-recover-code') - ->setDescription('Send a message with code to recover password') ->addArgument('csvfile', InputArgument::REQUIRED, 'CSV file with the list of users') ->addOption('template', null, InputOption::VALUE_REQUIRED, 'Template for email') ->addOption('expiration', null, InputOption::VALUE_REQUIRED, 'Expiration of the link, as an unix timestamp') @@ -108,7 +108,7 @@ class ChillUserSendRenewPasswordCodeCommand extends Command $this->sendRecoverCode($user); } - return 0; + return Command::SUCCESS; } /** diff --git a/src/Bundle/ChillMainBundle/Command/ExecuteCronJobCommand.php b/src/Bundle/ChillMainBundle/Command/ExecuteCronJobCommand.php index c3b5919d7..1dc56314b 100644 --- a/src/Bundle/ChillMainBundle/Command/ExecuteCronJobCommand.php +++ b/src/Bundle/ChillMainBundle/Command/ExecuteCronJobCommand.php @@ -19,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface; class ExecuteCronJobCommand extends Command { + protected static $defaultDescription = 'Execute the cronjob(s) given as argument, or one cronjob scheduled by system.'; + public function __construct( private readonly CronManagerInterface $cronManager, ) { @@ -28,7 +30,6 @@ class ExecuteCronJobCommand extends Command protected function configure() { $this - ->setDescription('Execute the cronjob(s) given as argument, or one cronjob scheduled by system.') ->setHelp("If no job is specified, the next available cronjob will be executed by system.\nThis command should be execute every 15 minutes (more or less)") ->addArgument('job', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'one or more job to force execute (by default, all jobs are executed)', []) ->addUsage(''); @@ -39,13 +40,13 @@ class ExecuteCronJobCommand extends Command if ([] === $input->getArgument('job')) { $this->cronManager->run(); - return 0; + return Command::SUCCESS; } foreach ($input->getArgument('job') as $jobName) { $this->cronManager->run($jobName); } - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadAddressesBEFromBestAddressCommand.php b/src/Bundle/ChillMainBundle/Command/LoadAddressesBEFromBestAddressCommand.php index cbcba6ea4..dfe485f04 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadAddressesBEFromBestAddressCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadAddressesBEFromBestAddressCommand.php @@ -20,6 +20,8 @@ use Symfony\Component\Console\Output\OutputInterface; class LoadAddressesBEFromBestAddressCommand extends Command { + protected static $defaultDescription = 'Import BE addresses from BeST Address (see https://osoc19.github.io/best/)'; + public function __construct( private readonly AddressReferenceBEFromBestAddress $addressImporter, private readonly PostalCodeBEFromBestAddress $postalCodeBEFromBestAddressImporter, @@ -32,8 +34,7 @@ class LoadAddressesBEFromBestAddressCommand extends Command $this ->setName('chill:main:address-ref-from-best-addresses') ->addArgument('lang', InputArgument::REQUIRED, "Language code, for example 'fr'") - ->addArgument('list', InputArgument::IS_ARRAY, "The list to add, for example 'full', or 'extract' (dev) or '1xxx' (brussel CP)") - ->setDescription('Import BE addresses from BeST Address (see https://osoc19.github.io/best/)'); + ->addArgument('list', InputArgument::IS_ARRAY, "The list to add, for example 'full', or 'extract' (dev) or '1xxx' (brussel CP)"); } protected function execute(InputInterface $input, OutputInterface $output): int @@ -42,6 +43,6 @@ class LoadAddressesBEFromBestAddressCommand extends Command $this->addressImporter->import($input->getArgument('lang'), $input->getArgument('list')); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadAddressesFRFromBANOCommand.php b/src/Bundle/ChillMainBundle/Command/LoadAddressesFRFromBANOCommand.php index 89a159fc4..2bfc3be5c 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadAddressesFRFromBANOCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadAddressesFRFromBANOCommand.php @@ -19,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface; class LoadAddressesFRFromBANOCommand extends Command { + protected static $defaultDescription = 'Import FR addresses from bano (see https://bano.openstreetmap.fr'; + public function __construct(private readonly AddressReferenceFromBano $addressReferenceFromBano) { parent::__construct(); @@ -27,8 +29,7 @@ class LoadAddressesFRFromBANOCommand extends Command protected function configure() { $this->setName('chill:main:address-ref-from-bano') - ->addArgument('departementNo', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'a list of departement numbers') - ->setDescription('Import FR addresses from bano (see https://bano.openstreetmap.fr'); + ->addArgument('departementNo', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'a list of departement numbers'); } protected function execute(InputInterface $input, OutputInterface $output): int @@ -39,6 +40,6 @@ class LoadAddressesFRFromBANOCommand extends Command $this->addressReferenceFromBano->import($departementNo); } - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadAddressesLUFromBDAddressCommand.php b/src/Bundle/ChillMainBundle/Command/LoadAddressesLUFromBDAddressCommand.php index 499751c7c..2477a486d 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadAddressesLUFromBDAddressCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadAddressesLUFromBDAddressCommand.php @@ -35,6 +35,6 @@ class LoadAddressesLUFromBDAddressCommand extends Command { $this->addressImporter->import(); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php b/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php index e4b3ae673..376df4e52 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php @@ -54,8 +54,6 @@ class LoadAndUpdateLanguagesCommand extends Command { $this ->setName('chill:main:languages:populate') - ->setDescription('Load or update languages in db. This command does not delete existing '. - 'languages, but will update names according to available languages') ->addOption( self::INCLUDE_REGIONAL_VERSION, null, @@ -122,6 +120,6 @@ class LoadAndUpdateLanguagesCommand extends Command $em->flush(); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php b/src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php index b6a9be75c..3f7f82523 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php @@ -55,9 +55,7 @@ class LoadCountriesCommand extends Command */ protected function configure() { - $this->setName('chill:main:countries:populate') - ->setDescription('Load or update countries in db. This command does not delete existing countries, '. - 'but will update names according to available languages'); + $this->setName('chill:main:countries:populate'); } /** @@ -83,6 +81,6 @@ class LoadCountriesCommand extends Command $em->flush(); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadPostalCodeFR.php b/src/Bundle/ChillMainBundle/Command/LoadPostalCodeFR.php index be29cad9f..eb0bef879 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadPostalCodeFR.php +++ b/src/Bundle/ChillMainBundle/Command/LoadPostalCodeFR.php @@ -18,6 +18,8 @@ use Symfony\Component\Console\Output\OutputInterface; class LoadPostalCodeFR extends Command { + protected static $defaultDescription = 'Load France\'s postal code from online open data'; + public function __construct(private readonly PostalCodeFRFromOpenData $loader) { parent::__construct(); @@ -25,14 +27,13 @@ class LoadPostalCodeFR extends Command public function configure(): void { - $this->setName('chill:main:postal-code:load:FR') - ->setDescription('Load France\'s postal code from online open data'); + $this->setName('chill:main:postal-code:load:FR'); } public function execute(InputInterface $input, OutputInterface $output): int { $this->loader->import(); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php b/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php index fe11f8b9f..4f0896114 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php @@ -25,6 +25,8 @@ use Symfony\Component\Validator\Validator\ValidatorInterface; class LoadPostalCodesCommand extends Command { + protected static $defaultDescription = 'Add the postal code from a csv file.'; + public function __construct(private readonly EntityManagerInterface $entityManager, private readonly ValidatorInterface $validator) { parent::__construct(); @@ -33,7 +35,6 @@ class LoadPostalCodesCommand extends Command protected function configure() { $this->setName('chill:main:postal-code:populate') - ->setDescription('Add the postal code from a csv file.') ->setHelp('This script will try to avoid existing postal code ' ."using the postal code and name. \n" .'The CSV file must have the following columns: ' @@ -101,7 +102,7 @@ class LoadPostalCodesCommand extends Command $output->writeln(''.$num.' were added !'); - return 0; + return Command::SUCCESS; } private function addPostalCode($row, OutputInterface $output) @@ -194,14 +195,8 @@ class LoadPostalCodesCommand extends Command } } -class ExistingPostalCodeException extends \Exception -{ -} +class ExistingPostalCodeException extends \Exception {} -class CountryCodeNotFoundException extends \Exception -{ -} +class CountryCodeNotFoundException extends \Exception {} -class PostalCodeNotValidException extends \Exception -{ -} +class PostalCodeNotValidException extends \Exception {} diff --git a/src/Bundle/ChillMainBundle/Command/SetPasswordCommand.php b/src/Bundle/ChillMainBundle/Command/SetPasswordCommand.php index a83663ed0..6924b8049 100644 --- a/src/Bundle/ChillMainBundle/Command/SetPasswordCommand.php +++ b/src/Bundle/ChillMainBundle/Command/SetPasswordCommand.php @@ -18,13 +18,14 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactory; -use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; /** * Class SetPasswordCommand. */ class SetPasswordCommand extends Command { + protected static $defaultDescription = 'set a password to user'; + /** * SetPasswordCommand constructor. */ @@ -42,7 +43,7 @@ class SetPasswordCommand extends Command public function _setPassword(User $user, $password) { - $defaultEncoder = new MessageDigestPasswordEncoder('sha512', true, 5000); + $defaultEncoder = new \Symfony\Component\PasswordHasher\Hasher\MessageDigestPasswordHasher('sha512', true, 5000); $encoders = [ User::class => $defaultEncoder, ]; @@ -56,7 +57,6 @@ class SetPasswordCommand extends Command public function configure() { $this->setName('chill:user:set_password') - ->setDescription('set a password to user') ->addArgument('username', InputArgument::REQUIRED, 'the user\'s ' .'username you want to change password') ->addArgument('password', InputArgument::OPTIONAL, 'the new password'); @@ -80,6 +80,6 @@ class SetPasswordCommand extends Command $this->_setPassword($user, $password); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Command/SynchronizeEntityInfoViewsCommand.php b/src/Bundle/ChillMainBundle/Command/SynchronizeEntityInfoViewsCommand.php index 71bee0e0e..16a90dbe8 100644 --- a/src/Bundle/ChillMainBundle/Command/SynchronizeEntityInfoViewsCommand.php +++ b/src/Bundle/ChillMainBundle/Command/SynchronizeEntityInfoViewsCommand.php @@ -18,22 +18,20 @@ use Symfony\Component\Console\Output\OutputInterface; class SynchronizeEntityInfoViewsCommand extends Command { + protected static $defaultDescription = 'Update or create sql views which provide info for various entities'; + public function __construct( private readonly ViewEntityInfoManager $viewEntityInfoManager, ) { parent::__construct('chill:db:sync-views'); } - protected function configure(): void - { - $this - ->setDescription('Update or create sql views which provide info for various entities'); - } + protected function configure(): void {} protected function execute(InputInterface $input, OutputInterface $output): int { $this->viewEntityInfoManager->synchronizeOnDB(); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillMainBundle/Controller/AbsenceController.php b/src/Bundle/ChillMainBundle/Controller/AbsenceController.php index 809b7b901..3961c9f3a 100644 --- a/src/Bundle/ChillMainBundle/Controller/AbsenceController.php +++ b/src/Bundle/ChillMainBundle/Controller/AbsenceController.php @@ -12,28 +12,25 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; use Chill\MainBundle\Form\AbsenceType; +use Chill\MainBundle\Security\ChillSecurity; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; class AbsenceController extends AbstractController { - /** - * @Route( - * "/{_locale}/absence", - * name="chill_main_user_absence_index", - * methods={"GET", "POST"} - * ) - */ + public function __construct(private readonly ChillSecurity $security, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} + + #[Route(path: '/{_locale}/absence', name: 'chill_main_user_absence_index', methods: ['GET', 'POST'])] public function setAbsence(Request $request) { - $user = $this->getUser(); + $user = $this->security->getUser(); $form = $this->createForm(AbsenceType::class, $user); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->flush(); return $this->redirectToRoute('chill_main_user_absence_index'); @@ -45,19 +42,13 @@ class AbsenceController extends AbstractController ]); } - /** - * @Route( - * "/{_locale}/absence/unset", - * name="chill_main_user_absence_unset", - * methods={"GET", "POST"} - * ) - */ + #[Route(path: '/{_locale}/absence/unset', name: 'chill_main_user_absence_unset', methods: ['GET', 'POST'])] public function unsetAbsence(Request $request) { - $user = $this->getUser(); + $user = $this->security->getUser(); $user->setAbsenceStart(null); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->flush(); return $this->redirectToRoute('chill_main_user_absence_index'); diff --git a/src/Bundle/ChillMainBundle/Controller/AddressApiController.php b/src/Bundle/ChillMainBundle/Controller/AddressApiController.php index 6bc952923..5ea68cdbc 100644 --- a/src/Bundle/ChillMainBundle/Controller/AddressApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/AddressApiController.php @@ -20,18 +20,18 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; class AddressApiController extends ApiController { + public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} + /** * Duplicate an existing address. - * - * @Route("/api/1.0/main/address/{id}/duplicate.json", name="chill_api_main_address_duplicate", - * methods={"POST"}) */ + #[Route(path: '/api/1.0/main/address/{id}/duplicate.json', name: 'chill_api_main_address_duplicate', methods: ['POST'])] public function duplicate(Address $address): JsonResponse { $this->denyAccessUnlessGranted('ROLE_USER'); $new = Address::createFromAddress($address); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->persist($new); $em->flush(); diff --git a/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php b/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php index edc58bed5..e50cea6bb 100644 --- a/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php +++ b/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php @@ -26,13 +26,9 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; final class AddressReferenceAPIController extends ApiController { - public function __construct(private readonly AddressReferenceRepository $addressReferenceRepository, private readonly PaginatorFactory $paginatorFactory) - { - } + public function __construct(private readonly AddressReferenceRepository $addressReferenceRepository, private readonly PaginatorFactory $paginatorFactory) {} - /** - * @Route("/api/1.0/main/address-reference/by-postal-code/{id}/search.json") - */ + #[Route(path: '/api/1.0/main/address-reference/by-postal-code/{id}/search.json')] public function search(PostalCode $postalCode, Request $request): JsonResponse { $this->denyAccessUnlessGranted('ROLE_USER'); diff --git a/src/Bundle/ChillMainBundle/Controller/AddressToReferenceMatcherController.php b/src/Bundle/ChillMainBundle/Controller/AddressToReferenceMatcherController.php index 079f4783b..680a63859 100644 --- a/src/Bundle/ChillMainBundle/Controller/AddressToReferenceMatcherController.php +++ b/src/Bundle/ChillMainBundle/Controller/AddressToReferenceMatcherController.php @@ -23,13 +23,9 @@ use Symfony\Component\Serializer\SerializerInterface; class AddressToReferenceMatcherController { - public function __construct(private readonly Security $security, private readonly EntityManagerInterface $entityManager, private readonly SerializerInterface $serializer) - { - } + public function __construct(private readonly Security $security, private readonly EntityManagerInterface $entityManager, private readonly SerializerInterface $serializer) {} - /** - * @Route("/api/1.0/main/address/reference-match/{id}/set/reviewed", methods={"POST"}) - */ + #[Route(path: '/api/1.0/main/address/reference-match/{id}/set/reviewed', methods: ['POST'])] public function markAddressAsReviewed(Address $address): JsonResponse { if (!$this->security->isGranted('ROLE_USER')) { @@ -50,9 +46,8 @@ class AddressToReferenceMatcherController /** * Set an address back to "to review". Only if the address is in "reviewed" state. - * - * @Route("/api/1.0/main/address/reference-match/{id}/set/to_review", methods={"POST"}) */ + #[Route(path: '/api/1.0/main/address/reference-match/{id}/set/to_review', methods: ['POST'])] public function markAddressAsToReview(Address $address): JsonResponse { if (!$this->security->isGranted('ROLE_USER')) { @@ -75,9 +70,7 @@ class AddressToReferenceMatcherController ); } - /** - * @Route("/api/1.0/main/address/reference-match/{id}/sync-with-reference", methods={"POST"}) - */ + #[Route(path: '/api/1.0/main/address/reference-match/{id}/sync-with-reference', methods: ['POST'])] public function syncAddressWithReference(Address $address): JsonResponse { if (null === $address->getAddressReference()) { diff --git a/src/Bundle/ChillMainBundle/Controller/AdminController.php b/src/Bundle/ChillMainBundle/Controller/AdminController.php index 46fbfb351..abdfb679d 100644 --- a/src/Bundle/ChillMainBundle/Controller/AdminController.php +++ b/src/Bundle/ChillMainBundle/Controller/AdminController.php @@ -16,41 +16,31 @@ use Symfony\Component\Routing\Annotation\Route; class AdminController extends AbstractController { - /** - * @Route("/{_locale}/admin", name="chill_main_admin_central") - */ + #[Route(path: '/{_locale}/admin', name: 'chill_main_admin_central')] public function indexAction() { return $this->render('@ChillMain/Admin/index.html.twig'); } - /** - * @Route("/{_locale}/admin/language", name="chill_main_language_admin") - */ + #[Route(path: '/{_locale}/admin/language', name: 'chill_main_language_admin')] public function indexLanguageAction() { return $this->render('@ChillMain/Admin/indexLanguage.html.twig'); } - /** - * @Route("/{_locale}/admin/location", name="chill_main_location_admin") - */ + #[Route(path: '/{_locale}/admin/location', name: 'chill_main_location_admin')] public function indexLocationAction() { return $this->render('@ChillMain/Admin/indexLocation.html.twig'); } - /** - * @Route("/{_locale}/admin/user", name="chill_main_user_admin") - */ + #[Route(path: '/{_locale}/admin/user', name: 'chill_main_user_admin')] public function indexUserAction() { return $this->render('@ChillMain/Admin/indexUser.html.twig'); } - /** - * @Route("/{_locale}/admin/dashboard", name="chill_main_dashboard_admin") - */ + #[Route(path: '/{_locale}/admin/dashboard', name: 'chill_main_dashboard_admin')] public function indexDashboardAction() { return $this->render('@ChillMain/Admin/indexDashboard.html.twig'); diff --git a/src/Bundle/ChillMainBundle/Controller/CountryApiController.php b/src/Bundle/ChillMainBundle/Controller/CountryApiController.php new file mode 100644 index 000000000..12e5258fd --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/CountryApiController.php @@ -0,0 +1,16 @@ +isGranted('ROLE_ADMIN')) { @@ -30,9 +28,7 @@ class DefaultController extends AbstractController return $this->render('@ChillMain/layout.html.twig'); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/homepage", name="chill_main_homepage_without_locale") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/homepage', name: 'chill_main_homepage_without_locale')] public function indexWithoutLocaleAction() { return $this->redirectToRoute('chill_main_homepage'); diff --git a/src/Bundle/ChillMainBundle/Controller/ExportController.php b/src/Bundle/ChillMainBundle/Controller/ExportController.php index 2df7008d6..08b89e4bb 100644 --- a/src/Bundle/ChillMainBundle/Controller/ExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/ExportController.php @@ -65,9 +65,7 @@ class ExportController extends AbstractController $this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/exports/download/{alias}", name="chill_main_export_download", methods={"GET"}) - */ + #[Route(path: '/{_locale}/exports/download/{alias}', name: 'chill_main_export_download', methods: ['GET'])] public function downloadResultAction(Request $request, mixed $alias) { /** @var ExportManager $exportManager */ @@ -107,12 +105,9 @@ class ExportController extends AbstractController * This action must work with GET queries. * * @param string $alias - * - * @return Response - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/exports/generate/{alias}", name="chill_main_export_generate", methods={"GET"}) */ - public function generateAction(Request $request, $alias) + #[Route(path: '/{_locale}/exports/generate/{alias}', name: 'chill_main_export_generate', methods: ['GET'])] + public function generateAction(Request $request, $alias): Response { /** @var ExportManager $exportManager */ $exportManager = $this->exportManager; @@ -130,10 +125,9 @@ class ExportController extends AbstractController } /** - * @Route("/{_locale}/exports/generate-from-saved/{id}", name="chill_main_export_generate_from_saved") - * * @throws \RedisException */ + #[Route(path: '/{_locale}/exports/generate-from-saved/{id}', name: 'chill_main_export_generate_from_saved')] public function generateFromSavedExport(SavedExport $savedExport): RedirectResponse { $this->denyAccessUnlessGranted(SavedExportVoter::GENERATE, $savedExport); @@ -154,9 +148,8 @@ class ExportController extends AbstractController /** * Render the list of available exports. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/exports/", name="chill_main_export_index") */ + #[Route(path: '/{_locale}/exports/', name: 'chill_main_export_index')] public function indexAction(): Response { $exportManager = $this->exportManager; @@ -179,9 +172,8 @@ class ExportController extends AbstractController * stored in the session (if valid), and then a redirection is done to next step. * 3. 'generate': gather data from session from the previous steps, and * make a redirection to the "generate" action with data in query (HTTP GET) - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/exports/new/{alias}", name="chill_main_export_new") */ + #[Route(path: '/{_locale}/exports/new/{alias}', name: 'chill_main_export_new')] public function newAction(Request $request, string $alias): Response { // first check for ACL @@ -205,9 +197,7 @@ class ExportController extends AbstractController }; } - /** - * @Route("/{_locale}/export/saved/update-from-key/{id}/{key}", name="chill_main_export_saved_edit_options_from_key") - */ + #[Route(path: '/{_locale}/export/saved/update-from-key/{id}/{key}', name: 'chill_main_export_saved_edit_options_from_key')] public function editSavedExportOptionsFromKey(SavedExport $savedExport, string $key): Response { $this->denyAccessUnlessGranted('ROLE_USER'); @@ -227,9 +217,7 @@ class ExportController extends AbstractController return $this->redirectToRoute('chill_main_export_saved_edit', ['id' => $savedExport->getId()]); } - /** - * @Route("/{_locale}/export/save-from-key/{alias}/{key}", name="chill_main_export_save_from_key") - */ + #[Route(path: '/{_locale}/export/save-from-key/{alias}/{key}', name: 'chill_main_export_save_from_key')] public function saveFromKey(string $alias, string $key, Request $request): Response { $this->denyAccessUnlessGranted('ROLE_USER'); @@ -300,7 +288,7 @@ class ExportController extends AbstractController $builder = $this->formFactory ->createNamedBuilder( - null, + '', FormType::class, $defaultFormData, [ @@ -644,7 +632,7 @@ class ExportController extends AbstractController } } - private function rebuildRawData(string $key): array + private function rebuildRawData(?string $key): array { if (null === $key) { throw $this->createNotFoundException('key does not exists'); diff --git a/src/Bundle/ChillMainBundle/Controller/GeographicalUnitApiController.php b/src/Bundle/ChillMainBundle/Controller/GeographicalUnitApiController.php new file mode 100644 index 000000000..19a1da160 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/GeographicalUnitApiController.php @@ -0,0 +1,16 @@ + 'json'])] public function getGeographicalUnitCoveringAddress(Address $address): JsonResponse { if (!$this->security->isGranted('ROLE_USER')) { diff --git a/src/Bundle/ChillMainBundle/Controller/LocationTypeController.php b/src/Bundle/ChillMainBundle/Controller/LocationTypeController.php index bc28f9d12..418f49578 100644 --- a/src/Bundle/ChillMainBundle/Controller/LocationTypeController.php +++ b/src/Bundle/ChillMainBundle/Controller/LocationTypeController.php @@ -13,6 +13,4 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\CRUD\Controller\CRUDController; -class LocationTypeController extends CRUDController -{ -} +class LocationTypeController extends CRUDController {} diff --git a/src/Bundle/ChillMainBundle/Controller/LoginController.php b/src/Bundle/ChillMainBundle/Controller/LoginController.php index e04f478a8..ca4717728 100644 --- a/src/Bundle/ChillMainBundle/Controller/LoginController.php +++ b/src/Bundle/ChillMainBundle/Controller/LoginController.php @@ -33,12 +33,9 @@ class LoginController extends AbstractController /** * Show a login form. - * - * @return Response - * - * @\Symfony\Component\Routing\Annotation\Route(path="/login", name="login") */ - public function loginAction(Request $request) + #[\Symfony\Component\Routing\Annotation\Route(path: '/login', name: 'login')] + public function loginAction(Request $request): Response { return $this->render('@ChillMain/Login/login.html.twig', [ 'last_username' => $this->helper->getLastUsername(), @@ -46,7 +43,5 @@ class LoginController extends AbstractController ]); } - public function LoginCheckAction(Request $request) - { - } + public function LoginCheckAction(Request $request) {} } diff --git a/src/Bundle/ChillMainBundle/Controller/NewsItemApiController.php b/src/Bundle/ChillMainBundle/Controller/NewsItemApiController.php index b40d3bc95..e122b7a3b 100644 --- a/src/Bundle/ChillMainBundle/Controller/NewsItemApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/NewsItemApiController.php @@ -25,14 +25,12 @@ class NewsItemApiController private readonly NewsItemRepository $newsItemRepository, private readonly SerializerInterface $serializer, private readonly PaginatorFactory $paginatorFactory, - ) { - } + ) {} /** * Get list of news items filtered on start and end date. - * - * @Route("/api/1.0/main/news/current.json", methods={"get"}) */ + #[Route(path: '/api/1.0/main/news/current.json', methods: ['get'])] public function listCurrentNewsItems(): JsonResponse { $total = $this->newsItemRepository->countCurrentNews(); diff --git a/src/Bundle/ChillMainBundle/Controller/NewsItemHistoryController.php b/src/Bundle/ChillMainBundle/Controller/NewsItemHistoryController.php index cf1f4922b..78b7077ee 100644 --- a/src/Bundle/ChillMainBundle/Controller/NewsItemHistoryController.php +++ b/src/Bundle/ChillMainBundle/Controller/NewsItemHistoryController.php @@ -28,12 +28,9 @@ final readonly class NewsItemHistoryController private readonly PaginatorFactory $paginatorFactory, private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory, private readonly Environment $environment, - ) { - } + ) {} - /** - * @Route("/{_locale}/news-items/history", name="chill_main_news_items_history") - */ + #[Route(path: '/{_locale}/news-items/history', name: 'chill_main_news_items_history')] public function list(): Response { $filter = $this->buildFilterOrder(); @@ -49,9 +46,7 @@ final readonly class NewsItemHistoryController ])); } - /** - * @Route("/{_locale}/news-items/{id}", name="chill_main_single_news_item") - */ + #[Route(path: '/{_locale}/news-items/{id}', name: 'chill_main_single_news_item')] public function showSingleItem(NewsItem $newsItem, Request $request): Response { return new Response($this->environment->render( diff --git a/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php b/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php index 61459f4d8..1c086cdf2 100644 --- a/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php @@ -26,34 +26,24 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\SerializerInterface; -/** - * @Route("/api/1.0/main/notification") - */ +#[Route(path: '/api/1.0/main/notification')] class NotificationApiController { - public function __construct(private readonly EntityManagerInterface $entityManager, private readonly NotificationRepository $notificationRepository, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly SerializerInterface $serializer) - { - } + public function __construct(private readonly EntityManagerInterface $entityManager, private readonly NotificationRepository $notificationRepository, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly SerializerInterface $serializer) {} - /** - * @Route("/{id}/mark/read", name="chill_api_main_notification_mark_read", methods={"POST"}) - */ + #[Route(path: '/{id}/mark/read', name: 'chill_api_main_notification_mark_read', methods: ['POST'])] public function markAsRead(Notification $notification): JsonResponse { return $this->markAs('read', $notification); } - /** - * @Route("/{id}/mark/unread", name="chill_api_main_notification_mark_unread", methods={"POST"}) - */ + #[Route(path: '/{id}/mark/unread', name: 'chill_api_main_notification_mark_unread', methods: ['POST'])] public function markAsUnread(Notification $notification): JsonResponse { return $this->markAs('unread', $notification); } - /** - * @Route("/my/unread") - */ + #[Route(path: '/my/unread')] public function myUnreadNotifications(Request $request): JsonResponse { $total = $this->notificationRepository->countUnreadByUser($this->security->getUser()); diff --git a/src/Bundle/ChillMainBundle/Controller/NotificationController.php b/src/Bundle/ChillMainBundle/Controller/NotificationController.php index f9ae1be02..7ca6a3465 100644 --- a/src/Bundle/ChillMainBundle/Controller/NotificationController.php +++ b/src/Bundle/ChillMainBundle/Controller/NotificationController.php @@ -13,7 +13,6 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\Entity\Notification; use Chill\MainBundle\Entity\NotificationComment; -use Chill\MainBundle\Entity\User; use Chill\MainBundle\Form\NotificationCommentType; use Chill\MainBundle\Form\NotificationType; use Chill\MainBundle\Notification\Exception\NotificationHandlerNotFound; @@ -22,6 +21,7 @@ use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Repository\NotificationRepository; use Chill\MainBundle\Repository\UserRepository; use Chill\MainBundle\Security\Authorization\NotificationVoter; +use Chill\MainBundle\Security\ChillSecurity; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -32,30 +32,19 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; use function in_array; -/** - * @Route("/{_locale}/notification") - */ +#[Route(path: '/{_locale}/notification')] class NotificationController extends AbstractController { - public function __construct(private readonly EntityManagerInterface $em, private readonly LoggerInterface $chillLogger, private readonly LoggerInterface $logger, private readonly Security $security, private readonly NotificationRepository $notificationRepository, private readonly NotificationHandlerManager $notificationHandlerManager, private readonly PaginatorFactory $paginatorFactory, private readonly TranslatorInterface $translator, private readonly UserRepository $userRepository) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly LoggerInterface $chillLogger, private readonly LoggerInterface $logger, private readonly ChillSecurity $security, private readonly NotificationRepository $notificationRepository, private readonly NotificationHandlerManager $notificationHandlerManager, private readonly PaginatorFactory $paginatorFactory, private readonly TranslatorInterface $translator, private readonly UserRepository $userRepository, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} - /** - * @Route("/create", name="chill_main_notification_create") - */ + #[Route(path: '/create', name: 'chill_main_notification_create')] public function createAction(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - if (!$this->security->getUser() instanceof User) { - throw new AccessDeniedHttpException('You must be authenticated and a user to create a notification'); - } - if (!$request->query->has('entityClass')) { throw new BadRequestHttpException('Missing entityClass parameter'); } @@ -70,13 +59,13 @@ class NotificationController extends AbstractController ->setRelatedEntityId($request->query->getInt('entityId')) ->setSender($this->security->getUser()); - if ($request->query->has('tos')) { - foreach ($request->query->get('tos') as $toId) { - if (null === $to = $this->userRepository->find($toId)) { - throw new NotFoundHttpException("user with id {$toId} is not found"); - } - $notification->addAddressee($to); + $tos = $request->query->all('tos'); + + foreach ($tos as $toId) { + if (null === $to = $this->userRepository->find($toId)) { + throw new NotFoundHttpException("user with id {$toId} is not found"); } + $notification->addAddressee($to); } try { @@ -109,9 +98,7 @@ class NotificationController extends AbstractController ]); } - /** - * @Route("/{id}/edit", name="chill_main_notification_edit") - */ + #[Route(path: '/{id}/edit', name: 'chill_main_notification_edit')] public function editAction(Notification $notification, Request $request): Response { $this->denyAccessUnlessGranted(NotificationVoter::NOTIFICATION_UPDATE, $notification); @@ -139,17 +126,11 @@ class NotificationController extends AbstractController ]); } - /** - * @Route("/{id}/access_key", name="chill_main_notification_grant_access_by_access_key") - */ + #[Route(path: '/{id}/access_key', name: 'chill_main_notification_grant_access_by_access_key')] public function getAccessByAccessKey(Notification $notification, Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - if (!$this->security->getUser() instanceof User) { - throw new AccessDeniedHttpException('You must be authenticated and a user to create a notification'); - } - foreach (['accessKey'/* , 'email' */] as $param) { if (!$request->query->has($param)) { throw new BadRequestHttpException("Missing {$param} parameter"); @@ -170,7 +151,7 @@ class NotificationController extends AbstractController $notification->addAddressee($this->security->getUser()); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $logMsg = '[Notification] a user is granted access to notification trough an access key'; $context = [ @@ -185,18 +166,12 @@ class NotificationController extends AbstractController return $this->redirectToRoute('chill_main_notification_show', ['id' => $notification->getId()]); } - /** - * @Route("/inbox", name="chill_main_notification_my") - */ + #[Route(path: '/inbox', name: 'chill_main_notification_my')] public function inboxAction(): Response { - $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); + $this->denyAccessUnlessGranted('ROLE_USER'); $currentUser = $this->security->getUser(); - if (!$currentUser instanceof User) { - throw new AccessDeniedHttpException('Only regular user should access this page'); - } - $notificationsNbr = $this->notificationRepository->countAllForAttendee($currentUser); $paginator = $this->paginatorFactory->create($notificationsNbr); @@ -215,9 +190,7 @@ class NotificationController extends AbstractController ]); } - /** - * @Route("/sent", name="chill_main_notification_sent") - */ + #[Route(path: '/sent', name: 'chill_main_notification_sent')] public function sentAction(): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); @@ -241,9 +214,7 @@ class NotificationController extends AbstractController ]); } - /** - * @Route("/{id}/show", name="chill_main_notification_show") - */ + #[Route(path: '/{id}/show', name: 'chill_main_notification_show')] public function showAction(Notification $notification, Request $request): Response { $this->denyAccessUnlessGranted(NotificationVoter::NOTIFICATION_SEE, $notification); @@ -314,8 +285,8 @@ class NotificationController extends AbstractController ]); // we mark the notification as read after having computed the response - if ($this->getUser() instanceof User && !$notification->isReadBy($this->getUser())) { - $notification->markAsReadBy($this->getUser()); + if (!$notification->isReadBy($this->security->getUser())) { + $notification->markAsReadBy($this->security->getUser()); $this->em->flush(); } diff --git a/src/Bundle/ChillMainBundle/Controller/PasswordController.php b/src/Bundle/ChillMainBundle/Controller/PasswordController.php index 8d9bf9c74..958f66fd1 100644 --- a/src/Bundle/ChillMainBundle/Controller/PasswordController.php +++ b/src/Bundle/ChillMainBundle/Controller/PasswordController.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Form\UserPasswordType; +use Chill\MainBundle\Security\ChillSecurity; use Chill\MainBundle\Security\PasswordRecover\PasswordRecoverEvent; use Chill\MainBundle\Security\PasswordRecover\PasswordRecoverVoter; use Chill\MainBundle\Security\PasswordRecover\RecoverPasswordHelper; @@ -24,8 +25,8 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Contracts\Translation\TranslatorInterface; @@ -33,70 +34,23 @@ use Symfony\Contracts\Translation\TranslatorInterface; /** * Class PasswordController. */ -class PasswordController extends AbstractController +final class PasswordController extends AbstractController { - /** - * @var LoggerInterface - */ - protected $chillLogger; - - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; - - /** - * @var UserPasswordEncoderInterface - */ - protected $passwordEncoder; - - /** - * @var RecoverPasswordHelper - */ - protected $recoverPasswordHelper; - - /** - * @var TokenManager - */ - protected $tokenManager; - - /** - * @var TranslatorInterface - */ - protected $translator; - /** * PasswordController constructor. */ - public function __construct( - LoggerInterface $chillLogger, - UserPasswordEncoderInterface $passwordEncoder, - RecoverPasswordHelper $recoverPasswordHelper, - TokenManager $tokenManager, - TranslatorInterface $translator, - EventDispatcherInterface $eventDispatcher, - ) { - $this->chillLogger = $chillLogger; - $this->passwordEncoder = $passwordEncoder; - $this->translator = $translator; - $this->tokenManager = $tokenManager; - $this->recoverPasswordHelper = $recoverPasswordHelper; - $this->eventDispatcher = $eventDispatcher; - } + public function __construct(private readonly LoggerInterface $chillLogger, private readonly \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface $passwordEncoder, private readonly RecoverPasswordHelper $recoverPasswordHelper, private readonly TokenManager $tokenManager, private readonly TranslatorInterface $translator, private readonly EventDispatcherInterface $eventDispatcher, private readonly ChillSecurity $security, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} /** * @return Response - * - * @\Symfony\Component\Routing\Annotation\Route(path="/public/{_locale}/password/request-changed", name="password_request_recover_changed") */ + #[Route(path: '/public/{_locale}/password/request-changed', name: 'password_request_recover_changed')] public function changeConfirmedAction() { return $this->render('@ChillMain/Password/recover_password_changed.html.twig'); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/public/{_locale}/password/recover", name="password_recover") - */ + #[Route(path: '/public/{_locale}/password/recover', name: 'password_recover')] public function recoverAction(Request $request): Response|\Symfony\Component\HttpFoundation\RedirectResponse { if (false === $this->isGranted(PasswordRecoverVoter::ASK_TOKEN)) { @@ -110,7 +64,7 @@ class PasswordController extends AbstractController $hash = $query->getAlnum(TokenManager::HASH); $token = $query->getAlnum(TokenManager::TOKEN); $timestamp = $query->getAlnum(TokenManager::TIMESTAMP); - $user = $this->getDoctrine()->getRepository(User::class) + $user = $this->managerRegistry->getRepository(User::class) ->findOneByUsernameCanonical($username); if (null === $user) { @@ -138,7 +92,7 @@ class PasswordController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $password = $form->get('new_password')->getData(); - $user->setPassword($this->passwordEncoder->encodePassword($user, $password)); + $user->setPassword($this->passwordEncoder->hashPassword($user, $password)); // logging for prod $this ->chillLogger @@ -149,7 +103,7 @@ class PasswordController extends AbstractController ] ); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->redirectToRoute('password_request_recover_changed'); } @@ -162,9 +116,8 @@ class PasswordController extends AbstractController /** * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException - * - * @\Symfony\Component\Routing\Annotation\Route(path="/public/{_locale}/password/request-recover", name="password_request_recover") */ + #[Route(path: '/public/{_locale}/password/request-recover', name: 'password_request_recover')] public function requestRecoverAction(Request $request): Response|\Symfony\Component\HttpFoundation\RedirectResponse { if (false === $this->isGranted(PasswordRecoverVoter::ASK_TOKEN)) { @@ -179,7 +132,7 @@ class PasswordController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { /** @var \Doctrine\ORM\QueryBuilder $qb */ - $qb = $this->getDoctrine()->getManager() + $qb = $this->managerRegistry->getManager() ->createQueryBuilder(); $qb->select('u') ->from(User::class, 'u') @@ -235,9 +188,8 @@ class PasswordController extends AbstractController /** * @return Response - * - * @\Symfony\Component\Routing\Annotation\Route(path="/public/{_locale}/password/request-confirm", name="password_request_recover_confirm") */ + #[Route(path: '/public/{_locale}/password/request-confirm', name: 'password_request_recover_confirm')] public function requestRecoverConfirmAction() { return $this->render('@ChillMain/Password/request_recover_password_confirm.html.twig'); @@ -245,13 +197,15 @@ class PasswordController extends AbstractController /** * @return Response - * - * @Route("/{_locale}/my/password", name="change_my_password") */ + #[Route(path: '/{_locale}/my/password', name: 'change_my_password')] public function UserPasswordAction(Request $request) { + if (!$this->security->isGranted('ROLE_USER')) { + throw new AccessDeniedHttpException(); + } // get authentified user - $user = $this->getUser(); + $user = $this->security->getUser(); // create a form for password_encoder $form = $this->passwordForm($user); @@ -269,13 +223,13 @@ class PasswordController extends AbstractController 'update password for an user', [ 'method' => $request->getMethod(), - 'user' => $user->getUsername(), + 'user' => $user->getUserIdentifier(), ] ); - $user->setPassword($this->passwordEncoder->encodePassword($user, $password)); + $user->setPassword($this->passwordEncoder->hashPassword($user, $password)); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->flush(); $this->addFlash('success', $this->translator->trans('Password successfully updated!')); @@ -301,7 +255,7 @@ class PasswordController extends AbstractController 'constraints' => [ new Callback([ 'callback' => function ($pattern, ExecutionContextInterface $context, $payload) { - $qb = $this->getDoctrine()->getManager() + $qb = $this->managerRegistry->getManager() ->createQueryBuilder(); $qb->select('COUNT(u)') ->from(User::class, 'u') @@ -324,7 +278,7 @@ class PasswordController extends AbstractController } /** - * @return \Symfony\Component\Form\Form + * @return \Symfony\Component\Form\FormInterface */ private function passwordForm(User $user) { diff --git a/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php b/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php index 97b255a85..2abb7333f 100644 --- a/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php @@ -21,15 +21,12 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; class PermissionApiController extends AbstractController { - public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly Security $security) - { - } + public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly Security $security) {} /** - * @Route("/api/1.0/main/permissions/info.json", methods={"POST"}) - * * @throws \Symfony\Component\Serializer\Exception\ExceptionInterface */ + #[Route(path: '/api/1.0/main/permissions/info.json', methods: ['POST'])] public function getPermissions(Request $request): JsonResponse { $this->denyAccessUnlessGranted('ROLE_USER'); diff --git a/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php b/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php index 208e13875..d4ee293b1 100644 --- a/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php +++ b/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php @@ -47,12 +47,9 @@ final class PermissionsGroupController extends AbstractController private readonly EntityManagerInterface $em, private readonly PermissionsGroupRepository $permissionsGroupRepository, private readonly RoleScopeRepository $roleScopeRepository, - ) { - } + ) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/{id}/add_link_role_scope", name="admin_permissionsgroup_add_role_scope", methods={"PUT"}) - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/add_link_role_scope', name: 'admin_permissionsgroup_add_role_scope', methods: ['POST'])] public function addLinkRoleScopeAction(Request $request, int $id): Response { $permissionsGroup = $this->permissionsGroupRepository->find($id); @@ -64,7 +61,7 @@ final class PermissionsGroupController extends AbstractController $form = $this->createAddRoleScopeForm($permissionsGroup); $form->handleRequest($request); - if ($form->isValid()) { + if ($form->isSubmitted() && $form->isValid()) { $roleScope = $this->getPersistentRoleScopeBy( $form['composed_role_scope']->getData()->getRole(), $form['composed_role_scope']->getData()->getScope() @@ -77,7 +74,7 @@ final class PermissionsGroupController extends AbstractController $this->em->flush(); $this->addFlash( - 'notice', + 'success', $this->translator->trans('The permissions have been added') ); @@ -130,9 +127,8 @@ final class PermissionsGroupController extends AbstractController /** * Creates a new PermissionsGroup entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/create", name="admin_permissionsgroup_create", methods={"POST"}) */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/create', name: 'admin_permissionsgroup_create', methods: ['POST'])] public function createAction(Request $request): Response { $permissionsGroup = new PermissionsGroup(); @@ -154,9 +150,8 @@ final class PermissionsGroupController extends AbstractController /** * remove an association between permissionsGroup and roleScope. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/{pgid}/delete_link_role_scope/{rsid}", name="admin_permissionsgroup_delete_role_scope", methods={"DELETE"}) */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{pgid}/delete_link_role_scope/{rsid}', name: 'admin_permissionsgroup_delete_role_scope', methods: ['POST'])] public function deleteLinkRoleScopeAction(int $pgid, int $rsid): Response { $permissionsGroup = $this->permissionsGroupRepository->find($pgid); @@ -212,9 +207,8 @@ final class PermissionsGroupController extends AbstractController /** * Displays a form to edit an existing PermissionsGroup entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/{id}/edit", name="admin_permissionsgroup_edit") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/edit', name: 'admin_permissionsgroup_edit')] public function editAction(int $id): Response { $permissionsGroup = $this->permissionsGroupRepository->find($id); @@ -260,9 +254,8 @@ final class PermissionsGroupController extends AbstractController /** * Lists all PermissionsGroup entities. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/", name="admin_permissionsgroup") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/', name: 'admin_permissionsgroup')] public function indexAction(): Response { $entities = $this->permissionsGroupRepository->findAllOrderedAlphabetically(); @@ -274,9 +267,8 @@ final class PermissionsGroupController extends AbstractController /** * Displays a form to create a new PermissionsGroup entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/new", name="admin_permissionsgroup_new") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/new', name: 'admin_permissionsgroup_new')] public function newAction(): Response { $permissionsGroup = new PermissionsGroup(); @@ -290,9 +282,8 @@ final class PermissionsGroupController extends AbstractController /** * Finds and displays a PermissionsGroup entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/{id}/show", name="admin_permissionsgroup_show") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/show', name: 'admin_permissionsgroup_show')] public function showAction(int $id): Response { $permissionsGroup = $this->permissionsGroupRepository->find($id); @@ -343,9 +334,8 @@ final class PermissionsGroupController extends AbstractController /** * Edits an existing PermissionsGroup entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/permissionsgroup/{id}/update", name="admin_permissionsgroup_update", methods={"POST", "PUT"}) */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/update', name: 'admin_permissionsgroup_update', methods: ['POST', 'PUT'])] public function updateAction(Request $request, int $id): Response { $permissionsGroup = $this->permissionsGroupRepository @@ -426,7 +416,6 @@ final class PermissionsGroupController extends AbstractController 'admin_permissionsgroup_add_role_scope', ['id' => $permissionsGroup->getId()] )) - ->setMethod('PUT') ->add('composed_role_scope', ComposedRoleScopeType::class) ->add('submit', SubmitType::class, ['label' => 'Add permission']) ->getForm(); diff --git a/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php b/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php index e51f74e40..cd13ad455 100644 --- a/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php +++ b/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php @@ -26,13 +26,9 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; final class PostalCodeAPIController extends ApiController { - public function __construct(private readonly CountryRepository $countryRepository, private readonly PostalCodeRepositoryInterface $postalCodeRepository, private readonly PaginatorFactory $paginatorFactory) - { - } + public function __construct(private readonly CountryRepository $countryRepository, private readonly PostalCodeRepositoryInterface $postalCodeRepository, private readonly PaginatorFactory $paginatorFactory) {} - /** - * @Route("/api/1.0/main/postal-code/search.json") - */ + #[Route(path: '/api/1.0/main/postal-code/search.json')] public function search(Request $request): JsonResponse { $this->denyAccessUnlessGranted('ROLE_USER'); diff --git a/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php b/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php index f186561d5..edd8efda8 100644 --- a/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php +++ b/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php @@ -29,18 +29,15 @@ class PostalCodeController extends AbstractController */ protected $translatableStringHelper; - public function __construct(TranslatableStringHelper $translatableStringHelper) + public function __construct(TranslatableStringHelper $translatableStringHelper, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) { $this->translatableStringHelper = $translatableStringHelper; } /** - * @Route( - * "{_locale}/postalcode/search" - * ) - * * @return JsonResponse */ + #[Route(path: '{_locale}/postalcode/search')] public function searchAction(Request $request) { $pattern = $request->query->getAlnum('q', ''); @@ -49,7 +46,7 @@ class PostalCodeController extends AbstractController return new JsonResponse(['results' => [], 'pagination' => ['more' => false]]); } - $query = $this->getDoctrine()->getManager() + $query = $this->managerRegistry->getManager() ->createQuery( sprintf( 'SELECT p.id AS id, p.name AS name, p.code AS code, ' diff --git a/src/Bundle/ChillMainBundle/Controller/SavedExportController.php b/src/Bundle/ChillMainBundle/Controller/SavedExportController.php index 0269ff0f5..82d41a9e1 100644 --- a/src/Bundle/ChillMainBundle/Controller/SavedExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/SavedExportController.php @@ -34,13 +34,9 @@ use Symfony\Contracts\Translation\TranslatorInterface; class SavedExportController { - public function __construct(private readonly \Twig\Environment $templating, private readonly EntityManagerInterface $entityManager, private readonly ExportManager $exportManager, private readonly FormFactoryInterface $formFactory, private readonly SavedExportRepositoryInterface $savedExportRepository, private readonly Security $security, private readonly SessionInterface $session, private readonly TranslatorInterface $translator, private readonly UrlGeneratorInterface $urlGenerator) - { - } + public function __construct(private readonly \Twig\Environment $templating, private readonly EntityManagerInterface $entityManager, private readonly ExportManager $exportManager, private readonly FormFactoryInterface $formFactory, private readonly SavedExportRepositoryInterface $savedExportRepository, private readonly Security $security, private readonly SessionInterface $session, private readonly TranslatorInterface $translator, private readonly UrlGeneratorInterface $urlGenerator) {} - /** - * @Route("/{_locale}/exports/saved/{id}/delete", name="chill_main_export_saved_delete") - */ + #[Route(path: '/{_locale}/exports/saved/{id}/delete', name: 'chill_main_export_saved_delete')] public function delete(SavedExport $savedExport, Request $request): Response { if (!$this->security->isGranted(SavedExportVoter::DELETE, $savedExport)) { @@ -73,9 +69,7 @@ class SavedExportController ); } - /** - * @Route("/{_locale}/exports/saved/{id}/edit", name="chill_main_export_saved_edit") - */ + #[Route(path: '/{_locale}/exports/saved/{id}/edit', name: 'chill_main_export_saved_edit')] public function edit(SavedExport $savedExport, Request $request): Response { if (!$this->security->isGranted(SavedExportVoter::EDIT, $savedExport)) { @@ -106,9 +100,7 @@ class SavedExportController ); } - /** - * @Route("/{_locale}/exports/saved/my", name="chill_main_export_saved_list_my") - */ + #[Route(path: '/{_locale}/exports/saved/my', name: 'chill_main_export_saved_list_my')] public function list(): Response { $user = $this->security->getUser(); diff --git a/src/Bundle/ChillMainBundle/Controller/ScopeController.php b/src/Bundle/ChillMainBundle/Controller/ScopeController.php index 3ccf13c07..45278d7af 100644 --- a/src/Bundle/ChillMainBundle/Controller/ScopeController.php +++ b/src/Bundle/ChillMainBundle/Controller/ScopeController.php @@ -13,20 +13,27 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Form\ScopeType; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; /** * Class ScopeController. */ class ScopeController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} + /** * Creates a new Scope entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/scope/create", name="admin_scope_create", methods={"POST"}) */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/create', name: 'admin_scope_create', methods: ['POST'])] public function createAction(Request $request) { $scope = new Scope(); @@ -34,7 +41,7 @@ class ScopeController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->persist($scope); $em->flush(); @@ -49,20 +56,18 @@ class ScopeController extends AbstractController /** * Displays a form to edit an existing Scope entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/scope/{id}/edit", name="admin_scope_edit") */ - public function editAction(mixed $id) + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/{id}/edit', name: 'admin_scope_edit')] + public function editAction(Scope $scope, Request $request): Response { - $em = $this->getDoctrine()->getManager(); - - $scope = $em->getRepository(Scope::class)->find($id); - - if (!$scope) { - throw $this->createNotFoundException('Unable to find Scope entity.'); - } - $editForm = $this->createEditForm($scope); + $editForm->handleRequest($request); + + if ($editForm->isSubmitted() && $editForm->isValid()) { + $this->entityManager->flush(); + + return $this->redirectToRoute('admin_scope_edit', ['id' => $scope->getId()]); + } return $this->render('@ChillMain/Scope/edit.html.twig', [ 'entity' => $scope, @@ -72,12 +77,11 @@ class ScopeController extends AbstractController /** * Lists all Scope entities. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/scope/", name="admin_scope") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/', name: 'admin_scope')] public function indexAction() { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $entities = $em->getRepository(Scope::class)->findAll(); @@ -88,9 +92,8 @@ class ScopeController extends AbstractController /** * Displays a form to create a new Scope entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/scope/new", name="admin_scope_new") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/new', name: 'admin_scope_new')] public function newAction() { $scope = new Scope(); @@ -107,7 +110,7 @@ class ScopeController extends AbstractController */ public function showAction(mixed $id) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $scope = $em->getRepository(Scope::class)->find($id); @@ -120,44 +123,12 @@ class ScopeController extends AbstractController ]); } - /** - * Edits an existing Scope entity. - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/scope/{id}/update", name="admin_scope_update", methods={"POST", "PUT"}) - */ - public function updateAction(Request $request, mixed $id) - { - $em = $this->getDoctrine()->getManager(); - - $scope = $em->getRepository(Scope::class)->find($id); - - if (!$scope) { - throw $this->createNotFoundException('Unable to find Scope entity.'); - } - - $editForm = $this->createEditForm($scope); - $editForm->handleRequest($request); - - if ($editForm->isSubmitted() && $editForm->isValid()) { - $em->flush(); - - return $this->redirectToRoute('admin_scope_edit', ['id' => $id]); - } - - return $this->render('@ChillMain/Scope/edit.html.twig', [ - 'entity' => $scope, - 'edit_form' => $editForm->createView(), - ]); - } - /** * Creates a form to create a Scope entity. * * @param Scope $scope The entity - * - * @return \Symfony\Component\Form\Form The form */ - private function createCreateForm(Scope $scope) + private function createCreateForm(Scope $scope): FormInterface { $form = $this->createForm(ScopeType::class, $scope, [ 'action' => $this->generateUrl('admin_scope_create'), @@ -173,15 +144,10 @@ class ScopeController extends AbstractController * Creates a form to edit a Scope entity. * * @param Scope $scope The entity - * - * @return \Symfony\Component\Form\Form The form */ - private function createEditForm(Scope $scope) + private function createEditForm(Scope $scope): FormInterface { - $form = $this->createForm(ScopeType::class, $scope, [ - 'action' => $this->generateUrl('admin_scope_update', ['id' => $scope->getId()]), - 'method' => 'PUT', - ]); + $form = $this->createForm(ScopeType::class, $scope); $form->add('submit', SubmitType::class, ['label' => 'Update']); diff --git a/src/Bundle/ChillMainBundle/Controller/SearchController.php b/src/Bundle/ChillMainBundle/Controller/SearchController.php index b5d359a53..09e558b0a 100644 --- a/src/Bundle/ChillMainBundle/Controller/SearchController.php +++ b/src/Bundle/ChillMainBundle/Controller/SearchController.php @@ -32,13 +32,9 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class SearchController extends AbstractController { - public function __construct(protected SearchProvider $searchProvider, protected TranslatorInterface $translator, protected PaginatorFactory $paginatorFactory, protected SearchApi $searchApi) - { - } + public function __construct(protected SearchProvider $searchProvider, protected TranslatorInterface $translator, protected PaginatorFactory $paginatorFactory, protected SearchApi $searchApi) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/search/advanced/{name}", name="chill_main_advanced_search") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/search/advanced/{name}', name: 'chill_main_advanced_search')] public function advancedSearchAction(mixed $name, Request $request) { try { @@ -83,9 +79,7 @@ class SearchController extends AbstractController ); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/search/advanced", name="chill_main_advanced_search_list") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/search/advanced', name: 'chill_main_advanced_search_list')] public function advancedSearchListAction(Request $request) { /** @var Chill\MainBundle\Search\SearchProvider $variable */ @@ -102,9 +96,7 @@ class SearchController extends AbstractController return $this->render('@ChillMain/Search/choose_list.html.twig'); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/search.{_format}", name="chill_main_search", requirements={"_format"="html|json"}, defaults={"_format"="html"}) - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/search.{_format}', name: 'chill_main_search', requirements: ['_format' => 'html|json', '_locale' => '[a-z]{1,3}'], defaults: ['_format' => 'html'])] public function searchAction(Request $request, mixed $_format) { $pattern = trim((string) $request->query->get('q', '')); @@ -194,14 +186,12 @@ class SearchController extends AbstractController ); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/api/1.0/search.{_format}", name="chill_main_search_global", requirements={"_format"="json"}, defaults={"_format"="json"}) - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/api/1.0/search.{_format}', name: 'chill_main_search_global', requirements: ['_format' => 'json'], defaults: ['_format' => 'json'])] public function searchApi(Request $request, mixed $_format): JsonResponse { // TODO this is an incomplete implementation $query = $request->query->get('q', ''); - $types = $request->query->get('type', []); + $types = $request->query->all('type'); if (0 === \count($types)) { throw new BadRequestHttpException('The request must contains at one type'); @@ -221,7 +211,7 @@ class SearchController extends AbstractController $builder = $this ->get('form.factory') ->createNamedBuilder( - null, + '', FormType::class, $data, ['method' => Request::METHOD_POST] diff --git a/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php b/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php index 7999cb697..97507739e 100644 --- a/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php +++ b/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php @@ -20,16 +20,9 @@ use Symfony\Component\Security\Core\Security; class TimelineCenterController extends AbstractController { - public function __construct(protected TimelineBuilder $timelineBuilder, protected PaginatorFactory $paginatorFactory, private readonly Security $security) - { - } + public function __construct(protected TimelineBuilder $timelineBuilder, protected PaginatorFactory $paginatorFactory, private readonly Security $security) {} - /** - * @Route("/{_locale}/center/timeline", - * name="chill_center_timeline", - * methods={"GET"} - * ) - */ + #[Route(path: '/{_locale}/center/timeline', name: 'chill_center_timeline', methods: ['GET'])] public function centerAction(Request $request) { // collect reachable center for each group diff --git a/src/Bundle/ChillMainBundle/Controller/UserApiController.php b/src/Bundle/ChillMainBundle/Controller/UserApiController.php index 6809d3289..262bfdfde 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserApiController.php @@ -13,41 +13,33 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Security\ChillSecurity; use Doctrine\ORM\QueryBuilder; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; class UserApiController extends ApiController { - /** - * @Route( - * "/api/1.0/main/user-current-location.{_format}", - * name="chill_main_user_current_location", - * requirements={ - * "_format": "json" - * } - * ) - */ + public function __construct(private readonly ChillSecurity $security) {} + + #[Route(path: '/api/1.0/main/user-current-location.{_format}', name: 'chill_main_user_current_location', requirements: ['_format' => 'json'])] public function currentLocation(mixed $_format): JsonResponse { + if (!$this->isGranted('ROLE_USER')) { + throw new AccessDeniedHttpException(); + } + return $this->json( - $this->getUser()->getCurrentLocation(), + $this->security->getUser()->getCurrentLocation(), JsonResponse::HTTP_OK, [], ['groups' => ['read']] ); } - /** - * @Route( - * "/api/1.0/main/whoami.{_format}", - * name="chill_main_user_whoami", - * requirements={ - * "_format": "json" - * } - * ) - */ + #[Route(path: '/api/1.0/main/whoami.{_format}', name: 'chill_main_user_whoami', requirements: ['_format' => 'json'])] public function whoami(mixed $_format): JsonResponse { return $this->json( diff --git a/src/Bundle/ChillMainBundle/Controller/UserController.php b/src/Bundle/ChillMainBundle/Controller/UserController.php index 58b99e59e..95c78300f 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserController.php @@ -20,6 +20,7 @@ use Chill\MainBundle\Form\UserPasswordType; use Chill\MainBundle\Form\UserType; use Chill\MainBundle\Pagination\PaginatorInterface; use Chill\MainBundle\Repository\UserRepository; +use Chill\MainBundle\Security\ChillSecurity; use Chill\MainBundle\Templating\Listing\FilterOrderHelper; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; @@ -30,7 +31,6 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Contracts\Translation\TranslatorInterface; @@ -38,17 +38,21 @@ class UserController extends CRUDController { final public const FORM_GROUP_CENTER_COMPOSED = 'composed_groupcenter'; - public function __construct(private readonly LoggerInterface $logger, private readonly ValidatorInterface $validator, private readonly UserPasswordEncoderInterface $passwordEncoder, private readonly UserRepository $userRepository, protected ParameterBagInterface $parameterBag, private readonly TranslatorInterface $translator) - { - } + public function __construct( + private readonly LoggerInterface $logger, + private readonly ValidatorInterface $validator, + private readonly \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface $passwordEncoder, + private readonly UserRepository $userRepository, + protected ParameterBagInterface $parameterBag, + private readonly TranslatorInterface $translator, + private readonly ChillSecurity $security, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} - /** - * @Route("/{_locale}/admin/main/user/{uid}/add_link_groupcenter", - * name="admin_user_add_groupcenter") - */ + #[Route(path: '/{_locale}/admin/main/user/{uid}/add_link_groupcenter', name: 'admin_user_add_groupcenter')] public function addLinkGroupCenterAction(Request $request, mixed $uid): Response { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $user = $em->getRepository(User::class)->find($uid); @@ -94,13 +98,10 @@ class UserController extends CRUDController ]); } - /** - * @Route("/{_locale}/admin/main/user/{uid}/delete_link_groupcenter/{gcid}", - * name="admin_user_delete_groupcenter") - */ + #[Route(path: '/{_locale}/admin/main/user/{uid}/delete_link_groupcenter/{gcid}', name: 'admin_user_delete_groupcenter')] public function deleteLinkGroupCenterAction(mixed $uid, mixed $gcid, Request $request): RedirectResponse { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $user = $em->getRepository(User::class)->find($uid); @@ -158,7 +159,7 @@ class UserController extends CRUDController if ($form->isSubmitted() && $form->isValid()) { $this->onFormValid($action, $entity, $form, $request); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $this->onPreFlush($action, $entity, $form, $request); $em->flush(); @@ -194,12 +195,11 @@ class UserController extends CRUDController /** * Displays a form to edit the user current location. - * - * @Route("/{_locale}/main/user/current-location/edit", name="chill_main_user_currentlocation_edit") */ + #[Route(path: '/{_locale}/main/user/current-location/edit', name: 'chill_main_user_currentlocation_edit')] public function editCurrentLocationAction(Request $request) { - $user = $this->getUser(); + $user = $this->security->getUser(); $form = $this->createForm(UserCurrentLocationType::class, $user) ->add('submit', SubmitType::class, ['label' => 'Save']) ->handleRequest($request); @@ -209,7 +209,7 @@ class UserController extends CRUDController $user->setCurrentLocation($currentLocation); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans('Current location successfully updated')); return $this->redirect( @@ -226,9 +226,8 @@ class UserController extends CRUDController /** * Displays a form to edit the user password. - * - * @Route("/{_locale}/admin/user/{id}/edit_password", name="admin_user_edit_password") */ + #[Route(path: '/{_locale}/admin/user/{id}/edit_password', name: 'admin_user_edit_password')] public function editPasswordAction(User $user, Request $request) { $editForm = $this->createEditPasswordForm($user); @@ -243,9 +242,9 @@ class UserController extends CRUDController 'user' => $user->getUsername(), ]); - $user->setPassword($this->passwordEncoder->encodePassword($user, $password)); + $user->setPassword($this->passwordEncoder->hashPassword($user, $password)); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans('Password successfully updated!')); return $this->redirect( @@ -346,7 +345,7 @@ class UserController extends CRUDController // for "new", encode the password if ('new' === $action && $this->parameterBag->get('chill_main.access_user_change_password')) { $entity->setPassword($this->passwordEncoder - ->encodePassword($entity, $form['plainPassword']->getData())); + ->hashPassword($entity, $form['plainPassword']->getData())); } // default behaviour @@ -422,7 +421,7 @@ class UserController extends CRUDController private function getPersistedGroupCenter(GroupCenter $groupCenter) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $groupCenterManaged = $em->getRepository(GroupCenter::class) ->findOneBy([ diff --git a/src/Bundle/ChillMainBundle/Controller/UserExportController.php b/src/Bundle/ChillMainBundle/Controller/UserExportController.php index e25e6074f..6d944a4c3 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserExportController.php @@ -27,16 +27,14 @@ final readonly class UserExportController private UserRepositoryInterface $userRepository, private Security $security, private TranslatorInterface $translator, - ) { - } + ) {} /** * @throws \League\Csv\CannotInsertRecord * @throws \League\Csv\Exception * @throws \League\Csv\UnavailableStream - * - * @Route("/{_locale}/admin/main/users/export/list.{_format}", requirements={"_format": "csv"}, name="chill_main_users_export_list") */ + #[Route(path: '/{_locale}/admin/main/users/export/list.{_format}', requirements: ['_format' => 'csv'], name: 'chill_main_users_export_list')] public function userList(Request $request, string $_format = 'csv'): StreamedResponse { if (!$this->security->isGranted('ROLE_ADMIN')) { @@ -96,9 +94,8 @@ final readonly class UserExportController * @throws \League\Csv\CannotInsertRecord * @throws \League\Csv\Exception * @throws \League\Csv\UnavailableStream - * - * @Route("/{_locale}/admin/main/users/export/permissions.{_format}", requirements={"_format": "csv"}, name="chill_main_users_export_permissions") */ + #[Route(path: '/{_locale}/admin/main/users/export/permissions.{_format}', requirements: ['_format' => 'csv'], name: 'chill_main_users_export_permissions')] public function userPermissionsList(string $_format = 'csv'): StreamedResponse { if (!$this->security->isGranted('ROLE_ADMIN')) { diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php b/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php index 144c27688..1bbf5c0c1 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php @@ -21,12 +21,9 @@ class UserJobScopeHistoriesController extends AbstractController { public function __construct( private readonly Environment $engine, - ) { - } + ) {} - /** - * @Route("/{_locale}/admin/main/user/{id}/job-scope-history", name="admin_user_job_scope_history") - */ + #[Route(path: '/{_locale}/admin/main/user/{id}/job-scope-history', name: 'admin_user_job_scope_history')] public function indexAction(User $user): Response { $jobHistories = $user->getUserJobHistoriesOrdered(); diff --git a/src/Bundle/ChillMainBundle/Controller/UserProfileController.php b/src/Bundle/ChillMainBundle/Controller/UserProfileController.php index 3b83069bb..a48d1a1e2 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserProfileController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserProfileController.php @@ -12,29 +12,35 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; use Chill\MainBundle\Form\UserPhonenumberType; +use Chill\MainBundle\Security\ChillSecurity; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Component\Routing\Annotation\Route; -class UserProfileController extends AbstractController +final class UserProfileController extends AbstractController { public function __construct( private readonly TranslatorInterface $translator, - ) { - } + private readonly ChillSecurity $security, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} /** * User profile that allows editing of phonenumber and visualization of certain data. - * - * @Route("/{_locale}/main/user/my-profile", name="chill_main_user_profile") */ + #[Route(path: '/{_locale}/main/user/my-profile', name: 'chill_main_user_profile')] public function __invoke(Request $request) { - $user = $this->getUser(); + if (!$this->security->isGranted('ROLE_USER')) { + throw new AccessDeniedHttpException(); + } + + $user = $this->security->getUser(); $editForm = $this->createPhonenumberEditForm($user); $editForm->handleRequest($request); @@ -43,7 +49,7 @@ class UserProfileController extends AbstractController $user->setPhonenumber($phonenumber); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans('user.profile.Phonenumber successfully updated!')); return $this->redirectToRoute('chill_main_user_profile'); diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowAddSignatureController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowAddSignatureController.php new file mode 100644 index 000000000..2aa180b7a --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/WorkflowAddSignatureController.php @@ -0,0 +1,79 @@ +security->isGranted(EntityWorkflowStepSignatureVoter::SIGN, $signature)) { + throw new AccessDeniedHttpException('not authorized to sign this step'); + } + + $entityWorkflow = $signature->getStep()->getEntityWorkflow(); + + if (EntityWorkflowSignatureStateEnum::PENDING !== $signature->getState()) { + if ($request->query->has('returnPath')) { + return new RedirectResponse($request->query->get('returnPath')); + } + + return new RedirectResponse( + $this->urlGenerator->generate('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]) + ); + } + + $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow); + if (null === $storedObject) { + throw new NotFoundHttpException('No stored object found'); + } + + $zones = $this->PDFSignatureZoneAvailable->getAvailableSignatureZones($entityWorkflow); + + $signatureClient = []; + $signatureClient['id'] = $signature->getId(); + $signatureClient['storedObject'] = $this->normalizer->normalize($storedObject, 'json'); + $signatureClient['zones'] = $zones; + + return new Response( + $this->twig->render( + '@ChillMain/Workflow/_signature_sign.html.twig', + ['signature' => $signatureClient] + ) + ); + } +} diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php index dd7d642c9..28dca8016 100644 --- a/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php @@ -29,15 +29,12 @@ use Symfony\Component\Serializer\SerializerInterface; class WorkflowApiController { - public function __construct(private readonly EntityManagerInterface $entityManager, private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly SerializerInterface $serializer) - { - } + public function __construct(private readonly EntityManagerInterface $entityManager, private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly SerializerInterface $serializer) {} /** * Return a list of workflow which are waiting an action for the user. - * - * @Route("/api/1.0/main/workflow/my", methods={"GET"}) */ + #[Route(path: '/api/1.0/main/workflow/my', methods: ['GET'])] public function myWorkflow(Request $request): JsonResponse { if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) { @@ -74,9 +71,8 @@ class WorkflowApiController /** * Return a list of workflow which are waiting an action for the user. - * - * @Route("/api/1.0/main/workflow/my-cc", methods={"GET"}) */ + #[Route(path: '/api/1.0/main/workflow/my-cc', methods: ['GET'])] public function myWorkflowCc(Request $request): JsonResponse { if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) { @@ -111,17 +107,13 @@ class WorkflowApiController ); } - /** - * @Route("/api/1.0/main/workflow/{id}/subscribe", methods={"POST"}) - */ + #[Route(path: '/api/1.0/main/workflow/{id}/subscribe', methods: ['POST'])] public function subscribe(EntityWorkflow $entityWorkflow, Request $request): Response { return $this->handleSubscription($entityWorkflow, $request, 'subscribe'); } - /** - * @Route("/api/1.0/main/workflow/{id}/unsubscribe", methods={"POST"}) - */ + #[Route(path: '/api/1.0/main/workflow/{id}/unsubscribe', methods: ['POST'])] public function unsubscribe(EntityWorkflow $entityWorkflow, Request $request): Response { return $this->handleSubscription($entityWorkflow, $request, 'unsubscribe'); diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php index a88248c1a..2f8a0fd55 100644 --- a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php +++ b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php @@ -13,24 +13,28 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; -use Chill\MainBundle\Entity\Workflow\EntityWorkflowComment; use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep; -use Chill\MainBundle\Form\EntityWorkflowCommentType; +use Chill\MainBundle\Form\WorkflowSignatureMetadataType; use Chill\MainBundle\Form\WorkflowStepType; use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository; +use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureRepository; use Chill\MainBundle\Security\Authorization\EntityWorkflowVoter; +use Chill\MainBundle\Security\ChillSecurity; use Chill\MainBundle\Workflow\EntityWorkflowManager; +use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\NonUniqueResultException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\Clock\ClockInterface; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\Security; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\Registry; use Symfony\Component\Workflow\TransitionBlocker; @@ -38,13 +42,21 @@ use Symfony\Contracts\Translation\TranslatorInterface; class WorkflowController extends AbstractController { - public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly ValidatorInterface $validator, private readonly PaginatorFactory $paginatorFactory, private readonly Registry $registry, private readonly EntityManagerInterface $entityManager, private readonly TranslatorInterface $translator, private readonly Security $security) - { - } + public function __construct( + private readonly EntityWorkflowManager $entityWorkflowManager, + private readonly EntityWorkflowRepository $entityWorkflowRepository, + private readonly ValidatorInterface $validator, + private readonly PaginatorFactory $paginatorFactory, + private readonly Registry $registry, + private readonly EntityManagerInterface $entityManager, + private readonly TranslatorInterface $translator, + private readonly ChillSecurity $security, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + private readonly ClockInterface $clock, + private readonly EntityWorkflowStepSignatureRepository $entityWorkflowStepSignatureRepository, + ) {} - /** - * @Route("/{_locale}/main/workflow/create", name="chill_main_workflow_create") - */ + #[Route(path: '/{_locale}/main/workflow/create', name: 'chill_main_workflow_create')] public function create(Request $request): Response { if (!$request->query->has('entityClass')) { @@ -64,7 +76,7 @@ class WorkflowController extends AbstractController ->setRelatedEntityClass($request->query->get('entityClass')) ->setRelatedEntityId($request->query->getInt('entityId')) ->setWorkflowName($request->query->get('workflow')) - ->addSubscriberToFinal($this->getUser()); + ->addSubscriberToFinal($this->security->getUser()); $errors = $this->validator->validate($entityWorkflow, null, ['creation']); @@ -81,16 +93,14 @@ class WorkflowController extends AbstractController $this->denyAccessUnlessGranted(EntityWorkflowVoter::CREATE, $entityWorkflow); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->persist($entityWorkflow); $em->flush(); return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]); } - /** - * @Route("/{_locale}/main/workflow/{id}/delete", name="chill_main_workflow_delete") - */ + #[Route(path: '/{_locale}/main/workflow/{id}/delete', name: 'chill_main_workflow_delete')] public function delete(EntityWorkflow $entityWorkflow, Request $request): Response { $this->denyAccessUnlessGranted(EntityWorkflowVoter::DELETE, $entityWorkflow); @@ -115,9 +125,7 @@ class WorkflowController extends AbstractController ]); } - /** - * @Route("/{_locale}/main/workflow-step/{id}/access_key", name="chill_main_workflow_grant_access_by_key") - */ + #[Route(path: '/{_locale}/main/workflow-step/{id}/access_key', name: 'chill_main_workflow_grant_access_by_key')] public function getAccessByAccessKey(EntityWorkflowStep $entityWorkflowStep, Request $request): Response { if (null === $accessKey = $request->query->get('accessKey', null)) { @@ -125,17 +133,17 @@ class WorkflowController extends AbstractController } if (!$this->getUser() instanceof User) { - throw new AccessDeniedException('Not a valid user'); + throw new AccessDeniedHttpException('Not a valid user'); } if ($entityWorkflowStep->getAccessKey() !== $accessKey) { - throw new AccessDeniedException('Access key is invalid'); + throw new AccessDeniedHttpException('Access key is invalid'); } if (!$entityWorkflowStep->isWaitingForTransition()) { $this->addFlash('error', $this->translator->trans('workflow.Steps is not waiting for transition. Maybe someone apply the transition before you ?')); } else { - $entityWorkflowStep->addDestUserByAccessKey($this->getUser()); + $entityWorkflowStep->addDestUserByAccessKey($this->security->getUser()); $this->entityManager->flush(); $this->addFlash('success', $this->translator->trans('workflow.You get access to this step')); } @@ -145,18 +153,17 @@ class WorkflowController extends AbstractController /** * Previous workflows where the user has applyed a transition. - * - * @Route("/{_locale}/main/workflow/list/previous_transitionned", name="chill_main_workflow_list_previous_transitionned") */ + #[Route(path: '/{_locale}/main/workflow/list/previous_transitionned', name: 'chill_main_workflow_list_previous_transitionned')] public function myPreviousWorkflowsTransitionned(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - $total = $this->entityWorkflowRepository->countByPreviousTransitionned($this->getUser()); + $total = $this->entityWorkflowRepository->countByPreviousTransitionned($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByPreviousTransitionned( - $this->getUser(), + $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() @@ -175,18 +182,17 @@ class WorkflowController extends AbstractController /** * Previous workflows where the user was mentioned, but did not give any reaction. - * - * @Route("/{_locale}/main/workflow/list/previous_without_reaction", name="chill_main_workflow_list_previous_without_reaction") */ + #[Route(path: '/{_locale}/main/workflow/list/previous_without_reaction', name: 'chill_main_workflow_list_previous_without_reaction')] public function myPreviousWorkflowsWithoutReaction(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - $total = $this->entityWorkflowRepository->countByPreviousDestWithoutReaction($this->getUser()); + $total = $this->entityWorkflowRepository->countByPreviousDestWithoutReaction($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByPreviousDestWithoutReaction( - $this->getUser(), + $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() @@ -203,18 +209,16 @@ class WorkflowController extends AbstractController ); } - /** - * @Route("/{_locale}/main/workflow/list/cc", name="chill_main_workflow_list_cc") - */ + #[Route(path: '/{_locale}/main/workflow/list/cc', name: 'chill_main_workflow_list_cc')] public function myWorkflowsCc(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - $total = $this->entityWorkflowRepository->countByDest($this->getUser()); + $total = $this->entityWorkflowRepository->countByDest($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByCc( - $this->getUser(), + $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() @@ -230,18 +234,16 @@ class WorkflowController extends AbstractController ); } - /** - * @Route("/{_locale}/main/workflow/list/dest", name="chill_main_workflow_list_dest") - */ + #[Route(path: '/{_locale}/main/workflow/list/dest', name: 'chill_main_workflow_list_dest')] public function myWorkflowsDest(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - $total = $this->entityWorkflowRepository->countByDest($this->getUser()); + $total = $this->entityWorkflowRepository->countByDest($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByDest( - $this->getUser(), + $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() @@ -257,18 +259,16 @@ class WorkflowController extends AbstractController ); } - /** - * @Route("/{_locale}/main/workflow/list/subscribed", name="chill_main_workflow_list_subscribed") - */ + #[Route(path: '/{_locale}/main/workflow/list/subscribed', name: 'chill_main_workflow_list_subscribed')] public function myWorkflowsSubscribed(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); - $total = $this->entityWorkflowRepository->countBySubscriber($this->getUser()); + $total = $this->entityWorkflowRepository->countBySubscriber($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findBySubscriber( - $this->getUser(), + $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() @@ -285,8 +285,9 @@ class WorkflowController extends AbstractController } /** - * @Route("/{_locale}/main/workflow/{id}/show", name="chill_main_workflow_show") + * @throws NonUniqueResultException */ + #[Route(path: '/{_locale}/main/workflow/{id}/show', name: 'chill_main_workflow_show')] public function show(EntityWorkflow $entityWorkflow, Request $request): Response { $this->denyAccessUnlessGranted(EntityWorkflowVoter::SEE, $entityWorkflow); @@ -294,10 +295,11 @@ class WorkflowController extends AbstractController $handler = $this->entityWorkflowManager->getHandler($entityWorkflow); $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); $errors = []; + $signatures = $entityWorkflow->getCurrentStep()->getSignatures(); if (\count($workflow->getEnabledTransitions($entityWorkflow)) > 0) { // possible transition - + $stepDTO = new WorkflowTransitionContextDTO($entityWorkflow); $usersInvolved = $entityWorkflow->getUsersInvolved(); $currentUserFound = array_search($this->security->getUser(), $usersInvolved, true); @@ -307,9 +309,8 @@ class WorkflowController extends AbstractController $transitionForm = $this->createForm( WorkflowStepType::class, - $entityWorkflow->getCurrentStep(), + $stepDTO, [ - 'transition' => true, 'entity_workflow' => $entityWorkflow, 'suggested_users' => $usersInvolved, ] @@ -328,12 +329,14 @@ class WorkflowController extends AbstractController throw $this->createAccessDeniedException(sprintf("not allowed to apply transition {$transition}: %s", implode(', ', $msgs))); } - // TODO symfony 5: add those "future" on context ($workflow->apply($entityWorkflow, $transition, $context) - $entityWorkflow->futureCcUsers = $transitionForm['future_cc_users']->getData() ?? []; - $entityWorkflow->futureDestUsers = $transitionForm['future_dest_users']->getData() ?? []; - $entityWorkflow->futureDestEmails = $transitionForm['future_dest_emails']->getData() ?? []; + $byUser = $this->security->getUser(); - $workflow->apply($entityWorkflow, $transition); + $workflow->apply($entityWorkflow, $transition, [ + 'context' => $stepDTO, + 'byUser' => $byUser, + 'transition' => $transition, + 'transitionAt' => $this->clock->now(), + ]); $this->entityManager->flush(); @@ -345,22 +348,6 @@ class WorkflowController extends AbstractController } } - /* - $commentForm = $this->createForm(EntityWorkflowCommentType::class, $newComment = new EntityWorkflowComment()); - $commentForm->handleRequest($request); - - if ($commentForm->isSubmitted() && $commentForm->isValid()) { - $this->entityManager->persist($newComment); - $this->entityManager->flush(); - - $this->addFlash('success', $this->translator->trans('workflow.Comment added')); - - return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]); - } elseif ($commentForm->isSubmitted() && !$commentForm->isValid()) { - $this->addFlash('error', $this->translator->trans('This form contains errors')); - } - */ - return $this->render( '@ChillMain/Workflow/index.html.twig', [ @@ -370,7 +357,7 @@ class WorkflowController extends AbstractController 'transition_form' => isset($transitionForm) ? $transitionForm->createView() : null, 'entity_workflow' => $entityWorkflow, 'transition_form_errors' => $errors, - // 'comment_form' => $commentForm->createView(), + 'signatures' => $signatures, ] ); } @@ -389,4 +376,65 @@ class WorkflowController extends AbstractController return $lines; } + + #[Route(path: '/{_locale}/main/workflow/signature/{signature_id}/metadata', name: 'chill_main_workflow_signature_metadata')] + public function addSignatureMetadata(int $signature_id, Request $request): Response + { + $signature = $this->entityWorkflowStepSignatureRepository->find($signature_id); + + if (null === $signature) { + throw new NotFoundHttpException('signature not found'); + } + + if ($signature->isSigned()) { + $this->addFlash( + 'notice', + $this->translator->trans('workflow.signature_zone.already_signed_alert') + ); + + return $this->redirectToRoute('chill_main_workflow_show', ['id' => $signature->getStep()->getEntityWorkflow()->getId()]); + } + + if ($signature->getSigner() instanceof User) { + return $this->redirectToRoute('chill_main_workflow_signature_add', [ + 'id' => $signature_id, + 'returnPath' => $request->query->get('returnPath', null), + ]); + } + + $metadataForm = $this->createForm(WorkflowSignatureMetadataType::class); + $metadataForm->add('submit', SubmitType::class, ['label' => $this->translator->trans('Save')]); + + $metadataForm->handleRequest($request); + + if ($metadataForm->isSubmitted() && $metadataForm->isValid()) { + $data = $metadataForm->getData(); + + $signature->setSignatureMetadata( + [ + 'base_signer' => [ + 'document_type' => $data['documentType'], + 'document_number' => $data['documentNumber'], + 'expiration_date' => $data['expirationDate'], + ], + ] + ); + + $this->entityManager->persist($signature); + $this->entityManager->flush(); + + return $this->redirectToRoute('chill_main_workflow_signature_add', [ + 'id' => $signature_id, + 'returnPath' => $request->query->get('returnPath', null), + ]); + } + + return $this->render( + '@ChillMain/Workflow/_signature_metadata.html.twig', + [ + 'metadata_form' => $metadataForm->createView(), + 'person' => $signature->getSigner(), + ] + ); + } } diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowOnHoldController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowOnHoldController.php new file mode 100644 index 000000000..077b8effa --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/WorkflowOnHoldController.php @@ -0,0 +1,98 @@ +getCurrentStep(); + $currentUser = $this->security->getUser(); + + if (!$currentUser instanceof User) { + throw new AccessDeniedHttpException('only user can put a workflow on hold'); + } + + $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); + $enabledTransitions = $workflow->getEnabledTransitions($entityWorkflow); + + if (0 === count($enabledTransitions)) { + throw new AccessDeniedHttpException('You are not allowed to apply any transitions to this workflow, therefore you cannot toggle the hold status.'); + } + + $stepHold = new EntityWorkflowStepHold($currentStep, $currentUser); + + $this->entityManager->persist($stepHold); + $this->entityManager->flush(); + + return new RedirectResponse( + $this->urlGenerator->generate( + 'chill_main_workflow_show', + ['id' => $entityWorkflow->getId()] + ) + ); + } + + #[Route(path: '/{_locale}/main/workflow/{id}/remove_hold', name: 'chill_main_workflow_remove_hold')] + public function removeOnHold(EntityWorkflowStep $entityWorkflowStep): Response + { + $user = $this->security->getUser(); + + if (!$user instanceof User) { + throw new AccessDeniedHttpException('only user can remove workflow on hold'); + } + + if (!$entityWorkflowStep->isOnHoldByUser($user)) { + throw new AccessDeniedHttpException('You are not allowed to remove workflow on hold'); + } + + $hold = $entityWorkflowStep->getHoldsOnStep()->findFirst(fn (int $index, EntityWorkflowStepHold $entityWorkflowStepHold) => $user === $entityWorkflowStepHold->getByUser()); + + if (null === $hold) { + // this should not happens... + throw new NotFoundHttpException(); + } + + $this->entityManager->remove($hold); + $this->entityManager->flush(); + + return new RedirectResponse( + $this->urlGenerator->generate( + 'chill_main_workflow_show', + ['id' => $entityWorkflowStep->getEntityWorkflow()->getId()] + ) + ); + } +} diff --git a/src/Bundle/ChillMainBundle/Cron/CronManager.php b/src/Bundle/ChillMainBundle/Cron/CronManager.php index a5912ceff..e32e44817 100644 --- a/src/Bundle/ChillMainBundle/Cron/CronManager.php +++ b/src/Bundle/ChillMainBundle/Cron/CronManager.php @@ -55,8 +55,7 @@ final readonly class CronManager implements CronManagerInterface private EntityManagerInterface $entityManager, private iterable $jobs, private LoggerInterface $logger, - ) { - } + ) {} public function run(?string $forceJob = null): void { diff --git a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php index 8cb335fba..1c99a3a74 100644 --- a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php +++ b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php @@ -18,7 +18,6 @@ use Doctrine\Persistence\ObjectManager; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactory; -use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; /** * Load fixtures users into database. @@ -65,7 +64,7 @@ class LoadUsers extends AbstractFixture implements ContainerAwareInterface, Orde foreach (self::$refs as $username => $params) { $user = new User(); - $defaultEncoder = new MessageDigestPasswordEncoder('sha512', true, 5000); + $defaultEncoder = new \Symfony\Component\PasswordHasher\Hasher\MessageDigestPasswordHasher('sha512', true, 5000); $encoderFactory = new EncoderFactory([ User::class => $defaultEncoder, diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 0e91347f3..9d788c64e 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -15,7 +15,9 @@ use Chill\MainBundle\Controller\AddressApiController; use Chill\MainBundle\Controller\CenterController; use Chill\MainBundle\Controller\CivilityApiController; use Chill\MainBundle\Controller\CivilityController; +use Chill\MainBundle\Controller\CountryApiController; use Chill\MainBundle\Controller\CountryController; +use Chill\MainBundle\Controller\GeographicalUnitApiController; use Chill\MainBundle\Controller\LanguageController; use Chill\MainBundle\Controller\LocationController; use Chill\MainBundle\Controller\LocationTypeController; @@ -667,6 +669,7 @@ class ChillMainExtension extends Extension implements ], [ 'class' => Country::class, + 'controller' => CountryApiController::class, 'name' => 'country', 'base_path' => '/api/1.0/main/country', 'base_role' => 'ROLE_USER', @@ -787,6 +790,7 @@ class ChillMainExtension extends Extension implements ], [ 'class' => GeographicalUnitLayer::class, + 'controller' => GeographicalUnitApiController::class, 'name' => 'geographical-unit-layer', 'base_path' => '/api/1.0/main/geographical-unit-layer', 'base_role' => 'ROLE_USER', diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php index b84f110ef..b1bb3951f 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php @@ -85,6 +85,29 @@ class Configuration implements ConfigurationInterface ->end() ->end() ->end() // end of notifications + ->arrayNode('workflow_signature') + ->children() + ->arrayNode('base_signer') + ->children() + ->arrayNode('document_kinds') + ->arrayPrototype() + ->children() + ->scalarNode('key')->cannotBeEmpty()->end() + ->arrayNode('labels') + ->arrayPrototype() + ->children() + ->scalarNode('lang')->cannotBeEmpty()->end() + ->scalarNode('label')->cannotBeEmpty()->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() // end of workflow signature document types ->arrayNode('phone_helper') ->canBeUnset() ->children() diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/RoleProvidersCompilerPass.php b/src/Bundle/ChillMainBundle/DependencyInjection/RoleProvidersCompilerPass.php deleted file mode 100644 index c4bbc846d..000000000 --- a/src/Bundle/ChillMainBundle/DependencyInjection/RoleProvidersCompilerPass.php +++ /dev/null @@ -1,41 +0,0 @@ -hasDefinition('chill.main.role_provider')) { - throw new \LogicException('service chill.main.role_provider is not defined. It is required by RoleProviderCompilerPass'); - } - - $definition = $container->getDefinition( - 'chill.main.role_provider' - ); - - $taggedServices = $container->findTaggedServiceIds( - 'chill.role' - ); - - foreach ($taggedServices as $id => $tagAttributes) { - $definition->addMethodCall( - 'addProvider', - [new Reference($id)] - ); - } - } -} diff --git a/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php b/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php index 907997258..e6ac2308a 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php @@ -21,9 +21,7 @@ use Symfony\Component\Security\Core\Security; class TrackCreateUpdateSubscriber implements EventSubscriber { - public function __construct(private readonly Security $security) - { - } + public function __construct(private readonly Security $security) {} public function getSubscribedEvents() { diff --git a/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php b/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php index beed15f31..de6af9625 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php @@ -15,9 +15,7 @@ class Point implements \JsonSerializable { public static string $SRID = '4326'; - private function __construct(private readonly ?float $lon, private readonly ?float $lat) - { - } + private function __construct(private readonly ?float $lon, private readonly ?float $lat) {} public static function fromArrayGeoJson(array $array): self { diff --git a/src/Bundle/ChillMainBundle/Doctrine/Model/TrackCreationTrait.php b/src/Bundle/ChillMainBundle/Doctrine/Model/TrackCreationTrait.php index 29f1c2f43..3286390f7 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Model/TrackCreationTrait.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Model/TrackCreationTrait.php @@ -12,26 +12,18 @@ declare(strict_types=1); namespace Chill\MainBundle\Doctrine\Model; use Chill\MainBundle\Entity\User; -use DateTime; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; trait TrackCreationTrait { - /** - * @ORM\Column(type="datetime_immutable", nullable=true, options={"default": NULL}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $createdAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $createdBy = null; public function getCreatedAt(): ?\DateTimeInterface diff --git a/src/Bundle/ChillMainBundle/Doctrine/Model/TrackUpdateTrait.php b/src/Bundle/ChillMainBundle/Doctrine/Model/TrackUpdateTrait.php index 8a3f98972..551b5a50f 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Model/TrackUpdateTrait.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Model/TrackUpdateTrait.php @@ -12,26 +12,18 @@ declare(strict_types=1); namespace Chill\MainBundle\Doctrine\Model; use Chill\MainBundle\Entity\User; -use DateTime; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; trait TrackUpdateTrait { - /** - * @ORM\Column(type="datetime_immutable", nullable=true, options={"default": NULL}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $updatedAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $updatedBy = null; public function getUpdatedAt(): ?\DateTimeInterface diff --git a/src/Bundle/ChillMainBundle/Entity/Address.php b/src/Bundle/ChillMainBundle/Entity/Address.php index f6584fddd..38b309a76 100644 --- a/src/Bundle/ChillMainBundle/Entity/Address.php +++ b/src/Bundle/ChillMainBundle/Entity/Address.php @@ -17,7 +17,6 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\ThirdPartyBundle\Entity\ThirdParty; -use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -26,13 +25,10 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; /** * Address. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_main_address") - * - * @ORM\HasLifecycleCallbacks */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'chill_main_address')] class Address implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; @@ -55,62 +51,39 @@ class Address implements TrackCreationInterface, TrackUpdateInterface */ final public const ADDR_REFERENCE_STATUS_REVIEWED = 'reviewed'; - /** - * @ORM\ManyToOne(targetEntity=AddressReference::class) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\ManyToOne(targetEntity: AddressReference::class)] private ?AddressReference $addressReference = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $buildingName = ''; - /** - * @ORM\Column(type="boolean", options={"default": false}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $confidential = false; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $corridor = ''; /** * used for the CEDEX information. - * - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $distribution = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $extra = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $flat = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $floor = ''; /** @@ -119,122 +92,85 @@ class Address implements TrackCreationInterface, TrackUpdateInterface * This list is computed by a materialized view. It won't be populated until a refresh is done * on the materialized view. * - * @var Collection + * @var Collection * * @readonly - * - * @ORM\ManyToMany(targetEntity=GeographicalUnit::class) - * - * @ORM\JoinTable( - * name="view_chill_main_address_geographical_unit", - * joinColumns={@ORM\JoinColumn(name="address_id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="geographical_unit_id")} - * ) */ + #[ORM\ManyToMany(targetEntity: GeographicalUnit::class)] + #[ORM\JoinTable(name: 'view_chill_main_address_geographical_unit', joinColumns: [new ORM\JoinColumn(name: 'address_id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'geographical_unit_id')])] private Collection $geographicalUnits; /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"write"}) - * * @readonly */ + #[Groups(['write'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; /** * True if the address is a "no address", aka homeless person, ... - * - * @Groups({"write"}) - * - * @ORM\Column(type="boolean", options={"default": false}) */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $isNoAddress = false; /** * A ThirdParty reference for person's addresses that are linked to a third party. - * - * @ORM\ManyToOne(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty") - * - * @Groups({"write"}) - * - * @ORM\JoinColumn(nullable=true, onDelete="SET NULL") */ + #[Groups(['write'])] + #[ORM\ManyToOne(targetEntity: ThirdParty::class)] + #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] private ?ThirdParty $linkedToThirdParty = null; /** * A geospatial field storing the coordinates of the Address. - * - * @ORM\Column(type="point", nullable=true) - * - * @Groups({"write"}) */ + #[Groups(['write'])] + #[ORM\Column(type: 'point', nullable: true)] private ?Point $point = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode") - * - * @ORM\JoinColumn(nullable=false) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\ManyToOne(targetEntity: PostalCode::class)] + #[ORM\JoinColumn(nullable: false)] private ?PostalCode $postcode = null; /** * @var self::ADDR_REFERENCE_STATUS_* - * - * @ORM\Column(type="text", nullable=false, options={"default": self::ADDR_REFERENCE_STATUS_MATCH}) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => self::ADDR_REFERENCE_STATUS_MATCH])] private string $refStatus = self::ADDR_REFERENCE_STATUS_MATCH; - /** - * @ORM\Column(type="datetime_immutable", nullable=false, options={"default": "CURRENT_TIMESTAMP"}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false, options: ['default' => 'CURRENT_TIMESTAMP'])] private \DateTimeImmutable $refStatusLastUpdate; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $steps = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $street = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $streetNumber = ''; /** * Indicates when the address starts validation. Used to build an history * of address. By default, the current date. - * - * @ORM\Column(type="date") - * - * @Groups({"write"}) */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE)] private \DateTime $validFrom; /** * Indicates when the address ends. Used to build an history * of address. - * - * @ORM\Column(type="date", nullable=true) - * - * @Groups({"write"}) */ + #[Groups(['write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)] private ?\DateTime $validTo = null; public function __construct() @@ -510,7 +446,7 @@ class Address implements TrackCreationInterface, TrackUpdateInterface return $this; } - public function setLinkedToThirdParty($linkedToThirdParty): self + public function setLinkedToThirdParty(?ThirdParty $linkedToThirdParty): self { $this->linkedToThirdParty = $linkedToThirdParty; diff --git a/src/Bundle/ChillMainBundle/Entity/AddressReference.php b/src/Bundle/ChillMainBundle/Entity/AddressReference.php index 49b510f8c..b512162bf 100644 --- a/src/Bundle/ChillMainBundle/Entity/AddressReference.php +++ b/src/Bundle/ChillMainBundle/Entity/AddressReference.php @@ -15,112 +15,68 @@ use Chill\MainBundle\Doctrine\Model\Point; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_main_address_reference", indexes={ - * - * @ORM\Index(name="address_refid", columns={"refId"}) - * }, - * uniqueConstraints={ - * - * @ORM\UniqueConstraint(name="chill_main_address_reference_unicity", columns={"refId", "source"}) - * }) - * - * @ORM\HasLifecycleCallbacks - */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'chill_main_address_reference')] +#[ORM\Index(name: 'address_refid', columns: ['refId'])] +#[ORM\UniqueConstraint(name: 'chill_main_address_reference_unicity', columns: ['refId', 'source'])] class AddressReference { /** * This is an internal column which is populated by database. * * This column will ease the search operations - * - * @ORM\Column(type="text", options={"default": ""}) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => ''])] private string $addressCanonical = ''; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $createdAt = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $deletedAt = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $municipalityCode = ''; /** * A geospatial field storing the coordinates of the Address. - * - * @ORM\Column(type="point") - * - * @groups({"read"}) */ + #[Groups(['read'])] + #[ORM\Column(type: 'point')] private ?Point $point = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode") - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\ManyToOne(targetEntity: PostalCode::class)] private ?PostalCode $postcode = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $refId = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $source = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $street = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $streetNumber = ''; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $updatedAt = null; public function getCreatedAt(): ?\DateTimeImmutable diff --git a/src/Bundle/ChillMainBundle/Entity/Center.php b/src/Bundle/ChillMainBundle/Entity/Center.php index b81200bdb..0d0858a6e 100644 --- a/src/Bundle/ChillMainBundle/Entity/Center.php +++ b/src/Bundle/ChillMainBundle/Entity/Center.php @@ -16,51 +16,33 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="centers") - */ +#[ORM\Entity] +#[ORM\Table(name: 'centers')] class Center implements HasCenterInterface, \Stringable { /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\MainBundle\Entity\GroupCenter", - * mappedBy="center" - * ) + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'center', targetEntity: GroupCenter::class)] private Collection $groupCenters; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\Column(type="string", length=255) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $name = ''; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $isActive = true; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Regroupment::class, mappedBy="centers") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Regroupment::class, mappedBy: 'centers')] private Collection $regroupments; /** @@ -100,10 +82,7 @@ class Center implements HasCenterInterface, \Stringable return $this->groupCenters; } - /** - * @return int - */ - public function getId() + public function getId(): ?int { return $this->id; } @@ -132,7 +111,7 @@ class Center implements HasCenterInterface, \Stringable /** * @return $this */ - public function setName($name) + public function setName(string $name) { $this->name = $name; diff --git a/src/Bundle/ChillMainBundle/Entity/Civility.php b/src/Bundle/ChillMainBundle/Entity/Civility.php index 322155fe5..2105c8b87 100644 --- a/src/Bundle/ChillMainBundle/Entity/Civility.php +++ b/src/Bundle/ChillMainBundle/Entity/Civility.php @@ -14,54 +14,32 @@ namespace Chill\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Table(name="chill_main_civility") - * - * @ORM\Entity - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={"chill_main_civility": Civility::class}) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['chill_main_civility' => Civility::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_main_civility')] class Civility { - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $abbreviation = []; - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $active = true; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $name = []; - /** - * @ORM\Column(type="float", name="ordering", nullable=true, options={"default": 0.0}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', nullable: true, options: ['default' => '0.0'])] private float $order = 0; public function getAbbreviation(): array diff --git a/src/Bundle/ChillMainBundle/Entity/Country.php b/src/Bundle/ChillMainBundle/Entity/Country.php index 91484ba46..533caeaec 100644 --- a/src/Bundle/ChillMainBundle/Entity/Country.php +++ b/src/Bundle/ChillMainBundle/Entity/Country.php @@ -17,46 +17,30 @@ use Symfony\Component\Serializer\Annotation\Groups; /** * Country. - * - * @ORM\Entity - * - * @ORM\Table(name="country") - * - * @ORM\Cache(usage="READ_ONLY", region="country_cache_region") - * - * @ORM\HasLifecycleCallbacks */ +#[ORM\Entity] +#[ORM\Cache(usage: 'READ_ONLY', region: 'country_cache_region')] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'country')] class Country { - /** - * @ORM\Column(type="string", length=3) - * - * @groups({"read", "docgen:read"}) - * - * @Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 3)] + #[Context(['is-translatable' => true], groups: ['docgen:read'])] private string $countryCode = ''; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; /** * @var array - * - * @ORM\Column(type="json") - * - * @groups({"read", "docgen:read"}) - * - * @Context({"is-translatable": true}, groups={"docgen:read"}) */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Context(['is-translatable' => true], groups: ['docgen:read'])] private array $name = []; public function getCountryCode(): string diff --git a/src/Bundle/ChillMainBundle/Entity/CronJobExecution.php b/src/Bundle/ChillMainBundle/Entity/CronJobExecution.php index 368c72a52..f2f1194c8 100644 --- a/src/Bundle/ChillMainBundle/Entity/CronJobExecution.php +++ b/src/Bundle/ChillMainBundle/Entity/CronJobExecution.php @@ -13,42 +13,29 @@ namespace Chill\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_main_cronjob_execution") - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_main_cronjob_execution')] class CronJobExecution { final public const FAILURE = 100; final public const SUCCESS = 1; - /** - * @ORM\Column(type="datetime_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $lastEnd = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false)] private \DateTimeImmutable $lastStart; - /** - * @ORM\Column(type="integer", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])] private ?int $lastStatus = null; - /** - * @ORM\Column(type="json", options={"default": "'{}'::jsonb", "jsonb": true}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, options: ['default' => "'{}'::jsonb", 'jsonb' => true])] private array $lastExecutionData = []; - public function __construct(/** - * @ORM\Column(type="text", nullable=false) - * - * @ORM\Id - */ + public function __construct( + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false)] + #[ORM\Id] private string $key, ) { $this->lastStart = new \DateTimeImmutable('now'); diff --git a/src/Bundle/ChillMainBundle/Entity/DashboardConfigItem.php b/src/Bundle/ChillMainBundle/Entity/DashboardConfigItem.php index ed9cc07bf..6fdd34cfc 100644 --- a/src/Bundle/ChillMainBundle/Entity/DashboardConfigItem.php +++ b/src/Bundle/ChillMainBundle/Entity/DashboardConfigItem.php @@ -15,52 +15,31 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_main_dashboard_config_item") - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_main_dashboard_config_item')] class DashboardConfigItem { - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"dashboardConfigItem:read", "read"}) - */ + #[Serializer\Groups(['dashboardConfigItem:read', 'read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="string") - * - * @Serializer\Groups({"dashboardConfigItem:read", "read"}) - * - * @Assert\NotNull - */ + #[Serializer\Groups(['dashboardConfigItem:read', 'read'])] + #[Assert\NotNull] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] private string $type = ''; - /** - * @ORM\Column(type="string") - * - * @Serializer\Groups({"dashboardConfigItem:read", "read"}) - * - * @Assert\NotNull - */ + #[Serializer\Groups(['dashboardConfigItem:read', 'read'])] + #[Assert\NotNull] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] private string $position = ''; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $user = null; - /** - * @ORM\Column(type="json", options={"default": "[]", "jsonb": true}) - * - * @Serializer\Groups({"dashboardConfigItem:read"}) - */ + #[Serializer\Groups(['dashboardConfigItem:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, options: ['default' => '[]', 'jsonb' => true])] private array $metadata = []; public function getId(): ?int diff --git a/src/Bundle/ChillMainBundle/Entity/Embeddable/CommentEmbeddable.php b/src/Bundle/ChillMainBundle/Entity/Embeddable/CommentEmbeddable.php index cf858d60f..ea0d4ec29 100644 --- a/src/Bundle/ChillMainBundle/Entity/Embeddable/CommentEmbeddable.php +++ b/src/Bundle/ChillMainBundle/Entity/Embeddable/CommentEmbeddable.php @@ -11,29 +11,21 @@ declare(strict_types=1); namespace Chill\MainBundle\Entity\Embeddable; -use DateTime; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Embeddable - */ +#[ORM\Embeddable] class CommentEmbeddable { - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $comment = null; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTime $date = null; /** * Embeddable does not support associations. - * - * @ORM\Column(type="integer", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true)] private ?int $userId = null; public function getComment(): ?string @@ -69,10 +61,7 @@ class CommentEmbeddable $this->date = $date; } - /** - * @param int $userId - */ - public function setUserId($userId) + public function setUserId(?int $userId) { $this->userId = $userId; } diff --git a/src/Bundle/ChillMainBundle/Entity/Embeddable/PrivateCommentEmbeddable.php b/src/Bundle/ChillMainBundle/Entity/Embeddable/PrivateCommentEmbeddable.php index 3cfed7844..0c2af22f7 100644 --- a/src/Bundle/ChillMainBundle/Entity/Embeddable/PrivateCommentEmbeddable.php +++ b/src/Bundle/ChillMainBundle/Entity/Embeddable/PrivateCommentEmbeddable.php @@ -14,16 +14,13 @@ namespace Chill\MainBundle\Entity\Embeddable; use Chill\MainBundle\Entity\User; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Embeddable - */ +#[ORM\Embeddable] class PrivateCommentEmbeddable { /** - * @ORM\Column(type="json", nullable=false, options={"default": "{}"}) - * * @var array */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '{}'])] private array $comments = []; public function getCommentForUser(User $user): string @@ -60,7 +57,7 @@ class PrivateCommentEmbeddable return $this; } - public function setComments($comments) + public function setComments(array $comments) { $this->comments = $comments; diff --git a/src/Bundle/ChillMainBundle/Entity/GeographicalUnit.php b/src/Bundle/ChillMainBundle/Entity/GeographicalUnit.php index 5c70b7bfe..668f95482 100644 --- a/src/Bundle/ChillMainBundle/Entity/GeographicalUnit.php +++ b/src/Bundle/ChillMainBundle/Entity/GeographicalUnit.php @@ -13,43 +13,26 @@ namespace Chill\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Table(name="chill_main_geographical_unit", uniqueConstraints={ - * - * @ORM\UniqueConstraint(name="geographical_unit_refid", columns={"layer_id", "unitRefId"}) - * }) - * - * @ORM\Entity(readOnly=true) - */ +#[ORM\Entity(readOnly: true)] +#[ORM\Table(name: 'chill_main_geographical_unit')] +#[ORM\UniqueConstraint(name: 'geographical_unit_refid', columns: ['layer_id', 'unitRefId'])] class GeographicalUnit { - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private string $geom; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=GeographicalUnitLayer::class, inversedBy="units") - */ + #[ORM\ManyToOne(targetEntity: GeographicalUnitLayer::class, inversedBy: 'units')] private ?GeographicalUnitLayer $layer = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $unitName; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $unitRefId; public function getId(): ?int diff --git a/src/Bundle/ChillMainBundle/Entity/GeographicalUnit/SimpleGeographicalUnitDTO.php b/src/Bundle/ChillMainBundle/Entity/GeographicalUnit/SimpleGeographicalUnitDTO.php index fda115208..481b530d9 100644 --- a/src/Bundle/ChillMainBundle/Entity/GeographicalUnit/SimpleGeographicalUnitDTO.php +++ b/src/Bundle/ChillMainBundle/Entity/GeographicalUnit/SimpleGeographicalUnitDTO.php @@ -25,34 +25,29 @@ class SimpleGeographicalUnitDTO * @readonly * * @psalm-readonly - * - * @Serializer\Groups({"read"}) */ + #[Serializer\Groups(['read'])] public int $id, /** * @readonly * * @psalm-readonly - * - * @Serializer\Groups({"read"}) */ + #[Serializer\Groups(['read'])] public string $unitName, /** * @readonly * * @psalm-readonly - * - * @Serializer\Groups({"read"}) */ + #[Serializer\Groups(['read'])] public string $unitRefId, /** * @readonly * * @psalm-readonly - * - * @Serializer\Groups({"read"}) */ + #[Serializer\Groups(['read'])] public int $layerId, - ) { - } + ) {} } diff --git a/src/Bundle/ChillMainBundle/Entity/GeographicalUnitLayer.php b/src/Bundle/ChillMainBundle/Entity/GeographicalUnitLayer.php index c875fecd4..5b311b465 100644 --- a/src/Bundle/ChillMainBundle/Entity/GeographicalUnitLayer.php +++ b/src/Bundle/ChillMainBundle/Entity/GeographicalUnitLayer.php @@ -16,46 +16,29 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Table(name="chill_main_geographical_unit_layer", uniqueConstraints={ - * - * @ORM\UniqueConstraint(name="geographical_unit_layer_refid", columns={"refId"}) - * }) - * - * @ORM\Entity - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_main_geographical_unit_layer')] +#[ORM\UniqueConstraint(name: 'geographical_unit_layer_refid', columns: ['refId'])] class GeographicalUnitLayer { - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="json", nullable=false, options={"default": "[]"}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '[]'])] private array $name = []; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $refId = ''; /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=GeographicalUnit::class, mappedBy="layer") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'layer', targetEntity: GeographicalUnit::class)] private Collection $units; public function __construct() diff --git a/src/Bundle/ChillMainBundle/Entity/GroupCenter.php b/src/Bundle/ChillMainBundle/Entity/GroupCenter.php index bcd4bc8bd..5a1349bcc 100644 --- a/src/Bundle/ChillMainBundle/Entity/GroupCenter.php +++ b/src/Bundle/ChillMainBundle/Entity/GroupCenter.php @@ -15,51 +15,28 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table(name="group_centers") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region") - */ +#[ORM\Entity] +#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'acl_cache_region')] +#[ORM\Table(name: 'group_centers')] class GroupCenter { - /** - * @ORM\ManyToOne( - * targetEntity="Chill\MainBundle\Entity\Center", - * inversedBy="groupCenters" - * ) - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE") - */ + #[ORM\ManyToOne(targetEntity: Center::class, inversedBy: 'groupCenters')] + #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE')] private ?Center $center = null; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\ManyToOne( - * targetEntity="Chill\MainBundle\Entity\PermissionsGroup", - * inversedBy="groupCenters") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE") - */ + #[ORM\ManyToOne(targetEntity: PermissionsGroup::class, inversedBy: 'groupCenters')] + #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE')] private ?PermissionsGroup $permissionsGroup = null; /** - * @ORM\ManyToMany( - * targetEntity="Chill\MainBundle\Entity\User", - * mappedBy="groupCenters" - * ) - * - * @var Collection + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'groupCenters')] private Collection $users; /** diff --git a/src/Bundle/ChillMainBundle/Entity/Language.php b/src/Bundle/ChillMainBundle/Entity/Language.php index 1a91de7b8..894b929ac 100644 --- a/src/Bundle/ChillMainBundle/Entity/Language.php +++ b/src/Bundle/ChillMainBundle/Entity/Language.php @@ -16,35 +16,24 @@ use Symfony\Component\Serializer\Annotation as Serializer; /** * Language. - * - * @ORM\Entity - * - * @ORM\Table(name="language") - * - * @ORM\Cache(usage="READ_ONLY", region="language_cache_region") - * - * @ORM\HasLifecycleCallbacks */ +#[ORM\Entity] +#[ORM\Cache(usage: 'READ_ONLY', region: 'language_cache_region')] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'language')] class Language { - /** - * @ORM\Id - * - * @ORM\Column(type="string") - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Id] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] private ?string $id = null; /** * @var string array - * - * @ORM\Column(type="json") - * - * @Serializer\Groups({"docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $name = []; /** @@ -70,11 +59,9 @@ class Language /** * Set id. * - * @param string $id - * * @return Language */ - public function setId($id) + public function setId(?string $id) { $this->id = $id; @@ -88,7 +75,7 @@ class Language * * @return Language */ - public function setName($name) + public function setName(array $name) { $this->name = $name; diff --git a/src/Bundle/ChillMainBundle/Entity/Location.php b/src/Bundle/ChillMainBundle/Entity/Location.php index 29a049d35..228fd089f 100644 --- a/src/Bundle/ChillMainBundle/Entity/Location.php +++ b/src/Bundle/ChillMainBundle/Entity/Location.php @@ -20,118 +20,67 @@ use libphonenumber\PhoneNumber; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; -/** - * @ORM\Table(name="chill_main_location") - * - * @ORM\Entity(repositoryClass=LocationRepository::class) - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "location": Location::class - * }) - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['location' => Location::class])] +#[ORM\Entity(repositoryClass: LocationRepository::class)] +#[ORM\Table(name: 'chill_main_location')] class Location implements TrackCreationInterface, TrackUpdateInterface { - /** - * @ORM\Column(type="boolean", nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: true)] private bool $active = true; - /** - * @ORM\ManyToOne(targetEntity=Address::class, cascade={"persist"}) - * - * @ORM\JoinColumn(nullable=true) - * - * @Serializer\Groups({"read", "write", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'write', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: Address::class, cascade: ['persist'])] + #[ORM\JoinColumn(nullable: true)] private ?Address $address = null; - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $availableForUsers = false; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $createdAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $createdBy = null; - /** - * @ORM\Column(type="string", length=255, nullable=true) - * - * @Serializer\Groups({"read", "write", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] private ?string $email = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=LocationType::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Serializer\Groups({"read", "write", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'write', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: LocationType::class)] + #[ORM\JoinColumn(nullable: false)] private ?LocationType $locationType = null; - /** - * @ORM\Column(type="string", length=255, nullable=true) - * - * @Serializer\Groups({"read", "write", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] private ?string $name = null; - /** - * @ORM\Column(type="phone_number", nullable=true) - * - * @Serializer\Groups({"read", "write", "docgen:read"}) - * - * @PhonenumberConstraint(type="any") - */ + #[Serializer\Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: 'phone_number', nullable: true)] + #[PhonenumberConstraint(type: 'any')] private ?PhoneNumber $phonenumber1 = null; - /** - * @ORM\Column(type="phone_number", nullable=true) - * - * @Serializer\Groups({"read", "write", "docgen:read"}) - * - * @PhonenumberConstraint(type="any") - */ + #[Serializer\Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: 'phone_number', nullable: true)] + #[PhonenumberConstraint(type: 'any')] private ?PhoneNumber $phonenumber2 = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $updatedAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $updatedBy = null; public function getActive(): ?bool diff --git a/src/Bundle/ChillMainBundle/Entity/LocationType.php b/src/Bundle/ChillMainBundle/Entity/LocationType.php index c6a176ab6..df212646a 100644 --- a/src/Bundle/ChillMainBundle/Entity/LocationType.php +++ b/src/Bundle/ChillMainBundle/Entity/LocationType.php @@ -17,17 +17,10 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; -/** - * @ORM\Table(name="chill_main_location_type") - * - * @ORM\Entity(repositoryClass=LocationTypeRepository::class) - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "location-type": LocationType::class - * }) - * - * @UniqueEntity({"defaultFor"}) - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['location-type' => LocationType::class])] +#[UniqueEntity(['defaultFor'])] +#[ORM\Entity(repositoryClass: LocationTypeRepository::class)] +#[ORM\Table(name: 'chill_main_location_type')] class LocationType { final public const DEFAULT_FOR_3PARTY = 'thirdparty'; @@ -40,66 +33,39 @@ class LocationType final public const STATUS_REQUIRED = 'required'; - /** - * @ORM\Column(type="boolean", nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: true)] private bool $active = true; - /** - * @ORM\Column(type="string", length=32, options={"default": "optional"}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 32, options: ['default' => 'optional'])] private string $addressRequired = self::STATUS_OPTIONAL; - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $availableForUsers = true; - /** - * @ORM\Column(type="string", length=32, options={"default": "optional"}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 32, options: ['default' => 'optional'])] private string $contactData = self::STATUS_OPTIONAL; - /** - * @ORM\Column(type="string", nullable=true, length=32, unique=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true, length: 32, unique: true)] private ?string $defaultFor = null; - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $editableByUsers = true; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $title = []; public function getActive(): ?bool diff --git a/src/Bundle/ChillMainBundle/Entity/NewsItem.php b/src/Bundle/ChillMainBundle/Entity/NewsItem.php index 604c58c5f..7acf2de86 100644 --- a/src/Bundle/ChillMainBundle/Entity/NewsItem.php +++ b/src/Bundle/ChillMainBundle/Entity/NewsItem.php @@ -19,66 +19,40 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_main_news") - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_main_news')] class NewsItem implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="text") - * - * @Groups({"read"}) - * - * @Assert\NotBlank - * - * @Assert\NotNull - */ + #[Groups(['read'])] + #[Assert\NotBlank] + #[Assert\NotNull] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $title = ''; - /** - * @ORM\Column(type="text") - * - * @Groups({"read"}) - * - * @Assert\NotBlank - * - * @Assert\NotNull - */ + #[Groups(['read'])] + #[Assert\NotBlank] + #[Assert\NotNull] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $content = ''; - /** - * @ORM\Column(type="date_immutable", nullable=false) - * - * @Assert\NotNull - * - * @Groups({"read"}) - */ + #[Assert\NotNull] + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)] private ?\DateTimeImmutable $startDate = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Assert\GreaterThanOrEqual(propertyPath="startDate") - * - * @Groups({"read"}) - */ + #[Assert\GreaterThanOrEqual(propertyPath: 'startDate')] + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; public function getTitle(): string diff --git a/src/Bundle/ChillMainBundle/Entity/Notification.php b/src/Bundle/ChillMainBundle/Entity/Notification.php index 8604b5ee1..d85a144b0 100644 --- a/src/Bundle/ChillMainBundle/Entity/Notification.php +++ b/src/Bundle/ChillMainBundle/Entity/Notification.php @@ -18,44 +18,30 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Context\ExecutionContextInterface; -/** - * @ORM\Entity - * - * @ORM\Table( - * name="chill_main_notification", - * indexes={ - * - * @ORM\Index(name="chill_main_notification_related_entity_idx", columns={"relatedentityclass", "relatedentityid"}) - * } - * ) - * - * @ORM\HasLifecycleCallbacks - */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'chill_main_notification')] +#[ORM\Index(name: 'chill_main_notification_related_entity_idx', columns: ['relatedentityclass', 'relatedentityid'])] class Notification implements TrackUpdateInterface { - /** - * @ORM\Column(type="text", nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false)] private string $accessKey; private array $addedAddresses = []; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_notification_addresses_user") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_notification_addresses_user')] private Collection $addressees; /** * a list of destinee which will receive notifications. * * @var array|string[] - * - * @ORM\Column(type="json") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $addressesEmails = []; /** @@ -68,76 +54,50 @@ class Notification implements TrackUpdateInterface private ?ArrayCollection $addressesOnLoad = null; /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=NotificationComment::class, mappedBy="notification", orphanRemoval=true) - * - * @ORM\OrderBy({"createdAt": "ASC"}) + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'notification', targetEntity: NotificationComment::class, orphanRemoval: true)] + #[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::ASC])] private Collection $comments; - /** - * @ORM\Column(type="datetime_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private \DateTimeImmutable $date; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $message = ''; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $relatedEntityClass = ''; - /** - * @ORM\Column(type="integer") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private int $relatedEntityId; private array $removedAddresses = []; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $sender = null; - /** - * @ORM\Column(type="text", options={"default": ""}) - * - * @Assert\NotBlank(message="notification.Title must be defined") - */ + #[Assert\NotBlank(message: 'notification.Title must be defined')] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => ''])] private string $title = ''; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_notification_addresses_unread") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_notification_addresses_unread')] private Collection $unreadBy; - /** - * @ORM\Column(type="datetime_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private ?\DateTimeImmutable $updatedAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $updatedBy = null; public function __construct() @@ -187,10 +147,9 @@ class Notification implements TrackUpdateInterface } /** - * @Assert\Callback - * * @param array $payload */ + #[Assert\Callback] public function assertCountAddresses(ExecutionContextInterface $context, $payload): void { if (0 === (\count($this->getAddressesEmails()) + \count($this->getAddressees()))) { @@ -314,9 +273,7 @@ class Notification implements TrackUpdateInterface return $this->addUnreadBy($user); } - /** - * @ORM\PreFlush - */ + #[ORM\PreFlush] public function registerUnread() { foreach ($this->addedAddresses as $addressee) { diff --git a/src/Bundle/ChillMainBundle/Entity/NotificationComment.php b/src/Bundle/ChillMainBundle/Entity/NotificationComment.php index 49d1e859d..53d3fba2f 100644 --- a/src/Bundle/ChillMainBundle/Entity/NotificationComment.php +++ b/src/Bundle/ChillMainBundle/Entity/NotificationComment.php @@ -18,48 +18,29 @@ use Doctrine\ORM\Event\PrePersistEventArgs; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table("chill_main_notification_comment") - * - * @ORM\HasLifecycleCallbacks - */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table('chill_main_notification_comment')] class NotificationComment implements TrackCreationInterface, TrackUpdateInterface { - /** - * @ORM\Column(type="text") - * - * @Assert\NotBlank(message="notification.Comment content might not be blank") - */ + #[Assert\NotBlank(message: 'notification.Comment content might not be blank')] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $content = ''; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $createdAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $createdBy = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=Notification::class, inversedBy="comments") - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: Notification::class, inversedBy: 'comments')] + #[ORM\JoinColumn(nullable: false)] private ?Notification $notification = null; /** @@ -71,16 +52,12 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac /** * TODO typo in property (hotfixed). - * - * @ORM\Column(type="datetime_immutable", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $updateAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $updatedBy = null; public function getContent(): string @@ -118,9 +95,7 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac return $this->updatedBy; } - /** - * @ORM\PreFlush - */ + #[ORM\PreFlush] public function onFlushMarkNotificationAsUnread(PreFlushEventArgs $eventArgs): void { if ($this->recentlyPersisted) { @@ -136,9 +111,7 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac } } - /** - * @ORM\PrePersist - */ + #[ORM\PrePersist] public function onPrePersist(PrePersistEventArgs $eventArgs): void { $this->recentlyPersisted = true; diff --git a/src/Bundle/ChillMainBundle/Entity/PermissionsGroup.php b/src/Bundle/ChillMainBundle/Entity/PermissionsGroup.php index 4a28267cd..4902fca95 100644 --- a/src/Bundle/ChillMainBundle/Entity/PermissionsGroup.php +++ b/src/Bundle/ChillMainBundle/Entity/PermissionsGroup.php @@ -16,56 +16,36 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Context\ExecutionContextInterface; -/** - * @ORM\Entity - * - * @ORM\Table(name="permission_groups") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region") - */ +#[ORM\Entity] +#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'acl_cache_region')] +#[ORM\Table(name: 'permission_groups')] class PermissionsGroup { /** * @var string[] - * - * @ORM\Column(type="json") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $flags = []; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\MainBundle\Entity\GroupCenter", - * mappedBy="permissionsGroup" - * ) + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'permissionsGroup', targetEntity: GroupCenter::class)] private Collection $groupCenters; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\Column(type="string", length=255, nullable=false, options={"default": ""}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: false, options: ['default' => ''])] private string $name = ''; /** - * @var Collection - * - * @ORM\ManyToMany( - * targetEntity="Chill\MainBundle\Entity\RoleScope", - * inversedBy="permissionsGroups", - * cascade={ "persist" }) - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: RoleScope::class, inversedBy: 'permissionsGroups', cascade: ['persist'])] + #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE')] private Collection $roleScopes; /** @@ -157,7 +137,7 @@ class PermissionsGroup /** * @return $this */ - public function setName($name) + public function setName(string $name) { $this->name = $name; diff --git a/src/Bundle/ChillMainBundle/Entity/PostalCode.php b/src/Bundle/ChillMainBundle/Entity/PostalCode.php index 4d906d6c8..ecab19a5f 100644 --- a/src/Bundle/ChillMainBundle/Entity/PostalCode.php +++ b/src/Bundle/ChillMainBundle/Entity/PostalCode.php @@ -21,24 +21,16 @@ use Symfony\Component\Serializer\Annotation\Groups; /** * PostalCode. - * - * @ORM\Entity - * - * @ORM\Table( - * name="chill_main_postal_code", - * uniqueConstraints={ - * - * @ORM\UniqueConstraint(name="postal_code_import_unicity", columns={"code", "refpostalcodeid", "postalcodesource"}, - * options={"where": "refpostalcodeid is not null"}) - * }, - * indexes={ - * - * @ORM\Index(name="search_name_code", columns={"code", "label"}), - * @ORM\Index(name="search_by_reference_code", columns={"code", "refpostalcodeid"}) - * }) - * - * @ORM\HasLifecycleCallbacks */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'chill_main_postal_code')] +#[ORM\Index(name: 'search_name_code', columns: ['code', 'label'])] +#[ORM\Index(name: 'search_by_reference_code', columns: ['code', 'refpostalcodeid'])] +#[ORM\UniqueConstraint(name: 'postal_code_import_unicity', columns: ['code', 'refpostalcodeid', 'postalcodesource'], options: ['where' => 'refpostalcodeid is not null'])] +#[ORM\UniqueConstraint(name: 'postal_code_import_unicity', columns: ['code', 'refpostalcodeid', 'postalcodesource'], options: ['where' => 'refpostalcodeid is not null'])] // , +#[ORM\Index(name: 'search_name_code', columns: ['code', 'label'])] // , +#[ORM\Index(name: 'search_by_reference_code', columns: ['code', 'refpostalcodeid'])] class PostalCode implements TrackUpdateInterface, TrackCreationInterface { use TrackCreationTrait; @@ -49,74 +41,45 @@ class PostalCode implements TrackUpdateInterface, TrackCreationInterface * This is an internal column which is populated by database. * * This column will ease the search operations - * - * @ORM\Column(type="text", options={"default": ""}) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => ''])] private string $canonical = ''; - /** - * @ORM\Column(type="point", nullable=true) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: 'point', nullable: true)] private ?Point $center = null; - /** - * @ORM\Column(type="string", length=100) - * - * @groups({"write", "read"}) - */ + #[Groups(['write', 'read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 100)] private ?string $code = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Country") - * - * @groups({"write", "read"}) - */ + #[Groups(['write', 'read'])] + #[ORM\ManyToOne(targetEntity: Country::class)] private ?Country $country = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $deletedAt = null; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @groups({"write", "read"}) - */ + #[Groups(['write', 'read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\Column(type="string", length=255, name="label") - * - * @groups({"write", "read"}) - */ + #[Groups(['write', 'read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, name: 'label')] private ?string $name = null; - /** - * @ORM\Column(name="origin", type="integer", nullable=true) - * - * @groups({"write", "read"}) - */ + #[Groups(['write', 'read'])] + #[ORM\Column(name: 'origin', type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true)] private int $origin = 0; - /** - * @ORM\Column(type="string", length=255, nullable=true) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] private ?string $postalCodeSource = null; - /** - * @ORM\Column(type="string", length=255, nullable=true) - * - * @groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] private ?string $refPostalCodeId = null; public function getCenter(): ?Point @@ -194,11 +157,9 @@ class PostalCode implements TrackUpdateInterface, TrackCreationInterface /** * Set code. * - * @param string $code - * * @return PostalCode */ - public function setCode($code) + public function setCode(?string $code) { $this->code = $code; @@ -220,11 +181,9 @@ class PostalCode implements TrackUpdateInterface, TrackCreationInterface /** * Set name. * - * @param string $name - * * @return PostalCode */ - public function setName($name) + public function setName(?string $name) { $this->name = $name; @@ -234,11 +193,9 @@ class PostalCode implements TrackUpdateInterface, TrackCreationInterface /** * Set origin. * - * @param int $origin - * * @return PostalCode */ - public function setOrigin($origin) + public function setOrigin(int $origin) { $this->origin = $origin; diff --git a/src/Bundle/ChillMainBundle/Entity/Regroupment.php b/src/Bundle/ChillMainBundle/Entity/Regroupment.php index 4945a62c7..389eceb31 100644 --- a/src/Bundle/ChillMainBundle/Entity/Regroupment.php +++ b/src/Bundle/ChillMainBundle/Entity/Regroupment.php @@ -15,42 +15,26 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table(name="regroupment") - */ +#[ORM\Entity] +#[ORM\Table(name: 'regroupment')] class Regroupment { /** - * @ORM\ManyToMany( - * targetEntity=Center::class, - * inversedBy="regroupments" - * ) - * - * @ORM\Id - * - * @var Collection
+ * @var Collection */ + #[ORM\ManyToMany(targetEntity: Center::class, inversedBy: 'regroupments')] + #[ORM\Id] private Collection $centers; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $isActive = true; - /** - * @ORM\Column(type="text", options={"default": ""}, nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => ''], nullable: false)] private string $name = ''; public function __construct() diff --git a/src/Bundle/ChillMainBundle/Entity/RoleScope.php b/src/Bundle/ChillMainBundle/Entity/RoleScope.php index 4777505f5..4048debb1 100644 --- a/src/Bundle/ChillMainBundle/Entity/RoleScope.php +++ b/src/Bundle/ChillMainBundle/Entity/RoleScope.php @@ -15,47 +15,28 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table(name="role_scopes") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region") - */ +#[ORM\Entity] +#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'acl_cache_region')] +#[ORM\Table(name: 'role_scopes')] class RoleScope { - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; /** - * @var Collection - * - * @ORM\ManyToMany( - * targetEntity="Chill\MainBundle\Entity\PermissionsGroup", - * mappedBy="roleScopes") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: PermissionsGroup::class, mappedBy: 'roleScopes')] private Collection $permissionsGroups; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private ?string $role = null; - /** - * @ORM\ManyToOne( - * targetEntity="Chill\MainBundle\Entity\Scope", - * inversedBy="roleScopes") - * - * @ORM\JoinColumn(nullable=true, name="scope_id") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE") - */ + #[ORM\ManyToOne(targetEntity: Scope::class, inversedBy: 'roleScopes')] + #[ORM\JoinColumn(nullable: true, name: 'scope_id')] + #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE')] private ?Scope $scope = null; public function __construct() diff --git a/src/Bundle/ChillMainBundle/Entity/SavedExport.php b/src/Bundle/ChillMainBundle/Entity/SavedExport.php index 224423783..eec6b83e4 100644 --- a/src/Bundle/ChillMainBundle/Entity/SavedExport.php +++ b/src/Bundle/ChillMainBundle/Entity/SavedExport.php @@ -20,53 +20,34 @@ use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_main_saved_export") - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_main_saved_export')] class SavedExport implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Assert\NotBlank - */ + #[Assert\NotBlank] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $description = ''; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $exportAlias; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="uuid", unique="true") - * - * @ORM\GeneratedValue(strategy="NONE") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: 'uuid', unique: true)] + #[ORM\GeneratedValue(strategy: 'NONE')] private UuidInterface $id; - /** - * @ORM\Column(type="json", nullable=false, options={"default": "[]"}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '[]'])] private array $options = []; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Assert\NotBlank - */ + #[Assert\NotBlank] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $title = ''; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private User $user; public function __construct() diff --git a/src/Bundle/ChillMainBundle/Entity/Scope.php b/src/Bundle/ChillMainBundle/Entity/Scope.php index 464d60488..dd04f8a47 100644 --- a/src/Bundle/ChillMainBundle/Entity/Scope.php +++ b/src/Bundle/ChillMainBundle/Entity/Scope.php @@ -18,55 +18,34 @@ use Symfony\Component\Serializer\Annotation\Context; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * - * @ORM\Table(name="scopes") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "scope": Scope::class - * }) - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['scope' => Scope::class])] +#[ORM\Entity] +#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'acl_cache_region')] +#[ORM\Table(name: 'scopes')] class Scope { - /** - * @ORM\Column(type="boolean", nullable=false, options={"default": true}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: false, options: ['default' => true])] private bool $active = true; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; /** * translatable names. - * - * @ORM\Column(type="json") - * - * @Groups({"read", "docgen:read"}) - * - * @Context({"is-translatable": true}, groups={"docgen:read"}) */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Context(['is-translatable' => true], groups: ['docgen:read'])] private array $name = []; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\MainBundle\Entity\RoleScope", - * mappedBy="scope") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'scope', targetEntity: RoleScope::class)] + #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE')] private Collection $roleScopes; /** diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index b94d90760..0c8c87553 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -19,6 +19,7 @@ use Doctrine\Common\Collections\Criteria; use Doctrine\Common\Collections\Selectable; use Doctrine\ORM\Mapping as ORM; use libphonenumber\PhoneNumber; +use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Context\ExecutionContextInterface; @@ -26,150 +27,93 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint; /** * User. - * - * @ORM\Entity - * - * @ORM\Table(name="users") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "user": User::class - * }) */ -class User implements UserInterface, \Stringable +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['user' => User::class])] +#[ORM\Entity] +#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'acl_cache_region')] +#[ORM\Table(name: 'users')] +class User implements UserInterface, \Stringable, PasswordAuthenticatedUserInterface { - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] protected ?int $id = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $absenceStart = null; /** * Array where SAML attributes's data are stored. - * - * @ORM\Column(type="json", nullable=false) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false)] private array $attributes = []; - /** - * @ORM\ManyToOne(targetEntity=Civility::class) - */ + #[ORM\ManyToOne(targetEntity: Civility::class)] private ?Civility $civility = null; - /** - * @ORM\ManyToOne(targetEntity=Location::class) - */ + #[ORM\ManyToOne(targetEntity: Location::class)] private ?Location $currentLocation = null; - /** - * @ORM\Column(type="string", length=150, nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 150, nullable: true)] private ?string $email = null; - /** - * @ORM\Column( - * type="string", - * length=150, - * nullable=true, - * unique=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 150, nullable: true, unique: true)] private ?string $emailCanonical = null; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $enabled = true; /** - * @var Collection - * - * @ORM\ManyToMany( - * targetEntity="Chill\MainBundle\Entity\GroupCenter", - * inversedBy="users") - * - * @ORM\Cache(usage="NONSTRICT_READ_WRITE") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: GroupCenter::class, inversedBy: 'users')] + #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE')] private Collection $groupCenters; - /** - * @ORM\Column(type="string", length=200) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 200)] private string $label = ''; - /** - * @ORM\Column(type="boolean") - * sf4 check: in yml was false by default !? - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] // sf4 check: in yml was false by default !? private bool $locked = true; - /** - * @ORM\ManyToOne(targetEntity=Center::class) - */ + #[ORM\ManyToOne(targetEntity: Center::class)] private ?Center $mainCenter = null; - /** - * @ORM\ManyToOne(targetEntity=Location::class) - */ + #[ORM\ManyToOne(targetEntity: Location::class)] private ?Location $mainLocation = null; /** - * @var Collection&Selectable - * - * @ORM\OneToMany(targetEntity=UserScopeHistory::class, - * mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true) + * @var \Doctrine\Common\Collections\Collection&Selectable */ + #[ORM\OneToMany(mappedBy: 'user', targetEntity: UserScopeHistory::class, cascade: ['persist', 'remove'], orphanRemoval: true)] private Collection&Selectable $scopeHistories; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $password = ''; /** * @internal must be set to null if we use bcrypt - * - * @ORM\Column(type="string", length=255, nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] private ?string $salt = null; /** - * @var Collection&Selectable - * - * @ORM\OneToMany(targetEntity=UserJobHistory::class, - * mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true) + * @var \Doctrine\Common\Collections\Collection&Selectable */ + #[ORM\OneToMany(mappedBy: 'user', targetEntity: UserJobHistory::class, cascade: ['persist', 'remove'], orphanRemoval: true)] private Collection&Selectable $jobHistories; - /** - * @ORM\Column(type="string", length=80) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 80)] private string $username = ''; - /** - * @ORM\Column( - * type="string", - * length=80, - * unique=true, - * nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 80, unique: true, nullable: true)] private ?string $usernameCanonical = null; /** * The user's mobile phone number. - * - * @ORM\Column(type="phone_number", nullable=true) - * - * @PhonenumberConstraint() */ + #[ORM\Column(type: 'phone_number', nullable: true)] + #[PhonenumberConstraint] private ?PhoneNumber $phonenumber = null; /** @@ -197,9 +141,7 @@ class User implements UserInterface, \Stringable return $this; } - public function eraseCredentials() - { - } + public function eraseCredentials() {} public function getAbsenceStart(): ?\DateTimeImmutable { @@ -308,10 +250,7 @@ class User implements UserInterface, \Stringable return new ArrayCollection($sortedScopeHistories); } - /** - * @return string - */ - public function getPassword() + public function getPassword(): ?string { return $this->password; } @@ -373,6 +312,11 @@ class User implements UserInterface, \Stringable return $this->username; } + public function getUserIdentifier(): string + { + return $this->username; + } + /** * @return string */ @@ -493,7 +437,7 @@ class User implements UserInterface, \Stringable /** * @return $this */ - public function setEmail($email) + public function setEmail(?string $email) { $this->email = $email; @@ -503,7 +447,7 @@ class User implements UserInterface, \Stringable /** * @return $this */ - public function setEmailCanonical($emailCanonical) + public function setEmailCanonical(?string $emailCanonical) { $this->emailCanonical = $emailCanonical; @@ -554,7 +498,7 @@ class User implements UserInterface, \Stringable $this->scopeHistories[] = $newScope; $criteria = new Criteria(); - $criteria->orderBy(['startDate' => \Doctrine\Common\Collections\Order::Ascending, 'id' => \Doctrine\Common\Collections\Order::Ascending]); + $criteria->orderBy(['startDate' => 'ASC', 'id' => 'ASC']); /** @var \Iterator $scopes */ $scopes = $this->scopeHistories->matching($criteria)->getIterator(); @@ -577,7 +521,7 @@ class User implements UserInterface, \Stringable /** * @return $this */ - public function setPassword($password) + public function setPassword(string $password) { $this->password = $password; @@ -587,7 +531,7 @@ class User implements UserInterface, \Stringable /** * @return $this */ - public function setSalt($salt) + public function setSalt(?string $salt) { $this->salt = $salt; @@ -649,7 +593,7 @@ class User implements UserInterface, \Stringable /** * @return $this */ - public function setUsernameCanonical($usernameCanonical) + public function setUsernameCanonical(?string $usernameCanonical) { $this->usernameCanonical = $usernameCanonical; diff --git a/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php b/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php index 7916d9891..4437b7356 100644 --- a/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php +++ b/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php @@ -11,45 +11,29 @@ declare(strict_types=1); namespace Chill\MainBundle\Entity\User; -use App\Repository\UserJobHistoryRepository; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\UserJob; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Table(name="chill_main_user_job_history") - * - * @ORM\Entity(repositoryClass=UserJobHistoryRepository::class) - */ +#[ORM\Entity(repositoryClass: \Chill\MainBundle\Repository\User\UserJobHistoryRepository::class)] +#[ORM\Table(name: 'chill_main_user_job_history')] class UserJobHistory { - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=UserJob::class) - */ + #[ORM\ManyToOne(targetEntity: UserJob::class)] private ?UserJob $job = null; - /** - * @ORM\Column(type="datetime_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private \DateTimeImmutable $startDate; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private User $user; public function getEndDate(): ?\DateTimeImmutable diff --git a/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php b/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php index 6ac768de2..64ecbfd64 100644 --- a/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php +++ b/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php @@ -11,45 +11,30 @@ declare(strict_types=1); namespace Chill\MainBundle\Entity\User; -use App\Repository\UserScopeHistoryRepository; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Repository\User\UserScopeHistoryRepository; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Table(name="chill_main_user_scope_history") - * - * @ORM\Entity(repositoryClass=UserScopeHistoryRepository::class) - */ +#[ORM\Entity(repositoryClass: UserScopeHistoryRepository::class)] +#[ORM\Table(name: 'chill_main_user_scope_history')] class UserScopeHistory { - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=Scope::class) - */ + #[ORM\ManyToOne(targetEntity: Scope::class)] private ?Scope $scope = null; - /** - * @ORM\Column(type="datetime_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private \DateTimeImmutable $startDate; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private User $user; public function getEndDate(): ?\DateTimeImmutable diff --git a/src/Bundle/ChillMainBundle/Entity/UserJob.php b/src/Bundle/ChillMainBundle/Entity/UserJob.php index 6be1a5efe..2efb85e34 100644 --- a/src/Bundle/ChillMainBundle/Entity/UserJob.php +++ b/src/Bundle/ChillMainBundle/Entity/UserJob.php @@ -14,42 +14,26 @@ namespace Chill\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table("chill_main_user_job") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "user_job": UserJob::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['user_job' => UserJob::class])] +#[ORM\Entity] +#[ORM\Table('chill_main_user_job')] class UserJob { - /** - * @ORM\Column(name="active", type="boolean") - */ + #[ORM\Column(name: 'active', type: \Doctrine\DBAL\Types\Types::BOOLEAN)] protected bool $active = true; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] protected ?int $id = null; /** * @var array - * - * @ORM\Column(name="label", type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(name: 'label', type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] protected array $label = []; public function getId(): ?int diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php index e26547428..89efde7c0 100644 --- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php @@ -17,23 +17,18 @@ use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Workflow\Validator\EntityWorkflowCreation; +use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Selectable; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table("chill_main_workflow_entity") - * - * @EntityWorkflowCreation(groups={"creation"}) - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "entity_workflow": EntityWorkflow::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['entity_workflow' => EntityWorkflow::class])] +#[ORM\Entity] +#[ORM\Table('chill_main_workflow_entity')] +#[EntityWorkflowCreation(groups: ['creation'])] class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; @@ -41,70 +36,29 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface use TrackUpdateTrait; /** - * a list of future cc users for the next steps. - * - * @var array|User[] - */ - public array $futureCcUsers = []; - - /** - * a list of future dest emails for the next steps. - * - * This is in used in order to let controller inform who will be the future emails which will validate - * the next step. This is necessary to perform some computation about the next emails, before they are - * associated to the entity EntityWorkflowStep. - * - * @var array|string[] - */ - public array $futureDestEmails = []; - - /** - * a list of future dest users for the next steps. - * - * This is in used in order to let controller inform who will be the future users which will validate - * the next step. This is necessary to perform some computation about the next users, before they are - * associated to the entity EntityWorkflowStep. - * - * @var array|User[] - */ - public array $futureDestUsers = []; - - /** - * @ORM\OneToMany(targetEntity=EntityWorkflowComment::class, mappedBy="entityWorkflow", orphanRemoval=true) - * - * @var Collection + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'entityWorkflow', targetEntity: EntityWorkflowComment::class, orphanRemoval: true)] private Collection $comments; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $relatedEntityClass = ''; - /** - * @ORM\Column(type="integer") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private int $relatedEntityId; /** - * @ORM\OneToMany(targetEntity=EntityWorkflowStep::class, mappedBy="entityWorkflow", orphanRemoval=true, cascade={"persist"}) - * - * @ORM\OrderBy({"transitionAt": "ASC", "id": "ASC"}) - * - * @Assert\Valid(traverse=true) - * - * @var Collection + * @var Collection&Selectable */ - private Collection $steps; + #[Assert\Valid(traverse: true)] + #[ORM\OneToMany(mappedBy: 'entityWorkflow', targetEntity: EntityWorkflowStep::class, cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['transitionAt' => \Doctrine\Common\Collections\Criteria::ASC, 'id' => 'ASC'])] + private Collection&Selectable $steps; /** * @var array|EntityWorkflowStep[]|null @@ -112,21 +66,17 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface private ?array $stepsChainedCache = null; /** - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_workflow_entity_subscriber_to_final") - * - * @var Collection + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_workflow_entity_subscriber_to_final')] private Collection $subscriberToFinal; /** - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_workflow_entity_subscriber_to_step") - * - * @var Collection + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_workflow_entity_subscriber_to_step')] private Collection $subscriberToStep; /** @@ -134,9 +84,7 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface */ private ?EntityWorkflowStep $transitionningStep = null; - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $workflowName; public function __construct() @@ -295,17 +243,21 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface throw new \RuntimeException(); } - public function getSteps(): ArrayCollection|Collection + public function getSteps(): Collection&Selectable { return $this->steps; } + /** + * @throws \Exception + */ public function getStepsChained(): array { if (\is_array($this->stepsChainedCache)) { return $this->stepsChainedCache; } + /** @var \ArrayIterator $iterator */ $iterator = $this->steps->getIterator(); $current = null; $steps = []; @@ -366,7 +318,7 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface } } - return $usersInvolved; + return array_values($usersInvolved); } public function getWorkflowName(): string @@ -387,8 +339,6 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface public function isFreeze(): bool { - $steps = $this->getStepsChained(); - foreach ($this->getStepsChained() as $step) { if ($step->isFreezeAfter()) { return true; @@ -398,6 +348,11 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface return false; } + public function isOnHoldByUser(User $user): bool + { + return $this->getCurrentStep()->isOnHoldByUser($user); + } + public function isUserSubscribedToFinal(User $user): bool { return $this->subscriberToFinal->contains($user); @@ -466,11 +421,47 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface * * @return $this */ - public function setStep(string $step): self - { + public function setStep( + string $step, + WorkflowTransitionContextDTO $transitionContextDTO, + string $transition, + \DateTimeImmutable $transitionAt, + ?User $byUser = null, + ): self { + $previousStep = $this->getCurrentStep(); + + $previousStep + ->setTransitionAfter($transition) + ->setTransitionAt($transitionAt) + ->setTransitionBy($byUser); + $newStep = new EntityWorkflowStep(); $newStep->setCurrentStep($step); + foreach ($transitionContextDTO->futureCcUsers as $user) { + $newStep->addCcUser($user); + } + + foreach ($transitionContextDTO->futureDestUsers as $user) { + $newStep->addDestUser($user); + } + + if (null !== $transitionContextDTO->futureUserSignature) { + $newStep->addDestUser($transitionContextDTO->futureUserSignature); + } + + foreach ($transitionContextDTO->futureDestEmails as $email) { + $newStep->addDestEmail($email); + } + + if (null !== $transitionContextDTO->futureUserSignature) { + new EntityWorkflowStepSignature($newStep, $transitionContextDTO->futureUserSignature); + } else { + foreach ($transitionContextDTO->futurePersonSignatures as $personSignature) { + new EntityWorkflowStepSignature($newStep, $personSignature); + } + } + // copy the freeze if ($this->isFreeze()) { $newStep->setFreezeAfter(true); @@ -496,4 +487,41 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface return $this->steps->get($this->steps->count() - 2); } + + public function isOnHoldAtCurrentStep(): bool + { + return $this->getCurrentStep()->getHoldsOnStep()->count() > 0; + } + + /** + * Determines if the workflow has become stale after a given date. + * + * This function checks the creation date and the transition states of the workflow steps. + * A workflow is considered stale if: + * - The creation date is before the given date and no transitions have occurred since the creation. + * - Or if there are no transitions after the given date. + * + * @param \DateTimeImmutable $at the date to compare against the workflow's status + * + * @return bool true if the workflow is stale after the given date, false otherwise + */ + public function isStaledAt(\DateTimeImmutable $at): bool + { + // if there is no transition since the creation, then the workflow is staled + if ('initial' === $this->getCurrentStep()->getCurrentStep() + && null === $this->getCurrentStep()->getTransitionAt() + ) { + if (null === $this->getCreatedAt()) { + return false; + } + + if ($this->getCreatedAt() < $at) { + return true; + } + + return false; + } + + return $this->getCurrentStepChained()->getPrevious()->getTransitionAt() < $at; + } } diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowComment.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowComment.php index 9b02bbb9e..2943e5cff 100644 --- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowComment.php +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowComment.php @@ -17,34 +17,23 @@ use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table("chill_main_workflow_entity_comment") - */ +#[ORM\Entity] +#[ORM\Table('chill_main_workflow_entity_comment')] class EntityWorkflowComment implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Column(type="text", options={"default": ""}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => ''])] private string $comment = ''; - /** - * @ORM\ManyToOne(targetEntity=EntityWorkflow::class, inversedBy="comments") - */ + #[ORM\ManyToOne(targetEntity: EntityWorkflow::class, inversedBy: 'comments')] private ?EntityWorkflow $entityWorkflow = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; public function getComment(): string diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSignatureStateEnum.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSignatureStateEnum.php new file mode 100644 index 000000000..2d3e4269f --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSignatureStateEnum.php @@ -0,0 +1,20 @@ + - * - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_workflow_entity_step_cc_user") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_workflow_entity_step_cc_user')] private Collection $ccUser; - /** - * @ORM\Column(type="text", options={"default": ""}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => ''])] private string $comment = ''; - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private ?string $currentStep = ''; - /** - * @ORM\Column(type="json") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $destEmail = []; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_workflow_entity_step_user") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_workflow_entity_step_user')] private Collection $destUser; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=User::class) - * - * @ORM\JoinTable(name="chill_main_workflow_entity_step_user_by_accesskey") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_workflow_entity_step_user_by_accesskey')] private Collection $destUserByAccessKey; /** - * @ORM\ManyToOne(targetEntity=EntityWorkflow::class, inversedBy="steps") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'step', targetEntity: EntityWorkflowStepSignature::class, cascade: ['persist'], orphanRemoval: true)] + private Collection $signatures; + + #[ORM\ManyToOne(targetEntity: EntityWorkflow::class, inversedBy: 'steps')] private ?EntityWorkflow $entityWorkflow = null; - /** - * @ORM\Column(type="boolean", options={"default": false}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $freezeAfter = false; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="boolean", options={"default": false}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $isFinal = false; /** @@ -106,33 +85,32 @@ class EntityWorkflowStep */ private ?EntityWorkflowStep $previous = null; - /** - * @ORM\Column(type="text", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true, options: ['default' => null])] private ?string $transitionAfter = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $transitionAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $transitionBy = null; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $transitionByEmail = null; + /** + * @var \Doctrine\Common\Collections\Collection + */ + #[ORM\OneToMany(mappedBy: 'step', targetEntity: EntityWorkflowStepHold::class)] + private Collection $holdsOnStep; + public function __construct() { $this->ccUser = new ArrayCollection(); $this->destUser = new ArrayCollection(); $this->destUserByAccessKey = new ArrayCollection(); + $this->signatures = new ArrayCollection(); + $this->holdsOnStep = new ArrayCollection(); $this->accessKey = bin2hex(openssl_random_pseudo_bytes(32)); } @@ -172,6 +150,27 @@ class EntityWorkflowStep return $this; } + /** + * @internal use @see{EntityWorkflowStepSignature}'s constructor instead + */ + public function addSignature(EntityWorkflowStepSignature $signature): self + { + if (!$this->signatures->contains($signature)) { + $this->signatures[] = $signature; + } + + return $this; + } + + public function removeSignature(EntityWorkflowStepSignature $signature): self + { + if ($this->signatures->contains($signature)) { + $this->signatures->removeElement($signature); + } + + return $this; + } + public function getAccessKey(): string { return $this->accessKey; @@ -234,6 +233,14 @@ class EntityWorkflowStep return $this->entityWorkflow; } + /** + * @return Collection + */ + public function getSignatures(): Collection + { + return $this->signatures; + } + public function getId(): ?int { return $this->id; @@ -279,6 +286,17 @@ class EntityWorkflowStep return $this->freezeAfter; } + public function isOnHoldByUser(User $user): bool + { + foreach ($this->getHoldsOnStep() as $onHold) { + if ($onHold->getByUser() === $user) { + return true; + } + } + + return false; + } + public function isWaitingForTransition(): bool { if (null !== $this->transitionAfter) { @@ -413,9 +431,12 @@ class EntityWorkflowStep return $this; } - /** - * @Assert\Callback - */ + public function getHoldsOnStep(): Collection + { + return $this->holdsOnStep; + } + + #[Assert\Callback] public function validateOnCreation(ExecutionContextInterface $context, mixed $payload): void { return; @@ -434,4 +455,13 @@ class EntityWorkflowStep } } } + + public function addOnHold(EntityWorkflowStepHold $onHold): self + { + if (!$this->holdsOnStep->contains($onHold)) { + $this->holdsOnStep->add($onHold); + } + + return $this; + } } diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepHold.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepHold.php new file mode 100644 index 000000000..3d163dfc5 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepHold.php @@ -0,0 +1,54 @@ +addOnHold($this); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getStep(): EntityWorkflowStep + { + return $this->step; + } + + public function getByUser(): User + { + return $this->byUser; + } +} diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepSignature.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepSignature.php new file mode 100644 index 000000000..5b659d844 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStepSignature.php @@ -0,0 +1,196 @@ + null])] + private ?\DateTimeImmutable $stateDate = null; + + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '[]'])] + private array $signatureMetadata = []; + + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])] + private ?int $zoneSignatureIndex = null; + + public function __construct( + #[ORM\ManyToOne(targetEntity: EntityWorkflowStep::class, inversedBy: 'signatures')] + private EntityWorkflowStep $step, + User|Person $signer, + ) { + $this->step->addSignature($this); + $this->setSigner($signer); + } + + private function setSigner(User|Person $signer): void + { + if ($signer instanceof User) { + $this->userSigner = $signer; + } else { + $this->personSigner = $signer; + } + } + + public function getId(): ?int + { + return $this->id; + } + + public function getStep(): EntityWorkflowStep + { + return $this->step; + } + + public function getSigner(): User|Person + { + if (null !== $this->userSigner) { + return $this->userSigner; + } + + return $this->personSigner; + } + + public function getSignatureMetadata(): array + { + return $this->signatureMetadata; + } + + public function setSignatureMetadata(array $signatureMetadata): EntityWorkflowStepSignature + { + $this->signatureMetadata = $signatureMetadata; + + return $this; + } + + public function getState(): EntityWorkflowSignatureStateEnum + { + return $this->state; + } + + /** + * @return $this + * + * @internal You should not use this method directly, use @see{Chill\MainBundle\Workflow\SignatureStepStateChanger} instead + */ + public function setState(EntityWorkflowSignatureStateEnum $state): EntityWorkflowStepSignature + { + $this->state = $state; + + return $this; + } + + public function getStateDate(): ?\DateTimeImmutable + { + return $this->stateDate; + } + + /** + * @return $this + * + * @internal You should not use this method directly, use @see{Chill\MainBundle\Workflow\SignatureStepStateChanger} instead + */ + public function setStateDate(?\DateTimeImmutable $stateDate): EntityWorkflowStepSignature + { + $this->stateDate = $stateDate; + + return $this; + } + + public function getZoneSignatureIndex(): ?int + { + return $this->zoneSignatureIndex; + } + + /** + * @return $this + * + * @internal You should not use this method directly, use @see{Chill\MainBundle\Workflow\SignatureStepStateChanger} instead + */ + public function setZoneSignatureIndex(?int $zoneSignatureIndex): EntityWorkflowStepSignature + { + $this->zoneSignatureIndex = $zoneSignatureIndex; + + return $this; + } + + public function isSigned(): bool + { + return EntityWorkflowSignatureStateEnum::SIGNED == $this->getState(); + } + + public function isPending(): bool + { + return EntityWorkflowSignatureStateEnum::PENDING == $this->getState(); + } + + /** + * Checks whether all signatures associated with a given workflow step are not pending. + * + * Iterates over each signature in the provided workflow step, and returns false if any signature + * is found to be pending. If all signatures are not pending, returns true. + * + * @param EntityWorkflowStep $step the workflow step whose signatures are to be checked + * + * @return bool true if all signatures are not pending, false otherwise + */ + public static function isAllSignatureNotPendingForStep(EntityWorkflowStep $step): bool + { + foreach ($step->getSignatures() as $signature) { + if ($signature->isPending()) { + return false; + } + } + + return true; + } + + /** + * @return 'person'|'user' + */ + public function getSignerKind(): string + { + if ($this->personSigner instanceof Person) { + return 'person'; + } + + return 'user'; + } +} diff --git a/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php b/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php index 61ff268c4..ce43c230a 100644 --- a/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php +++ b/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php @@ -26,8 +26,7 @@ final readonly class ExportFormHelper private AuthorizationHelperForCurrentUserInterface $authorizationHelper, private ExportManager $exportManager, private FormFactoryInterface $formFactory, - ) { - } + ) {} public function getDefaultData(string $step, DirectExportInterface|ExportInterface $export, array $options = []): array { diff --git a/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php index 3be1af08a..0fad30b4f 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php @@ -15,9 +15,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class DateTimeHelper { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function getLabel($header): callable { diff --git a/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php index 07a4f9f88..9161316e7 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php @@ -79,9 +79,7 @@ class ExportAddressHelper */ private ?array $unitRefsKeysCache = []; - public function __construct(private readonly AddressRender $addressRender, private readonly AddressRepository $addressRepository, private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly AddressRender $addressRender, private readonly AddressRepository $addressRepository, private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function addSelectClauses(int $params, QueryBuilder $queryBuilder, $entityName = 'address', $prefix = 'add') { diff --git a/src/Bundle/ChillMainBundle/Export/Helper/TranslatableStringExportLabelHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/TranslatableStringExportLabelHelper.php index fc19f7466..1b561390a 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/TranslatableStringExportLabelHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/TranslatableStringExportLabelHelper.php @@ -21,9 +21,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelperInterface; */ class TranslatableStringExportLabelHelper { - public function __construct(private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function getLabel(string $key, array $values, string $header) { diff --git a/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php index 36b126df9..ee164b93c 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php @@ -16,9 +16,7 @@ use Chill\MainBundle\Templating\Entity\UserRender; class UserHelper { - public function __construct(private readonly UserRender $userRender, private readonly UserRepositoryInterface $userRepository) - { - } + public function __construct(private readonly UserRender $userRender, private readonly UserRepositoryInterface $userRepository) {} /** * Return a callable that will transform a value into a string representing a user. diff --git a/src/Bundle/ChillMainBundle/Export/ListInterface.php b/src/Bundle/ChillMainBundle/Export/ListInterface.php index 53442f0e7..9b88525ca 100644 --- a/src/Bundle/ChillMainBundle/Export/ListInterface.php +++ b/src/Bundle/ChillMainBundle/Export/ListInterface.php @@ -20,6 +20,4 @@ namespace Chill\MainBundle\Export; * * When used, the `ExportManager` will not handle aggregator for this class. */ -interface ListInterface extends ExportInterface -{ -} +interface ListInterface extends ExportInterface {} diff --git a/src/Bundle/ChillMainBundle/Export/SortExportElement.php b/src/Bundle/ChillMainBundle/Export/SortExportElement.php index 0536f6569..6228109ed 100644 --- a/src/Bundle/ChillMainBundle/Export/SortExportElement.php +++ b/src/Bundle/ChillMainBundle/Export/SortExportElement.php @@ -17,8 +17,7 @@ final readonly class SortExportElement { public function __construct( private TranslatorInterface $translator, - ) { - } + ) {} /** * @param array $elements diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/AddressDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/AddressDataMapper.php index c88e2275b..a4cab4a9b 100644 --- a/src/Bundle/ChillMainBundle/Form/DataMapper/AddressDataMapper.php +++ b/src/Bundle/ChillMainBundle/Form/DataMapper/AddressDataMapper.php @@ -28,7 +28,7 @@ class AddressDataMapper implements DataMapperInterface * @param Address $address * @param \Iterator $forms */ - public function mapDataToForms($address, $forms) + public function mapDataToForms($address, \Traversable $forms) { if (null === $address) { return; @@ -78,7 +78,7 @@ class AddressDataMapper implements DataMapperInterface * @param \Iterator $forms * @param Address $address */ - public function mapFormsToData($forms, &$address) + public function mapFormsToData(\Traversable $forms, &$address) { if (!$address instanceof Address) { $address = new Address(); diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php index 73d048c1a..2a19c8e0b 100644 --- a/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php +++ b/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php @@ -17,7 +17,7 @@ use Symfony\Component\Form\FormInterface; final readonly class ExportPickCenterDataMapper implements DataMapperInterface { - public function mapDataToForms($viewData, $forms): void + public function mapDataToForms($viewData, \Traversable $forms): void { if (null === $viewData) { return; @@ -31,7 +31,7 @@ final readonly class ExportPickCenterDataMapper implements DataMapperInterface // NOTE: we do not map back the regroupments } - public function mapFormsToData($forms, &$viewData): void + public function mapFormsToData(\Traversable $forms, &$viewData): void { /** @var array $forms */ $forms = iterator_to_array($forms); diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/PrivateCommentDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/PrivateCommentDataMapper.php index 10f9c26e3..3f1284db8 100644 --- a/src/Bundle/ChillMainBundle/Form/DataMapper/PrivateCommentDataMapper.php +++ b/src/Bundle/ChillMainBundle/Form/DataMapper/PrivateCommentDataMapper.php @@ -19,11 +19,9 @@ use Symfony\Component\Security\Core\Security; final class PrivateCommentDataMapper extends AbstractType implements DataMapperInterface { - public function __construct(private readonly Security $security) - { - } + public function __construct(private readonly Security $security) {} - public function mapDataToForms($viewData, $forms) + public function mapDataToForms($viewData, \Traversable $forms) { if (null === $viewData) { return null; @@ -38,7 +36,7 @@ final class PrivateCommentDataMapper extends AbstractType implements DataMapperI $forms['comments']->setData($viewData->getCommentForUser($this->security->getUser())); } - public function mapFormsToData($forms, &$viewData) + public function mapFormsToData(\Traversable $forms, &$viewData) { $forms = iterator_to_array($forms); diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php index 6a139de7b..254860e64 100644 --- a/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php +++ b/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php @@ -17,7 +17,7 @@ use Symfony\Component\Form\Exception; class RollingDateDataMapper implements DataMapperInterface { - public function mapDataToForms($viewData, $forms) + public function mapDataToForms($viewData, \Traversable $forms) { if (null === $viewData) { return; @@ -33,7 +33,7 @@ class RollingDateDataMapper implements DataMapperInterface $forms['fixedDate']->setData($viewData->getFixedDate()); } - public function mapFormsToData($forms, &$viewData): void + public function mapFormsToData(\Traversable $forms, &$viewData): void { $forms = iterator_to_array($forms); diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/ScopePickerDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/ScopePickerDataMapper.php index 267927ff1..d6a0cea20 100644 --- a/src/Bundle/ChillMainBundle/Form/DataMapper/ScopePickerDataMapper.php +++ b/src/Bundle/ChillMainBundle/Form/DataMapper/ScopePickerDataMapper.php @@ -16,11 +16,9 @@ use Symfony\Component\Form\DataMapperInterface; class ScopePickerDataMapper implements DataMapperInterface { - public function __construct(private readonly ?Scope $scope = null) - { - } + public function __construct(private readonly ?Scope $scope = null) {} - public function mapDataToForms($data, $forms) + public function mapDataToForms($data, \Traversable $forms) { $forms = iterator_to_array($forms); @@ -39,7 +37,7 @@ class ScopePickerDataMapper implements DataMapperInterface } } - public function mapFormsToData($forms, &$data) + public function mapFormsToData(\Traversable $forms, &$data) { $forms = iterator_to_array($forms); diff --git a/src/Bundle/ChillMainBundle/Form/Event/CustomizeFormEvent.php b/src/Bundle/ChillMainBundle/Form/Event/CustomizeFormEvent.php index aba5e2bc4..42606ebd7 100644 --- a/src/Bundle/ChillMainBundle/Form/Event/CustomizeFormEvent.php +++ b/src/Bundle/ChillMainBundle/Form/Event/CustomizeFormEvent.php @@ -17,9 +17,7 @@ class CustomizeFormEvent extends \Symfony\Contracts\EventDispatcher\Event { final public const NAME = 'chill_main.customize_form'; - public function __construct(protected string $type, protected FormBuilderInterface $builder) - { - } + public function __construct(protected string $type, protected FormBuilderInterface $builder) {} public function getBuilder(): FormBuilderInterface { diff --git a/src/Bundle/ChillMainBundle/Form/LocationFormType.php b/src/Bundle/ChillMainBundle/Form/LocationFormType.php index e4748d850..7f61cccce 100644 --- a/src/Bundle/ChillMainBundle/Form/LocationFormType.php +++ b/src/Bundle/ChillMainBundle/Form/LocationFormType.php @@ -24,9 +24,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; final class LocationFormType extends AbstractType { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/AddressToIdDataTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/AddressToIdDataTransformer.php index c04a4b158..04094537b 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/AddressToIdDataTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/AddressToIdDataTransformer.php @@ -17,9 +17,7 @@ use Symfony\Component\Form\Exception\TransformationFailedException; final readonly class AddressToIdDataTransformer implements DataTransformerInterface { - public function __construct(private AddressRepository $addressRepository) - { - } + public function __construct(private AddressRepository $addressRepository) {} public function reverseTransform($value) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php index 9a8b0a6d7..d328d38f0 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; class CenterTransformer implements DataTransformerInterface { - public function __construct(private readonly CenterRepository $centerRepository, private readonly bool $multiple = false) - { - } + public function __construct(private readonly CenterRepository $centerRepository, private readonly bool $multiple = false) {} public function reverseTransform($id) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php index bd54b0c09..d193ea2ef 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php @@ -22,9 +22,7 @@ use Symfony\Component\Serializer\SerializerInterface; class EntityToJsonTransformer implements DataTransformerInterface { - public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly SerializerInterface $serializer, private readonly bool $multiple, private readonly string $type) - { - } + public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly SerializerInterface $serializer, private readonly bool $multiple, private readonly string $type) {} public function reverseTransform($value) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/MultipleObjectsToIdTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/MultipleObjectsToIdTransformer.php index 436b72ce3..808093278 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/MultipleObjectsToIdTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/MultipleObjectsToIdTransformer.php @@ -17,9 +17,7 @@ use Symfony\Component\Form\DataTransformerInterface; class MultipleObjectsToIdTransformer implements DataTransformerInterface { - public function __construct(private readonly EntityManagerInterface $em, private readonly ?string $class = null) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly ?string $class = null) {} /** * Transforms a string (id) to an object (item). diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php index ffdee60bd..e56778bf2 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php @@ -17,9 +17,7 @@ use Symfony\Component\Form\Exception\TransformationFailedException; class ObjectToIdTransformer implements DataTransformerInterface { - public function __construct(private readonly EntityManagerInterface $em, private readonly ?string $class = null) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly ?string $class = null) {} /** * Transforms a string (id) to an object. diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php index 5f9117577..dde8b7b9e 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php @@ -18,9 +18,7 @@ use Symfony\Component\Form\Exception\TransformationFailedException; class PostalCodeToIdTransformer implements DataTransformerInterface { - public function __construct(private readonly PostalCodeRepositoryInterface $postalCodeRepository) - { - } + public function __construct(private readonly PostalCodeRepositoryInterface $postalCodeRepository) {} public function reverseTransform($value) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php index cb5adec47..2779f2cdd 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php @@ -18,9 +18,7 @@ use Symfony\Component\Form\Exception\TransformationFailedException; class ScopeTransformer implements DataTransformerInterface { - public function __construct(private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly EntityManagerInterface $em) {} public function reverseTransform($id) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php b/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php index 7a70e7ca6..c9bc4dd82 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php @@ -55,7 +55,6 @@ class DateIntervalType extends AbstractType { $builder ->add('n', IntegerType::class, [ - 'scale' => 0, 'constraints' => [ new GreaterThan([ 'value' => 0, diff --git a/src/Bundle/ChillMainBundle/Form/Type/Export/ExportType.php b/src/Bundle/ChillMainBundle/Form/Type/Export/ExportType.php index 930712084..e5d0887f3 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Export/ExportType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Export/ExportType.php @@ -29,9 +29,7 @@ class ExportType extends AbstractType final public const PICK_FORMATTER_KEY = 'pick_formatter'; - public function __construct(private readonly ExportManager $exportManager, private readonly SortExportElement $sortExportElement) - { - } + public function __construct(private readonly ExportManager $exportManager, private readonly SortExportElement $sortExportElement) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/Export/FilterType.php b/src/Bundle/ChillMainBundle/Form/Type/Export/FilterType.php index a968f4aa2..d4873df83 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Export/FilterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Export/FilterType.php @@ -24,9 +24,7 @@ class FilterType extends AbstractType { final public const ENABLED_FIELD = 'enabled'; - public function __construct() - { - } + public function __construct() {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php b/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php index 6e4231580..fa8caf488 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php @@ -33,8 +33,7 @@ final class PickCenterType extends AbstractType private readonly ExportManager $exportManager, private readonly RegroupmentRepository $regroupmentRepository, private readonly AuthorizationHelperForCurrentUserInterface $authorizationHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php b/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php index 8750ee006..190e09f30 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php @@ -41,9 +41,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ final class PickAddressType extends AbstractType { - public function __construct(private readonly AddressToIdDataTransformer $addressToIdDataTransformer, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly AddressToIdDataTransformer $addressToIdDataTransformer, private readonly TranslatorInterface $translator) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php b/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php index 12b170a73..ba6cc874d 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php @@ -34,9 +34,7 @@ use function count; */ class PickCenterType extends AbstractType { - public function __construct(protected AuthorizationHelperInterface $authorizationHelper, protected Security $security, protected CenterRepository $centerRepository) - { - } + public function __construct(protected AuthorizationHelperInterface $authorizationHelper, protected Security $security, protected CenterRepository $centerRepository) {} /** * add a data transformer if user can reach only one center. diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickCivilityType.php b/src/Bundle/ChillMainBundle/Form/Type/PickCivilityType.php index abe190de5..f9aa09ce8 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickCivilityType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickCivilityType.php @@ -21,9 +21,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PickCivilityType extends AbstractType { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function configureOptions(OptionsResolver $resolver) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickLocationTypeType.php b/src/Bundle/ChillMainBundle/Form/Type/PickLocationTypeType.php index 7fb50fd4a..8aa216da1 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickLocationTypeType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickLocationTypeType.php @@ -19,9 +19,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PickLocationTypeType extends AbstractType { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function configureOptions(OptionsResolver $resolver) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php b/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php index 041176905..1a1ed4354 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php @@ -21,9 +21,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PickPostalCodeType extends AbstractType { - public function __construct(private readonly PostalCodeToIdTransformer $postalCodeToIdTransformer) - { - } + public function __construct(private readonly PostalCodeToIdTransformer $postalCodeToIdTransformer) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php index ad23e5655..aab9d4c51 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php @@ -27,9 +27,7 @@ use Symfony\Component\Serializer\SerializerInterface; */ class PickUserDynamicType extends AbstractType { - public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly SerializerInterface $serializer, private readonly NormalizerInterface $normalizer) - { - } + public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly SerializerInterface $serializer, private readonly NormalizerInterface $normalizer) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickUserLocationType.php b/src/Bundle/ChillMainBundle/Form/Type/PickUserLocationType.php index bea96b79b..9d1cdb626 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickUserLocationType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickUserLocationType.php @@ -20,9 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PickUserLocationType extends AbstractType { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly LocationRepository $locationRepository) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly LocationRepository $locationRepository) {} public function configureOptions(OptionsResolver $resolver) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php b/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php index 44354922f..0d26b5a95 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php @@ -21,9 +21,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PrivateCommentType extends AbstractType { - public function __construct(protected PrivateCommentDataMapper $dataMapper) - { - } + public function __construct(protected PrivateCommentDataMapper $dataMapper) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php b/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php index fd27a9bcb..6f10626c6 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php @@ -39,9 +39,11 @@ use Symfony\Component\Security\Core\Security; */ class ScopePickerType extends AbstractType { - public function __construct(private readonly AuthorizationHelperInterface $authorizationHelper, private readonly Security $security, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct( + private readonly AuthorizationHelperInterface $authorizationHelper, + private readonly Security $security, + private readonly TranslatableStringHelperInterface $translatableStringHelper, + ) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php b/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php index 370de1137..e9ff503df 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php @@ -26,9 +26,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; */ class Select2CountryType extends AbstractType { - public function __construct(private readonly RequestStack $requestStack, private readonly ObjectManager $em, protected TranslatableStringHelper $translatableStringHelper, protected ParameterBagInterface $parameterBag) - { - } + public function __construct(private readonly RequestStack $requestStack, private readonly ObjectManager $em, protected TranslatableStringHelper $translatableStringHelper, protected ParameterBagInterface $parameterBag) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php b/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php index 9d634857a..68a3970ba 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php @@ -26,9 +26,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; */ class Select2LanguageType extends AbstractType { - public function __construct(private readonly RequestStack $requestStack, private readonly ObjectManager $em, protected TranslatableStringHelper $translatableStringHelper, protected ParameterBagInterface $parameterBag) - { - } + public function __construct(private readonly RequestStack $requestStack, private readonly ObjectManager $em, protected TranslatableStringHelper $translatableStringHelper, protected ParameterBagInterface $parameterBag) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/UserPasswordType.php b/src/Bundle/ChillMainBundle/Form/UserPasswordType.php index 5103e25c0..256e68731 100644 --- a/src/Bundle/ChillMainBundle/Form/UserPasswordType.php +++ b/src/Bundle/ChillMainBundle/Form/UserPasswordType.php @@ -17,7 +17,6 @@ use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\RepeatedType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; @@ -32,12 +31,12 @@ class UserPasswordType extends AbstractType protected $chillLogger; /** - * @var UserPasswordEncoderInterface + * @var \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface */ protected $passwordEncoder; public function __construct( - UserPasswordEncoderInterface $passwordEncoder, + \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface $passwordEncoder, LoggerInterface $chillLogger, ) { $this->passwordEncoder = $passwordEncoder; diff --git a/src/Bundle/ChillMainBundle/Form/UserType.php b/src/Bundle/ChillMainBundle/Form/UserType.php index 4a6bb8f9a..9d62fbc6a 100644 --- a/src/Bundle/ChillMainBundle/Form/UserType.php +++ b/src/Bundle/ChillMainBundle/Form/UserType.php @@ -36,9 +36,7 @@ use Symfony\Component\Validator\Constraints\Regex; class UserType extends AbstractType { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, protected ParameterBagInterface $parameterBag) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, protected ParameterBagInterface $parameterBag) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillMainBundle/Form/WorkflowSignatureMetadataType.php b/src/Bundle/ChillMainBundle/Form/WorkflowSignatureMetadataType.php new file mode 100644 index 000000000..114a462f6 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Form/WorkflowSignatureMetadataType.php @@ -0,0 +1,62 @@ +parameterBag->get('chill_main')['workflow_signature']['base_signer']['document_kinds']; + + $choices = []; + + foreach ($documentTypeChoices as $documentType) { + $labels = []; + + foreach ($documentType['labels'] as $label) { + $labels[$label['lang']] = $label['label']; + } + + $localizedLabel = $this->translatableStringHelper->localize($labels); + if (null !== $localizedLabel) { + $choices[$localizedLabel] = $documentType['key']; + } + } + + $builder + ->add('documentType', ChoiceType::class, [ + 'label' => 'workflow.signature_zone.metadata.docType', + 'expanded' => false, + 'required' => true, + 'choices' => $choices, + ]) + ->add('documentNumber', TextType::class, [ + 'required' => true, + 'label' => 'workflow.signature_zone.metadata.docNumber', + ]) + ->add('expirationDate', ChillDateType::class, [ + 'required' => true, + 'input' => 'datetime_immutable', + 'label' => 'workflow.signature_zone.metadata.docExpiration', + ]); + } +} diff --git a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php index f0360d4bb..e2aece468 100644 --- a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php +++ b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php @@ -12,14 +12,13 @@ declare(strict_types=1); namespace Chill\MainBundle\Form; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; -use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep; use Chill\MainBundle\Form\Type\ChillCollectionType; use Chill\MainBundle\Form\Type\ChillTextareaType; use Chill\MainBundle\Form\Type\PickUserDynamicType; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; -use Chill\MainBundle\Workflow\EntityWorkflowManager; +use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO; +use Chill\PersonBundle\Form\Type\PickPersonDynamicType; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\FormBuilderInterface; @@ -34,171 +33,179 @@ use Symfony\Component\Workflow\Transition; class WorkflowStepType extends AbstractType { - public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly Registry $registry, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct( + private readonly Registry $registry, + private readonly TranslatableStringHelperInterface $translatableStringHelper, + ) {} public function buildForm(FormBuilderInterface $builder, array $options) { /** @var EntityWorkflow $entityWorkflow */ $entityWorkflow = $options['entity_workflow']; - $handler = $this->entityWorkflowManager->getHandler($entityWorkflow); $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); $place = $workflow->getMarking($entityWorkflow); $placeMetadata = $workflow->getMetadataStore()->getPlaceMetadata(array_keys($place->getPlaces())[0]); - if (true === $options['transition']) { - if (null === $options['entity_workflow']) { - throw new \LogicException('if transition is true, entity_workflow should be defined'); - } + if (null === $options['entity_workflow']) { + throw new \LogicException('if transition is true, entity_workflow should be defined'); + } - $transitions = $this->registry - ->get($options['entity_workflow'], $entityWorkflow->getWorkflowName()) - ->getEnabledTransitions($entityWorkflow); + $transitions = $this->registry + ->get($options['entity_workflow'], $entityWorkflow->getWorkflowName()) + ->getEnabledTransitions($entityWorkflow); - $choices = array_combine( - array_map( - static fn (Transition $transition) => $transition->getName(), - $transitions - ), + $choices = array_combine( + array_map( + static fn (Transition $transition) => $transition->getName(), $transitions - ); + ), + $transitions + ); - if (\array_key_exists('validationFilterInputLabels', $placeMetadata)) { - $inputLabels = $placeMetadata['validationFilterInputLabels']; + if (\array_key_exists('validationFilterInputLabels', $placeMetadata)) { + $inputLabels = $placeMetadata['validationFilterInputLabels']; - $builder->add('transitionFilter', ChoiceType::class, [ - 'multiple' => false, - 'label' => 'workflow.My decision', - 'choices' => [ - 'forward' => 'forward', - 'backward' => 'backward', - 'neutral' => 'neutral', - ], - 'choice_label' => fn (string $key) => $this->translatableStringHelper->localize($inputLabels[$key]), - 'choice_attr' => static fn (string $key) => [ - $key => $key, - ], - 'mapped' => false, - 'expanded' => true, - 'data' => 'forward', - ]); - } - - $builder - ->add('transition', ChoiceType::class, [ - 'label' => 'workflow.Next step', - 'mapped' => false, - 'multiple' => false, - 'expanded' => true, - 'choices' => $choices, - 'constraints' => [new NotNull()], - 'choice_label' => function (Transition $transition) use ($workflow) { - $meta = $workflow->getMetadataStore()->getTransitionMetadata($transition); - - if (\array_key_exists('label', $meta)) { - return $this->translatableStringHelper->localize($meta['label']); - } - - return $transition->getName(); - }, - 'choice_attr' => static function (Transition $transition) use ($workflow) { - $toFinal = true; - $isForward = 'neutral'; - - $metadata = $workflow->getMetadataStore()->getTransitionMetadata($transition); - - if (\array_key_exists('isForward', $metadata)) { - if ($metadata['isForward']) { - $isForward = 'forward'; - } else { - $isForward = 'backward'; - } - } - - foreach ($transition->getTos() as $to) { - $meta = $workflow->getMetadataStore()->getPlaceMetadata($to); - - if ( - !\array_key_exists('isFinal', $meta) || false === $meta['isFinal'] - ) { - $toFinal = false; - } - } - - return [ - 'data-is-transition' => 'data-is-transition', - 'data-to-final' => $toFinal ? '1' : '0', - 'data-is-forward' => $isForward, - ]; - }, - ]) - ->add('future_dest_users', PickUserDynamicType::class, [ - 'label' => 'workflow.dest for next steps', - 'multiple' => true, - 'mapped' => false, - 'suggested' => $options['suggested_users'], - ]) - ->add('future_cc_users', PickUserDynamicType::class, [ - 'label' => 'workflow.cc for next steps', - 'multiple' => true, - 'mapped' => false, - 'required' => false, - 'suggested' => $options['suggested_users'], - ]) - ->add('future_dest_emails', ChillCollectionType::class, [ - 'label' => 'workflow.dest by email', - 'help' => 'workflow.dest by email help', - 'mapped' => false, - 'allow_add' => true, - 'entry_type' => EmailType::class, - 'button_add_label' => 'workflow.Add an email', - 'button_remove_label' => 'workflow.Remove an email', - 'empty_collection_explain' => 'workflow.Any email', - 'entry_options' => [ - 'constraints' => [ - new NotNull(), new NotBlank(), new Email(), - ], - 'label' => 'Email', - ], - ]); + $builder->add('transitionFilter', ChoiceType::class, [ + 'multiple' => false, + 'label' => 'workflow.My decision', + 'choices' => [ + 'forward' => 'forward', + 'backward' => 'backward', + 'neutral' => 'neutral', + ], + 'choice_label' => fn (string $key) => $this->translatableStringHelper->localize($inputLabels[$key]), + 'choice_attr' => static fn (string $key) => [ + $key => $key, + ], + 'mapped' => false, + 'expanded' => true, + 'data' => 'forward', + ]); } - if ( - $handler->supportsFreeze($entityWorkflow) - && !$entityWorkflow->isFreeze() - ) { - $builder - ->add('freezeAfter', CheckboxType::class, [ - 'required' => false, - 'label' => 'workflow.Freeze', - 'help' => 'workflow.The associated element will be freezed', - ]); - } + $builder + ->add('transition', ChoiceType::class, [ + 'label' => 'workflow.Next step', + 'mapped' => false, + 'multiple' => false, + 'expanded' => true, + 'choices' => $choices, + 'constraints' => [new NotNull()], + 'choice_label' => function (Transition $transition) use ($workflow) { + $meta = $workflow->getMetadataStore()->getTransitionMetadata($transition); + + if (\array_key_exists('label', $meta)) { + return $this->translatableStringHelper->localize($meta['label']); + } + + return $transition->getName(); + }, + 'choice_attr' => static function (Transition $transition) use ($workflow) { + $toFinal = true; + $isForward = 'neutral'; + $isSignature = []; + + $metadata = $workflow->getMetadataStore()->getTransitionMetadata($transition); + + if (\array_key_exists('isForward', $metadata)) { + if ($metadata['isForward']) { + $isForward = 'forward'; + } else { + $isForward = 'backward'; + } + } + + foreach ($transition->getTos() as $to) { + $meta = $workflow->getMetadataStore()->getPlaceMetadata($to); + + if ( + !\array_key_exists('isFinal', $meta) || false === $meta['isFinal'] + ) { + $toFinal = false; + } + + if (\array_key_exists('isSignature', $meta)) { + $isSignature = $meta['isSignature']; + } + } + + return [ + 'data-is-transition' => 'data-is-transition', + 'data-to-final' => $toFinal ? '1' : '0', + 'data-is-forward' => $isForward, + 'data-is-signature' => json_encode($isSignature), + ]; + }, + ]) + ->add('isPersonOrUserSignature', ChoiceType::class, [ + 'mapped' => false, + 'multiple' => false, + 'expanded' => true, + 'label' => 'workflow.signature_zone.type of signature', + 'choices' => [ + 'workflow.signature_zone.persons' => 'person', + 'workflow.signature_zone.user' => 'user', + ], + ]) + ->add('futurePersonSignatures', PickPersonDynamicType::class, [ + 'label' => 'workflow.signature_zone.person signatures', + 'multiple' => true, + 'empty_data' => '[]', + ]) + ->add('futureUserSignature', PickUserDynamicType::class, [ + 'label' => 'workflow.signature_zone.user signature', + 'multiple' => false, + ]) + ->add('futureDestUsers', PickUserDynamicType::class, [ + 'label' => 'workflow.dest for next steps', + 'multiple' => true, + 'empty_data' => '[]', + 'suggested' => $options['suggested_users'], + ]) + ->add('futureCcUsers', PickUserDynamicType::class, [ + 'label' => 'workflow.cc for next steps', + 'multiple' => true, + 'required' => false, + 'suggested' => $options['suggested_users'], + 'empty_data' => '[]', + 'attr' => ['class' => 'future-cc-users'], + ]) + ->add('futureDestEmails', ChillCollectionType::class, [ + 'label' => 'workflow.dest by email', + 'help' => 'workflow.dest by email help', + 'allow_add' => true, + 'entry_type' => EmailType::class, + 'button_add_label' => 'workflow.Add an email', + 'button_remove_label' => 'workflow.Remove an email', + 'empty_collection_explain' => 'workflow.Any email', + 'entry_options' => [ + 'constraints' => [ + new NotNull(), new NotBlank(), new Email(), + ], + 'label' => 'Email', + ], + ]); $builder ->add('comment', ChillTextareaType::class, [ 'required' => false, 'label' => 'Comment', + 'empty_data' => '', ]); } public function configureOptions(OptionsResolver $resolver) { $resolver - ->setDefined('class') - ->setRequired('transition') - ->setAllowedTypes('transition', 'bool') + ->setDefault('data_class', WorkflowTransitionContextDTO::class) ->setRequired('entity_workflow') ->setAllowedTypes('entity_workflow', EntityWorkflow::class) ->setDefault('suggested_users', []) ->setDefault('constraints', [ new Callback( - function ($step, ExecutionContextInterface $context, $payload) { - /** @var EntityWorkflowStep $step */ - $form = $context->getObject(); - $workflow = $this->registry->get($step->getEntityWorkflow(), $step->getEntityWorkflow()->getWorkflowName()); - $transition = $form['transition']->getData(); + function (WorkflowTransitionContextDTO $step, ExecutionContextInterface $context, $payload) { + $workflow = $this->registry->get($step->entityWorkflow, $step->entityWorkflow->getWorkflowName()); + $transition = $step->transition; $toFinal = true; if (null === $transition) { @@ -214,8 +221,8 @@ class WorkflowStepType extends AbstractType $toFinal = false; } } - $destUsers = $form['future_dest_users']->getData(); - $destEmails = $form['future_dest_emails']->getData(); + $destUsers = $step->futureDestUsers; + $destEmails = $step->futureDestEmails; if (!$toFinal && [] === $destUsers && [] === $destEmails) { $context @@ -226,20 +233,6 @@ class WorkflowStepType extends AbstractType } } ), - new Callback( - function ($step, ExecutionContextInterface $context, $payload) { - $form = $context->getObject(); - - foreach ($form->get('future_dest_users')->getData() as $u) { - if (in_array($u, $form->get('future_cc_users')->getData(), true)) { - $context - ->buildViolation('workflow.The user in cc cannot be a dest user in the same workflow step') - ->atPath('ccUsers') - ->addViolation(); - } - } - } - ), ]); } } diff --git a/src/Bundle/ChillMainBundle/Notification/Counter/NotificationByUserCounter.php b/src/Bundle/ChillMainBundle/Notification/Counter/NotificationByUserCounter.php index e08543e8c..b61f38a35 100644 --- a/src/Bundle/ChillMainBundle/Notification/Counter/NotificationByUserCounter.php +++ b/src/Bundle/ChillMainBundle/Notification/Counter/NotificationByUserCounter.php @@ -24,9 +24,7 @@ use Symfony\Component\Security\Core\User\UserInterface; final readonly class NotificationByUserCounter implements NotificationCounterInterface { - public function __construct(private CacheItemPoolInterface $cacheItemPool, private NotificationRepository $notificationRepository) - { - } + public function __construct(private CacheItemPoolInterface $cacheItemPool, private NotificationRepository $notificationRepository) {} public function addNotification(UserInterface $u): int { diff --git a/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php b/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php index 7eba06242..7b535f1a7 100644 --- a/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php +++ b/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php @@ -24,9 +24,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class NotificationMailer { - public function __construct(private readonly MailerInterface $mailer, private readonly LoggerInterface $logger, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly MailerInterface $mailer, private readonly LoggerInterface $logger, private readonly TranslatorInterface $translator) {} public function postPersistComment(NotificationComment $comment, PostPersistEventArgs $eventArgs): void { diff --git a/src/Bundle/ChillMainBundle/Notification/EventListener/PersistNotificationOnTerminateEventSubscriber.php b/src/Bundle/ChillMainBundle/Notification/EventListener/PersistNotificationOnTerminateEventSubscriber.php index fc2cd35ea..3268fee05 100644 --- a/src/Bundle/ChillMainBundle/Notification/EventListener/PersistNotificationOnTerminateEventSubscriber.php +++ b/src/Bundle/ChillMainBundle/Notification/EventListener/PersistNotificationOnTerminateEventSubscriber.php @@ -18,9 +18,7 @@ use Symfony\Component\HttpKernel\Event\TerminateEvent; class PersistNotificationOnTerminateEventSubscriber implements EventSubscriberInterface { - public function __construct(private readonly EntityManagerInterface $em, private readonly NotificationPersisterInterface $persister) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly NotificationPersisterInterface $persister) {} public static function getSubscribedEvents() { @@ -33,7 +31,7 @@ class PersistNotificationOnTerminateEventSubscriber implements EventSubscriberIn public function onKernelTerminate(TerminateEvent $event): void { - if ($event->isMasterRequest()) { + if ($event->isMainRequest()) { $this->persistNotifications(); } } diff --git a/src/Bundle/ChillMainBundle/Notification/Exception/NotificationHandlerNotFound.php b/src/Bundle/ChillMainBundle/Notification/Exception/NotificationHandlerNotFound.php index a55104d23..b1acff57b 100644 --- a/src/Bundle/ChillMainBundle/Notification/Exception/NotificationHandlerNotFound.php +++ b/src/Bundle/ChillMainBundle/Notification/Exception/NotificationHandlerNotFound.php @@ -11,6 +11,4 @@ declare(strict_types=1); namespace Chill\MainBundle\Notification\Exception; -class NotificationHandlerNotFound extends \RuntimeException -{ -} +class NotificationHandlerNotFound extends \RuntimeException {} diff --git a/src/Bundle/ChillMainBundle/Notification/Mailer.php b/src/Bundle/ChillMainBundle/Notification/Mailer.php index 3b3374d51..48adcd24f 100644 --- a/src/Bundle/ChillMainBundle/Notification/Mailer.php +++ b/src/Bundle/ChillMainBundle/Notification/Mailer.php @@ -34,9 +34,7 @@ class Mailer * * @param mixed[] $routeParameters */ - public function __construct(private readonly MailerInterface $mailer, private readonly LoggerInterface $logger, private readonly Environment $twig, private readonly RouterInterface $router, private readonly TranslatorInterface $translator, protected $routeParameters) - { - } + public function __construct(private readonly MailerInterface $mailer, private readonly LoggerInterface $logger, private readonly Environment $twig, private readonly RouterInterface $router, private readonly TranslatorInterface $translator, protected $routeParameters) {} /** * @return string diff --git a/src/Bundle/ChillMainBundle/Notification/NotificationHandlerManager.php b/src/Bundle/ChillMainBundle/Notification/NotificationHandlerManager.php index 04116a434..aa6e700bc 100644 --- a/src/Bundle/ChillMainBundle/Notification/NotificationHandlerManager.php +++ b/src/Bundle/ChillMainBundle/Notification/NotificationHandlerManager.php @@ -17,9 +17,7 @@ use Doctrine\ORM\EntityManagerInterface; final readonly class NotificationHandlerManager { - public function __construct(private iterable $handlers, private EntityManagerInterface $em) - { - } + public function __construct(private iterable $handlers, private EntityManagerInterface $em) {} /** * @throw NotificationHandlerNotFound if handler is not found diff --git a/src/Bundle/ChillMainBundle/Notification/NotificationPresence.php b/src/Bundle/ChillMainBundle/Notification/NotificationPresence.php index 9b606d18d..5c5cb3dcf 100644 --- a/src/Bundle/ChillMainBundle/Notification/NotificationPresence.php +++ b/src/Bundle/ChillMainBundle/Notification/NotificationPresence.php @@ -23,9 +23,7 @@ class NotificationPresence { private array $cache = []; - public function __construct(private readonly Security $security, private readonly NotificationRepository $notificationRepository) - { - } + public function __construct(private readonly Security $security, private readonly NotificationRepository $notificationRepository) {} /** * @param list $more diff --git a/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php b/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php index 8dd2935dd..a65758f5f 100644 --- a/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php +++ b/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php @@ -21,9 +21,7 @@ use Twig\Extension\RuntimeExtensionInterface; class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface { - public function __construct(private readonly FormFactoryInterface $formFactory, private readonly NotificationPresence $notificationPresence, private readonly UrlGeneratorInterface $urlGenerator) - { - } + public function __construct(private readonly FormFactoryInterface $formFactory, private readonly NotificationPresence $notificationPresence, private readonly UrlGeneratorInterface $urlGenerator) {} public function counterNotificationFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): string { diff --git a/src/Bundle/ChillMainBundle/Pagination/PageGenerator.php b/src/Bundle/ChillMainBundle/Pagination/PageGenerator.php index b887accaa..4c9cb68fe 100644 --- a/src/Bundle/ChillMainBundle/Pagination/PageGenerator.php +++ b/src/Bundle/ChillMainBundle/Pagination/PageGenerator.php @@ -18,9 +18,7 @@ class PageGenerator implements \Iterator { protected int $current = 1; - public function __construct(protected Paginator $paginator) - { - } + public function __construct(protected Paginator $paginator) {} public function current(): Page { diff --git a/src/Bundle/ChillMainBundle/Pagination/Paginator.php b/src/Bundle/ChillMainBundle/Pagination/Paginator.php index ee9f49805..b2500dfc2 100644 --- a/src/Bundle/ChillMainBundle/Pagination/Paginator.php +++ b/src/Bundle/ChillMainBundle/Pagination/Paginator.php @@ -57,8 +57,7 @@ class Paginator implements PaginatorInterface * the key in the GET parameter to indicate the number of item per page. */ protected string $itemPerPageKey, - ) { - } + ) {} public function count(): int { diff --git a/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php b/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php index 8956f2276..9a809287b 100644 --- a/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php +++ b/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php @@ -39,8 +39,7 @@ final readonly class PaginatorFactory implements PaginatorFactoryInterface * the request or inside the paginator. */ private int $itemPerPage = 20, - ) { - } + ) {} /** * create a paginator instance. diff --git a/src/Bundle/ChillMainBundle/Phonenumber/Templating.php b/src/Bundle/ChillMainBundle/Phonenumber/Templating.php index 69da56eca..51d57c9e9 100644 --- a/src/Bundle/ChillMainBundle/Phonenumber/Templating.php +++ b/src/Bundle/ChillMainBundle/Phonenumber/Templating.php @@ -16,9 +16,7 @@ use Twig\TwigFilter; class Templating extends AbstractExtension { - public function __construct(protected PhonenumberHelper $phonenumberHelper) - { - } + public function __construct(protected PhonenumberHelper $phonenumberHelper) {} public function formatPhonenumber($phonenumber) { diff --git a/src/Bundle/ChillMainBundle/Redis/ChillRedis.php b/src/Bundle/ChillMainBundle/Redis/ChillRedis.php index 439bb3558..b9e454b46 100644 --- a/src/Bundle/ChillMainBundle/Redis/ChillRedis.php +++ b/src/Bundle/ChillMainBundle/Redis/ChillRedis.php @@ -16,6 +16,4 @@ use Redis; /** * Redis client configured by chill main. */ -class ChillRedis extends \Redis -{ -} +class ChillRedis extends \Redis {} diff --git a/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php b/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php index 86faf6ea1..3e8d060c3 100644 --- a/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php @@ -20,11 +20,11 @@ use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Persistence\ObjectRepository; -final class AddressReferenceRepository implements ObjectRepository +final readonly class AddressReferenceRepository implements ObjectRepository { - private readonly EntityManagerInterface $entityManager; + private EntityManagerInterface $entityManager; - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/AddressRepository.php b/src/Bundle/ChillMainBundle/Repository/AddressRepository.php index 074b1fc32..4dbd09cab 100644 --- a/src/Bundle/ChillMainBundle/Repository/AddressRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/AddressRepository.php @@ -17,9 +17,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class AddressRepository implements ObjectRepository +final readonly class AddressRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/CenterRepository.php b/src/Bundle/ChillMainBundle/Repository/CenterRepository.php index 0b507faa1..1bc5a7405 100644 --- a/src/Bundle/ChillMainBundle/Repository/CenterRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/CenterRepository.php @@ -15,9 +15,9 @@ use Chill\MainBundle\Entity\Center; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class CenterRepository implements CenterRepositoryInterface +final readonly class CenterRepository implements CenterRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/CountryRepository.php b/src/Bundle/ChillMainBundle/Repository/CountryRepository.php index 701019dba..ae318e35e 100644 --- a/src/Bundle/ChillMainBundle/Repository/CountryRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/CountryRepository.php @@ -17,9 +17,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class CountryRepository implements ObjectRepository +final readonly class CountryRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/GeographicalUnitLayerLayerRepository.php b/src/Bundle/ChillMainBundle/Repository/GeographicalUnitLayerLayerRepository.php index 11a03c209..1135b889d 100644 --- a/src/Bundle/ChillMainBundle/Repository/GeographicalUnitLayerLayerRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/GeographicalUnitLayerLayerRepository.php @@ -15,9 +15,9 @@ use Chill\MainBundle\Entity\GeographicalUnitLayer; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class GeographicalUnitLayerLayerRepository implements GeographicalUnitLayerRepositoryInterface +final readonly class GeographicalUnitLayerLayerRepository implements GeographicalUnitLayerRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $em) { diff --git a/src/Bundle/ChillMainBundle/Repository/GeographicalUnitRepository.php b/src/Bundle/ChillMainBundle/Repository/GeographicalUnitRepository.php index 608609a11..35ec31ff3 100644 --- a/src/Bundle/ChillMainBundle/Repository/GeographicalUnitRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/GeographicalUnitRepository.php @@ -18,9 +18,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; -final class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface +final readonly class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $em) { diff --git a/src/Bundle/ChillMainBundle/Repository/GroupCenterRepository.php b/src/Bundle/ChillMainBundle/Repository/GroupCenterRepository.php index 2d9ad8c5a..d0f5d8561 100644 --- a/src/Bundle/ChillMainBundle/Repository/GroupCenterRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/GroupCenterRepository.php @@ -16,9 +16,9 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectRepository; -final class GroupCenterRepository implements ObjectRepository +final readonly class GroupCenterRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/LanguageRepository.php b/src/Bundle/ChillMainBundle/Repository/LanguageRepository.php index d8c5d54f8..28d21d2c1 100644 --- a/src/Bundle/ChillMainBundle/Repository/LanguageRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/LanguageRepository.php @@ -15,9 +15,9 @@ use Chill\MainBundle\Entity\Language; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class LanguageRepository implements LanguageRepositoryInterface +final readonly class LanguageRepository implements LanguageRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/PermissionsGroupRepository.php b/src/Bundle/ChillMainBundle/Repository/PermissionsGroupRepository.php index 910d924db..598894b61 100644 --- a/src/Bundle/ChillMainBundle/Repository/PermissionsGroupRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/PermissionsGroupRepository.php @@ -16,9 +16,9 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectRepository; -final class PermissionsGroupRepository implements ObjectRepository +final readonly class PermissionsGroupRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php index 0949f52ba..0779ea90a 100644 --- a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php @@ -19,11 +19,11 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\ORM\Query\ResultSetMappingBuilder; -final class PostalCodeRepository implements PostalCodeRepositoryInterface +final readonly class PostalCodeRepository implements PostalCodeRepositoryInterface { - private readonly EntityManagerInterface $entityManager; + private EntityManagerInterface $entityManager; - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php b/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php index e18279944..793015f5b 100644 --- a/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php @@ -18,9 +18,9 @@ use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NoResultException; use Doctrine\Persistence\ObjectRepository; -final class RegroupmentRepository implements ObjectRepository +final readonly class RegroupmentRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/RoleScopeRepository.php b/src/Bundle/ChillMainBundle/Repository/RoleScopeRepository.php index ddf52af5b..a00d2ce35 100644 --- a/src/Bundle/ChillMainBundle/Repository/RoleScopeRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/RoleScopeRepository.php @@ -16,9 +16,9 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectRepository; -final class RoleScopeRepository implements ObjectRepository +final readonly class RoleScopeRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/ScopeRepository.php b/src/Bundle/ChillMainBundle/Repository/ScopeRepository.php index aa3c78270..4f752bce0 100644 --- a/src/Bundle/ChillMainBundle/Repository/ScopeRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/ScopeRepository.php @@ -17,11 +17,11 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; -final class ScopeRepository implements ScopeRepositoryInterface +final readonly class ScopeRepository implements ScopeRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; - public function __construct(EntityManagerInterface $entityManager, private readonly TranslatableStringHelperInterface $translatableStringHelper) + public function __construct(EntityManagerInterface $entityManager, private TranslatableStringHelperInterface $translatableStringHelper) { $this->repository = $entityManager->getRepository(Scope::class); } diff --git a/src/Bundle/ChillMainBundle/Repository/UserACLAwareRepository.php b/src/Bundle/ChillMainBundle/Repository/UserACLAwareRepository.php index 5b830ce27..f14424f6f 100644 --- a/src/Bundle/ChillMainBundle/Repository/UserACLAwareRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/UserACLAwareRepository.php @@ -19,9 +19,7 @@ use Doctrine\ORM\EntityManagerInterface; class UserACLAwareRepository implements UserACLAwareRepositoryInterface { - public function __construct(private readonly ParentRoleHelper $parentRoleHelper, private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly ParentRoleHelper $parentRoleHelper, private readonly EntityManagerInterface $em) {} public function findUsersByReachedACL(string $role, $center, $scope = null, bool $onlyEnabled = true): array { diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php index 66b3ab379..62282fbe9 100644 --- a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php @@ -99,6 +99,24 @@ class EntityWorkflowRepository implements ObjectRepository return $this->repository->findAll(); } + /** + * @return list + */ + public function findByRelatedEntity($entityClass, $relatedEntityId): array + { + $qb = $this->repository->createQueryBuilder('w'); + + $query = $qb->where( + $qb->expr()->andX( + $qb->expr()->eq('w.relatedEntityClass', ':entity_class'), + $qb->expr()->eq('w.relatedEntityId', ':entity_id'), + ) + )->setParameter('entity_class', $entityClass) + ->setParameter('entity_id', $relatedEntityId); + + return $query->getQuery()->getResult(); + } + /** * @param mixed|null $limit * @param mixed|null $offset @@ -180,6 +198,34 @@ class EntityWorkflowRepository implements ObjectRepository return $this->repository->findOneBy($criteria); } + /** + * Finds workflows that are not finalized and are older than the specified date. + * + * @param \DateTimeImmutable $olderThanDate the date to compare against + * + * @return list the list of workflow IDs that meet the criteria + */ + public function findWorkflowsWithoutFinalStepAndOlderThan(\DateTimeImmutable $olderThanDate): array + { + $qb = $this->repository->createQueryBuilder('sw'); + + $qb->select('sw.id') + // only the workflow which are not finalized + ->where('NOT EXISTS (SELECT 1 FROM chill_main_entity_workflow_step ews WHERE ews.isFinal = TRUE AND ews.entityWorkflow = sw.id)') + ->andWhere( + $qb->expr()->orX( + // only the workflow where all the last transition is older than transitionAt + ':olderThanDate > ALL (SELECT ews.transitionAt FROM chill_main_entity_workflow_step ews WHERE ews.transitionAt IS NOT NULL AND ews.entityWorkflow = sw.id)', + // or the workflow which have only the initial step, with no transition + '1 = (SELECT COUNT(ews.id) FROM chill_main_entity_workflow_step ews WHERE ews.step = :initial AND ews.transitionAt IS NULL AND ews.createdAt < :olderThanDate AND ews.entityWorkflow = sw.id)', + ) + ) + ->andWhere('sw.createdAt < :olderThanDate') + ->setParameter('olderThanDate', $olderThanDate); + + return $qb->getQuery()->getResult(); + } + public function getClassName(): string { return EntityWorkflow::class; @@ -212,7 +258,10 @@ class EntityWorkflowRepository implements ObjectRepository $qb->where( $qb->expr()->andX( - $qb->expr()->isMemberOf(':user', 'step.destUser'), + $qb->expr()->orX( + $qb->expr()->isMemberOf(':user', 'step.destUser'), + $qb->expr()->isMemberOf(':user', 'step.destUserByAccessKey'), + ), $qb->expr()->isNull('step.transitionAfter'), $qb->expr()->eq('step.isFinal', "'FALSE'") ) diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowSignatureACLAwareRepositoryInterface.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowSignatureACLAwareRepositoryInterface.php new file mode 100644 index 000000000..996374231 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowSignatureACLAwareRepositoryInterface.php @@ -0,0 +1,23 @@ + + */ + public function findByPersonAndPendingState(Person $person): array; +} diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepHoldRepository.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepHoldRepository.php new file mode 100644 index 000000000..a925246e4 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepHoldRepository.php @@ -0,0 +1,79 @@ + + */ +class EntityWorkflowStepHoldRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, EntityWorkflowStepHold::class); + } + + /** + * Find an EntityWorkflowStepHold by its ID. + */ + public function findById(int $id): ?EntityWorkflowStepHold + { + return $this->find($id); + } + + /** + * Find all EntityWorkflowStepHold records. + * + * @return EntityWorkflowStepHold[] + */ + public function findAllHolds(): array + { + return $this->findAll(); + } + + /** + * Find EntityWorkflowStepHold by a specific step. + * + * @return EntityWorkflowStepHold[] + */ + public function findByStep(EntityWorkflowStep $step): array + { + return $this->findBy(['step' => $step]); + } + + /** + * Find a single EntityWorkflowStepHold by step and user. + * + * @throws NonUniqueResultException + */ + public function findOneByStepAndUser(EntityWorkflowStep $step, User $user): ?EntityWorkflowStepHold + { + try { + return $this->createQueryBuilder('e') + ->andWhere('e.step = :step') + ->andWhere('e.byUser = :user') + ->setParameter('step', $step) + ->setParameter('user', $user) + ->getQuery() + ->getSingleResult(); + } catch (NoResultException) { + return null; + } + } +} diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepRepository.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepRepository.php index 545ec2873..db57836c2 100644 --- a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepRepository.php @@ -18,9 +18,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -class EntityWorkflowStepRepository implements ObjectRepository +readonly class EntityWorkflowStepRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureACLAwareRepository.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureACLAwareRepository.php new file mode 100644 index 000000000..1ac21e533 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureACLAwareRepository.php @@ -0,0 +1,54 @@ +repository->findByPerson($person); + + $filteredSignatures = []; + + foreach ($signatures as $signature) { + if (EntityWorkflowSignatureStateEnum::SIGNED === $signature->getState() || EntityWorkflowSignatureStateEnum::CANCELED === $signature->getState() || EntityWorkflowSignatureStateEnum::REJECTED === $signature->getState()) { + continue; + } + + $workflow = $signature->getStep()->getEntityWorkflow(); + + $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($workflow); + + if (null === $storedObject) { + continue; + } + + if ($this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) { + $filteredSignatures[] = $signature; + } + } + + return $filteredSignatures; + } +} diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureRepository.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureRepository.php new file mode 100644 index 000000000..8bd3de586 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowStepSignatureRepository.php @@ -0,0 +1,39 @@ + + */ +class EntityWorkflowStepSignatureRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, EntityWorkflowStepSignature::class); + } + + public function findByPerson(Person $person): array + { + $qb = $this->createQueryBuilder('ewss'); + $qb->select('ewss'); + $qb->where($qb->expr()->eq('ewss.personSigner', ':person')); + + $qb->setParameter('person', $person); + + return $qb->getQuery()->getResult(); + } +} diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss index 2523ee202..4f215859f 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss @@ -31,6 +31,8 @@ // Specific templates @import './scss/notification'; +@import './scss/hover.scss'; + /* * BASE LAYOUT POSITION */ @@ -496,6 +498,7 @@ div.workflow { div.breadcrumb { display: initial; margin-bottom: 0; + margin-right: .5rem; padding-right: 0.5em; background-color: tint-color($chill-yellow, 90%); border: 1px solid $chill-yellow; diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/js/date.ts b/src/Bundle/ChillMainBundle/Resources/public/chill/js/date.ts index 8c087146a..9198f835e 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/js/date.ts +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/js/date.ts @@ -59,6 +59,10 @@ export const ISOToDatetime = (str: string|null): Date|null => { [hours, minutes, seconds] = time.split(':').map(s => parseInt(s)); ; + if ('0000' === timezone) { + return new Date(Date.UTC(year, month-1, date, hours, minutes, seconds)); + } + return new Date(year, month-1, date, hours, minutes, seconds); } diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/hover.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/hover.scss new file mode 100644 index 000000000..95fe12efc --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/hover.scss @@ -0,0 +1,11 @@ + + +.row.row-hover { + padding: 0.3rem; + + &:hover { + background-color: $gray-100; + border-top: 1px solid $gray-400; + border-bottom: 1px solid $gray-400; + } +} diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss index 5158a826e..d37765e6b 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss @@ -17,6 +17,10 @@ ul.record_actions { display: inline-block; } + &.slim { + margin-bottom: 0; + } + &.column { flex-direction: column; } diff --git a/src/Bundle/ChillMainBundle/Resources/public/lib/download-report/download-report.js b/src/Bundle/ChillMainBundle/Resources/public/lib/download-report/download-report.js index e7dce2d48..9251639a8 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/lib/download-report/download-report.js +++ b/src/Bundle/ChillMainBundle/Resources/public/lib/download-report/download-report.js @@ -15,9 +15,9 @@ * along with this program. If not, see . */ -var mime = require('mime') +import mime from 'mime'; -var download_report = (url, container) => { +export const download_report = (url, container) => { var download_text = container.dataset.downloadText, alias = container.dataset.alias; @@ -70,5 +70,3 @@ var download_report = (url, container) => { .replaceChild(problem_text, container.firstChild); }); }; - -module.exports = download_report; diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/editor_config.ts similarity index 72% rename from src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.js rename to src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/editor_config.ts index ddbc4afa7..7a72c0ffa 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/editor_config.ts @@ -39,23 +39,5 @@ ClassicEditor.defaultConfig = { 'redo' ] }, - language: 'fr' + language: 'fr', }; - - -let Fields = []; -Fields.push.apply(Fields, document.querySelectorAll('textarea[ckeditor]')); -// enable for custom fields -//Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea')); - -Fields.forEach(function(field) { - ClassicEditor - .create( field ) - .then( editor => { - //console.log( 'CkEditor was initialized', editor ); - }) - .catch( error => { - console.error( error.stack ); - }) - ; -}); diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.ts b/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.ts new file mode 100644 index 000000000..ed07ce9db --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.ts @@ -0,0 +1,15 @@ +import ClassicEditor from "./editor_config"; + +const ckeditorFields: NodeListOf = document.querySelectorAll('textarea[ckeditor]'); +ckeditorFields.forEach((field: HTMLTextAreaElement): void => { + ClassicEditor + .create( field ) + .then( editor => { + //console.log( 'CkEditor was initialized', editor ); + }) + .catch( error => { + console.error( error.stack ); + }) + ; +}); +//Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea')); diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/collection/index.ts b/src/Bundle/ChillMainBundle/Resources/public/module/collection/index.ts index de428335d..875e99fad 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/module/collection/index.ts +++ b/src/Bundle/ChillMainBundle/Resources/public/module/collection/index.ts @@ -53,14 +53,17 @@ export const handleAdd = (button: any): void => { let empty_explain: HTMLLIElement | null = collection.querySelector('li[data-collection-empty-explain]'), entry = document.createElement('li'), - counter = collection.childNodes.length + 1, - content = prototype.replace(new RegExp('__name__', 'g'), counter.toString()), + counter = collection.querySelectorAll('li.entry').length, // Updated counter logic + content = prototype.replace(/__name__/g, counter.toString()), event = new CustomEvent('collection-add-entry', {detail: new CollectionEventPayload(collection, entry)}); + console.log(counter) + console.log(content) + entry.innerHTML = content; entry.classList.add('entry'); - if ("dataCollectionRegular" in collection.dataset) { + if ("collectionRegular" in collection.dataset) { initializeRemove(collection, entry); if (empty_explain !== null) { empty_explain.remove(); diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js index 6b33c0f52..03220630f 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js @@ -159,3 +159,5 @@ document.addEventListener('DOMContentLoaded', function(e) { loadDynamicPicker(document) }) +window.loadDynamicPicker = loadDynamicPicker; + diff --git a/src/Bundle/ChillMainBundle/Resources/public/page/export/download-export.js b/src/Bundle/ChillMainBundle/Resources/public/page/export/download-export.js new file mode 100644 index 000000000..d0163dc96 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/page/export/download-export.js @@ -0,0 +1,16 @@ +import {download_report} from "../../lib/download-report/download-report"; + +window.addEventListener("DOMContentLoaded", function(e) { + const export_generate_url = window.export_generate_url; + + if (typeof export_generate_url === 'undefined') { + console.error('Alias not found!'); + throw new Error('Alias not found!'); + } + + const query = window.location.search, + container = document.querySelector("#download_container") + ; + + download_report(export_generate_url + query.toString(), container); +}); diff --git a/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js b/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js index 2f91c7777..1536417b1 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js @@ -4,38 +4,124 @@ window.addEventListener('DOMContentLoaded', function() { let divTransitions = document.querySelector('#transitions'), futureDestUsersContainer = document.querySelector('#futureDests') - ; - - if (null !== divTransitions) { - new ShowHide({ - load_event: null, - froms: [divTransitions], - container: [futureDestUsersContainer], - test: function(divs, arg2, arg3) { - for (let div of divs) { - for (let input of div.querySelectorAll('input')) { - if (input.checked) { - if (input.dataset.toFinal === "1") { - return false; - } else { - return true; - } - } - } - } - - return true; - }, - }); - } + personSignatureField = document.querySelector('#person-signature-field'); + userSignatureField = document.querySelector('#user-signature-field'); + signatureTypeChoices = document.querySelector('#signature-type-choice'); + personChoice = document.querySelector('#workflow_step_isPersonOrUserSignature_0'); + userChoice = document.querySelector('#workflow_step_isPersonOrUserSignature_1'); + signatureZone = document.querySelector('#signature-zone'); + ; let - transitionFilterContainer = document.querySelector('#transitionFilter'), - transitions = document.querySelector('#transitions') + transitionFilterContainer = document.querySelector('#transitionFilter'), + transitionsContainer = document.querySelector('#transitions') ; + // ShowHide instance for signatureTypeChoices. This should always be present in the DOM and we toggle visibility. + // The field is not mapped and so not submitted with the form. Without it's presence upon DOM loading other show hides do not function well. + signatureTypeChoices.style.display = 'none'; + + + // ShowHide instance for future dest users + new ShowHide({ + debug: false, + load_event: null, + froms: [divTransitions], + container: [futureDestUsersContainer], + test: function(froms, event) { + for (let transition of froms) { + for (let input of transition.querySelectorAll('input')) { + if (input.checked) { + const inputData = JSON.parse(input.getAttribute('data-is-signature')) + if (inputData.includes('person') || inputData.includes('user')) { + signatureTypeChoices.style.display = ''; + return false; + } else { + personChoice.checked = false + userChoice.checked = false + + signatureTypeChoices.style.display = 'none'; + return true; + } + } + } + } + return false; + } + }); + + // ShowHide signature zone + new ShowHide({ + debug: false, + load_event: null, + froms: [divTransitions], + container: [signatureZone], + test: function(froms, event) { + for (let transition of froms) { + for (let input of transition.querySelectorAll('input')) { + if (input.checked) { + const inputData = JSON.parse(input.getAttribute('data-is-signature')) + if (inputData.includes('person') || inputData.includes('user')) { + signatureTypeChoices.style.display = ''; + return true; + } + } + } + } + return false; + } + }); + + // ShowHides for personSignatureField or userSignatureField within signature zone + new ShowHide({ + debug: false, + froms: [signatureTypeChoices], + container: [personSignatureField], + test: function(froms, event) { + for (let container of froms) { + return personChoice.checked; + } + return false; + }, + }); + + new ShowHide({ + debug: false, + froms: [signatureTypeChoices], + container: [userSignatureField], + test: function(froms, event) { + for (let container of froms) { + return userChoice.checked; + } + return false; + }, + }); + + if (null !== divTransitions) { + new ShowHide({ + load_event: null, + froms: [divTransitions], + container: [futureDestUsersContainer], + test: function(divs, arg2, arg3) { + for (let div of divs) { + for (let input of div.querySelectorAll('input')) { + if (input.checked) { + if (input.dataset.toFinal === "1") { + return false; + } else { + return true; + } + } + } + } + + return true; + }, + }); + } + if (null !== transitionFilterContainer) { - transitions.querySelectorAll('.form-check').forEach(function(row) { + transitionsContainer.querySelectorAll('.form-check').forEach(function(row) { const isForward = row.querySelector('input').dataset.isForward; @@ -66,5 +152,4 @@ window.addEventListener('DOMContentLoaded', function() { }); }); } - }); diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/DashboardWidgets/NewsItem.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/DashboardWidgets/NewsItem.vue index d3b499cac..6c1435f58 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/DashboardWidgets/NewsItem.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/DashboardWidgets/NewsItem.vue @@ -125,7 +125,7 @@ const preprocess = (markdown: string): string => { } const postprocess = (html: string): string => { - DOMPurify.addHook('afterSanitizeAttributes', (node) => { + DOMPurify.addHook('afterSanitizeAttributes', (node: any) => { if ('target' in node) { node.setAttribute('target', '_blank'); node.setAttribute('rel', 'noopener noreferrer'); diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue index f98d7a5cb..f82e8a88c 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue @@ -9,13 +9,16 @@ + {{ $t('on_hold') }}
@@ -73,7 +74,8 @@ const i18n = { you_subscribed_to_all_steps: "Vous recevrez une notification à chaque étape", you_subscribed_to_final_step: "Vous recevrez une notification à l'étape finale", by: "Par", - at: "Le" + at: "Le", + on_hold: "En attente" } } } diff --git a/src/Bundle/ChillMainBundle/Resources/views/CRUD/_edit_content.html.twig b/src/Bundle/ChillMainBundle/Resources/views/CRUD/_edit_content.html.twig index 0bfa5d54b..a6f139fd7 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/CRUD/_edit_content.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/CRUD/_edit_content.html.twig @@ -1,5 +1,5 @@ {% set formId = crudMainFormId|default('crud_main_form') %} - + {% block crud_content_header %}

{{ ('crud.'~crud_name~'.title_edit')|trans }}

{% endblock crud_content_header %} @@ -21,9 +21,9 @@
    {% block content_form_actions_back %}
  • - - {{ 'Cancel'|trans }} - +{# #} +{# {{ 'Cancel'|trans }}#} +{# #}
  • {% endblock %} {% block content_form_actions_before %}{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.html.twig new file mode 100644 index 000000000..5aafb6635 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.html.twig @@ -0,0 +1,395 @@ +{% extends '@ChillMain/layout.html.twig' %} + +{% block title %} + SASS Assets Catalogue +{% endblock %} + +{% block css %} + +{% endblock %} + +{% block content %} +
    +

    {{ block('title') }}

    + +Voir aussi: +Test 1 | +Test 2 + +

    Flex-table et flex-bloc

    +

    Base d'un placement flex alternatif à l'usage des tables. + Flex-table et flex-bloc utilisent la même structure html (seul la root class change). + Le placement est responsive. + La bordure utilise box-shadow pour simuler border-collapse (table). +

    +

    Une classe separator peut être appliquée sur item-row

    + + +<div class="flex-table"> + <div class="item-bloc"> + <div class="item-row"> + <div class="item-col"></div> + <div class="item-col"></div> + </div> + <div class="item-row separator"> + <div class="item-col"></div> + <div class="item-col"></div> + </div> + </div> + <div class="item-bloc"> + <div class="item-row"> + <div class="item-col"></div> + <div class="item-col"></div> + </div> + <div class="item-row"> + <div class="item-col"></div> + <div class="item-col"></div> + </div> + </div> +</div> + + +

    Flex-table

    +

    On fixe manuellement la largeur de la première colonne : +

    div.flex-table div.item-bloc div.item-row div.item-col:first-child { flex-basis: 20%; }
    +

    +
    +
    +
    +
    Title row1
    +
    +
      +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    +
    +
    +
    +
    Title row2
    +
    Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    +
    +
    +
    Title row3
    +
    Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    +
    +
    +
    +
    +
    Title row1
    +
    +
      +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    +
    +
    +
    +
    Title row2
    +
    Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    +
    +
    +
    + +

    Flex-bloc

    +

    On fixe manuellement la largeur des blocs : +

    div.flex-bloc div.item-bloc { flex-basis: 50%; }
    +

    +
    +
    +
    +
    Title row1
    +
    +
      +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    +
    +
    +
    +
    Title row2
    +
    Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    +
    +
    +
    Title row3
    +
    Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    +
    +
    +
    +
    +
    Title row1
    +
    +
      +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    • Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    • +
    +
    +
    +
    +
    Title row2
    +
    Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac viverra et a dui.
    +
    +
    +
    + +

    Wrap-list

    +

    Une liste inline qui s'aligne, puis glisse sous son titre.

    +
    + +
    +
    Problématiques sociales
    + +
    +
    + +<div class="wrap-list"> + <div class="wl-row"> + <div class="wl-col title">title</div> + <div class="wl-col list"> + <p class="wl-item">item</p> + <p class="wl-item">item</p> + ... + </div> + </div> + ... +</div> + + +

    Wrap-header

    +

    Réglage d'une zone de titre sur 2 lignes.

    +
    +
    +
    + Title + badge +
    +
    + badge +
    +
    +
    +
    from startdate to enddate
    +
    text
    +
    +
    + +<div class="wrap-header"> + <div class="wh-row"> + <div class="wh-col">line1 left</div> + <div class="wh-col">line1 right</div> + </div> + <div class="wh-row"> + <div class="wh-col">line2 left</div> + <div class="wh-col">line2 right</div> + </div> +</div> + + +

    Float-button top

    +

    Une zone de bouton flotte à droite d'un contenu. On peut voir en faisant varier la largeur que celui-ci vient s'adapter harmonieusement autour des boutons.

    +
    +
    +
    +
      +
    • +
    • +
    • +
    +
    + Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac. Proin fermentum mauris quam, ut suscipit nisl auctor at. Ut vestibulum ligula eget ex congue, efficitur interdum ipsum tincidunt. Integer id sapien et nibh tristique viverra et a dui. Ut blandit pharetra consectetur. Sed scelerisque eget purus at tempus. Etiam sit amet tellus et eros semper tempor. Curabitur suscipit pulvinar enim at lobortis. Ut nisl augue, cursus vel hendrerit sed, posuere vel sapien. Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    + +<div class="float-button top"> + <div class="box"> + <div class="action"> + floating button + </div> + content ... + </div> +</div> + + +

    Float-button bottom

    +

    Avec la même structure, on accroche la zone de bouton en bas, toujours à droite. Voir source.

    +
    +
    +
    +
      +
    • +
    • +
    • +
    +
    + Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac. Proin fermentum mauris quam, ut suscipit nisl auctor at. Ut vestibulum ligula eget ex congue, efficitur interdum ipsum tincidunt. Integer id sapien et nibh tristique viverra et a dui. Ut blandit pharetra consectetur. Sed scelerisque eget purus at tempus. Etiam sit amet tellus et eros semper tempor. Curabitur suscipit pulvinar enim at lobortis. Ut nisl augue, cursus vel hendrerit sed, posuere vel sapien. Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    + +<div class="float-button bottom"> + <div class="box"> + <div class="action"> + floating button + </div> + content ... + </div> +</div> + + + +

    Buttons

    + + +

    Variants of
    record_actions

    + +

    small

    + +
      +
    • +
    + +

    inline

    + +
    + This is inline and small + +
      +
    • +
    +
    + +

    slim

    + +

    Ajouter slim enlève la marge inférieure. Permet un meilleur alignement horizontal dans une row

    + +
    +
    +
    + Some text, ul_record_actions sans slim +
    +
    +
      +
    • +
    +
    +
    +
    +
    + Some text, ul_record_actions avec slim +
    +
    +
      +
    • +
    +
    +
    +
    + + + +<a class="btn btn-submit">Text</a> +Toutes les classes btn-* de bootstrap sont fonctionnelles + +

    Hover

    + +

    Ajouter .row-hover sur une class .row provoque un changement de background au survol

    + +
    +
    + +
    + A signé le 04/09/2024 à 13:55 +
    +
    +
    + +
    + +
    +
    +
    + +
    + A signé le 04/09/2024 à 13:57 +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test1.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test1.html.twig new file mode 100644 index 000000000..8b16da207 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test1.html.twig @@ -0,0 +1,84 @@ +{% extends '@ChillMain/layout.html.twig' %} + +{% block title %} + SASS Assets Tests - page 1 +{% endblock %} + +{% block css %} + +{% endblock %} + +{% block content %} +
    +

    CSS Tests - page 1 : float-button

    + +

    1) avec des li

    +
    +
    +
    +
      +
    • +
    • +
    • +
    +
    +
      +
    • Sed efficitur magna vel massa efficitur venenatis. Sed odio massa, scelerisque sit amet mauris eu, tristique dictum arcu. Sed posuere, elit eget cursus rhoncus, arcu ligula blandit nisi, in vulputate eros massa non risus.
    • +
    • +
      +
      +

      97, chemin Franck Julien,

      +

      1000 Bruxelles

      +

      Belgique

      +
      +
      +
      + + Couloir: 3 + +
      +
      +
      +
    • +
    • +33 8 27 17 12 19
    • +
    • gusikowski.yesenia@hotmail.com
    • +
    +
    +
    +

    2) avec des p

    + +
    +
    +
    +
      +
    • +
    • +
    • +
    +
    +

    Voir trick.

    +

    Sed efficitur magna vel massa efficitur venenatis. Sed odio massa, scelerisque sit amet mauris eu, tristique dictum arcu. Sed posuere, elit eget cursus rhoncus, arcu ligula blandit nisi, in vulputate eros massa non risus. Proin lacinia, sapien in pharetra ultricies, justo urna fermentum lectus, non tempor ipsum leo a ante. Aenean porta, ipsum in fringilla hendrerit, nisi justo vestibulum ex, non lacinia risus felis vitae diam. Curabitur sem eros, consectetur a auctor vel, facilisis sit amet sem.

    +

    Aenean finibus a nisl a scelerisque. Donec bibendum facilisis odio id euismod. Pellentesque luctus justo ligula, eget dictum ligula ultrices quis. Pellentesque at nunc est. Aenean luctus, tortor in lacinia porta, ex nisl dignissim magna, non vehicula elit risus at elit. Suspendisse in velit non augue egestas laoreet. Etiam blandit lacus at semper aliquam. Integer leo nunc, condimentum sagittis accumsan sit amet, consectetur vel massa. Aenean convallis nibh vel augue ullamcorper tempus. Integer eu laoreet sapien.

    +
    +
    + +

    3) avec des div

    +
    +
    +
    +
      +
    • +
    • +
    • +
    +
    +
    Voir trick.
    +
    Sed efficitur magna vel massa efficitur venenatis. Sed odio massa, scelerisque sit amet mauris eu, tristique dictum arcu. Sed posuere, elit eget cursus rhoncus, arcu ligula blandit nisi, in vulputate eros massa non risus. Proin lacinia, sapien in pharetra ultricies, justo urna fermentum lectus, non tempor ipsum leo a ante. Aenean porta, ipsum in fringilla hendrerit, nisi justo vestibulum ex, non lacinia risus felis vitae diam. + Curabitur sem eros, consectetur a auctor vel, facilisis sit amet sem.
    +
    Aenean finibus a nisl a scelerisque. Donec bibendum facilisis odio id euismod. Pellentesque luctus justo ligula, eget dictum ligula ultrices quis. Pellentesque at nunc est. Aenean luctus, tortor in lacinia porta, ex nisl dignissim magna, non vehicula elit risus at elit. Suspendisse in velit non augue egestas laoreet. Etiam blandit lacus at semper aliquam. Integer leo nunc, condimentum sagittis accumsan sit amet, consectetur vel massa. Aenean convallis nibh vel augue ullamcorper tempus. Integer eu laoreet sapien.
    +
    +
    + +
    +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test2.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test2.html.twig new file mode 100644 index 000000000..712ba3eef --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Dev/dev.assets.test2.html.twig @@ -0,0 +1,78 @@ +{% extends '@ChillMain/layout.html.twig' %} + +{% block title %} + SASS Assets Tests - page 2 +{% endblock %} + +{% block css %} +{% endblock %} + +{% block content %} +
    +

    CSS Tests - page 2: grid layout

    + +

    1) mgrid 1-2: avec grid-column et grid-row

    + +
    +
    + Nam rhoncus tristique ligula, tincidunt iaculis augue tincidunt ac. Proin fermentum mauris quam, ut suscipit nisl auctor at. Ut vestibulum ligula eget ex congue, efficitur interdum ipsum tincidunt. Integer id sapien et nibh tristique viverra et a dui. Ut blandit pharetra consectetur. Sed scelerisque eget purus at tempus. Etiam sit amet tellus et eros semper tempor. Curabitur suscipit pulvinar enim at lobortis. Ut nisl augue, cursus vel hendrerit sed, posuere vel sapien. Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    +
      +
    • +
    • +
    • +
    +
    +
    + +

    2) lgrid 3-4: avec grid-template-areas

    + +
    +
    + La zone qu'on crée avec les noms doit être rectangulaires. Actuellement, il n'existe pas de méthode pour créer une zone avec une forme de L (bien que la spécification indique qu'une prochaine version pourrait couvrir cette fonctionnalité). + [...] Si des zones ne sont pas rectangulaires, cela sera également considéré comme invalide. + Voir sur MDN: Définir des zones sur une grille + +
    +
    +
      +
    • +
    • +
    • +
    +
    +
    + +

    3) cgrid 5-6-7-8: avec masonry

    +

    Expérimental: dans FF about:config, il faut mettre layout.css.grid-template-masonry-value.enabled = true

    + +
    +
    + 1 Integer id sapien et nibh tristique viverra et a dui. Ut blandit pharetra consectetur. Sed scelerisque eget purus at tempus. Etiam sit amet tellus et eros semper tempor. Curabitur suscipit pulvinar enim at lobortis. Ut nisl augue, cursus vel hendrerit sed, posuere vel sapien. Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    + 2 Sed scelerisque eget purus at tempus. Etiam sit amet tellus et eros semper tempor. Curabitur suscipit pulvinar enim at lobortis. Ut nisl augue, cursus vel hendrerit sed, posuere vel sapien. Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    + 3 Curabitur suscipit pulvinar enim at lobortis. Ut nisl augue, cursus vel hendrerit sed, posuere vel sapien. Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    + 4 Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. In vitae tristique leo, a fringilla nisl. +
    +
    + 5 Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim a accumsan. +
    +
    + 6 Proin hendrerit arcu velit, eu ultrices dui interdum eget. Vestibulum consectetur sodales enim. +
    +
    + 7 Proin hendrerit arcu velit, eu ultrices dui interdum eget. +
    +
    + 8 Eu ultrices dui interdum eget. +
    +
    + +
    +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Dev/swagger-ui/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Dev/swagger-ui/index.html.twig new file mode 100644 index 000000000..21d1ac505 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Dev/swagger-ui/index.html.twig @@ -0,0 +1,22 @@ + + + + + + + SwaggerUI + + + +
    + + + + diff --git a/src/Bundle/ChillMainBundle/Resources/views/Export/download.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Export/download.html.twig index bd7dbf7e9..13d064691 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Export/download.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Export/download.html.twig @@ -22,15 +22,13 @@ {% block js %} +{{ encore_entry_link_tags('page_download_exports') }} +{% endblock %} + +{% block css %} + {{ encore_entry_script_tags('page_download_exports') }} {% endblock %} {% block content %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Menu/user.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Menu/user.html.twig index 00a50c6e3..52be8b50f 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Menu/user.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Menu/user.html.twig @@ -31,7 +31,7 @@ {{ render(controller('Chill\\MainBundle\\Controller\\UIController::showNotificationUserCounterAction')) }} - {% if is_granted('ROLE_PREVIOUS_ADMIN') %} + {% if is_granted('IS_IMPERSONATOR') %} {% endif %} @@ -39,7 +39,7 @@ - {% if transition_form.freezeAfter is defined %} - {{ form_row(transition_form.freezeAfter) }} - {% endif %} +
    +
    + {{ form_row(transition_form.isPersonOrUserSignature) }} + {{ form_errors(transition_form.isPersonOrUserSignature) }} +
    +
    + {{ form_row(transition_form.futureUserSignature) }} + {{ form_errors(transition_form.futureUserSignature) }} +
    +
    + {{ form_row(transition_form.futurePersonSignatures) }} + {{ form_errors(transition_form.futurePersonSignatures) }} +
    +
    - {{ form_row(transition_form.future_dest_users) }} - - {{ form_row(transition_form.future_cc_users) }} - - {{ form_row(transition_form.future_dest_emails) }} - {{ form_errors(transition_form.future_dest_users) }} +
    + {{ form_row(transition_form.futureDestUsers) }} + {{ form_errors(transition_form.futureDestUsers) }} +
    +
    + {{ form_row(transition_form.futureCcUsers) }} + {{ form_errors(transition_form.futureCcUsers) }} +
    +
    + {{ form_row(transition_form.futureDestEmails) }} + {{ form_errors(transition_form.futureDestEmails) }} +

    {{ form_label(transition_form.comment) }}

    diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig index a3e2e24b9..670d27ecc 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig @@ -40,11 +40,13 @@ {% set forward = workflow_metadata(step.entityWorkflow, 'isForward', transition) %}
    - {% if step.transitionBy is not null %}
    - {{ step.transitionBy|chill_entity_render_box({'at_date': step.transitionAt}) }} + {%- if step.transitionBy is not null -%} + {{ step.transitionBy|chill_entity_render_box({'at_date': step.transitionAt}) }} + {% else %} + {{ 'workflow.Automated transition'|trans }} + {%- endif -%}
    - {% endif %}
    {{ step.transitionAt|format_datetime('long', 'medium') }}
    @@ -76,7 +78,11 @@

    {{ 'workflow.Users allowed to apply transition'|trans }} :

      {% for u in step.destUser %} -
    • {{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}
    • +
    • {{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }} + {% if entity_workflow.isOnHoldAtCurrentStep %} + {{ 'workflow.On hold'|trans }} + {% endif %} +
    • {% endfor %}
    {% endif %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig new file mode 100644 index 000000000..b0e401645 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig @@ -0,0 +1,43 @@ +

    {{ 'workflow.signature_zone.title'|trans }}

    + +
    + diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_metadata.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_metadata.html.twig new file mode 100644 index 000000000..5b828832d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_metadata.html.twig @@ -0,0 +1,24 @@ +{% extends '@ChillMain/layout.html.twig' %} + +{% block title %} + {{ 'Signature'|trans }} +{% endblock %} + +{% block content %} +
    +

    {{ 'workflow.signature_zone.metadata.sign_by'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname}) }}

    + + {% if metadata_form is not null %} + {{ form_start(metadata_form) }} + {{ form_row(metadata_form.documentType) }} + {{ form_row(metadata_form.documentNumber) }} + {{ form_row(metadata_form.expirationDate) }} +
      +
    • + {{ form_widget(metadata_form.submit, { 'attr' : { 'class' : 'btn btn-submit' }} ) }} +
    • +
    + {{ form_end(metadata_form) }} + {% endif %} +
    +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig new file mode 100644 index 000000000..03e5a9174 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig @@ -0,0 +1,35 @@ + + + + + + + + Signature + + {{ encore_entry_link_tags('mod_bootstrap') }} + {{ encore_entry_link_tags('mod_forkawesome') }} + {{ encore_entry_link_tags('chill') }} + {{ encore_entry_link_tags('vue_document_signature') }} + + + + + + {% block js %} + {{ encore_entry_script_tags('mod_document_action_buttons_group') }} + + {{ encore_entry_script_tags('vue_document_signature') }} + {% endblock %} + +
    +
    +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig index 782eae136..c5daff201 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig @@ -39,6 +39,9 @@

    {{ handler.entityTitle(entity_workflow) }}

    {{ macro.breadcrumb({'entity_workflow': entity_workflow}) }} + {% if entity_workflow.isOnHoldAtCurrentStep %} + {{ 'workflow.On hold'|trans }} + {% endif %}
    {% include handler_template with handler_template_data|merge({'display_action': true }) %} @@ -57,18 +60,28 @@
    {% include '@ChillMain/Workflow/_follow.html.twig' %}
    + {% if signatures|length > 0 %} +
    {% include '@ChillMain/Workflow/_signature.html.twig' %}
    + {% endif %}
    {% include '@ChillMain/Workflow/_decision.html.twig' %}
    {#
    {% include '@ChillMain/Workflow/_comment.html.twig' %}
    #}
    {% include '@ChillMain/Workflow/_history.html.twig' %}
    - {# useful ? - #} +
    {% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig index 5d8c39c63..5dd6dc714 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig @@ -69,6 +69,9 @@
    {{ macro.breadcrumb(l) }} + {% if l.entity_workflow.isOnHoldAtCurrentStep %} + {{ 'workflow.On hold'|trans }} + {% endif %}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig index 71d1efcf1..e3087769f 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig @@ -3,24 +3,28 @@ {% if step.previous is not null %}
  • {{ 'By'|trans ~ ' : ' }} - {{ step.previous.transitionBy|chill_entity_render_box({'at_date': step.previous.transitionAt }) }} + {% if step.previous.transitionBy is not null %}{{ step.previous.transitionBy|chill_entity_render_box({'at_date': step.previous.transitionAt }) }}{% else %}{{ 'workflow.Automated transition'|trans }}{% endif %}
  • {{ 'Le'|trans ~ ' : ' }} {{ step.previous.transitionAt|format_datetime('short', 'short') }}
  • -
  • - {{ 'workflow.For'|trans ~ ' : ' }} - - {% for d in step.destUser %}{{ d|chill_entity_render_string({'at_date': step.previous.transitionAt}) }}{% if not loop.last %}, {% endif %}{% endfor %} - -
  • -
  • - {{ 'workflow.Cc'|trans ~ ' : ' }} - - {% for u in step.ccUser %}{{ u|chill_entity_render_string({'at_date': step.previous.transitionAt }) }}{% if not loop.last %}, {% endif %}{% endfor %} - -
  • + {% if step.destUser|length > 0 %} +
  • + {{ 'workflow.For'|trans ~ ' : ' }} + + {% for d in step.destUser %}{{ d|chill_entity_render_string({'at_date': step.previous.transitionAt}) }}{% if not loop.last %}, {% endif %}{% endfor %} + +
  • + {% endif %} + {% if step.ccUser|length > 0 %} +
  • + {{ 'workflow.Cc'|trans ~ ' : ' }} + + {% for u in step.ccUser %}{{ u|chill_entity_render_string({'at_date': step.previous.transitionAt }) }}{% if not loop.last %}, {% endif %}{% endfor %} + +
  • + {% endif %} {% else %}
  • {{ 'workflow.Created by'|trans ~ ' : ' }} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/person_signature_form.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/person_signature_form.html.twig new file mode 100644 index 000000000..e69de29bb diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_notification_on_transition_completed_content.fr.txt.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_notification_on_transition_completed_content.fr.txt.twig index 1e8469968..034b9c38a 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_notification_on_transition_completed_content.fr.txt.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_notification_on_transition_completed_content.fr.txt.twig @@ -8,6 +8,6 @@ Vous êtes invités à valider cette étape au plus tôt. Vous pouvez visualiser le workflow sur cette page: -{{ absolute_url(path('chill_main_workflow_show', {'id': entity_workflow.id})) }} +{{ absolute_url(path('chill_main_workflow_show', {'id': entity_workflow.id, '_locale': 'fr'})) }} Cordialement, diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_send_access_key.fr.txt.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_send_access_key.fr.txt.twig index 6237cb68a..b4574567d 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_send_access_key.fr.txt.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/workflow_send_access_key.fr.txt.twig @@ -6,7 +6,7 @@ Titre du workflow: "{{ entityTitle }}". Vous êtes invité·e à valider cette étape. Pour obtenir un accès, vous pouvez cliquer sur le lien suivant: -{{ absolute_url(path('chill_main_workflow_grant_access_by_key', {'id': entity_workflow.currentStep.id, 'accessKey': entity_workflow.currentStep.accessKey})) }} +{{ absolute_url(path('chill_main_workflow_grant_access_by_key', {'id': entity_workflow.currentStep.id, 'accessKey': entity_workflow.currentStep.accessKey, '_locale': fr})) }} Dès que vous aurez cliqué une fois sur le lien, vous serez autorisé à valider cette étape. diff --git a/src/Bundle/ChillMainBundle/Routing/MenuBuilder/AdminNewsMenuBuilder.php b/src/Bundle/ChillMainBundle/Routing/MenuBuilder/AdminNewsMenuBuilder.php index 0ce6a9824..08e72884f 100644 --- a/src/Bundle/ChillMainBundle/Routing/MenuBuilder/AdminNewsMenuBuilder.php +++ b/src/Bundle/ChillMainBundle/Routing/MenuBuilder/AdminNewsMenuBuilder.php @@ -17,9 +17,7 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class AdminNewsMenuBuilder implements LocalMenuBuilderInterface { - public function __construct(private readonly AuthorizationCheckerInterface $authorizationChecker) - { - } + public function __construct(private readonly AuthorizationCheckerInterface $authorizationChecker) {} public function buildMenu($menuId, MenuItem $menu, array $parameters) { diff --git a/src/Bundle/ChillMainBundle/Routing/MenuBuilder/SectionMenuBuilder.php b/src/Bundle/ChillMainBundle/Routing/MenuBuilder/SectionMenuBuilder.php index a8deba828..ab73932b5 100644 --- a/src/Bundle/ChillMainBundle/Routing/MenuBuilder/SectionMenuBuilder.php +++ b/src/Bundle/ChillMainBundle/Routing/MenuBuilder/SectionMenuBuilder.php @@ -26,9 +26,7 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface /** * SectionMenuBuilder constructor. */ - public function __construct(protected AuthorizationCheckerInterface $authorizationChecker, protected TranslatorInterface $translator, protected ParameterBagInterface $parameterBag) - { - } + public function __construct(protected AuthorizationCheckerInterface $authorizationChecker, protected TranslatorInterface $translator, protected ParameterBagInterface $parameterBag) {} public function buildMenu($menuId, MenuItem $menu, array $parameters) { diff --git a/src/Bundle/ChillMainBundle/Routing/MenuBuilder/UserMenuBuilder.php b/src/Bundle/ChillMainBundle/Routing/MenuBuilder/UserMenuBuilder.php index 9775fe474..3427face3 100644 --- a/src/Bundle/ChillMainBundle/Routing/MenuBuilder/UserMenuBuilder.php +++ b/src/Bundle/ChillMainBundle/Routing/MenuBuilder/UserMenuBuilder.php @@ -22,9 +22,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class UserMenuBuilder implements LocalMenuBuilderInterface { - public function __construct(private readonly NotificationByUserCounter $notificationByUserCounter, private readonly WorkflowByUserCounter $workflowByUserCounter, private readonly Security $security, private readonly TranslatorInterface $translator, protected ParameterBagInterface $parameterBag, private readonly RequestStack $requestStack) - { - } + public function __construct(private readonly NotificationByUserCounter $notificationByUserCounter, private readonly WorkflowByUserCounter $workflowByUserCounter, private readonly Security $security, private readonly TranslatorInterface $translator, protected ParameterBagInterface $parameterBag, private readonly RequestStack $requestStack) {} public function buildMenu($menuId, \Knp\Menu\MenuItem $menu, array $parameters) { diff --git a/src/Bundle/ChillMainBundle/Routing/MenuComposer.php b/src/Bundle/ChillMainBundle/Routing/MenuComposer.php index a1bd1d52f..e16b10e8f 100644 --- a/src/Bundle/ChillMainBundle/Routing/MenuComposer.php +++ b/src/Bundle/ChillMainBundle/Routing/MenuComposer.php @@ -29,9 +29,7 @@ class MenuComposer private RouteCollection $routeCollection; - public function __construct(private readonly RouterInterface $router, private readonly FactoryInterface $menuFactory, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly RouterInterface $router, private readonly FactoryInterface $menuFactory, private readonly TranslatorInterface $translator) {} public function addLocalMenuBuilder(LocalMenuBuilderInterface $menuBuilder, $menuId) { diff --git a/src/Bundle/ChillMainBundle/Routing/MenuTwig.php b/src/Bundle/ChillMainBundle/Routing/MenuTwig.php index b8fa40d25..3b6ce7e02 100644 --- a/src/Bundle/ChillMainBundle/Routing/MenuTwig.php +++ b/src/Bundle/ChillMainBundle/Routing/MenuTwig.php @@ -31,9 +31,7 @@ class MenuTwig extends AbstractExtension 'activeRouteKey' => null, ]; - public function __construct(private readonly MenuComposer $menuComposer) - { - } + public function __construct(private readonly MenuComposer $menuComposer) {} /** * Render a Menu corresponding to $menuId. diff --git a/src/Bundle/ChillMainBundle/Search/AbstractSearch.php b/src/Bundle/ChillMainBundle/Search/AbstractSearch.php index 9c3f96f5d..c4e0fecd9 100644 --- a/src/Bundle/ChillMainBundle/Search/AbstractSearch.php +++ b/src/Bundle/ChillMainBundle/Search/AbstractSearch.php @@ -24,17 +24,15 @@ abstract class AbstractSearch implements SearchInterface /** * parse string expected to be a date and transform to a DateTime object. * - * @param type $string - * * @return \DateTime * * @throws ParsingException if the date is not parseable */ - public function parseDate($string) + public function parseDate(string $string) { try { return new \DateTime($string); - } catch (ParsingException $ex) { + } catch (\Exception $ex) { $exception = new ParsingException('The date is ' .'not parsable', 0, $ex); diff --git a/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php b/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php index 84d7d3786..12568287d 100644 --- a/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php +++ b/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php @@ -17,9 +17,7 @@ use Chill\MainBundle\Search\SearchApiQuery; class SearchUserApiProvider implements SearchApiInterface { - public function __construct(private readonly UserRepository $userRepository) - { - } + public function __construct(private readonly UserRepository $userRepository) {} public function getResult(string $key, array $metadata, float $pertinence) { diff --git a/src/Bundle/ChillMainBundle/Search/Model/Result.php b/src/Bundle/ChillMainBundle/Search/Model/Result.php index 3d407e9c4..d2365d348 100644 --- a/src/Bundle/ChillMainBundle/Search/Model/Result.php +++ b/src/Bundle/ChillMainBundle/Search/Model/Result.php @@ -19,8 +19,7 @@ class Result * mixed an arbitrary result. */ private $result, - ) { - } + ) {} public function getRelevance(): float { diff --git a/src/Bundle/ChillMainBundle/Search/ParsingException.php b/src/Bundle/ChillMainBundle/Search/ParsingException.php index b70dd81eb..241079925 100644 --- a/src/Bundle/ChillMainBundle/Search/ParsingException.php +++ b/src/Bundle/ChillMainBundle/Search/ParsingException.php @@ -11,6 +11,4 @@ declare(strict_types=1); namespace Chill\MainBundle\Search; -class ParsingException extends \Exception -{ -} +class ParsingException extends \Exception {} diff --git a/src/Bundle/ChillMainBundle/Search/SearchApi.php b/src/Bundle/ChillMainBundle/Search/SearchApi.php index b7307c140..267b90313 100644 --- a/src/Bundle/ChillMainBundle/Search/SearchApi.php +++ b/src/Bundle/ChillMainBundle/Search/SearchApi.php @@ -20,9 +20,7 @@ use Doctrine\ORM\Query\ResultSetMappingBuilder; class SearchApi { - public function __construct(private readonly EntityManagerInterface $em, private readonly iterable $providers, private readonly PaginatorFactory $paginator) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly iterable $providers, private readonly PaginatorFactory $paginator) {} public function getResults(string $pattern, array $types, array $parameters): Collection { diff --git a/src/Bundle/ChillMainBundle/Search/SearchApiResult.php b/src/Bundle/ChillMainBundle/Search/SearchApiResult.php index 4fc1cf928..9d6a0f948 100644 --- a/src/Bundle/ChillMainBundle/Search/SearchApiResult.php +++ b/src/Bundle/ChillMainBundle/Search/SearchApiResult.php @@ -17,21 +17,15 @@ class SearchApiResult { private mixed $result; - public function __construct(private readonly float $relevance) - { - } + public function __construct(private readonly float $relevance) {} - /** - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] public function getRelevance(): float { return $this->relevance; } - /** - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] public function getResult() { return $this->result; diff --git a/src/Bundle/ChillMainBundle/Search/Utils/SearchExtractionResult.php b/src/Bundle/ChillMainBundle/Search/Utils/SearchExtractionResult.php index c753013cb..b992b00c1 100644 --- a/src/Bundle/ChillMainBundle/Search/Utils/SearchExtractionResult.php +++ b/src/Bundle/ChillMainBundle/Search/Utils/SearchExtractionResult.php @@ -13,9 +13,7 @@ namespace Chill\MainBundle\Search\Utils; class SearchExtractionResult { - public function __construct(private readonly string $filteredSubject, private readonly array $found) - { - } + public function __construct(private readonly string $filteredSubject, private readonly array $found) {} public function getFilteredSubject(): string { diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php index 352c28be2..d80020285 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php @@ -18,6 +18,4 @@ use Symfony\Component\Security\Core\Authorization\Voter\Voter; * * This abstract Voter provide generic methods to handle object specific to Chill */ -abstract class AbstractChillVoter extends Voter implements ChillVoterInterface -{ -} +abstract class AbstractChillVoter extends Voter implements ChillVoterInterface {} diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php index 94605f8a0..52f1646c4 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php @@ -34,8 +34,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface private readonly ScopeResolverDispatcher $scopeResolverDispatcher, private readonly UserACLAwareRepositoryInterface $userACLAwareRepository, private readonly ParentRoleHelper $parentRoleHelper, - ) { - } + ) {} /** * Filter an array of centers, return only center which are reachable. @@ -201,7 +200,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface * * @return bool true if the user has access */ - public function userHasAccess(User $user, mixed $entity, string $attribute) + public function userHasAccess(UserInterface $user, mixed $entity, string $attribute): bool { $centers = $this->centerResolverManager->resolveCenters($entity); diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperForCurrentUser.php b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperForCurrentUser.php index 0a9d837a6..bb59cc003 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperForCurrentUser.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperForCurrentUser.php @@ -17,9 +17,7 @@ use Symfony\Component\Security\Core\Security; class AuthorizationHelperForCurrentUser implements AuthorizationHelperForCurrentUserInterface { - public function __construct(private readonly AuthorizationHelperInterface $authorizationHelper, private readonly Security $security) - { - } + public function __construct(private readonly AuthorizationHelperInterface $authorizationHelper, private readonly Security $security) {} public function getReachableCenters(string $role, ?Scope $scope = null): array { diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/ChillVoterInterface.php b/src/Bundle/ChillMainBundle/Security/Authorization/ChillVoterInterface.php index 2ed1856d2..f8b0102c7 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/ChillVoterInterface.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/ChillVoterInterface.php @@ -14,6 +14,4 @@ namespace Chill\MainBundle\Security\Authorization; /** * Provides methods for compiling voter and build admin role fields. */ -interface ChillVoterInterface -{ -} +interface ChillVoterInterface {} diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php index 3e7af8a14..dbc958cc4 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php @@ -18,8 +18,7 @@ final readonly class DefaultVoterHelper implements VoterHelperInterface public function __construct( private AuthorizationHelper $authorizationHelper, private array $configuration, - ) { - } + ) {} public function supports($attribute, $subject): bool { diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperFactory.php b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperFactory.php index 1f16004b2..805ba03e5 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperFactory.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperFactory.php @@ -13,9 +13,7 @@ namespace Chill\MainBundle\Security\Authorization; class DefaultVoterHelperFactory implements VoterHelperFactoryInterface { - public function __construct(protected AuthorizationHelper $authorizationHelper) - { - } + public function __construct(protected AuthorizationHelper $authorizationHelper) {} public function generate($context): VoterGeneratorInterface { diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperGenerator.php b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperGenerator.php index e0183cb7f..6a1fe5356 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperGenerator.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperGenerator.php @@ -15,9 +15,7 @@ final class DefaultVoterHelperGenerator implements VoterGeneratorInterface { private array $configuration = []; - public function __construct(private readonly AuthorizationHelper $authorizationHelper) - { - } + public function __construct(private readonly AuthorizationHelper $authorizationHelper) {} public function addCheckFor(?string $class, array $attributes): self { diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowStepSignatureVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowStepSignatureVoter.php new file mode 100644 index 000000000..683f1352f --- /dev/null +++ b/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowStepSignatureVoter.php @@ -0,0 +1,41 @@ +getSigner() instanceof Person) { + return true; + } + + if ($subject->getSigner() === $token->getUser()) { + return true; + } + + return false; + } +} diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowTransitionVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowTransitionVoter.php new file mode 100644 index 000000000..811c45f64 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowTransitionVoter.php @@ -0,0 +1,88 @@ + [ + self::APPLY_ALL_TRANSITIONS, + ], + ]; + } + + protected function supports(string $attribute, $subject): bool + { + return self::APPLY_ALL_TRANSITIONS === $attribute && $subject instanceof EntityWorkflowStep; + } + + protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool + { + /** @var EntityWorkflowStep $subject */ + $entityWorkflow = $subject->getEntityWorkflow(); + + if (!$this->accessDecisionManager->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow)) { + return false; + } + + $handler = $this->workflowManager->getHandler($entityWorkflow); + $entity = $handler->getRelatedEntity($entityWorkflow); + + if (null === $entity) { + return false; + } + + $centers = $this->centerResolverManager->resolveCenters($entity); + $reachableCenters = $this->authorizationHelper->getReachableCenters(self::APPLY_ALL_TRANSITIONS); + + foreach ($centers as $center) { + if (in_array($center, $reachableCenters, true)) { + return true; + } + } + + return false; + } +} diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowVoter.php index 1da50e22e..44766a583 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowVoter.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/EntityWorkflowVoter.php @@ -27,9 +27,7 @@ class EntityWorkflowVoter extends Voter final public const SHOW_ENTITY_LINK = 'CHILL_MAIN_WORKFLOW_LINK_SHOW'; - public function __construct(private readonly EntityWorkflowManager $manager, private readonly Security $security) - { - } + public function __construct(private readonly EntityWorkflowManager $manager, private readonly Security $security) {} protected function supports($attribute, $subject) { diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/WorkflowEntityDeletionVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/WorkflowEntityDeletionVoter.php index 637516ab9..3444a57a6 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/WorkflowEntityDeletionVoter.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/WorkflowEntityDeletionVoter.php @@ -12,17 +12,16 @@ declare(strict_types=1); namespace Chill\MainBundle\Security\Authorization; use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository; +use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; class WorkflowEntityDeletionVoter extends Voter { /** - * @param \Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface[] $handlers + * @param EntityWorkflowHandlerInterface[] $handlers */ - public function __construct(private $handlers, private readonly EntityWorkflowRepository $entityWorkflowRepository) - { - } + public function __construct(private $handlers, private readonly EntityWorkflowRepository $entityWorkflowRepository) {} protected function supports($attribute, $subject) { @@ -32,7 +31,7 @@ class WorkflowEntityDeletionVoter extends Voter foreach ($this->handlers as $handler) { if ($handler->isObjectSupported($subject) - && \in_array($attribute, $handler->getDeletionRoles($subject), true)) { + && \in_array($attribute, $handler->getDeletionRoles(), true)) { return true; } } diff --git a/src/Bundle/ChillMainBundle/Security/ChillSecurity.php b/src/Bundle/ChillMainBundle/Security/ChillSecurity.php new file mode 100644 index 000000000..eb21d00df --- /dev/null +++ b/src/Bundle/ChillMainBundle/Security/ChillSecurity.php @@ -0,0 +1,54 @@ +security->getUser(); + } + + public function getUser(): User + { + $user = $this->security->getUser(); + + if (!$user instanceof User) { + throw new \LogicException(sprintf('authenticated user should be an instance of %s, %s given', User::class, null !== $user ? $user::class : self::class)); + } + + return $user; + } + + public function isGranted($attribute, $subject = null): bool + { + return $this->security->isGranted($attribute, $subject); + } + + public function getToken(): ?TokenInterface + { + return $this->security->getToken(); + } +} diff --git a/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php b/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php index 5985d8567..264b77056 100644 --- a/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php +++ b/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php @@ -30,8 +30,7 @@ class PasswordRecoverEvent extends \Symfony\Contracts\EventDispatcher\Event private readonly ?User $user = null, private $ip = null, private readonly bool $safelyGenerated = false, - ) { - } + ) {} public function getIp() { diff --git a/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php b/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php index b19552d55..b325a9345 100644 --- a/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php +++ b/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php @@ -20,9 +20,7 @@ class RecoverPasswordHelper { final public const RECOVER_PASSWORD_ROUTE = 'password_recover'; - public function __construct(private readonly TokenManager $tokenManager, private readonly UrlGeneratorInterface $urlGenerator, private readonly MailerInterface $mailer) - { - } + public function __construct(private readonly TokenManager $tokenManager, private readonly UrlGeneratorInterface $urlGenerator, private readonly MailerInterface $mailer) {} /** * @param bool $absolute diff --git a/src/Bundle/ChillMainBundle/Security/ProvideRoleInterface.php b/src/Bundle/ChillMainBundle/Security/ProvideRoleInterface.php index 204329f60..d34ea4f33 100644 --- a/src/Bundle/ChillMainBundle/Security/ProvideRoleInterface.php +++ b/src/Bundle/ChillMainBundle/Security/ProvideRoleInterface.php @@ -22,8 +22,10 @@ namespace Chill\MainBundle\Security; * my_role_declaration: * # ... * tags: - * - { name: chill.role } + * - { name: chill_main.provide_role } * + * + * This tag is also automatically added using dependency injection autoconfiguration. */ interface ProvideRoleInterface { diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php index 9855477fd..903b8c5c5 100644 --- a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php +++ b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php @@ -16,9 +16,7 @@ final readonly class CenterResolverDispatcher implements CenterResolverDispatche /** * @param \Chill\MainBundle\Security\Resolver\CenterResolverInterface[] $resolvers */ - public function __construct(private iterable $resolvers = []) - { - } + public function __construct(private iterable $resolvers = []) {} public function resolveCenter($entity, ?array $options = []) { diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php index 2ded14071..f629459b4 100644 --- a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php +++ b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php @@ -18,9 +18,7 @@ final readonly class CenterResolverManager implements CenterResolverManagerInter /** * @param \Chill\MainBundle\Security\Resolver\CenterResolverInterface[] $resolvers */ - public function __construct(private iterable $resolvers = []) - { - } + public function __construct(private iterable $resolvers = []) {} public function resolveCenters($entity, ?array $options = []): array { diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php b/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php index 3959cc5a3..032c28a9b 100644 --- a/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php +++ b/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php @@ -15,9 +15,7 @@ use Twig\TwigFilter; final class ResolverTwigExtension extends \Twig\Extension\AbstractExtension { - public function __construct(private readonly CenterResolverManagerInterface $centerResolverDispatcher, private readonly ScopeResolverDispatcher $scopeResolverDispatcher) - { - } + public function __construct(private readonly CenterResolverManagerInterface $centerResolverDispatcher, private readonly ScopeResolverDispatcher $scopeResolverDispatcher) {} public function getFilters() { diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php b/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php index a61d92b4a..387bc724e 100644 --- a/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php +++ b/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php @@ -19,9 +19,7 @@ final readonly class ScopeResolverDispatcher /** * @param \Chill\MainBundle\Security\Resolver\ScopeResolverInterface[] $resolvers */ - public function __construct(private iterable $resolvers) - { - } + public function __construct(private iterable $resolvers) {} public function isConcerned($entity, ?array $options = []): bool { diff --git a/src/Bundle/ChillMainBundle/Security/RoleProvider.php b/src/Bundle/ChillMainBundle/Security/RoleProvider.php index 95e4a666f..ccaa92409 100644 --- a/src/Bundle/ChillMainBundle/Security/RoleProvider.php +++ b/src/Bundle/ChillMainBundle/Security/RoleProvider.php @@ -13,11 +13,6 @@ namespace Chill\MainBundle\Security; class RoleProvider { - /** - * @var ProvideRoleInterface[] - */ - private array $providers = []; - /** * an array where keys are the role, and value is the title * for the given role. @@ -26,15 +21,12 @@ class RoleProvider */ private ?array $rolesTitlesCache = null; - /** - * Add a role provider. - * - * @internal This function is called by the dependency injector: it inject provider - */ - public function addProvider(ProvideRoleInterface $provider) - { - $this->providers[] = $provider; - } + public function __construct( + /** + * @var iterable + */ + private readonly iterable $providers, + ) {} public function getRoles(): array { diff --git a/src/Bundle/ChillMainBundle/Security/UserProvider/UserProvider.php b/src/Bundle/ChillMainBundle/Security/UserProvider/UserProvider.php index 408128c6f..a561fe0bc 100644 --- a/src/Bundle/ChillMainBundle/Security/UserProvider/UserProvider.php +++ b/src/Bundle/ChillMainBundle/Security/UserProvider/UserProvider.php @@ -15,15 +15,12 @@ use Chill\MainBundle\Entity\User; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NoResultException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; -use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; class UserProvider implements UserProviderInterface { - public function __construct(protected EntityManagerInterface $em) - { - } + public function __construct(protected EntityManagerInterface $em) {} public function loadUserByUsername($username): UserInterface { @@ -38,7 +35,7 @@ class UserProvider implements UserProviderInterface ->setParameter('pattern', $username) ->getSingleResult(); } catch (NoResultException $e) { - throw new UsernameNotFoundException('Bad credentials.', 0, $e); + throw new \Symfony\Component\Security\Core\Exception\UserNotFoundException('Bad credentials.', 0, $e); } return $user; @@ -53,7 +50,7 @@ class UserProvider implements UserProviderInterface $reloadedUser = $this->em->getRepository(User::class)->find($user->getId()); if (null === $reloadedUser) { - throw new UsernameNotFoundException(sprintf('User with ID "%s" could not be reloaded.', $user->getId())); + throw new \Symfony\Component\Security\Core\Exception\UserNotFoundException(sprintf('User with ID "%s" could not be reloaded.', $user->getId())); } return $reloadedUser; diff --git a/src/Bundle/ChillMainBundle/Serializer/Model/Collection.php b/src/Bundle/ChillMainBundle/Serializer/Model/Collection.php index 9d80eabe9..6349f5d85 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Model/Collection.php +++ b/src/Bundle/ChillMainBundle/Serializer/Model/Collection.php @@ -15,9 +15,7 @@ use Chill\MainBundle\Pagination\PaginatorInterface; class Collection { - public function __construct(private $items, private readonly PaginatorInterface $paginator) - { - } + public function __construct(private $items, private readonly PaginatorInterface $paginator) {} public function getItems() { diff --git a/src/Bundle/ChillMainBundle/Serializer/Model/Counter.php b/src/Bundle/ChillMainBundle/Serializer/Model/Counter.php index 4ef3fe849..476d68568 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Model/Counter.php +++ b/src/Bundle/ChillMainBundle/Serializer/Model/Counter.php @@ -13,9 +13,7 @@ namespace Chill\MainBundle\Serializer\Model; class Counter implements \JsonSerializable { - public function __construct(private ?int $counter) - { - } + public function __construct(private ?int $counter) {} public function getCounter(): ?int { diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php index 1a5ebe86b..bbae6bd40 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php @@ -47,9 +47,7 @@ class AddressNormalizer implements ContextAwareNormalizerInterface, NormalizerAw 'confidential', ]; - public function __construct(private readonly AddressRender $addressRender) - { - } + public function __construct(private readonly AddressRender $addressRender) {} /** * @param Address $address diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php index 8e937ee66..7c41bcb8a 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php @@ -20,9 +20,7 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class CenterNormalizer implements DenormalizerInterface, NormalizerInterface { - public function __construct(private readonly CenterRepository $repository) - { - } + public function __construct(private readonly CenterRepository $repository) {} public function denormalize($data, $type, $format = null, array $context = []) { diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CommentEmbeddableDocGenNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CommentEmbeddableDocGenNormalizer.php index 4cf80ccd7..59f0302f0 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CommentEmbeddableDocGenNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CommentEmbeddableDocGenNormalizer.php @@ -23,9 +23,7 @@ class CommentEmbeddableDocGenNormalizer implements ContextAwareNormalizerInterfa { use NormalizerAwareTrait; - public function __construct(private readonly UserRepository $userRepository) - { - } + public function __construct(private readonly UserRepository $userRepository) {} /** * @param CommentEmbeddable $object diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php index 69e7744e4..9ee8bf158 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php @@ -20,9 +20,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; class DateNormalizer implements ContextAwareNormalizerInterface, DenormalizerInterface { - public function __construct(private readonly RequestStack $requestStack, private readonly ParameterBagInterface $parameterBag) - { - } + public function __construct(private readonly RequestStack $requestStack, private readonly ParameterBagInterface $parameterBag) {} public function denormalize($data, $type, $format = null, array $context = []) { diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php index b90f587bb..ed34a45be 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php @@ -19,9 +19,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; class DoctrineExistingEntityNormalizer implements DenormalizerInterface { - public function __construct(private readonly EntityManagerInterface $em, private readonly ClassMetadataFactoryInterface $serializerMetadataFactory) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly ClassMetadataFactoryInterface $serializerMetadataFactory) {} public function denormalize($data, $type, $format = null, array $context = []) { diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowNormalizer.php index 83e84f7a0..a84220099 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowNormalizer.php @@ -23,9 +23,7 @@ class EntityWorkflowNormalizer implements NormalizerInterface, NormalizerAwareIn { use NormalizerAwareTrait; - public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly MetadataExtractor $metadataExtractor, private readonly Registry $registry) - { - } + public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly MetadataExtractor $metadataExtractor, private readonly Registry $registry) {} /** * @param EntityWorkflow $object @@ -47,6 +45,7 @@ class EntityWorkflowNormalizer implements NormalizerInterface, NormalizerAwareIn 'steps' => $this->normalizer->normalize($object->getStepsChained(), $format, $context), 'datas' => $this->normalizer->normalize($handler->getEntityData($object), $format, $context), 'title' => $handler->getEntityTitle($object), + 'isOnHoldAtCurrentStep' => $object->isOnHoldAtCurrentStep(), ]; } diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowStepNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowStepNormalizer.php index 2d924eb4d..0f640f38b 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowStepNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/EntityWorkflowStepNormalizer.php @@ -21,9 +21,7 @@ class EntityWorkflowStepNormalizer implements NormalizerAwareInterface, Normaliz { use NormalizerAwareTrait; - public function __construct(private readonly MetadataExtractor $metadataExtractor) - { - } + public function __construct(private readonly MetadataExtractor $metadataExtractor) {} /** * @param EntityWorkflowStep $object diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php index a19cd6778..2f6d57db1 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php @@ -23,9 +23,7 @@ class NotificationNormalizer implements NormalizerAwareInterface, NormalizerInte { use NormalizerAwareTrait; - public function __construct(private readonly NotificationHandlerManager $notificationHandlerManager, private readonly EntityManagerInterface $entityManager, private readonly Security $security) - { - } + public function __construct(private readonly NotificationHandlerManager $notificationHandlerManager, private readonly EntityManagerInterface $entityManager, private readonly Security $security) {} /** * @param Notification $object diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PrivateCommentEmbeddableNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PrivateCommentEmbeddableNormalizer.php index 1d7ee43ce..515e831c0 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PrivateCommentEmbeddableNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PrivateCommentEmbeddableNormalizer.php @@ -18,9 +18,7 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class PrivateCommentEmbeddableNormalizer implements NormalizerInterface, DenormalizerInterface { - public function __construct(private readonly Security $security) - { - } + public function __construct(private readonly Security $security) {} public function denormalize($data, string $type, ?string $format = null, array $context = []): PrivateCommentEmbeddable { diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php index e592b453e..c05468f6d 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php @@ -41,9 +41,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware 'isAbsent' => false, ]; - public function __construct(private readonly UserRender $userRender, private readonly ClockInterface $clock) - { - } + public function __construct(private readonly UserRender $userRender, private readonly ClockInterface $clock) {} /** * @param mixed|null $format diff --git a/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCode.php b/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCode.php index 80174053a..a4589b836 100644 --- a/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCode.php +++ b/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCode.php @@ -100,8 +100,7 @@ final readonly class CollateAddressWithReferenceOrPostalCode implements CollateA public function __construct( private Connection $connection, private LoggerInterface $logger, - ) { - } + ) {} /** * @throws \Throwable diff --git a/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJob.php b/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJob.php index 7c41db3a0..4e64a1f9f 100644 --- a/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJob.php +++ b/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJob.php @@ -22,8 +22,7 @@ final readonly class CollateAddressWithReferenceOrPostalCodeCronJob implements C public function __construct( private ClockInterface $clock, private CollateAddressWithReferenceOrPostalCodeInterface $collateAddressWithReferenceOrPostalCode, - ) { - } + ) {} public function canRun(?CronJobExecution $cronJobExecution): bool { diff --git a/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJob.php b/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJob.php index 77ce3a0c5..489e75151 100644 --- a/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJob.php +++ b/src/Bundle/ChillMainBundle/Service/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJob.php @@ -21,8 +21,7 @@ final readonly class RefreshAddressToGeographicalUnitMaterializedViewCronJob imp public function __construct( private Connection $connection, private ClockInterface $clock, - ) { - } + ) {} public function canRun(?CronJobExecution $cronJobExecution): bool { diff --git a/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php b/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php index 3484fe288..b545d3979 100644 --- a/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php +++ b/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php @@ -23,8 +23,7 @@ class ViewEntityInfoManager private readonly iterable $vienEntityInfoProviders, private readonly Connection $connection, private readonly LoggerInterface $logger, - ) { - } + ) {} public function synchronizeOnDB(): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBEFromBestAddress.php b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBEFromBestAddress.php index 681d49747..f383bd799 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBEFromBestAddress.php +++ b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBEFromBestAddress.php @@ -18,11 +18,9 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; class AddressReferenceBEFromBestAddress { - private const RELEASE = 'https://gitea.champs-libres.be/api/v1/repos/Chill-project/belgian-bestaddresses-transform/releases/tags/v1.0.0'; + private const RELEASE = 'https://gitea.champs-libres.be/api/v1/repos/Chill-project/belgian-bestaddresses-transform/releases/tags/v1.1.1'; - public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $baseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) - { - } + public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $baseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) {} public function import(string $lang, array $lists): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBaseImporter.php b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBaseImporter.php index b9e8971fb..f570796f1 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBaseImporter.php +++ b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceBaseImporter.php @@ -51,9 +51,7 @@ final class AddressReferenceBaseImporter private array $waitingForInsert = []; - public function __construct(private readonly Connection $defaultConnection, private readonly LoggerInterface $logger) - { - } + public function __construct(private readonly Connection $defaultConnection, private readonly LoggerInterface $logger) {} /** * Finalize the import process and make reconciliation with addresses. diff --git a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceFromBano.php b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceFromBano.php index a8b910424..fd17f2cd2 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceFromBano.php +++ b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceFromBano.php @@ -17,9 +17,7 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; class AddressReferenceFromBano { - public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $baseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) - { - } + public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $baseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) {} public function import(string $departementNo): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceLU.php b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceLU.php index d70b5085d..50ee16401 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceLU.php +++ b/src/Bundle/ChillMainBundle/Service/Import/AddressReferenceLU.php @@ -19,9 +19,7 @@ class AddressReferenceLU { private const RELEASE = 'https://data.public.lu/fr/datasets/r/5cadc5b8-6a7d-4283-87bc-f9e58dd771f7'; - public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $addressBaseImporter, private readonly PostalCodeBaseImporter $postalCodeBaseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) - { - } + public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $addressBaseImporter, private readonly PostalCodeBaseImporter $postalCodeBaseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) {} public function import(): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/AddressToReferenceMatcher.php b/src/Bundle/ChillMainBundle/Service/Import/AddressToReferenceMatcher.php index 32e8f0984..6a7bff632 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/AddressToReferenceMatcher.php +++ b/src/Bundle/ChillMainBundle/Service/Import/AddressToReferenceMatcher.php @@ -64,9 +64,7 @@ final readonly class AddressToReferenceMatcher '{{ reviewed }}' => Address::ADDR_REFERENCE_STATUS_REVIEWED, ]; - public function __construct(private Connection $connection, private LoggerInterface $logger) - { - } + public function __construct(private Connection $connection, private LoggerInterface $logger) {} public function checkAddressesMatchingReferences(): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/GeographicalUnitBaseImporter.php b/src/Bundle/ChillMainBundle/Service/Import/GeographicalUnitBaseImporter.php index 34d7d3210..642cea31a 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/GeographicalUnitBaseImporter.php +++ b/src/Bundle/ChillMainBundle/Service/Import/GeographicalUnitBaseImporter.php @@ -43,9 +43,7 @@ final class GeographicalUnitBaseImporter private array $waitingForInsert = []; - public function __construct(private readonly Connection $defaultConnection, private readonly LoggerInterface $logger) - { - } + public function __construct(private readonly Connection $defaultConnection, private readonly LoggerInterface $logger) {} public function finalize(): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBEFromBestAddress.php b/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBEFromBestAddress.php index 2ac71abb7..a95ba1abc 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBEFromBestAddress.php +++ b/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBEFromBestAddress.php @@ -20,9 +20,7 @@ class PostalCodeBEFromBestAddress { private const RELEASE = 'https://gitea.champs-libres.be/api/v1/repos/Chill-project/belgian-bestaddresses-transform/releases/tags/v1.0.0'; - public function __construct(private readonly PostalCodeBaseImporter $baseImporter, private readonly HttpClientInterface $client, private readonly LoggerInterface $logger) - { - } + public function __construct(private readonly PostalCodeBaseImporter $baseImporter, private readonly HttpClientInterface $client, private readonly LoggerInterface $logger) {} public function import(string $lang = 'fr'): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBaseImporter.php b/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBaseImporter.php index c028c4603..b1ace3875 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBaseImporter.php +++ b/src/Bundle/ChillMainBundle/Service/Import/PostalCodeBaseImporter.php @@ -55,9 +55,7 @@ class PostalCodeBaseImporter private array $waitingForInsert = []; - public function __construct(private readonly Connection $defaultConnection) - { - } + public function __construct(private readonly Connection $defaultConnection) {} public function finalize(): void { diff --git a/src/Bundle/ChillMainBundle/Service/Import/PostalCodeFRFromOpenData.php b/src/Bundle/ChillMainBundle/Service/Import/PostalCodeFRFromOpenData.php index e40b4dff9..8893181a8 100644 --- a/src/Bundle/ChillMainBundle/Service/Import/PostalCodeFRFromOpenData.php +++ b/src/Bundle/ChillMainBundle/Service/Import/PostalCodeFRFromOpenData.php @@ -25,9 +25,7 @@ class PostalCodeFRFromOpenData { private const CSV = 'https://datanova.laposte.fr/data-fair/api/v1/datasets/laposte-hexasmal/metadata-attachments/base-officielle-codes-postaux.csv'; - public function __construct(private readonly PostalCodeBaseImporter $baseImporter, private readonly HttpClientInterface $client, private readonly LoggerInterface $logger) - { - } + public function __construct(private readonly PostalCodeBaseImporter $baseImporter, private readonly HttpClientInterface $client, private readonly LoggerInterface $logger) {} public function import(): void { diff --git a/src/Bundle/ChillMainBundle/Service/Mailer/ChillMailer.php b/src/Bundle/ChillMainBundle/Service/Mailer/ChillMailer.php index 0d5d6b2d8..3edee4763 100644 --- a/src/Bundle/ChillMainBundle/Service/Mailer/ChillMailer.php +++ b/src/Bundle/ChillMainBundle/Service/Mailer/ChillMailer.php @@ -22,9 +22,7 @@ class ChillMailer implements MailerInterface { private string $prefix = '[Chill] '; - public function __construct(private readonly MailerInterface $initial, private readonly LoggerInterface $chillLogger) - { - } + public function __construct(private readonly MailerInterface $initial, private readonly LoggerInterface $chillLogger) {} public function send(RawMessage $message, ?Envelope $envelope = null): void { diff --git a/src/Bundle/ChillMainBundle/Service/RollingDate/RollingDate.php b/src/Bundle/ChillMainBundle/Service/RollingDate/RollingDate.php index c7c5c234d..1f7f01dbc 100644 --- a/src/Bundle/ChillMainBundle/Service/RollingDate/RollingDate.php +++ b/src/Bundle/ChillMainBundle/Service/RollingDate/RollingDate.php @@ -69,8 +69,7 @@ class RollingDate private readonly string $roll, private readonly ?\DateTimeImmutable $fixedDate = null, private readonly \DateTimeImmutable $pivotDate = new \DateTimeImmutable('now'), - ) { - } + ) {} public function getFixedDate(): ?\DateTimeImmutable { diff --git a/src/Bundle/ChillMainBundle/Service/ShortMessage/NullShortMessageSender.php b/src/Bundle/ChillMainBundle/Service/ShortMessage/NullShortMessageSender.php index 82dea7bc6..16bc87790 100644 --- a/src/Bundle/ChillMainBundle/Service/ShortMessage/NullShortMessageSender.php +++ b/src/Bundle/ChillMainBundle/Service/ShortMessage/NullShortMessageSender.php @@ -20,7 +20,5 @@ namespace Chill\MainBundle\Service\ShortMessage; class NullShortMessageSender implements ShortMessageSenderInterface { - public function send(ShortMessage $shortMessage): void - { - } + public function send(ShortMessage $shortMessage): void {} } diff --git a/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessage.php b/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessage.php index e028cf3c4..a2a5b6ed4 100644 --- a/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessage.php +++ b/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessage.php @@ -26,9 +26,7 @@ class ShortMessage final public const PRIORITY_MEDIUM = 'medium'; - public function __construct(private string $content, private PhoneNumber $phoneNumber, private string $priority = 'low') - { - } + public function __construct(private string $content, private PhoneNumber $phoneNumber, private string $priority = 'low') {} public function getContent(): string { diff --git a/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageHandler.php b/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageHandler.php index 55490b2eb..344ff3c17 100644 --- a/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageHandler.php +++ b/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageHandler.php @@ -25,9 +25,7 @@ use Symfony\Component\Messenger\Handler\MessageHandlerInterface; */ class ShortMessageHandler implements MessageHandlerInterface { - public function __construct(private readonly ShortMessageTransporterInterface $messageTransporter) - { - } + public function __construct(private readonly ShortMessageTransporterInterface $messageTransporter) {} public function __invoke(ShortMessage $message): void { diff --git a/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageTransporter.php b/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageTransporter.php index 76e45acbd..bbe4f0575 100644 --- a/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageTransporter.php +++ b/src/Bundle/ChillMainBundle/Service/ShortMessage/ShortMessageTransporter.php @@ -20,9 +20,7 @@ namespace Chill\MainBundle\Service\ShortMessage; class ShortMessageTransporter implements ShortMessageTransporterInterface { - public function __construct(private readonly ShortMessageSenderInterface $sender) - { - } + public function __construct(private readonly ShortMessageSenderInterface $sender) {} public function send(ShortMessage $shortMessage): void { diff --git a/src/Bundle/ChillMainBundle/Service/ShortMessageOvh/OvhShortMessageSender.php b/src/Bundle/ChillMainBundle/Service/ShortMessageOvh/OvhShortMessageSender.php index ec9b84935..cf70ed282 100644 --- a/src/Bundle/ChillMainBundle/Service/ShortMessageOvh/OvhShortMessageSender.php +++ b/src/Bundle/ChillMainBundle/Service/ShortMessageOvh/OvhShortMessageSender.php @@ -36,8 +36,7 @@ class OvhShortMessageSender implements ShortMessageSenderInterface // for DI, must remains as third argument private readonly LoggerInterface $logger, private readonly PhoneNumberUtil $phoneNumberUtil, - ) { - } + ) {} public function send(ShortMessage $shortMessage): void { diff --git a/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowCronJob.php b/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowCronJob.php new file mode 100644 index 000000000..be3dd2a5e --- /dev/null +++ b/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowCronJob.php @@ -0,0 +1,70 @@ +clock->now() >= $cronJobExecution->getLastEnd()->add(new \DateInterval('P1D')); + } + + public function getKey(): string + { + return self::KEY; + } + + public function run(array $lastExecutionData): ?array + { + $this->logger->info('Cronjob started: Canceling stale workflows.'); + + $olderThanDate = $this->clock->now()->sub(new \DateInterval(self::KEEP_INTERVAL)); + $staleWorkflowIds = $this->workflowRepository->findWorkflowsWithoutFinalStepAndOlderThan($olderThanDate); + $lastCanceled = $lastExecutionData[self::LAST_CANCELED_WORKFLOW] ?? 0; + $processedCount = 0; + + foreach ($staleWorkflowIds as $wId) { + try { + $this->messageBus->dispatch(new CancelStaleWorkflowMessage($wId)); + $lastCanceled = max($wId, $lastCanceled); + ++$processedCount; + } catch (\Exception $e) { + $this->logger->error("Failed to dispatch CancelStaleWorkflow for ID {$wId}", ['exception' => $e]); + continue; + } + } + + $this->logger->info("Cronjob completed: {$processedCount} workflows processed."); + + return [self::LAST_CANCELED_WORKFLOW => $lastCanceled]; + } +} diff --git a/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowHandler.php b/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowHandler.php new file mode 100644 index 000000000..54485dad5 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowHandler.php @@ -0,0 +1,88 @@ +getWorkflowId(); + $olderThanDate = $this->clock->now()->sub(new \DateInterval(CancelStaleWorkflowCronJob::KEEP_INTERVAL)); + + $workflow = $this->workflowRepository->find($message->getWorkflowId()); + if (null === $workflow) { + $this->logger->alert('Workflow was not found!', [$workflowId]); + + return; + } + + if (false === $workflow->isStaledAt($olderThanDate)) { + $this->logger->alert('Workflow has transitioned in the meantime.', [$workflowId]); + + throw new UnrecoverableMessageHandlingException('the workflow is not staled any more'); + } + + $workflowComponent = $this->registry->get($workflow, $workflow->getWorkflowName()); + $metadataStore = $workflowComponent->getMetadataStore(); + $transitions = $workflowComponent->getEnabledTransitions($workflow); + + $transitionApplied = false; + $wasInInitialPosition = 'initial' === $workflow->getStep(); + + foreach ($transitions as $transition) { + $isFinal = $metadataStore->getMetadata('isFinal', $transition); + $isFinalPositive = $metadataStore->getMetadata('isFinalPositive', $transition); + + if ($isFinal && !$isFinalPositive) { + $dto = new WorkflowTransitionContextDTO($workflow); + $workflowComponent->apply($workflow, $transition->getName(), [ + 'context' => $dto, + 'byUser' => null, + 'transitionAt' => $this->clock->now(), + 'transition' => $transition->getName(), + ]); + $this->logger->info('EntityWorkflow has been cancelled automatically.', [$workflowId]); + $transitionApplied = true; + break; + } + } + + if (!$transitionApplied) { + $this->logger->error('No valid transition found for EntityWorkflow.', [$workflowId]); + throw new UnrecoverableMessageHandlingException(sprintf('No valid transition found for EntityWorkflow %d.', $workflowId)); + } + + if ($wasInInitialPosition) { + $this->em->remove($workflow); + } + + $this->em->flush(); + } +} diff --git a/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowMessage.php b/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowMessage.php new file mode 100644 index 000000000..30d2b6ab8 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Service/Workflow/CancelStaleWorkflowMessage.php @@ -0,0 +1,22 @@ +workflowId; + } +} diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php index 8a4d99f82..f59b1cd66 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php @@ -30,9 +30,7 @@ class AddressRender implements ChillEntityRenderInterface 'extended_infos' => false, ]; - public function __construct(private readonly \Twig\Environment $templating, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly \Twig\Environment $templating, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function renderBox($addr, array $options): string { diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderExtension.php b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderExtension.php index 9c8d4599e..cc2664f55 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderExtension.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderExtension.php @@ -19,24 +19,7 @@ use Twig\TwigFilter; */ class ChillEntityRenderExtension extends AbstractExtension { - /** - * @var ChillEntityRender - */ - protected $defaultRender; - - /** - * @var iterable|ChillEntityRenderInterface[] - */ - protected $renders = []; - - /** - * ChillEntityRenderExtension constructor. - */ - public function __construct(iterable $renders) - { - $this->defaultRender = new ChillEntityRender(); - $this->renders = $renders; - } + public function __construct(private readonly ChillEntityRenderManagerInterface $renderManager) {} /** * @return array|TwigFilter[] @@ -53,34 +36,13 @@ class ChillEntityRenderExtension extends AbstractExtension ]; } - public function renderBox($entity, array $options = []): string + public function renderBox(?object $entity, array $options = []): string { - if (null === $entity) { - return ''; - } - - return $this->getRender($entity, $options) - ->renderBox($entity, $options); + return $this->renderManager->renderBox($entity, $options); } - public function renderString($entity, array $options = []): string + public function renderString(?object $entity, array $options = []): string { - if (null === $entity) { - return ''; - } - - return $this->getRender($entity, $options) - ->renderString($entity, $options); - } - - protected function getRender($entity, $options): ?ChillEntityRenderInterface - { - foreach ($this->renders as $render) { - if ($render->supports($entity, $options)) { - return $render; - } - } - - return $this->defaultRender; + return $this->renderManager->renderString($entity, $options); } } diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php index d628420c7..7a7a5e1fe 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php @@ -15,7 +15,7 @@ namespace Chill\MainBundle\Templating\Entity; * Interface to implement which will render an entity in template on a custom * manner. * - * @template T + * @template T of object */ interface ChillEntityRenderInterface { @@ -31,7 +31,7 @@ interface ChillEntityRenderInterface * * ``` * - * @param T $entity + * @param T|null $entity * * @phpstan-pure */ @@ -42,7 +42,7 @@ interface ChillEntityRenderInterface * * Example: returning the name of a person. * - * @param T $entity + * @param T|null $entity * * @phpstan-pure */ diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManager.php b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManager.php new file mode 100644 index 000000000..daca1fb8a --- /dev/null +++ b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManager.php @@ -0,0 +1,56 @@ + + */ + private iterable $renders, + ) { + $this->defaultRender = new ChillEntityRender(); + } + + public function renderBox($entity, array $options = []): string + { + if (null === $entity) { + return ''; + } + + return $this->getRender($entity, $options) + ->renderBox($entity, $options); + } + + public function renderString($entity, array $options = []): string + { + if (null === $entity) { + return ''; + } + + return $this->getRender($entity, $options) + ->renderString($entity, $options); + } + + private function getRender($entity, $options): ChillEntityRenderInterface + { + foreach ($this->renders as $render) { + if ($render->supports($entity, $options)) { + return $render; + } + } + + return $this->defaultRender; + } +} diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManagerInterface.php b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManagerInterface.php new file mode 100644 index 000000000..44b996d73 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderManagerInterface.php @@ -0,0 +1,19 @@ +searchBoxFields; } - public function setSearchBox($searchBoxFields = null): self + public function setSearchBox(?array $searchBoxFields = null): self { $this->searchBoxFields = $searchBoxFields; diff --git a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php index 420420db5..350f71d4b 100644 --- a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php +++ b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php @@ -37,9 +37,7 @@ class FilterOrderHelperBuilder */ private array $userPickers = []; - public function __construct(private readonly FormFactoryInterface $formFactory, private readonly RequestStack $requestStack) - { - } + public function __construct(private readonly FormFactoryInterface $formFactory, private readonly RequestStack $requestStack) {} public function addSingleCheckbox(string $name, string $label): self { diff --git a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperFactory.php b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperFactory.php index c9c094a15..0aff466dc 100644 --- a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperFactory.php +++ b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperFactory.php @@ -16,9 +16,7 @@ use Symfony\Component\HttpFoundation\RequestStack; class FilterOrderHelperFactory implements FilterOrderHelperFactoryInterface { - public function __construct(private readonly FormFactoryInterface $formFactory, private readonly RequestStack $requestStack) - { - } + public function __construct(private readonly FormFactoryInterface $formFactory, private readonly RequestStack $requestStack) {} public function create(string $context, ?array $options = []): FilterOrderHelperBuilder { diff --git a/src/Bundle/ChillMainBundle/Templating/Listing/Templating.php b/src/Bundle/ChillMainBundle/Templating/Listing/Templating.php index 81e571eb7..0bf487072 100644 --- a/src/Bundle/ChillMainBundle/Templating/Listing/Templating.php +++ b/src/Bundle/ChillMainBundle/Templating/Listing/Templating.php @@ -25,8 +25,7 @@ class Templating extends AbstractExtension public function __construct( private readonly RequestStack $requestStack, private readonly FilterOrderGetActiveFilterHelper $filterOrderGetActiveFilterHelper, - ) { - } + ) {} public function getFilters(): array { diff --git a/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php b/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php index b5fedeec0..b7fc7a8cc 100644 --- a/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php +++ b/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php @@ -15,11 +15,11 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Contracts\Translation\TranslatorInterface; -final class TranslatableStringHelper implements TranslatableStringHelperInterface +final readonly class TranslatableStringHelper implements TranslatableStringHelperInterface { - private readonly string $defaultLocale; + private string $defaultLocale; - public function __construct(private readonly RequestStack $requestStack, private readonly TranslatorInterface $translator, ParameterBagInterface $parameterBag) + public function __construct(private RequestStack $requestStack, private TranslatorInterface $translator, ParameterBagInterface $parameterBag) { $this->defaultLocale = $parameterBag->get('kernel.default_locale'); } diff --git a/src/Bundle/ChillMainBundle/Templating/TranslatableStringTwig.php b/src/Bundle/ChillMainBundle/Templating/TranslatableStringTwig.php index bdcc1d9d9..eceae8d9c 100644 --- a/src/Bundle/ChillMainBundle/Templating/TranslatableStringTwig.php +++ b/src/Bundle/ChillMainBundle/Templating/TranslatableStringTwig.php @@ -22,9 +22,7 @@ class TranslatableStringTwig extends AbstractExtension /** * TranslatableStringTwig constructor. */ - public function __construct(private readonly TranslatableStringHelper $helper) - { - } + public function __construct(private readonly TranslatableStringHelper $helper) {} /** * Returns a list of filters to add to the existing list. diff --git a/src/Bundle/ChillMainBundle/Test/DummyPaginator.php b/src/Bundle/ChillMainBundle/Test/DummyPaginator.php index b8555a397..d85608a6b 100644 --- a/src/Bundle/ChillMainBundle/Test/DummyPaginator.php +++ b/src/Bundle/ChillMainBundle/Test/DummyPaginator.php @@ -23,8 +23,7 @@ class DummyPaginator implements PaginatorFactoryInterface private readonly UrlGeneratorInterface $urlGenerator, private readonly string $route, private readonly array $routeParameters = [], - ) { - } + ) {} public function create(int $totalItems, ?string $route = null, ?array $routeParameters = null): PaginatorInterface { diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php index 0a2faa3a2..12182b96b 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php @@ -24,9 +24,9 @@ abstract class AbstractAggregatorTest extends KernelTestCase { public static function tearDownAfterClass(): void { - if (null !== self::$container) { + if (null !== self::getContainer()) { /** @var EntityManagerInterface $em */ - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $em->getConnection()->close(); } self::ensureKernelShutdown(); @@ -35,19 +35,19 @@ abstract class AbstractAggregatorTest extends KernelTestCase /** * provide data for `testAliasDidNotDisappears`. */ - public function dataProviderAliasDidNotDisappears() + public static function dataProviderAliasDidNotDisappears() { - $datas = $this->getFormData(); + $datas = static::getFormData(); if (!\is_array($datas)) { $datas = iterator_to_array($datas); } - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { - foreach ($this->getFormData() as $data) { + foreach (static::getFormData() as $data) { yield [clone $qb, $data]; } } @@ -57,38 +57,38 @@ abstract class AbstractAggregatorTest extends KernelTestCase /** * provide data for `testAlterQuery`. */ - public function dataProviderAlterQuery() + public static function dataProviderAlterQuery() { - $datas = $this->getFormData(); + $datas = static::getFormData(); if (!\is_array($datas)) { $datas = iterator_to_array($datas); } - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { - foreach ($this->getFormData() as $data) { + foreach (static::getFormData() as $data) { yield [clone $qb, $data]; } } } } - public function dataProviderQueryExecution(): iterable + public static function dataProviderQueryExecution(): iterable { - $datas = $this->getFormData(); + $datas = static::getFormData(); if (!\is_array($datas)) { $datas = iterator_to_array($datas); } - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { - foreach ($this->getFormData() as $data) { + foreach (static::getFormData() as $data) { yield [clone $qb, $data]; } } @@ -98,9 +98,9 @@ abstract class AbstractAggregatorTest extends KernelTestCase /** * prepare data for `testGetQueryKeys`. */ - public function dataProviderGetQueryKeys() + public static function dataProviderGetQueryKeys() { - $datas = $this->getFormData(); + $datas = static::getFormData(); if (!\is_array($datas)) { $datas = iterator_to_array($datas); @@ -114,15 +114,15 @@ abstract class AbstractAggregatorTest extends KernelTestCase /** * prepare date for method `testGetResultsAndLabels`. */ - public function dataProviderGetResultsAndLabels() + public static function dataProviderGetResultsAndLabels() { - $datas = $this->getFormData(); + $datas = static::getFormData(); if (!\is_array($datas)) { $datas = iterator_to_array($datas); } - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { @@ -151,7 +151,7 @@ abstract class AbstractAggregatorTest extends KernelTestCase * * @return array an array of data. Example : `array( array(), array('fields' => array(1,2,3), ...)` where an empty array and `array(1,2,3)` are possible values */ - abstract public function getFormData(); + abstract public static function getFormData(); /** * get an array of query builders that the aggregator will use. @@ -163,7 +163,7 @@ abstract class AbstractAggregatorTest extends KernelTestCase * * @return QueryBuilder[] */ - abstract public function getQueryBuilders(); + abstract public static function getQueryBuilders(); /** * Compare aliases array before and after that aggregator alter query. diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php index bb4cdc6f7..51403f51c 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php @@ -31,9 +31,9 @@ abstract class AbstractExportTest extends WebTestCase { use PrepareClientTrait; - public function dataProviderGetQueryKeys() + public static function dataProviderGetQueryKeys() { - foreach ($this->getFormData() as $data) { + foreach (static::getFormData() as $data) { yield [$data]; } } @@ -41,12 +41,12 @@ abstract class AbstractExportTest extends WebTestCase /** * create data for `ìnitiateQuery` method. */ - public function dataProviderInitiateQuery() + public static function dataProviderInitiateQuery() { - $acl = $this->getAcl(); + $acl = static::getAcl(); - foreach ($this->getModifiersCombination() as $modifiers) { - foreach ($this->getFormData() as $data) { + foreach (static::getModifiersCombination() as $modifiers) { + foreach (static::getFormData() as $data) { yield [$modifiers, $acl, $data]; } } @@ -67,13 +67,13 @@ abstract class AbstractExportTest extends WebTestCase * ); * ``` */ - public function getACL() + public static function getACL() { if (null === static::$kernel) { static::bootKernel(); } - $em = static::$container->get(EntityManagerInterface::class); + $em = static::getContainer()->get(EntityManagerInterface::class); $centers = $em->getRepository(\Chill\MainBundle\Entity\Center::class) ->findAll(); @@ -109,16 +109,16 @@ abstract class AbstractExportTest extends WebTestCase * * @return array an array of data. Example : `array( array(), array('fields' => array(1,2,3), ...)` where an empty array and `array(1,2,3)` are possible values */ - abstract public function getFormData(); + abstract public static function getFormData(): array; /** * get the possible modifiers which could apply in combination to this * export. * . * - * @return array of string[] an array which contains an array of possible modifiers. Example : `array( array('modifier_1', 'modifier_2'), array('modifier_1'), ...)` + * @return list> of string[] an array which contains an array of possible modifiers. Example : `array( array('modifier_1', 'modifier_2'), array('modifier_1'), ...)` */ - abstract public function getModifiersCombination(); + abstract public static function getModifiersCombination(): array; protected function getParameters(bool $filterStatsByCenter): ParameterBagInterface { diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php index 6f5d74de5..5c38515fc 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php @@ -35,9 +35,9 @@ abstract class AbstractFilterTest extends KernelTestCase public static function tearDownAfterClass(): void { - if (null !== self::$container) { + if (null !== self::getContainer()) { /** @var EntityManagerInterface $em */ - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $em->getConnection()->close(); } self::ensureKernelShutdown(); @@ -46,11 +46,11 @@ abstract class AbstractFilterTest extends KernelTestCase /** * provide data for `testAliasDidNotDisappears`. */ - public function dataProviderAliasDidNotDisappears() + public static function dataProviderAliasDidNotDisappears() { - $datas = $this->getFormData(); + $datas = static::getFormData(); - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { @@ -61,11 +61,11 @@ abstract class AbstractFilterTest extends KernelTestCase } } - public function dataProviderAlterQuery() + public static function dataProviderAlterQuery() { - $datas = $this->getFormData(); + $datas = static::getFormData(); - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { @@ -76,11 +76,11 @@ abstract class AbstractFilterTest extends KernelTestCase } } - public function dataProvideQueryExecution(): iterable + public static function dataProvideQueryExecution(): iterable { - $datas = $this->getFormData(); + $datas = static::getFormData(); - foreach ($this->getQueryBuilders() as $qb) { + foreach (static::getQueryBuilders() as $qb) { if ([] === $datas) { yield [clone $qb, []]; } else { @@ -91,9 +91,9 @@ abstract class AbstractFilterTest extends KernelTestCase } } - public function dataProviderDescriptionAction() + public static function dataProviderDescriptionAction() { - foreach ($this->getFormData() as $data) { + foreach (static::getFormData() as $data) { yield [$data]; } } @@ -117,7 +117,7 @@ abstract class AbstractFilterTest extends KernelTestCase * * @return array an array of data. Example : `array( array(), array('fields' => array(1,2,3), ...)` where an empty array and `array(1,2,3)` are possible values */ - abstract public function getFormData(); + abstract public static function getFormData(); /** * Return an array with different minimal query builders. @@ -127,7 +127,7 @@ abstract class AbstractFilterTest extends KernelTestCase * * @return QueryBuilder[] an array of query builder */ - abstract public function getQueryBuilders(); + abstract public static function getQueryBuilders(); /** * Compare aliases array before and after that filter alter query. diff --git a/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php b/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php index 00045e889..a8a91ba19 100644 --- a/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php +++ b/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php @@ -28,7 +28,7 @@ trait PrepareCenterTrait /** * prepare a mocked center, with and id and name given. */ - protected function prepareCenter(int $id, string $name): Center + protected static function prepareCenter(int $id, string $name): Center { $center = new Center(); $center->setName($name); diff --git a/src/Bundle/ChillMainBundle/Test/PrepareClientTrait.php b/src/Bundle/ChillMainBundle/Test/PrepareClientTrait.php index 1e18046c7..619436269 100644 --- a/src/Bundle/ChillMainBundle/Test/PrepareClientTrait.php +++ b/src/Bundle/ChillMainBundle/Test/PrepareClientTrait.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Test; +use Chill\MainBundle\Repository\UserRepository; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; @@ -31,13 +32,41 @@ trait PrepareClientTrait $username = 'center a_social', $password = 'password', ): KernelBrowser { + if ('admin' === $username) { + return $this->getClientAuthenticatedAsAdmin(); + } + if (!$this instanceof WebTestCase) { throw new \LogicException(sprintf('The current class does not implements %s', WebTestCase::class)); } - return static::createClient([], [ - 'PHP_AUTH_USER' => $username, - 'PHP_AUTH_PW' => $password, - ]); + $client = static::createClient(); + + $userRepository = static::getContainer()->get(UserRepository::class); + $user = $userRepository->findOneByUsernameOrEmail($username); + + if (null === $user) { + throw new \RuntimeException(sprintf('user with username or email %s not found', $username)); + } + + $client->loginUser($user); + + return $client; + } + + public function getClientAuthenticatedAsAdmin(): KernelBrowser + { + if (!$this instanceof WebTestCase) { + throw new \LogicException(sprintf('The current class does not implements %s', WebTestCase::class)); + } + + $client = static::createClient(); + + /** @var \Symfony\Component\Security\Core\User\InMemoryUserProvider $userProvider */ + $userProvider = static::getContainer()->get('security.user.provider.concrete.in_memory'); + $user = $userProvider->loadUserByIdentifier('admin'); + $client->loginUser($user); + + return $client; } } diff --git a/src/Bundle/ChillMainBundle/Test/PrepareScopeTrait.php b/src/Bundle/ChillMainBundle/Test/PrepareScopeTrait.php index dbd1825d8..7bf8a41a0 100644 --- a/src/Bundle/ChillMainBundle/Test/PrepareScopeTrait.php +++ b/src/Bundle/ChillMainBundle/Test/PrepareScopeTrait.php @@ -28,7 +28,7 @@ trait PrepareScopeTrait * * The name will be present in both lang `fr` and `en`. */ - protected function prepareScope(int $id, string $name): Scope + protected static function prepareScope(int $id, string $name): Scope { $scope = new Scope(); // set the name diff --git a/src/Bundle/ChillMainBundle/Test/PrepareUserTrait.php b/src/Bundle/ChillMainBundle/Test/PrepareUserTrait.php index 044d17400..fedc46fa1 100644 --- a/src/Bundle/ChillMainBundle/Test/PrepareUserTrait.php +++ b/src/Bundle/ChillMainBundle/Test/PrepareUserTrait.php @@ -50,7 +50,7 @@ trait PrepareUserTrait * * @throws \LogicException if the trait is not set up */ - protected function prepareUser(array $permissions) + protected static function prepareUser(array $permissions) { $user = new User(); diff --git a/src/Bundle/ChillMainBundle/Tests/Authorization/EntityWorkflowTransitionVoterTest.php b/src/Bundle/ChillMainBundle/Tests/Authorization/EntityWorkflowTransitionVoterTest.php new file mode 100644 index 000000000..035d4cf58 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Authorization/EntityWorkflowTransitionVoterTest.php @@ -0,0 +1,144 @@ +prophesize(EntityWorkflowHandlerInterface::class); + $handler->getRelatedEntity($entityWorkflow)->willReturn($object); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getHandler($entityWorkflow)->willReturn($handler); + + $centerResolver = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolver->resolveCenters($object)->willReturn([$center, new Center()]); + + $autorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class); + $autorizationHelper->getReachableCenters('CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION') + ->willReturn([$center, new Center()]); + + $token = new UsernamePasswordToken($user, 'default', $user->getRoles()); + + $accessDecision = $this->prophesize(AccessDecisionManagerInterface::class); + $accessDecision->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow) + ->willReturn(true)->shouldBeCalled(); + + $voter = new EntityWorkflowTransitionVoter( + $entityWorkflowManager->reveal(), + $autorizationHelper->reveal(), + $centerResolver->reveal(), + $accessDecision->reveal(), + ); + + self::assertEquals(Voter::ACCESS_GRANTED, $voter->vote($token, $entityWorkflow->getCurrentStep(), ['CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION'])); + } + + public function testVoteOnAttributeCenterNotReachable(): void + { + $entityWorkflow = new EntityWorkflow(); + $object = new \stdClass(); + $user = new User(); + + $handler = $this->prophesize(EntityWorkflowHandlerInterface::class); + $handler->getRelatedEntity($entityWorkflow)->willReturn($object); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getHandler($entityWorkflow)->willReturn($handler); + + $centerResolver = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolver->resolveCenters($object)->willReturn([new Center()]); + + $autorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class); + $autorizationHelper->getReachableCenters('CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION') + ->willReturn([new Center()]); + + $token = new UsernamePasswordToken($user, 'default', $user->getRoles()); + + $accessDecision = $this->prophesize(AccessDecisionManagerInterface::class); + $accessDecision->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow) + ->willReturn(true)->shouldBeCalled(); + + $voter = new EntityWorkflowTransitionVoter( + $entityWorkflowManager->reveal(), + $autorizationHelper->reveal(), + $centerResolver->reveal(), + $accessDecision->reveal(), + ); + + self::assertEquals(Voter::ACCESS_DENIED, $voter->vote($token, $entityWorkflow->getCurrentStep(), ['CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION'])); + } + + public function testVoteNotOnSupportedAttribute(): void + { + $entityWorkflow = new EntityWorkflow(); + $object = new \stdClass(); + $user = new User(); + + $handler = $this->prophesize(EntityWorkflowHandlerInterface::class); + $handler->getRelatedEntity($entityWorkflow)->willReturn($object); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getHandler($entityWorkflow)->willReturn($handler); + + $centerResolver = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolver->resolveCenters($object)->willReturn([new Center()]); + + $autorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class); + $autorizationHelper->getReachableCenters('CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION') + ->willReturn([new Center()]); + + $token = new UsernamePasswordToken($user, 'default', $user->getRoles()); + + $accessDecision = $this->prophesize(AccessDecisionManagerInterface::class); + $accessDecision->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow) + ->willReturn(true); + + $voter = new EntityWorkflowTransitionVoter( + $entityWorkflowManager->reveal(), + $autorizationHelper->reveal(), + $centerResolver->reveal(), + $accessDecision->reveal(), + ); + + self::assertEquals(Voter::ACCESS_ABSTAIN, $voter->vote($token, new \stdClass(), ['CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION'])); + self::assertEquals(Voter::ACCESS_ABSTAIN, $voter->vote($token, $entityWorkflow->getCurrentStep(), ['SOMETHING_ELSE'])); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php index f5574ef2e..a9aaaa130 100644 --- a/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php @@ -27,7 +27,7 @@ final class ParentRoleHelperTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->parentRoleHelper = self::$container->get(ParentRoleHelper::class); + $this->parentRoleHelper = self::getContainer()->get(ParentRoleHelper::class); } public function testGetReachableRoles() diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php index a45cc7d29..4a65c434c 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php @@ -32,10 +32,10 @@ final class AddressControllerTest extends \Symfony\Bundle\FrameworkBundle\Test\W self::ensureKernelShutdown(); } - public function generateAddressIds(): iterable + public static function generateAddressIds(): iterable { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $qb = $em->createQueryBuilder(); $addresses = $qb->select('a')->from(Address::class, 'a') diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php index 36796f47f..335f6f29b 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php @@ -25,11 +25,11 @@ final class AddressReferenceApiControllerTest extends WebTestCase { use PrepareClientTrait; - public function provideData() + public static function provideData() { self::bootKernel(); /** @var EntityManagerInterface $em */ - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $postalCode = $em->createQueryBuilder() ->select('pc') diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/AddressToReferenceMatcherControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/AddressToReferenceMatcherControllerTest.php index bd8c03860..ec4d3fa09 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/AddressToReferenceMatcherControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/AddressToReferenceMatcherControllerTest.php @@ -46,7 +46,7 @@ class AddressToReferenceMatcherControllerTest extends WebTestCase $this->assertResponseIsSuccessful(); - $this->addressRepository = self::$container->get(AddressRepository::class); + $this->addressRepository = self::getContainer()->get(AddressRepository::class); $address = $this->addressRepository->find($addressId); $this->assertEquals(Address::ADDR_REFERENCE_STATUS_REVIEWED, $address->getRefStatus()); @@ -63,7 +63,7 @@ class AddressToReferenceMatcherControllerTest extends WebTestCase $this->assertResponseIsSuccessful(); - $this->addressRepository = self::$container->get(AddressRepository::class); + $this->addressRepository = self::getContainer()->get(AddressRepository::class); $address = $this->addressRepository->find($addressId); $this->assertEquals(Address::ADDR_REFERENCE_STATUS_MATCH, $address->getRefStatus()); @@ -75,7 +75,7 @@ class AddressToReferenceMatcherControllerTest extends WebTestCase public static function addressToReviewProvider(): iterable { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $nb = $em->createQuery('SELECT count(a) FROM '.Address::class.' a') ->getSingleScalarResult(); @@ -101,7 +101,7 @@ class AddressToReferenceMatcherControllerTest extends WebTestCase public static function addressUnsyncedProvider(): iterable { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $nb = $em->createQuery('SELECT count(a) FROM '.AddressReference::class.' a') ->getSingleScalarResult(); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/ExportControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/ExportControllerTest.php index 10ad4060b..6c7ade9bb 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/ExportControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/ExportControllerTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Tests\Controller; +use Chill\MainBundle\Test\PrepareClientTrait; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** @@ -22,19 +23,14 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; */ final class ExportControllerTest extends WebTestCase { + use PrepareClientTrait; + public function testIndex() { - $client = self::createClient([], [ - 'PHP_AUTH_USER' => 'center a_social', - 'PHP_AUTH_PW' => 'password', - 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR', - ]); + $client = $this->getClientAuthenticatedAsAdmin(); $client->request('GET', '/fr/exports/'); - $this->assertTrue( - $client->getResponse()->isSuccessful(), - 'assert the list is shown' - ); + self::assertResponseIsSuccessful(); } } diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/GeographicalUnitByAddressApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/GeographicalUnitByAddressApiControllerTest.php index f47ddd40b..8a094d00b 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/GeographicalUnitByAddressApiControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/GeographicalUnitByAddressApiControllerTest.php @@ -40,7 +40,7 @@ class GeographicalUnitByAddressApiControllerTest extends WebTestCase public static function generateRandomAddress(): iterable { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $nb = $em->createQuery('SELECT COUNT(a) FROM '.Address::class.' a')->getSingleScalarResult(); /** @var Address $random */ diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/LoginControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/LoginControllerTest.php index 9dd664f5d..91b1d5ee3 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/LoginControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/LoginControllerTest.php @@ -61,11 +61,6 @@ final class LoginControllerTest extends WebTestCase $client->click($crawler->selectLink('Se déconnecter')->link()); $this->assertTrue($client->getResponse()->isRedirect()); - $client->followRedirect(); // redirect to login page - - // check we are back on login page - $this->assertMatchesRegularExpression('/\/login$/', $client->getResponse() - ->headers - ->get('location')); + $this->assertResponseRedirects('http://localhost/'); } } diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemControllerTest.php index 5aa515fd1..3881188e9 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemControllerTest.php @@ -42,7 +42,7 @@ class NewsItemControllerTest extends WebTestCase public static function tearDownAfterClass(): void { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); foreach (self::$entitiesToDelete as [$class, $id]) { $entity = $em->find($class, $id); @@ -58,7 +58,7 @@ class NewsItemControllerTest extends WebTestCase public static function generateNewsItemIds(): iterable { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $newsItem = new NewsItem(); $newsItem->setTitle('Lorem Ipsum'); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemsHistoryControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemsHistoryControllerTest.php index 19da9ac18..d36fca40c 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemsHistoryControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/NewsItemsHistoryControllerTest.php @@ -33,7 +33,7 @@ class NewsItemsHistoryControllerTest extends WebTestCase public static function tearDownAfterClass(): void { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); foreach (static::$toDelete as [$class, $entity]) { $query = $em->createQuery(sprintf('DELETE FROM %s e WHERE e.id = :id', $class)) @@ -54,7 +54,7 @@ class NewsItemsHistoryControllerTest extends WebTestCase public static function generateNewsItemIds(): iterable { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $news = new NewsItem(); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/NotificationApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/NotificationApiControllerTest.php index f64451af9..1c19a1466 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/NotificationApiControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/NotificationApiControllerTest.php @@ -28,25 +28,27 @@ final class NotificationApiControllerTest extends WebTestCase { use PrepareClientTrait; - private array $toDelete = []; + private static array $toDelete = []; protected function tearDown(): void { - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); - foreach ($this->toDelete as [$className, $id]) { + foreach (self::$toDelete as [$className, $id]) { $object = $em->find($className, $id); $em->remove($object); } $em->flush(); + + self::$toDelete = []; } - public function generateDataMarkAsRead() + public static function generateDataMarkAsRead() { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); - $userRepository = self::$container->get(UserRepository::class); + $em = self::getContainer()->get(EntityManagerInterface::class); + $userRepository = self::getContainer()->get(UserRepository::class); $userA = $userRepository->findOneBy(['username' => 'center a_social']); $userB = $userRepository->findOneBy(['username' => 'center b_social']); @@ -62,7 +64,9 @@ final class NotificationApiControllerTest extends WebTestCase $em->refresh($notification); $em->flush(); - $this->toDelete[] = [Notification::class, $notification->getId()]; + self::$toDelete[] = [Notification::class, $notification->getId()]; + + self::ensureKernelShutdown(); yield [$notification->getId()]; } @@ -77,10 +81,10 @@ final class NotificationApiControllerTest extends WebTestCase $this->assertResponseIsSuccessful('test marking as read'); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); /** @var Notification $notification */ $notification = $em->find(Notification::class, $notificationId); - $user = self::$container->get(UserRepository::class)->findOneBy(['username' => 'center a_social']); + $user = self::getContainer()->get(UserRepository::class)->findOneBy(['username' => 'center a_social']); $this->assertTrue($notification->isReadBy($user)); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/ScopeControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/ScopeControllerTest.php index 4a055f679..b88b0a852 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/ScopeControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/ScopeControllerTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Tests\Controller; +use Chill\MainBundle\Test\PrepareClientTrait; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** @@ -20,14 +21,12 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; */ final class ScopeControllerTest extends WebTestCase { + use PrepareClientTrait; + public function testCompleteScenario() { // Create a new client to browse the application - $client = self::createClient([], [ - 'PHP_AUTH_USER' => 'admin', - 'PHP_AUTH_PW' => 'password', - 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR', - ]); + $client = $this->getClientAuthenticatedAsAdmin(); // Create a new entry in the database $crawler = $client->request('GET', '/fr/admin/scope/'); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/SearchApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/SearchApiControllerTest.php index 925fa1527..4f265658b 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/SearchApiControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/SearchApiControllerTest.php @@ -24,7 +24,7 @@ final class SearchApiControllerTest extends WebTestCase { use PrepareClientTrait; - public function generateSearchData() + public static function generateSearchData() { yield ['per', ['person', 'thirdparty']]; diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/SearchControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/SearchControllerTest.php index c1807904d..949bff407 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/SearchControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/SearchControllerTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Tests\Controller; +use Chill\MainBundle\Test\PrepareClientTrait; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** @@ -22,9 +23,11 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; */ final class SearchControllerTest extends WebTestCase { + use PrepareClientTrait; + public function testDomainUnknow() { - $client = $this->getAuthenticatedClient(); + $client = $this->getClientAuthenticated(); $crawler = $client->request('GET', '/fr/search', ['q' => '@unknow domain']); @@ -41,7 +44,7 @@ final class SearchControllerTest extends WebTestCase public function testParsingIncorrect() { - $client = $this->getAuthenticatedClient(); + $client = $this->getClientAuthenticated(); $crawler = $client->request( 'GET', @@ -59,7 +62,7 @@ final class SearchControllerTest extends WebTestCase */ public function testSearchPath() { - $client = $this->getAuthenticatedClient(); + $client = $this->getClientAuthenticated(); $crawler = $client->request('GET', '/fr/search', ['q' => 'default search']); @@ -71,7 +74,7 @@ final class SearchControllerTest extends WebTestCase public function testSearchPathEmpty() { - $client = $this->getAuthenticatedClient(); + $client = $this->getClientAuthenticated(); $crawler = $client->request('GET', '/fr/search?q='); @@ -80,7 +83,7 @@ final class SearchControllerTest extends WebTestCase public function testUnknowName() { - $client = $this->getAuthenticatedClient(); + $client = $this->getClientAuthenticated(); $client->request( 'GET', @@ -90,12 +93,4 @@ final class SearchControllerTest extends WebTestCase $this->assertTrue($client->getResponse()->isNotFound()); } - - private function getAuthenticatedClient() - { - return self::createClient([], [ - 'PHP_AUTH_USER' => 'center b_social', - 'PHP_AUTH_PW' => 'password', - ]); - } } diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php index b29f28478..483211020 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php @@ -13,9 +13,10 @@ namespace Chill\MainBundle\Tests\Controller; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Repository\UserRepositoryInterface; +use Chill\MainBundle\Test\PrepareClientTrait; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; +use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; /** * @internal @@ -24,74 +25,49 @@ use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; */ final class UserControllerTest extends WebTestCase { - private \Symfony\Bundle\FrameworkBundle\KernelBrowser $client; + use PrepareClientTrait; - private array $toDelete = []; - - protected function setUp(): void - { - $this->client = self::createClient([], [ - 'PHP_AUTH_USER' => 'admin', - 'PHP_AUTH_PW' => 'password', - 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR', - ]); - } - - protected function tearDown(): void + public static function dataGenerateUserId() { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); - - foreach ($this->toDelete as [$class, $id]) { - $obj = $em->getRepository($class)->find($id); - $em->remove($obj); - } - - $em->flush(); - self::ensureKernelShutdown(); - } - - public function dataGenerateUserId() - { - self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); + /** @var UserPasswordHasherInterface::class $passwordHasher */ + $passwordHasher = self::getContainer()->get(UserPasswordHasherInterface::class); $user = new User(); $user->setUsername('Test_user '.uniqid()); - $user->setPassword(self::$container->get(UserPasswordEncoderInterface::class)->encodePassword( - $user, - 'password' - )); + $user->setPassword($passwordHasher->hashPassword($user, 'password')); $em->persist($user); $em->flush(); - $this->toDelete[] = [User::class, $user->getId()]; + self::ensureKernelShutdown(); yield [$user->getId(), $user->getUsername()]; - - self::ensureKernelShutdown(); } public function testList() { + $client = $this->getClientAuthenticatedAsAdmin(); + // get the list - $crawler = $this->client->request('GET', '/fr/admin/main/user'); - $this->assertEquals( - 200, - $this->client->getResponse()->getStatusCode(), - 'Unexpected HTTP status code for GET /admin/main/user' - ); + $client->request('GET', '/fr/admin/main/user'); + self::assertResponseIsSuccessful(); } public function testNew() { - $crawler = $this->client->request('GET', '/fr/admin/main/user/new'); + $client = $this->getClientAuthenticated('admin'); + + $crawler = $client->request('GET', '/fr/admin/main/user/new'); + + self::assertResponseIsSuccessful(); $username = 'Test_user'.uniqid(); $password = 'Password1234!'; // Fill in the form and submit it + $form = $crawler->selectButton('Créer & fermer')->form([ 'chill_mainbundle_user[username]' => $username, 'chill_mainbundle_user[plainPassword][first]' => $password, @@ -100,12 +76,12 @@ final class UserControllerTest extends WebTestCase 'chill_mainbundle_user[label]' => $username, ]); - $this->client->submit($form); - $crawler = $this->client->followRedirect(); + $client->submit($form); + $crawler = $client->followRedirect(); // Check data in the show view $this->assertStringContainsString( - 'Test_user', + $username, $crawler->text(), 'page contains the name of the user' ); @@ -119,15 +95,18 @@ final class UserControllerTest extends WebTestCase */ public function testUpdate(int $userId, string $username) { - $crawler = $this->client->request('GET', "/fr/admin/main/user/{$userId}/edit"); + $client = $this->getClientAuthenticatedAsAdmin(); + $crawler = $client->request('GET', "/fr/admin/main/user/{$userId}/edit"); + + self::assertResponseIsSuccessful(); $username = 'Foo bar '.uniqid(); $form = $crawler->selectButton('Enregistrer & fermer')->form([ 'chill_mainbundle_user[username]' => $username, ]); - $this->client->submit($form); - $crawler = $this->client->followRedirect(); + $client->submit($form); + $client->followRedirect(); // Check the element contains an attribute with value equals "Foo" $this->assertResponseIsSuccessful(); } @@ -137,7 +116,8 @@ final class UserControllerTest extends WebTestCase */ public function testUpdatePassword(int $userId, mixed $username) { - $crawler = $this->client->request('GET', "/fr/admin/user/{$userId}/edit_password"); + $client = $this->getClientAuthenticatedAsAdmin(); + $crawler = $client->request('GET', "/fr/admin/user/{$userId}/edit_password"); $newPassword = '1234Password!'; $form = $crawler->selectButton('Changer le mot de passe')->form([ @@ -145,10 +125,10 @@ final class UserControllerTest extends WebTestCase 'chill_mainbundle_user_password[new_password][second]' => $newPassword, ]); - $this->client->submit($form); + $client->submit($form); $this->assertTrue( - $this->client->getResponse()->isRedirect(), + $client->getResponse()->isRedirect(), 'the response is a redirection' ); @@ -157,11 +137,11 @@ final class UserControllerTest extends WebTestCase protected function isPasswordValid($username, $password) { - /** @var \Symfony\Component\Security\Core\Encoder\UserPasswordEncoder $passwordEncoder */ - $passwordEncoder = self::$container - ->get(UserPasswordEncoderInterface::class); + /** @var \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher $passwordEncoder */ + $passwordEncoder = self::getContainer() + ->get(UserPasswordHasherInterface::class); - $user = self::$container->get(UserRepositoryInterface::class) + $user = self::getContainer()->get(UserRepositoryInterface::class) ->findOneBy(['username' => $username]); $this->assertTrue($passwordEncoder->isPasswordValid($user, $password)); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowAddSignatureControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowAddSignatureControllerTest.php new file mode 100644 index 000000000..9b4507936 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowAddSignatureControllerTest.php @@ -0,0 +1,81 @@ +futurePersonSignatures[] = new Person(); + $entityWorkflow->setStep('step_signature', $stepTransition, 'to_signature', new \DateTimeImmutable('now'), new User()); + + $signature = $entityWorkflow->getCurrentStep()->getSignatures()->first(); + + $entityWorkflowManager = $this->createMock(EntityWorkflowManager::class); + $entityWorkflowManager->method('getAssociatedStoredObject') + ->with($entityWorkflow) + ->willReturn($storedObject); + + $pdfSignatureZoneAvailable = $this->createMock(PDFSignatureZoneAvailable::class); + $pdfSignatureZoneAvailable->method('getAvailableSignatureZones')->withAnyParameters() + ->willReturn([ + new PDFSignatureZone(1, 0.0, 0.0, 100, 100, new PDFPage(1, 500.0, 500.0)), + ]); + + $normalizer = $this->createMock(NormalizerInterface::class); + $normalizer->method('normalize')->withAnyParameters() + ->willReturn([]); + + $twig = $this->createMock(Environment::class); + $twig->method('render')->with('@ChillMain/Workflow/_signature_sign.html.twig', $this->isType('array')) + ->willReturn('ok'); + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + + $security = $this->createMock(Security::class); + $security->expects($this->once())->method('isGranted')->with(EntityWorkflowStepSignatureVoter::SIGN, $signature) + ->willReturn(true); + + $controller = new WorkflowAddSignatureController($entityWorkflowManager, $pdfSignatureZoneAvailable, $normalizer, $twig, $urlGenerator, $security); + + $actual = $controller($signature, new Request()); + + self::assertEquals(200, $actual->getStatusCode()); + self::assertEquals('ok', $actual->getContent()); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowOnHoldControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowOnHoldControllerTest.php new file mode 100644 index 000000000..198adca5f --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowOnHoldControllerTest.php @@ -0,0 +1,116 @@ +addPlaces(['initial', 'layout', 'sign']) + ->addTransition(new Transition('to_layout', 'initial', 'layout')) + ->addTransition(new Transition('to_sign', 'initial', 'sign')) + ->build(); + + $workflow = new Workflow($definition, new EntityWorkflowMarkingStore(), name: 'dummy_workflow'); + $registry = new Registry(); + $registry->addWorkflow($workflow, new class () implements WorkflowSupportStrategyInterface { + public function supports(WorkflowInterface $workflow, object $subject): bool + { + return true; + } + }); + + return $registry; + } + + public function testPutOnHoldPersistence(): void + { + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setWorkflowName('dummy_workflow'); + $security = $this->createMock(Security::class); + $security->method('getUser')->willReturn($user = new User()); + + $entityManager = $this->createMock(EntityManagerInterface::class); + $entityManager->expects($this->once()) + ->method('persist') + ->with($this->isInstanceOf(EntityWorkflowStepHold::class)); + + $entityManager->expects($this->once()) + ->method('flush'); + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $urlGenerator->method('generate') + ->with('chill_main_workflow_show', ['id' => null]) + ->willReturn('/some/url'); + + $controller = new WorkflowOnHoldController($entityManager, $security, $this->buildRegistry(), $urlGenerator); + + $request = new Request(); + $response = $controller->putOnHold($entityWorkflow, $request); + + self::assertEquals(302, $response->getStatusCode()); + } + + public function testRemoveOnHold(): void + { + $user = new User(); + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setWorkflowName('dummy_workflow'); + $onHold = new EntityWorkflowStepHold($step = $entityWorkflow->getCurrentStep(), $user); + + $security = $this->createMock(Security::class); + $security->method('getUser')->willReturn($user); + + $entityManager = $this->createMock(EntityManagerInterface::class); + $entityManager->expects($this->once()) + ->method('remove') + ->with($onHold); + + $entityManager->expects($this->once()) + ->method('flush'); + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $urlGenerator->method('generate') + ->with('chill_main_workflow_show', ['id' => null]) + ->willReturn('/some/url'); + + $controller = new WorkflowOnHoldController($entityManager, $security, $this->buildRegistry(), $urlGenerator); + + $response = $controller->removeOnHold($step); + + self::assertEquals(302, $response->getStatusCode()); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php b/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php index 50b0f5584..278cecd1e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php @@ -37,15 +37,15 @@ class CronJobDatabaseInteractionTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); - $this->cronJobExecutionRepository = self::$container->get(CronJobExecutionRepository::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); + $this->cronJobExecutionRepository = self::getContainer()->get(CronJobExecutionRepository::class); } public static function tearDownAfterClass(): void { self::bootKernel(); - $entityManager = self::$container->get(EntityManagerInterface::class); + $entityManager = self::getContainer()->get(EntityManagerInterface::class); $entityManager->createQuery('DELETE '.CronJobExecution::class.' cje WHERE cje.key LIKE :key') ->setParameter('key', 'test-with-data') diff --git a/src/Bundle/ChillMainBundle/Tests/Cron/CronManagerTest.php b/src/Bundle/ChillMainBundle/Tests/Cron/CronManagerTest.php index 80131a8e8..548017c90 100644 --- a/src/Bundle/ChillMainBundle/Tests/Cron/CronManagerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Cron/CronManagerTest.php @@ -161,9 +161,7 @@ final class CronManagerTest extends TestCase class JobCanRun implements CronJobInterface { - public function __construct(private readonly string $key) - { - } + public function __construct(private readonly string $key) {} public function canRun(?CronJobExecution $cronJobExecution): bool { diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/AgeTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/AgeTest.php index 212303274..cdb24b4b7 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/AgeTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/AgeTest.php @@ -28,10 +28,10 @@ final class AgeTest extends KernelTestCase { self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } - public function generateQueries(): iterable + public static function generateQueries(): iterable { yield [ 'SELECT AGE(a.validFrom, a.validTo) FROM '.Address::class.' a', diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php index bba3dccc0..2cf679be7 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php @@ -29,7 +29,7 @@ final class GreatestTest extends KernelTestCase { self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } public function testGreatestInDQL() diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php index 8feb75617..a62b3a92e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php @@ -31,7 +31,7 @@ class JsonBuildObjectTest extends KernelTestCase parent::setUp(); self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } /** @@ -51,7 +51,7 @@ class JsonBuildObjectTest extends KernelTestCase self::assertIsArray($result); } - public function provideQueries(): iterable + public static function provideQueries(): iterable { yield ['SELECT JSON_BUILD_OBJECT(1, 2, 3, 4) FROM '.Address::class.' a', [], []]; yield ["SELECT JSON_BUILD_OBJECT('st', a.street, 'sn', a.streetNumber) FROM ".Address::class.' a', [], []]; diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonExtractTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonExtractTest.php index 286aa71c9..dec63a64c 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonExtractTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonExtractTest.php @@ -28,10 +28,10 @@ final class JsonExtractTest extends KernelTestCase { self::bootKernel(); - $this->em = self::$container->get(EntityManagerInterface::class); + $this->em = self::getContainer()->get(EntityManagerInterface::class); } - public function dataGenerateDql(): iterable + public static function dataGenerateDql(): iterable { yield ['SELECT JSON_EXTRACT(c.name, \'fr\') FROM '.Country::class.' c', []]; diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php index 31f1714d1..d61f1af0e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php @@ -27,7 +27,7 @@ final class JsonbExistsInArrayTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->em = self::$container->get(EntityManagerInterface::class); + $this->em = self::getContainer()->get(EntityManagerInterface::class); } public function testDQLFunctionWorks() diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php index e8bb0f5b1..d7a3dffba 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php @@ -29,7 +29,7 @@ final class LeastTest extends KernelTestCase { self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } public function testGreatestInDQL() diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/NotificationTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/NotificationTest.php index c5118479a..26a9b5980 100644 --- a/src/Bundle/ChillMainBundle/Tests/Entity/NotificationTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Entity/NotificationTest.php @@ -34,7 +34,7 @@ final class NotificationTest extends KernelTestCase protected function tearDown(): void { - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); foreach ($this->toDelete as [$className, $id]) { $object = $em->find($className, $id); @@ -44,10 +44,10 @@ final class NotificationTest extends KernelTestCase $em->flush(); } - public function generateNotificationData() + public static function generateNotificationData() { self::bootKernel(); - $userRepository = self::$container->get(UserRepository::class); + $userRepository = self::getContainer()->get(UserRepository::class); $senderId = $userRepository ->findOneBy(['username' => 'center b_social']) @@ -110,7 +110,7 @@ final class NotificationTest extends KernelTestCase */ public function testPrePersistComputeUnread(int $senderId, array $addressesIds) { - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $notification = new Notification(); $notification ->setSender($em->find(User::class, $senderId)) diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowStepSignatureTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowStepSignatureTest.php new file mode 100644 index 000000000..62b6a7d6a --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowStepSignatureTest.php @@ -0,0 +1,69 @@ +entityManager = self::getContainer()->get(EntityManagerInterface::class); + } + + public function testConstruct() + { + $workflow = new EntityWorkflow(); + $workflow->setWorkflowName('vendee_internal') + ->setRelatedEntityId(0) + ->setRelatedEntityClass(AccompanyingPeriodWorkEvaluationDocument::class); + + $step = $workflow->getCurrentStep(); + + $person = $this->entityManager->createQuery('SELECT p FROM '.Person::class.' p') + ->setMaxResults(1) + ->getSingleResult(); + + $signature = new EntityWorkflowStepSignature($step, $person); + + self::assertCount(1, $step->getSignatures()); + self::assertSame($signature, $step->getSignatures()->first()); + + $this->entityManager->getConnection()->beginTransaction(); + $this->entityManager->persist($workflow); + $this->entityManager->persist($step); + $this->entityManager->persist($signature); + + $this->entityManager->flush(); + $this->entityManager->getConnection()->commit(); + + $this->entityManager->clear(); + + $signatureBis = $this->entityManager->find(EntityWorkflowStepSignature::class, $signature->getId()); + + self::assertEquals($signature->getId(), $signatureBis->getId()); + self::assertEquals($step->getId(), $signatureBis->getStep()->getId()); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowTest.php index f515490b8..3241a41fc 100644 --- a/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Entity/Workflow/EntityWorkflowTest.php @@ -11,7 +11,11 @@ declare(strict_types=1); namespace Chill\MainBundle\Tests\Entity\Workflow; +use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; +use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature; +use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO; +use Chill\PersonBundle\Entity\Person; use PHPUnit\Framework\TestCase; /** @@ -25,7 +29,7 @@ final class EntityWorkflowTest extends TestCase { $entityWorkflow = new EntityWorkflow(); - $entityWorkflow->setStep('final'); + $entityWorkflow->setStep('final', new WorkflowTransitionContextDTO($entityWorkflow), 'finalize', new \DateTimeImmutable()); $entityWorkflow->getCurrentStep()->setIsFinal(true); $this->assertTrue($entityWorkflow->isFinal()); @@ -37,16 +41,16 @@ final class EntityWorkflowTest extends TestCase $this->assertFalse($entityWorkflow->isFinal()); - $entityWorkflow->setStep('two'); + $entityWorkflow->setStep('two', new WorkflowTransitionContextDTO($entityWorkflow), 'two', new \DateTimeImmutable()); $this->assertFalse($entityWorkflow->isFinal()); - $entityWorkflow->setStep('previous_final'); + $entityWorkflow->setStep('previous_final', new WorkflowTransitionContextDTO($entityWorkflow), 'three', new \DateTimeImmutable()); $this->assertFalse($entityWorkflow->isFinal()); $entityWorkflow->getCurrentStep()->setIsFinal(true); - $entityWorkflow->setStep('final'); + $entityWorkflow->setStep('final', new WorkflowTransitionContextDTO($entityWorkflow), 'four', new \DateTimeImmutable()); $this->assertTrue($entityWorkflow->isFinal()); } @@ -57,23 +61,108 @@ final class EntityWorkflowTest extends TestCase $this->assertFalse($entityWorkflow->isFreeze()); - $entityWorkflow->setStep('step_one'); + $entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_one', new \DateTimeImmutable()); $this->assertFalse($entityWorkflow->isFreeze()); - $entityWorkflow->setStep('step_three'); + $entityWorkflow->setStep('step_three', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_three', new \DateTimeImmutable()); $this->assertFalse($entityWorkflow->isFreeze()); - $entityWorkflow->setStep('freezed'); + $entityWorkflow->setStep('freezed', new WorkflowTransitionContextDTO($entityWorkflow), 'to_freezed', new \DateTimeImmutable()); $entityWorkflow->getCurrentStep()->setFreezeAfter(true); $this->assertTrue($entityWorkflow->isFreeze()); - $entityWorkflow->setStep('after_freeze'); + $entityWorkflow->setStep('after_freeze', new WorkflowTransitionContextDTO($entityWorkflow), 'to_after_freeze', new \DateTimeImmutable()); $this->assertTrue($entityWorkflow->isFreeze()); $this->assertTrue($entityWorkflow->getCurrentStep()->isFreezeAfter()); } + + public function testPreviousStepMetadataAreFilled() + { + $entityWorkflow = new EntityWorkflow(); + $initialStep = $entityWorkflow->getCurrentStep(); + + $entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_one', new \DateTimeImmutable('2024-01-01'), $user1 = new User()); + + $previous = $entityWorkflow->getCurrentStep(); + + $entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_two', new \DateTimeImmutable('2024-01-02'), $user2 = new User()); + + $final = $entityWorkflow->getCurrentStep(); + + $stepsChained = $entityWorkflow->getStepsChained(); + + self::assertCount(3, $stepsChained); + self::assertSame($initialStep, $stepsChained[0]); + self::assertSame($previous, $stepsChained[1]); + self::assertSame($final, $stepsChained[2]); + self::assertEquals($user1, $initialStep->getTransitionBy()); + self::assertEquals('2024-01-01', $initialStep->getTransitionAt()?->format('Y-m-d')); + self::assertEquals('to_step_one', $initialStep->getTransitionAfter()); + self::assertEquals($user2, $previous->getTransitionBy()); + self::assertEquals('2024-01-02', $previous->getTransitionAt()?->format('Y-m-d')); + self::assertEquals('to_step_two', $previous->getTransitionAfter()); + } + + public function testSetStepSignatureForUserIsCreated() + { + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureUserSignature = $user = new User(); + + $entityWorkflow->setStep('new', $dto, 'to_new', new \DateTimeImmutable()); + + $actual = $entityWorkflow->getCurrentStep(); + + self::assertCount(1, $actual->getSignatures()); + self::assertSame($user, $actual->getSignatures()->first()->getSigner()); + } + + public function testSetStepSignatureForPersonIsCreated() + { + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futurePersonSignatures[] = $person1 = new Person(); + $dto->futurePersonSignatures[] = $person2 = new Person(); + + $entityWorkflow->setStep('new', $dto, 'to_new', new \DateTimeImmutable()); + + $actual = $entityWorkflow->getCurrentStep(); + $persons = $actual->getSignatures()->map(fn (EntityWorkflowStepSignature $signature) => $signature->getSigner()); + + self::assertCount(2, $actual->getSignatures()); + self::assertContains($person1, $persons); + self::assertContains($person2, $persons); + } + + public function testIsStaledAt(): void + { + $creationDate = new \DateTimeImmutable('2024-01-01'); + $firstStepDate = new \DateTimeImmutable('2024-01-02'); + $afterFistStep = new \DateTimeImmutable('2024-01-03'); + + $entityWorkflow = new EntityWorkflow(); + + self::assertFalse($entityWorkflow->isStaledAt($creationDate), 'an entityWorkflow with null createdAt date should never be staled at initial step'); + self::assertFalse($entityWorkflow->isStaledAt($firstStepDate), 'an entityWorkflow with null createdAt date should never be staled at initial step'); + self::assertFalse($entityWorkflow->isStaledAt($afterFistStep), 'an entityWorkflow with null createdAt date should never be staled at initial step'); + + $entityWorkflow->setCreatedAt($creationDate); + + self::assertFalse($entityWorkflow->isStaledAt($creationDate), 'an entityWorkflow with no step after initial should be staled'); + self::assertTrue($entityWorkflow->isStaledAt($firstStepDate), 'an entityWorkflow with no step after initial should be staled'); + self::assertTrue($entityWorkflow->isStaledAt($afterFistStep), 'an entityWorkflow with no step after initial should be staled'); + + // apply a first step + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $entityWorkflow->setStep('new_step', $dto, 'to_new_step', $firstStepDate); + + self::assertFalse($entityWorkflow->isStaledAt($creationDate)); + self::assertFalse($entityWorkflow->isStaledAt($firstStepDate)); + self::assertTrue($entityWorkflow->isStaledAt($afterFistStep)); + } } diff --git a/src/Bundle/ChillMainBundle/Tests/Export/AccompanyingCourseExportHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Export/AccompanyingCourseExportHelperTest.php index f726553e9..fc12c3c86 100644 --- a/src/Bundle/ChillMainBundle/Tests/Export/AccompanyingCourseExportHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Export/AccompanyingCourseExportHelperTest.php @@ -34,13 +34,13 @@ class AccompanyingCourseExportHelperTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->em = self::$container->get(EntityManagerInterface::class); + $this->em = self::getContainer()->get(EntityManagerInterface::class); } public static function tearDownAfterClass(): void { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); foreach (self::$entitiesToDelete as [$class, $id]) { $entity = $em->find($class, $id); diff --git a/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php b/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php index 30f0098dd..e2d0e1393 100644 --- a/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php @@ -210,7 +210,7 @@ final class ExportManagerTest extends KernelTestCase $filters = []; $aggregators = []; - $em = self::$container->get(EntityManagerInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); @@ -313,7 +313,7 @@ final class ExportManagerTest extends KernelTestCase // add formatter interface $formatter = new \Chill\MainBundle\Export\Formatter\SpreadSheetFormatter( - self::$container->get(TranslatorInterface::class), + self::getContainer()->get(TranslatorInterface::class), $exportManager ); @@ -507,7 +507,7 @@ final class ExportManagerTest extends KernelTestCase array $aggregators = [], array $filters = [], ): ExportManager { - $localUser = $user ?? self::$container->get( + $localUser = $user ?? self::getContainer()->get( UserRepositoryInterface::class ) ->findOneBy(['username' => 'center a_social']); @@ -516,9 +516,9 @@ final class ExportManagerTest extends KernelTestCase $tokenStorage->setToken($token); return new ExportManager( - $logger ?? self::$container->get('logger'), - $authorizationChecker ?? self::$container->get('security.authorization_checker'), - $authorizationHelper ?? self::$container->get('chill.main.security.authorization.helper'), + $logger ?? self::getContainer()->get('logger'), + $authorizationChecker ?? self::getContainer()->get('security.authorization_checker'), + $authorizationHelper ?? self::getContainer()->get('chill.main.security.authorization.helper'), $tokenStorage, $exports, $aggregators, @@ -532,17 +532,14 @@ class DummyFilterWithApplying implements FilterInterface public function __construct( private readonly ?string $role, private readonly string $applyOn, - ) { - } + ) {} public function getTitle() { return 'dummy'; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { @@ -559,9 +556,7 @@ class DummyFilterWithApplying implements FilterInterface return $this->role; } - public function alterQuery(QueryBuilder $qb, $data) - { - } + public function alterQuery(QueryBuilder $qb, $data) {} public function applyOn() { @@ -577,17 +572,14 @@ class DummyExport implements ExportInterface * @var array */ private readonly array $supportedModifiers, - ) { - } + ) {} public function getTitle() { return 'dummy'; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillMainBundle/Tests/Export/SortExportElementTest.php b/src/Bundle/ChillMainBundle/Tests/Export/SortExportElementTest.php index a14747c68..cd820bb1c 100644 --- a/src/Bundle/ChillMainBundle/Tests/Export/SortExportElementTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Export/SortExportElementTest.php @@ -39,9 +39,9 @@ class SortExportElementTest extends KernelTestCase { self::bootKernel(); - $sorter = self::$container->get(SortExportElement::class); - $translator = self::$container->get(TranslatorInterface::class); - $exportManager = self::$container->get(ExportManager::class); + $sorter = self::getContainer()->get(SortExportElement::class); + $translator = self::getContainer()->get(TranslatorInterface::class); + $exportManager = self::getContainer()->get(ExportManager::class); $filters = $exportManager->getAllFilters(); $sorter->sortFilters($filters); @@ -117,13 +117,9 @@ class SortExportElementTest extends KernelTestCase private function makeAggregator(string $title): AggregatorInterface { return new class ($title) implements AggregatorInterface { - public function __construct(private readonly string $title) - { - } + public function __construct(private readonly string $title) {} - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { @@ -150,9 +146,7 @@ class SortExportElementTest extends KernelTestCase return null; } - public function alterQuery(QueryBuilder $qb, $data) - { - } + public function alterQuery(QueryBuilder $qb, $data) {} public function applyOn() { @@ -164,18 +158,14 @@ class SortExportElementTest extends KernelTestCase private function makeFilter(string $title): FilterInterface { return new class ($title) implements FilterInterface { - public function __construct(private readonly string $title) - { - } + public function __construct(private readonly string $title) {} public function getTitle() { return $this->title; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { @@ -192,9 +182,7 @@ class SortExportElementTest extends KernelTestCase return null; } - public function alterQuery(QueryBuilder $qb, $data) - { - } + public function alterQuery(QueryBuilder $qb, $data) {} public function applyOn() { diff --git a/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php b/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php index c42595049..3d3813748 100644 --- a/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php @@ -18,12 +18,13 @@ use Chill\MainBundle\Form\Type\ScopePickerType; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder; +use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Persistence\ManagerRegistry; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension; use Symfony\Bridge\Doctrine\Form\Type\EntityType; -use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; @@ -38,7 +39,7 @@ final class ScopePickerTypeTest extends TypeTestCase { use ProphecyTrait; - public function testBuildOneScopeIsSuccessful() + public function estBuildOneScopeIsSuccessful() { $form = $this->factory->create(ScopePickerType::class, null, [ 'center' => new Center(), @@ -107,9 +108,14 @@ final class ScopePickerTypeTest extends TypeTestCase ); // add the mocks for creating EntityType - $entityManager = DoctrineTestHelper::createTestEntityManager(); $em = $this->prophesize(EntityManagerInterface::class); - $em->getClassMetadata(Scope::class)->willReturn($entityManager->getClassMetadata(Scope::class)); + $em->getClassMetadata(Scope::class)->will(function (array $args) { + $classMetadata = new ClassMetadataBuilder( + new ClassMetadataInfo(Scope::class) + ); + + return $classMetadata->getClassMetadata(); + }); $em->contains(Argument::type(Scope::class))->willReturn(true); $em->initializeObject(Argument::type(Scope::class))->will(static fn ($o) => $o); $emRevealed = $em->reveal(); diff --git a/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php b/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php index 4fd07643c..fb217eea6 100644 --- a/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php @@ -18,7 +18,10 @@ use Doctrine\ORM\EntityManagerInterface; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\TerminateEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** * @internal @@ -35,14 +38,17 @@ final class PersistNotificationOnTerminateEventSubscriberTest extends TestCase $em = $this->prophesize(EntityManagerInterface::class); $em->persist(Argument::type(Notification::class))->shouldBeCalledTimes(1); $em->flush()->shouldBeCalledTimes(1); - $event = $this->prophesize(TerminateEvent::class); - $event->isMasterRequest()->willReturn(true); + $event = new TerminateEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request(), + new Response() + ); $eventSubscriber = new PersistNotificationOnTerminateEventSubscriber($em->reveal(), $persister); $notification = new Notification(); $persister->persist($notification); - $eventSubscriber->onKernelTerminate($event->reveal()); + $eventSubscriber->onKernelTerminate($event); } } diff --git a/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php b/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php index 6ccd91ea8..787a5833a 100644 --- a/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php @@ -43,7 +43,7 @@ final class PageTest extends KernelTestCase * * @return array */ - public function generateGetFirstItemNumber() + public static function generateGetFirstItemNumber() { return [ [1, 10, 0], @@ -61,7 +61,7 @@ final class PageTest extends KernelTestCase * * @return array */ - public function generateGetLastItemNumber() + public static function generateGetLastItemNumber() { return [ [1, 10, 9], diff --git a/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php b/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php index 6d05dbe9e..f32a772eb 100644 --- a/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php @@ -43,7 +43,7 @@ final class PaginatorTest extends KernelTestCase * * @return array */ - public function generateHasNextPage() + public static function generateHasNextPage() { return [ [10, 10, 1, false], @@ -53,7 +53,7 @@ final class PaginatorTest extends KernelTestCase ]; } - public function generateHasPage() + public static function generateHasPage() { return [ [10, 10, -1, false], @@ -72,7 +72,7 @@ final class PaginatorTest extends KernelTestCase * * @return array */ - public function generateHasPreviousPage() + public static function generateHasPreviousPage() { return [ [10, 10, 1, false], @@ -88,7 +88,7 @@ final class PaginatorTest extends KernelTestCase * * @return array */ - public function generatePageNumber() + public static function generatePageNumber() { return [ [12, 10, 2], diff --git a/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php index 184c994e4..6f65c612f 100644 --- a/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php @@ -25,7 +25,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; */ final class PhonenumberHelperTest extends KernelTestCase { - public function formatPhonenumbers() + public static function formatPhonenumbers() { yield [ 'BE', diff --git a/src/Bundle/ChillMainBundle/Tests/Repository/NewsItemRepositoryTest.php b/src/Bundle/ChillMainBundle/Tests/Repository/NewsItemRepositoryTest.php index f91ed2068..d5e44d17e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Repository/NewsItemRepositoryTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Repository/NewsItemRepositoryTest.php @@ -35,7 +35,7 @@ class NewsItemRepositoryTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } protected function tearDown(): void diff --git a/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php b/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php index d783cc22c..07254594a 100644 --- a/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php @@ -11,14 +11,14 @@ declare(strict_types=1); namespace Chill\MainBundle\Tests\Search; +use PHPUnit\Framework\TestCase; + /** - * Description of AbstractSearch. - * * @internal * * @coversNothing */ -final class AbstractSearchTest extends \PHPUnit\Framework\TestCase +final class AbstractSearchTest extends TestCase { /** * @var \Chill\MainBundle\Search\AbstractSearch diff --git a/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractDateFromPatternTest.php b/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractDateFromPatternTest.php index f592b0e1a..00339b100 100644 --- a/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractDateFromPatternTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractDateFromPatternTest.php @@ -21,7 +21,7 @@ use PHPUnit\Framework\TestCase; */ final class ExtractDateFromPatternTest extends TestCase { - public function provideSubjects() + public static function provideSubjects() { yield ['15/06/1981', '', 1, '1981-06-15']; diff --git a/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php b/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php index 68b1ba9a8..96d7d4622 100644 --- a/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php @@ -22,7 +22,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; */ final class ExtractPhonenumberFromPatternTest extends KernelTestCase { - public function provideData() + public static function provideData() { yield ['BE', 'Diallo', 0, [], 'Diallo', 'no phonenumber']; diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php index cbdf83025..4ce7034ce 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php @@ -45,17 +45,17 @@ final class AuthorizationHelperTest extends KernelTestCase self::bootKernel(); } - public function dataProvider_getReachableCenters() + public static function dataProvider_getReachableCenters() { self::bootKernel(); - $centerA = $this->prepareCenter(1, 'center A'); - $centerB = $this->prepareCenter(2, 'center B'); - $scopeA = $this->prepareScope(1, 'scope default'); - $scopeB = $this->prepareScope(2, 'scope B'); - $scopeC = $this->prepareScope(3, 'scope C'); + $centerA = self::prepareCenter(1, 'center A'); + $centerB = self::prepareCenter(2, 'center B'); + $scopeA = self::prepareScope(1, 'scope default'); + $scopeB = self::prepareScope(2, 'scope B'); + $scopeC = self::prepareScope(3, 'scope C'); - $userA = $this->prepareUser([ + $userA = self::prepareUser([ [ 'center' => $centerA, 'permissionsGroup' => [ @@ -72,7 +72,7 @@ final class AuthorizationHelperTest extends KernelTestCase ], ]); - $ah = $this->getAuthorizationHelper(); + $ah = self::getAuthorizationHelper(); return [ // without scopes @@ -143,15 +143,15 @@ final class AuthorizationHelperTest extends KernelTestCase ]; } - public function dataProvider_getReachableScopes() + public static function dataProvider_getReachableScopes() { - $centerA = $this->prepareCenter(1, 'center A'); - $centerB = $this->prepareCenter(2, 'center B'); - $scopeA = $this->prepareScope(1, 'scope default'); - $scopeB = $this->prepareScope(2, 'scope B'); - $scopeC = $this->prepareScope(3, 'scope C'); + $centerA = self::prepareCenter(1, 'center A'); + $centerB = self::prepareCenter(2, 'center B'); + $scopeA = self::prepareScope(1, 'scope default'); + $scopeB = self::prepareScope(2, 'scope B'); + $scopeC = self::prepareScope(3, 'scope C'); - $userA = $this->prepareUser([ + $userA = self::prepareUser([ [ 'center' => $centerA, 'permissionsGroup' => [ @@ -579,9 +579,9 @@ final class AuthorizationHelperTest extends KernelTestCase /** * @return AuthorizationHelper */ - private function getAuthorizationHelper() + private static function getAuthorizationHelper() { - return self::$container + return self::getContainer() ->get(AuthorizationHelper::class); } } diff --git a/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php b/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php index b2481917e..052e61f64 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php @@ -28,15 +28,13 @@ final class TokenManagerTest extends KernelTestCase { self::bootKernel(); - $logger = self::$container + $logger = self::getContainer() ->get('logger'); $this->tokenManager = new TokenManager('secret', $logger); } - public static function setUpBefore() - { - } + public static function setUpBefore() {} public function testGenerate() { diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php index ff4af29d4..b7a38247f 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php @@ -28,7 +28,7 @@ final class CenterResolverDispatcherTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->dispatcher = self::$container->get(CenterResolverDispatcher::class); + $this->dispatcher = self::getContainer()->get(CenterResolverDispatcher::class); } /** diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php index 1ec23fdb3..733e17fec 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php @@ -35,9 +35,7 @@ final class DefaultScopeResolverTest extends TestCase { $scope = new Scope(); $entity = new class ($scope) implements HasScopeInterface { - public function __construct(private readonly Scope $scope) - { - } + public function __construct(private readonly Scope $scope) {} public function getScope() { @@ -53,9 +51,7 @@ final class DefaultScopeResolverTest extends TestCase public function testHasScopesInterface() { $entity = new class ($scopeA = new Scope(), $scopeB = new Scope()) implements HasScopesInterface { - public function __construct(private readonly Scope $scopeA, private readonly Scope $scopeB) - { - } + public function __construct(private readonly Scope $scopeA, private readonly Scope $scopeB) {} public function getScopes(): iterable { diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php index dd4b7f121..35245174c 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php @@ -36,9 +36,7 @@ final class ScopeResolverDispatcherTest extends TestCase { $scope = new Scope(); $entity = new class ($scope) implements HasScopeInterface { - public function __construct(private readonly Scope $scope) - { - } + public function __construct(private readonly Scope $scope) {} public function getScope() { diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php index 8d80490c1..74f44d05e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php @@ -32,7 +32,7 @@ final class DateNormalizerTest extends KernelTestCase $this->prophet = new Prophet(); } - public function generateDataNormalize() + public static function generateDataNormalize() { $datetime = \DateTime::createFromFormat('Y-m-d H:i:sO', '2021-06-05 15:05:01+02:00'); $date = \DateTime::createFromFormat('Y-m-d H:i:sO', '2021-06-05 00:00:00+02:00'); diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php index 225f67b3b..da1adbf89 100644 --- a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php @@ -29,17 +29,17 @@ final class DoctrineExistingEntityNormalizerTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $em = self::$container->get(EntityManagerInterface::class); - $serializerFactory = self::$container->get(ClassMetadataFactoryInterface::class); + $em = self::getContainer()->get(EntityManagerInterface::class); + $serializerFactory = self::getContainer()->get(ClassMetadataFactoryInterface::class); $this->normalizer = new DoctrineExistingEntityNormalizer($em, $serializerFactory); } - public function dataProviderUserId() + public static function dataProviderUserId() { self::bootKernel(); - $userIds = self::$container->get(EntityManagerInterface::class) + $userIds = self::getContainer()->get(EntityManagerInterface::class) ->getRepository(User::class) ->createQueryBuilder('u') ->select('u.id') diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/PhonenumberNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/PhonenumberNormalizerTest.php index 583dfc4cc..b36abdd3f 100644 --- a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/PhonenumberNormalizerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/PhonenumberNormalizerTest.php @@ -28,7 +28,7 @@ final class PhonenumberNormalizerTest extends TestCase { use ProphecyTrait; - public function dataProviderNormalizePhonenumber() + public static function dataProviderNormalizePhonenumber() { $phonenumberUtil = PhoneNumberUtil::getInstance(); diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/UserNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/UserNormalizerTest.php index 4a6fc032f..488495027 100644 --- a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/UserNormalizerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/UserNormalizerTest.php @@ -41,7 +41,7 @@ final class UserNormalizerTest extends TestCase /** * @throws NumberParseException */ - public function dataProviderUserNormalizer() + public static function dataProviderUserNormalizer() { $user = new User(); $userNoPhone = new User(); diff --git a/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeTest.php b/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeTest.php index 9d6af705a..6e1e9428e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeTest.php @@ -28,7 +28,7 @@ class CollateAddressWithReferenceOrPostalCodeTest extends KernelTestCase protected function setUp(): void { self::bootKernel(); - $this->connection = self::$container->get(Connection::class); + $this->connection = self::getContainer()->get(Connection::class); } public function testRun(): void diff --git a/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJobTest.php b/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJobTest.php index 827dc7e47..9987efabe 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJobTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/RefreshAddressToGeographicalUnitMaterializedViewCronJobTest.php @@ -66,7 +66,7 @@ final class RefreshAddressToGeographicalUnitMaterializedViewCronJobTest extends self::bootKernel(); $job = new \Chill\MainBundle\Service\AddressGeographicalUnit\RefreshAddressToGeographicalUnitMaterializedViewCronJob( - self::$container->get(Connection::class), + self::getContainer()->get(Connection::class), new MockClock() ); diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressReferenceBaseImporterTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressReferenceBaseImporterTest.php index 84f0c9fc0..076b65f7e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressReferenceBaseImporterTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressReferenceBaseImporterTest.php @@ -38,10 +38,10 @@ final class AddressReferenceBaseImporterTest extends KernelTestCase parent::setUp(); self::bootKernel(); - $this->importer = self::$container->get(AddressReferenceBaseImporter::class); - $this->addressReferenceRepository = self::$container->get(AddressReferenceRepository::class); - $this->entityManager = self::$container->get(EntityManagerInterface::class); - $this->postalCodeRepository = self::$container->get(PostalCodeRepository::class); + $this->importer = self::getContainer()->get(AddressReferenceBaseImporter::class); + $this->addressReferenceRepository = self::getContainer()->get(AddressReferenceRepository::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); + $this->postalCodeRepository = self::getContainer()->get(PostalCodeRepository::class); } public function testImportAddress(): void diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressToReferenceMatcherTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressToReferenceMatcherTest.php index 1bc888d59..0e2699fc3 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressToReferenceMatcherTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/Import/AddressToReferenceMatcherTest.php @@ -42,11 +42,11 @@ class AddressToReferenceMatcherTest extends KernelTestCase parent::setUp(); self::bootKernel(); - $this->addressToReferenceMatcher = self::$container->get(AddressToReferenceMatcher::class); - $this->addressReferenceRepository = self::$container->get(AddressReferenceRepository::class); - $this->countryRepository = self::$container->get(CountryRepository::class); - $this->addressReferenceBaseImporter = self::$container->get(AddressReferenceBaseImporter::class); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->addressToReferenceMatcher = self::getContainer()->get(AddressToReferenceMatcher::class); + $this->addressReferenceRepository = self::getContainer()->get(AddressReferenceRepository::class); + $this->countryRepository = self::getContainer()->get(CountryRepository::class); + $this->addressReferenceBaseImporter = self::getContainer()->get(AddressReferenceBaseImporter::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } public function testCheckAddressesMatchingReferences(): void diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Import/GeographicalUnitBaseImporterTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Import/GeographicalUnitBaseImporterTest.php index de72492a9..9154f2056 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/Import/GeographicalUnitBaseImporterTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/Import/GeographicalUnitBaseImporterTest.php @@ -34,8 +34,8 @@ final class GeographicalUnitBaseImporterTest extends KernelTestCase self::bootKernel(); - $this->connection = self::$container->get(Connection::class); - $this->entityManager = self::$container->get(EntityManagerInterface::class); + $this->connection = self::getContainer()->get(Connection::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); } public function testImportUnit(): void diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Import/PostalCodeBaseImporterTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Import/PostalCodeBaseImporterTest.php index 19c824eff..d7447e7a0 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/Import/PostalCodeBaseImporterTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/Import/PostalCodeBaseImporterTest.php @@ -38,10 +38,10 @@ final class PostalCodeBaseImporterTest extends KernelTestCase self::bootKernel(); - $this->entityManager = self::$container->get(EntityManagerInterface::class); - $this->importer = self::$container->get(PostalCodeBaseImporter::class); - $this->postalCodeRepository = self::$container->get(PostalCodeRepository::class); - $this->countryRepository = self::$container->get(CountryRepository::class); + $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); + $this->importer = self::getContainer()->get(PostalCodeBaseImporter::class); + $this->postalCodeRepository = self::getContainer()->get(PostalCodeRepository::class); + $this->countryRepository = self::getContainer()->get(CountryRepository::class); } public function testImportPostalCode(): void diff --git a/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php b/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php index d365d3567..ae63557eb 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php @@ -36,7 +36,7 @@ final class MenuComposerTest extends KernelTestCase protected function setUp(): void { self::bootKernel(['environment' => 'test']); - $this->menuComposer = self::$container + $this->menuComposer = self::getContainer() ->get('chill.main.menu_composer'); } diff --git a/src/Bundle/ChillMainBundle/Tests/Services/RollingDate/RollingDateConverterTest.php b/src/Bundle/ChillMainBundle/Tests/Services/RollingDate/RollingDateConverterTest.php index 25f3d03e6..5b2dfb954 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/RollingDate/RollingDateConverterTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/RollingDate/RollingDateConverterTest.php @@ -29,7 +29,7 @@ final class RollingDateConverterTest extends TestCase $this->converter = new RollingDateConverter(); } - public function generateDataConversionDate(): iterable + public static function generateDataConversionDate(): iterable { $format = 'Y-m-d His'; diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowCronJobTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowCronJobTest.php new file mode 100644 index 000000000..200b92099 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowCronJobTest.php @@ -0,0 +1,104 @@ +createMock(LoggerInterface::class); + + $cronJob = new CancelStaleWorkflowCronJob($this->createMock(EntityWorkflowRepository::class), $clock, $this->buildMessageBus(), $logger); + + self::assertEquals($expected, $cronJob->canRun($cronJobExecution)); + } + + /** + * @throws \DateMalformedStringException + * @throws \DateInvalidTimeZoneException + * @throws \Exception|Exception + */ + public function testRun(): void + { + $clock = new MockClock((new \DateTimeImmutable('now', new \DateTimeZone('+00:00')))->add(new \DateInterval('P120D'))); + $workflowRepository = $this->createMock(EntityWorkflowRepository::class); + + $workflowRepository->method('findWorkflowsWithoutFinalStepAndOlderThan')->willReturn([1, 3, 2]); + $messageBus = $this->buildMessageBus(true); + + $cronJob = new CancelStaleWorkflowCronJob($workflowRepository, $clock, $messageBus, new NullLogger()); + + $results = $cronJob->run([]); + + // Assert the result has the last canceled workflow ID + self::assertArrayHasKey('last-canceled-workflow-id', $results); + self::assertEquals(3, $results['last-canceled-workflow-id']); + } + + /** + * @throws \Exception + */ + public static function buildTestCanRunData(): iterable + { + yield [ + (new CronJobExecution('last-canceled-workflow-id'))->setLastEnd(new \DateTimeImmutable('2023-12-31 00:00:00', new \DateTimeZone('+00:00'))), + true, + ]; + + yield [ + (new CronJobExecution('last-canceled-workflow-id'))->setLastEnd(new \DateTimeImmutable('2023-12-30 23:59:59', new \DateTimeZone('+00:00'))), + true, + ]; + + yield [ + (new CronJobExecution('last-canceled-workflow-id'))->setLastEnd(new \DateTimeImmutable('2023-12-31 00:00:01', new \DateTimeZone('+00:00'))), + false, + ]; + } + + private function buildMessageBus(bool $expectDispatchAtLeastOnce = false): MessageBusInterface + { + $messageBus = $this->createMock(MessageBusInterface::class); + + $methodDispatch = match ($expectDispatchAtLeastOnce) { + true => $messageBus->expects($this->atLeastOnce())->method('dispatch')->with($this->isInstanceOf(CancelStaleWorkflowMessage::class)), + false => $messageBus->method('dispatch'), + }; + + $methodDispatch->willReturnCallback(fn (CancelStaleWorkflowMessage $message) => new Envelope($message)); + + return $messageBus; + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowHandlerTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowHandlerTest.php new file mode 100644 index 000000000..b6cac68de --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Services/Workflow/CancelStaleWorkflowHandlerTest.php @@ -0,0 +1,161 @@ +setWorkflowName('dummy_workflow'); + $workflow->setCreatedAt(new \DateTimeImmutable('2023-09-01')); + $workflow->setStep('step1', new WorkflowTransitionContextDTO($workflow), 'to_step1', $daysAgos, new User()); + + $em = $this->prophesize(EntityManagerInterface::class); + $em->flush()->shouldBeCalled(); + $em->remove($workflow)->shouldNotBeCalled(); + + $handler = $this->buildHandler($workflow, $em->reveal(), $clock); + + $handler(new CancelStaleWorkflowMessage(1)); + + self::assertEquals('canceled', $workflow->getStep()); + self::assertCount(3, $workflow->getSteps()); + } + + public function testWorkflowNotInStaledHandlerIsUnrecoverable(): void + { + $this->expectException(UnrecoverableMessageHandlingException::class); + + $clock = new MockClock('2024-01-01'); + $daysAgos = new \DateTimeImmutable('2023-12-31'); + + $workflow = new EntityWorkflow(); + $workflow->setWorkflowName('dummy_workflow'); + $workflow->setCreatedAt(new \DateTimeImmutable('2023-12-31')); + $workflow->setStep('step1', new WorkflowTransitionContextDTO($workflow), 'to_step1', $daysAgos, new User()); + + $em = $this->prophesize(EntityManagerInterface::class); + $em->flush()->shouldNotBeCalled(); + $em->remove($workflow)->shouldNotBeCalled(); + + $handler = $this->buildHandler($workflow, $em->reveal(), $clock); + + $handler(new CancelStaleWorkflowMessage(1)); + + self::assertEquals('canceled', $workflow->getStep()); + self::assertCount(3, $workflow->getSteps()); + } + + public function testWorkflowStaledInInitialStateIsCompletelyRemoved(): void + { + $clock = new MockClock('2024-01-01'); + + $workflow = new EntityWorkflow(); + $workflow->setWorkflowName('dummy_workflow'); + $workflow->setCreatedAt(new \DateTimeImmutable('2023-09-01')); + + $em = $this->prophesize(EntityManagerInterface::class); + $em->flush()->shouldBeCalled(); + $em->remove($workflow)->shouldBeCalled(); + + $handler = $this->buildHandler($workflow, $em->reveal(), $clock); + + $handler(new CancelStaleWorkflowMessage(1)); + + self::assertEquals('canceled', $workflow->getStep()); + self::assertCount(2, $workflow->getSteps()); + } + + private function buildHandler( + EntityWorkflow $entityWorkflow, + EntityManagerInterface $entityManager, + ClockInterface $clock, + ): CancelStaleWorkflowHandler { + // set an id for the workflow + $reflection = new \ReflectionClass($entityWorkflow); + $reflection->getProperty('id')->setValue($entityWorkflow, 1); + + $repository = $this->prophesize(EntityWorkflowRepository::class); + $repository->find(1)->willReturn($entityWorkflow); + + return new CancelStaleWorkflowHandler($repository->reveal(), $this->buildRegistry(), $entityManager, new NullLogger(), $clock); + } + + private function buildRegistry(): Registry + { + $definitionBuilder = new DefinitionBuilder(); + + $definitionBuilder + ->setInitialPlaces('initial') + ->addPlaces(['initial', 'step1', 'canceled', 'final']) + ->addTransition(new Transition('to_step1', 'initial', 'step1')) + ->addTransition($cancelInit = new Transition('cancel', 'initial', 'canceled')) + ->addTransition($finalizeInit = new Transition('finalize', 'initial', 'final')) + ->addTransition($cancelStep1 = new Transition('cancel', 'step1', 'canceled')) + ->addTransition($finalizeStep1 = new Transition('finalize', 'step1', 'final')); + + $transitionStorage = new \SplObjectStorage(); + $transitionStorage->attach($finalizeInit, ['isFinal' => true, 'isFinalPositive' => true]); + $transitionStorage->attach($cancelInit, ['isFinal' => true, 'isFinalPositive' => false]); + $transitionStorage->attach($finalizeStep1, ['isFinal' => true, 'isFinalPositive' => true]); + $transitionStorage->attach($cancelStep1, ['isFinal' => true, 'isFinalPositive' => false]); + + $definitionBuilder->setMetadataStore(new InMemoryMetadataStore([], [], $transitionStorage)); + $workflow = new Workflow($definitionBuilder->build(), new EntityWorkflowMarkingStore(), null, 'dummy_workflow'); + $supports = + new class () implements WorkflowSupportStrategyInterface { + public function supports(WorkflowInterface $workflow, object $subject): bool + { + return true; + } + }; + + + $registry = new Registry(); + $registry->addWorkflow($workflow, $supports); + + return $registry; + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php b/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php index 0fb6ff68c..0fbc69eab 100644 --- a/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php @@ -30,7 +30,7 @@ final class AddressRenderTest extends KernelTestCase self::bootKernel(); } - public function addressDataProviderBEWithBuilding(): \Iterator + public static function addressDataProviderBEWithBuilding(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -50,7 +50,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'Résidence "Les Bleuets" — Rue ABC, 5 — 012345 Locality — Belgium']; } - public function addressDataProviderBEWithSteps(): \Iterator + public static function addressDataProviderBEWithSteps(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -70,7 +70,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'esc 4 — Rue ABC, 5 — 012345 Locality — Belgium']; } - public function addressDataProviderFRWithBuilding(): \Iterator + public static function addressDataProviderFRWithBuilding(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -90,7 +90,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'Résidence "Les Bleuets" — 5, Rue ABC — 012345 Locality — France']; } - public function addressDataProviderFRWithSteps(): \Iterator + public static function addressDataProviderFRWithSteps(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -110,7 +110,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'esc 4 — 5, Rue ABC — 012345 Locality — France']; } - public function complexAddressDataProviderBE(): \Iterator + public static function complexAddressDataProviderBE(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -134,7 +134,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'Résidence "Les Bleuets" - appart 1 - ét 2 - coul 3 - esc 4 — Rue ABC, 5 — 012345 Locality — Belgium']; } - public function complexAddressDataProviderFR(): \Iterator + public static function complexAddressDataProviderFR(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -160,7 +160,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'appart 1 - ét 2 - coul 3 - esc 4 — Résidence "Les Bleuets" — 5, Rue ABC — A droite de la porte — 012345 Locality CEDEX — France']; } - public function noFullAddressDataProviderBE(): \Iterator + public static function noFullAddressDataProviderBE(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -177,7 +177,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, '012345 Locality — Belgium']; } - public function simpleAddressDataProviderBE(): \Iterator + public static function simpleAddressDataProviderBE(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -195,7 +195,7 @@ final class AddressRenderTest extends KernelTestCase yield [$addr, 'Rue ABC, 5 — 012345 Locality — Belgium']; } - public function simpleAddressDataProviderFR(): \Iterator + public static function simpleAddressDataProviderFR(): \Iterator { $addr = new Address(); $country = (new Country()) @@ -218,8 +218,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderComplexAddressBE(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -230,8 +230,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderComplexAddressFR(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -242,8 +242,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderNoFullAddressBE(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -254,8 +254,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderStringSimpleAddressBE(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -266,8 +266,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderStringSimpleAddressFR(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -278,8 +278,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderWithBuildingAddressBE(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -290,8 +290,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderWithBuildingAddressFR(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -302,8 +302,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderWithStepsAddressBE(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); @@ -314,8 +314,8 @@ final class AddressRenderTest extends KernelTestCase */ public function testRenderWithStepsAddressFR(Address $addr, string $expectedString): void { - $engine = self::$container->get(\Twig\Environment::class); - $translatableStringHelper = self::$container->get(TranslatableStringHelper::class); + $engine = self::getContainer()->get(\Twig\Environment::class); + $translatableStringHelper = self::getContainer()->get(TranslatableStringHelper::class); $renderer = new AddressRender($engine, $translatableStringHelper); $this->assertEquals($expectedString, $renderer->renderString($addr, [])); diff --git a/src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowMarkingStoreTest.php b/src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowMarkingStoreTest.php new file mode 100644 index 000000000..4922cab17 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowMarkingStoreTest.php @@ -0,0 +1,71 @@ +buildMarkingStore(); + $workflow = new EntityWorkflow(); + + $marking = $markingStore->getMarking($workflow); + + self::assertEquals(['initial' => 1], $marking->getPlaces()); + } + + public function testSetMarking(): void + { + $markingStore = $this->buildMarkingStore(); + $workflow = new EntityWorkflow(); + $previousStep = $workflow->getCurrentStep(); + + $dto = new WorkflowTransitionContextDTO($workflow); + $dto->futureCcUsers[] = $user1 = new User(); + $dto->futureDestUsers[] = $user2 = new User(); + $dto->futureDestEmails[] = $email = 'test@example.com'; + + $markingStore->setMarking($workflow, new Marking(['foo' => 1]), [ + 'context' => $dto, + 'transition' => 'bar_transition', + 'byUser' => $user3 = new User(), + 'transitionAt' => $at = new \DateTimeImmutable(), + ]); + + $currentStep = $workflow->getCurrentStep(); + self::assertEquals('foo', $currentStep->getCurrentStep()); + self::assertContains($email, $currentStep->getDestEmail()); + self::assertContains($user1, $currentStep->getCcUser()); + self::assertContains($user2, $currentStep->getDestUser()); + + self::assertSame($user3, $previousStep->getTransitionBy()); + self::assertSame($at, $previousStep->getTransitionAt()); + self::assertEquals('bar_transition', $previousStep->getTransitionAfter()); + } + + private function buildMarkingStore(): EntityWorkflowMarkingStore + { + return new EntityWorkflowMarkingStore(); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Workflow/EventSubscriber/EntityWorkflowGuardTransitionTest.php b/src/Bundle/ChillMainBundle/Tests/Workflow/EventSubscriber/EntityWorkflowGuardTransitionTest.php new file mode 100644 index 000000000..dd3b12e86 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Workflow/EventSubscriber/EntityWorkflowGuardTransitionTest.php @@ -0,0 +1,178 @@ +setInitialPlaces(['initial']) + ->addPlaces(['initial', 'intermediate', 'step1', 'step2', 'step3']) + ->addTransition(new Transition('intermediate', 'initial', 'intermediate')) + ->addTransition($transition1 = new Transition('transition1', 'intermediate', 'step1')) + ->addTransition($transition2 = new Transition('transition2', 'intermediate', 'step2')) + ->addTransition($transition3 = new Transition('transition3', 'intermediate', 'step3')) + ; + + $transitionMetadata = new \SplObjectStorage(); + $transitionMetadata->attach($transition1, ['transitionGuard' => 'only-dest']); + $transitionMetadata->attach($transition2, ['transitionGuard' => 'only-dest+system']); + $transitionMetadata->attach($transition3, ['transitionGuard' => 'system']); + + $builder->setMetadataStore(new InMemoryMetadataStore(transitionsMetadata: $transitionMetadata)); + + if (null !== $eventSubscriber) { + $eventDispatcher = new EventDispatcher(); + $eventDispatcher->addSubscriber($eventSubscriber); + } + + $workflow = new Workflow($builder->build(), new EntityWorkflowMarkingStore(), $eventDispatcher ?? null, 'dummy'); + + $registry = new Registry(); + $registry->addWorkflow( + $workflow, + new class () implements WorkflowSupportStrategyInterface { + public function supports(WorkflowInterface $workflow, object $subject): bool + { + return true; + } + } + ); + + return $registry; + } + + /** + * @dataProvider provideBlockingTransition + */ + public function testTransitionGuardBlocked(EntityWorkflow $entityWorkflow, string $transition, ?User $user, bool $isGrantedAllTransition, string $uuid): void + { + $userRender = $this->prophesize(UserRender::class); + $userRender->renderString(Argument::type(User::class), [])->willReturn('user-as-string'); + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + $security->isGranted(EntityWorkflowTransitionVoter::APPLY_ALL_TRANSITIONS, $entityWorkflow->getCurrentStep()) + ->willReturn($isGrantedAllTransition); + + $transitionGuard = new EntityWorkflowGuardTransition($userRender->reveal(), $security->reveal()); + $registry = self::buildRegistry($transitionGuard); + + $workflow = $registry->get($entityWorkflow, 'dummy'); + + $context = new WorkflowTransitionContextDTO($entityWorkflow); + + self::expectException(NotEnabledTransitionException::class); + try { + $workflow->apply($entityWorkflow, $transition, ['context' => $context, 'byUser' => $user, 'transition' => $transition, 'transitionAt' => new \DateTimeImmutable('now')]); + } catch (NotEnabledTransitionException $e) { + $list = $e->getTransitionBlockerList(); + + self::assertEquals(1, $list->count()); + $list = iterator_to_array($list->getIterator()); + self::assertEquals($uuid, $list[0]->getCode()); + + throw $e; + } + } + + /** + * @dataProvider provideValidTransition + */ + public function testTransitionGuardValid(EntityWorkflow $entityWorkflow, string $transition, ?User $user, bool $isGrantedAllTransition, string $newStep): void + { + $userRender = $this->prophesize(UserRender::class); + $userRender->renderString(Argument::type(User::class), [])->willReturn('user-as-string'); + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + $security->isGranted(EntityWorkflowTransitionVoter::APPLY_ALL_TRANSITIONS, $entityWorkflow->getCurrentStep()) + ->willReturn($isGrantedAllTransition); + + $transitionGuard = new EntityWorkflowGuardTransition($userRender->reveal(), $security->reveal()); + $registry = self::buildRegistry($transitionGuard); + + $workflow = $registry->get($entityWorkflow, 'dummy'); + $context = new WorkflowTransitionContextDTO($entityWorkflow); + + $workflow->apply($entityWorkflow, $transition, ['context' => $context, 'byUser' => $user, 'transition' => $transition, 'transitionAt' => new \DateTimeImmutable('now')]); + + self::assertEquals($newStep, $entityWorkflow->getStep()); + } + + public static function provideBlockingTransition(): iterable + { + yield [self::buildEntityWorkflow([new User()]), 'transition1', new User(), false, 'f3eeb57c-7532-11ec-9495-e7942a2ac7bc']; + yield [self::buildEntityWorkflow([]), 'transition1', null, false, 'd9e39a18-704c-11ef-b235-8fe0619caee7']; + yield [self::buildEntityWorkflow([new User()]), 'transition1', null, false, 'd9e39a18-704c-11ef-b235-8fe0619caee7']; + yield [self::buildEntityWorkflow([$user = new User()]), 'transition3', $user, false, '5b6b95e0-704d-11ef-a5a9-4b6fc11a8eeb']; + yield [self::buildEntityWorkflow([$user = new User()]), 'transition3', $user, true, '5b6b95e0-704d-11ef-a5a9-4b6fc11a8eeb']; + } + + public static function provideValidTransition(): iterable + { + yield [self::buildEntityWorkflow([$u = new User()]), 'transition1', $u, false, 'step1']; + yield [self::buildEntityWorkflow([$u = new User()]), 'transition2', $u, false, 'step2']; + yield [self::buildEntityWorkflow([new User()]), 'transition2', null, false, 'step2']; + yield [self::buildEntityWorkflow([]), 'transition2', null, false, 'step2']; + yield [self::buildEntityWorkflow([new User()]), 'transition3', null, false, 'step3']; + yield [self::buildEntityWorkflow([]), 'transition3', null, false, 'step3']; + + // transition allowed thanks to permission "apply all transitions" + yield [self::buildEntityWorkflow([new User()]), 'transition1', new User(), true, 'step1']; + yield [self::buildEntityWorkflow([new User()]), 'transition2', new User(), true, 'step2']; + } + + public static function buildEntityWorkflow(array $futureDestUsers): EntityWorkflow + { + $registry = self::buildRegistry(null); + $baseContext = ['transition' => 'intermediate', 'transitionAt' => new \DateTimeImmutable()]; + + // test a user not is destination is blocked + $entityWorkflow = new EntityWorkflow(); + $workflow = $registry->get($entityWorkflow, 'dummy'); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureDestUsers = $futureDestUsers; + $workflow->apply($entityWorkflow, 'intermediate', ['context' => $dto, ...$baseContext]); + + return $entityWorkflow; + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Workflow/SignatureStepStateChangerTest.php b/src/Bundle/ChillMainBundle/Tests/Workflow/SignatureStepStateChangerTest.php new file mode 100644 index 000000000..16579cbb5 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Workflow/SignatureStepStateChangerTest.php @@ -0,0 +1,146 @@ +setWorkflowName('dummy'); + $registry = $this->buildRegistry(); + $workflow = $registry->get($entityWorkflow, 'dummy'); + $clock = new MockClock(); + $user = new User(); + $changer = new SignatureStepStateChanger($registry, $clock, new NullLogger()); + + // move it to signature + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futurePersonSignatures = [new Person(), new Person()]; + $workflow->apply($entityWorkflow, 'to_signature', ['context' => $dto, 'transitionAt' => $clock->now(), + 'byUser' => $user, 'transition' => 'to_signature']); + + // get the signature created + $signatures = $entityWorkflow->getCurrentStep()->getSignatures(); + + if (2 !== count($signatures)) { + throw new \LogicException('there should have 2 signatures at this step'); + } + + // we mark the first signature as signed + $changer->markSignatureAsSigned($signatures[0], 1); + + self::assertEquals('signature', $entityWorkflow->getStep(), 'there should have any change in the entity workflow step'); + self::assertEquals(EntityWorkflowSignatureStateEnum::SIGNED, $signatures[0]->getState()); + self::assertEquals(1, $signatures[0]->getZoneSignatureIndex()); + self::assertNotNull($signatures[0]->getStateDate()); + + + // we mark the second signature as signed + $changer->markSignatureAsSigned($signatures[1], 2); + self::assertEquals(EntityWorkflowSignatureStateEnum::SIGNED, $signatures[1]->getState()); + self::assertEquals('post-signature', $entityWorkflow->getStep(), 'the entity workflow step should be post-signature'); + self::assertContains($user, $entityWorkflow->getCurrentStep()->getAllDestUser()); + self::assertEquals(2, $signatures[1]->getZoneSignatureIndex()); + self::assertNotNull($signatures[1]->getStateDate()); + } + + public function testMarkSignatureAsSignedScenarioWithoutRequiredMetadata() + { + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setWorkflowName('dummy'); + $registry = $this->buildRegistry(); + $workflow = $registry->get($entityWorkflow, 'dummy'); + $clock = new MockClock(); + $user = new User(); + $changer = new SignatureStepStateChanger($registry, $clock, new NullLogger()); + + // move it to signature + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futurePersonSignatures = [new Person()]; + $workflow->apply($entityWorkflow, 'to_signature-without-metadata', ['context' => $dto, 'transitionAt' => $clock->now(), + 'byUser' => $user, 'transition' => 'to_signature-without-metadata']); + + // get the signature created + $signatures = $entityWorkflow->getCurrentStep()->getSignatures(); + + if (1 !== count($signatures)) { + throw new \LogicException('there should have 2 signatures at this step'); + } + + // we mark the first signature as signed + $changer->markSignatureAsSigned($signatures[0], 1); + + self::assertEquals('signature-without-metadata', $entityWorkflow->getStep(), 'there should have any change in the entity workflow step'); + self::assertEquals(EntityWorkflowSignatureStateEnum::SIGNED, $signatures[0]->getState()); + self::assertEquals(1, $signatures[0]->getZoneSignatureIndex()); + self::assertNotNull($signatures[0]->getStateDate()); + } + + private function buildRegistry(): Registry + { + $builder = new DefinitionBuilder(); + $builder + ->setInitialPlaces('initial') + ->addPlaces(['initial', 'signature', 'signature-without-metadata', 'post-signature']) + ->addTransition(new Transition('to_signature', 'initial', 'signature')) + ->addTransition(new Transition('to_signature-without-metadata', 'initial', 'signature-without-metadata')) + ->addTransition(new Transition('to_post-signature', 'signature', 'post-signature')) + ->addTransition(new Transition('to_post-signature_2', 'signature-without-metadata', 'post-signature')) + ; + + $metadata = new InMemoryMetadataStore( + [], + [ + 'signature' => ['onSignatureCompleted' => ['transitionName' => 'to_post-signature']], + ] + ); + $builder->setMetadataStore($metadata); + + $workflow = new Workflow($builder->build(), new EntityWorkflowMarkingStore(), name: 'dummy'); + $registry = new Registry(); + $registry->addWorkflow( + $workflow, + new class () implements WorkflowSupportStrategyInterface { + public function supports(WorkflowInterface $workflow, object $subject): bool + { + return true; + } + } + ); + + return $registry; + } +} diff --git a/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php b/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php index 6b4253104..53d8faa16 100644 --- a/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php +++ b/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php @@ -37,9 +37,7 @@ class TimelineBuilder */ private array $providersByContext = []; - public function __construct(private readonly EntityManagerInterface $em, private readonly Environment $twig) - { - } + public function __construct(private readonly EntityManagerInterface $em, private readonly Environment $twig) {} /** * add a provider id. diff --git a/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php b/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php index e736ba749..584e634ea 100644 --- a/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php +++ b/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php @@ -15,9 +15,7 @@ class TimelineSingleQuery { private bool $distinct = false; - public function __construct(private ?string $id = null, private ?string $date = null, private ?string $key = null, private ?string $from = null, private ?string $where = null, private array $parameters = []) - { - } + public function __construct(private ?string $id = null, private ?string $date = null, private ?string $key = null, private ?string $from = null, private ?string $where = null, private array $parameters = []) {} public function buildSql(): string { diff --git a/src/Bundle/ChillMainBundle/Validation/Constraint/PhonenumberConstraint.php b/src/Bundle/ChillMainBundle/Validation/Constraint/PhonenumberConstraint.php index 147a02465..2c20de854 100644 --- a/src/Bundle/ChillMainBundle/Validation/Constraint/PhonenumberConstraint.php +++ b/src/Bundle/ChillMainBundle/Validation/Constraint/PhonenumberConstraint.php @@ -13,9 +13,7 @@ namespace Chill\MainBundle\Validation\Constraint; use Symfony\Component\Validator\Constraint; -/** - * @Annotation - */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)] class PhonenumberConstraint extends Constraint { public $notLandlineMessage = 'This is not a landline phonenumber'; @@ -29,7 +27,13 @@ class PhonenumberConstraint extends Constraint * * @var string 'landline', 'mobile' or 'any' */ - public $type; + public string $type; + + public function __construct(?array $options = null, ?string $type = null, ?array $groups = null, $payload = null) + { + parent::__construct($options ?? [], $groups, $payload); + $this->type = $type ?? 'any'; + } public function validatedBy() { diff --git a/src/Bundle/ChillMainBundle/Validation/Validator/RoleScopeScopePresence.php b/src/Bundle/ChillMainBundle/Validation/Validator/RoleScopeScopePresence.php index 8980b8376..0bbf1d373 100644 --- a/src/Bundle/ChillMainBundle/Validation/Validator/RoleScopeScopePresence.php +++ b/src/Bundle/ChillMainBundle/Validation/Validator/RoleScopeScopePresence.php @@ -21,9 +21,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class RoleScopeScopePresence extends ConstraintValidator { - public function __construct(private readonly RoleProvider $roleProvider, private readonly LoggerInterface $logger, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly RoleProvider $roleProvider, private readonly LoggerInterface $logger, private readonly TranslatorInterface $translator) {} public function validate($value, Constraint $constraint) { diff --git a/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php b/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php index f0fd1880c..0c02885ad 100644 --- a/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php +++ b/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php @@ -18,9 +18,7 @@ use Symfony\Component\Validator\ConstraintValidator; final class ValidPhonenumber extends ConstraintValidator { - public function __construct(private readonly LoggerInterface $logger, private readonly PhoneNumberHelperInterface $phonenumberHelper) - { - } + public function __construct(private readonly LoggerInterface $logger, private readonly PhoneNumberHelperInterface $phonenumberHelper) {} /** * @param string $value diff --git a/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistency.php b/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistency.php index b8edc98ad..3c283a96e 100644 --- a/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistency.php +++ b/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistency.php @@ -13,9 +13,7 @@ namespace Chill\MainBundle\Validator\Constraints\Entity; use Symfony\Component\Validator\Constraint; -/** - * @Annotation - */ +#[\Attribute(\Attribute::TARGET_CLASS)] class UserCircleConsistency extends Constraint { public $getUserFunction = 'getUser'; diff --git a/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php b/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php index 3ea5d495b..a1b631265 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php +++ b/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php @@ -22,9 +22,7 @@ use Symfony\Component\Workflow\Event\Event; final readonly class WorkflowByUserCounter implements NotificationCounterInterface, EventSubscriberInterface { - public function __construct(private EntityWorkflowStepRepository $workflowStepRepository, private CacheItemPoolInterface $cacheItemPool) - { - } + public function __construct(private EntityWorkflowStepRepository $workflowStepRepository, private CacheItemPoolInterface $cacheItemPool) {} public function addNotification(UserInterface $u): int { diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php index 1d185ba0e..c0d6469f6 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php +++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php @@ -14,6 +14,9 @@ namespace Chill\MainBundle\Workflow; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; +/** + * @template T of object + */ interface EntityWorkflowHandlerInterface { /** @@ -25,6 +28,9 @@ interface EntityWorkflowHandlerInterface public function getEntityTitle(EntityWorkflow $entityWorkflow, array $options = []): string; + /** + * @return T|null + */ public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?object; public function getRelatedObjects(object $object): array; @@ -51,4 +57,9 @@ interface EntityWorkflowHandlerInterface public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool; public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool; + + /** + * @return list + */ + public function findByRelatedEntity(object $object): array; } diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php index 6c45cef3d..9f7b54ccd 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php +++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Workflow; +use Chill\DocStoreBundle\Entity\StoredObject; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; use Chill\MainBundle\Workflow\Exception\HandlerNotFoundException; use Symfony\Component\Workflow\Registry; @@ -20,9 +21,7 @@ class EntityWorkflowManager /** * @param \Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface[] $handlers */ - public function __construct(private readonly iterable $handlers, private readonly Registry $registry) - { - } + public function __construct(private readonly iterable $handlers, private readonly Registry $registry) {} public function getHandler(EntityWorkflow $entityWorkflow, array $options = []): EntityWorkflowHandlerInterface { @@ -39,4 +38,29 @@ class EntityWorkflowManager { return $this->registry->all($entityWorkflow); } + + public function getAssociatedStoredObject(EntityWorkflow $entityWorkflow): ?StoredObject + { + foreach ($this->handlers as $handler) { + if ($handler instanceof EntityWorkflowWithStoredObjectHandlerInterface && $handler->supports($entityWorkflow)) { + return $handler->getAssociatedStoredObject($entityWorkflow); + } + } + + return null; + } + + /** + * @return list + */ + public function findByRelatedEntity(object $object): array + { + foreach ($this->handlers as $handler) { + if ([] !== $workflows = $handler->findByRelatedEntity($object)) { + return $workflows; + } + } + + return []; + } } diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowMarkingStore.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowMarkingStore.php new file mode 100644 index 000000000..ee07d7a62 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowMarkingStore.php @@ -0,0 +1,53 @@ +getCurrentStep(); + + return new Marking([$step->getCurrentStep() => 1]); + } + + public function setMarking(object $subject, Marking $marking, array $context = []): void + { + if (!$subject instanceof EntityWorkflow) { + throw new \UnexpectedValueException('Expected instance of EntityWorkflow'); + } + + $places = $marking->getPlaces(); + if (1 < count($places)) { + throw new \LogicException('Expected maximum one place'); + } + $next = array_keys($places)[0]; + + $transitionDTO = $context['context'] ?? null; + $transition = $context['transition']; + $byUser = $context['byUser'] ?? null; + $at = $context['transitionAt']; + + if (!$transitionDTO instanceof WorkflowTransitionContextDTO) { + throw new \UnexpectedValueException(sprintf('Expected instance of %s', WorkflowTransitionContextDTO::class)); + } + + $subject->setStep($next, $transitionDTO, $transition, $at, $byUser); + } +} diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowWithStoredObjectHandlerInterface.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowWithStoredObjectHandlerInterface.php new file mode 100644 index 000000000..a1c7561cd --- /dev/null +++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowWithStoredObjectHandlerInterface.php @@ -0,0 +1,27 @@ + + */ +interface EntityWorkflowWithStoredObjectHandlerInterface extends EntityWorkflowHandlerInterface +{ + public function getAssociatedStoredObject(EntityWorkflow $entityWorkflow): ?StoredObject; +} diff --git a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowGuardTransition.php b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowGuardTransition.php new file mode 100644 index 000000000..1c9d26fc7 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowGuardTransition.php @@ -0,0 +1,123 @@ + [ + ['guardEntityWorkflow', 0], + ], + ]; + } + + public function guardEntityWorkflow(GuardEvent $event) + { + if (!$event->getSubject() instanceof EntityWorkflow) { + return; + } + + /** @var EntityWorkflow $entityWorkflow */ + $entityWorkflow = $event->getSubject(); + + if ($entityWorkflow->isFinal()) { + $event->addTransitionBlocker( + new TransitionBlocker( + 'workflow.The workflow is finalized', + 'd6306280-7535-11ec-a40d-1f7bee26e2c0' + ) + ); + + return; + } + + $user = $this->security->getUser(); + $metadata = $event->getWorkflow()->getMetadataStore()->getTransitionMetadata($event->getTransition()); + $systemTransitions = explode('+', $metadata['transitionGuard'] ?? 'only-dest'); + + if (null === $user) { + if (in_array('system', $systemTransitions, true)) { + // it is safe to apply this transition + return; + } + + $event->addTransitionBlocker( + new TransitionBlocker( + 'workflow.Transition is not allowed for system', + 'd9e39a18-704c-11ef-b235-8fe0619caee7' + ) + ); + + return; + } + + // for users + if (!in_array('only-dest', $systemTransitions, true)) { + $event->addTransitionBlocker( + new TransitionBlocker( + 'workflow.Only system can apply this transition', + '5b6b95e0-704d-11ef-a5a9-4b6fc11a8eeb' + ) + ); + } + + if ( + !$entityWorkflow->getCurrentStep()->getAllDestUser()->contains($user) + ) { + if ($event->getMarking()->has('initial')) { + return; + } + + if ($this->security->isGranted(EntityWorkflowTransitionVoter::APPLY_ALL_TRANSITIONS, $entityWorkflow->getCurrentStep())) { + return; + } + + $event->addTransitionBlocker(new TransitionBlocker( + 'workflow.You are not allowed to apply a transition on this workflow. Only those users are allowed: %users%', + 'f3eeb57c-7532-11ec-9495-e7942a2ac7bc', + [ + '%users%' => implode( + ', ', + $entityWorkflow->getCurrentStep()->getAllDestUser()->map(fn (User $u) => $this->userRender->renderString($u, []))->toArray() + ), + ] + )); + } + } +} diff --git a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php index 804a6587f..8903d79eb 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php +++ b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php @@ -13,41 +13,17 @@ namespace Chill\MainBundle\Workflow\EventSubscriber; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; -use Chill\MainBundle\Templating\Entity\UserRender; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Core\Security; use Symfony\Component\Workflow\Event\Event; -use Symfony\Component\Workflow\Event\GuardEvent; -use Symfony\Component\Workflow\TransitionBlocker; -class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterface +final readonly class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterface { - public function __construct(private readonly LoggerInterface $chillLogger, private readonly Security $security, private readonly UserRender $userRender) - { - } - - public function addDests(Event $event): void - { - if (!$event->getSubject() instanceof EntityWorkflow) { - return; - } - - /** @var EntityWorkflow $entityWorkflow */ - $entityWorkflow = $event->getSubject(); - - foreach ($entityWorkflow->futureCcUsers as $user) { - $entityWorkflow->getCurrentStep()->addCcUser($user); - } - - foreach ($entityWorkflow->futureDestUsers as $user) { - $entityWorkflow->getCurrentStep()->addDestUser($user); - } - - foreach ($entityWorkflow->futureDestEmails as $email) { - $entityWorkflow->getCurrentStep()->addDestEmail($email); - } - } + public function __construct( + private LoggerInterface $chillLogger, + private Security $security, + ) {} public static function getSubscribedEvents(): array { @@ -55,52 +31,16 @@ class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterfac 'workflow.transition' => 'onTransition', 'workflow.completed' => [ ['markAsFinal', 2048], - ['addDests', 2048], - ], - 'workflow.guard' => [ - ['guardEntityWorkflow', 0], ], ]; } - public function guardEntityWorkflow(GuardEvent $event) - { - if (!$event->getSubject() instanceof EntityWorkflow) { - return; - } - - /** @var EntityWorkflow $entityWorkflow */ - $entityWorkflow = $event->getSubject(); - - if ($entityWorkflow->isFinal()) { - $event->addTransitionBlocker( - new TransitionBlocker( - 'workflow.The workflow is finalized', - 'd6306280-7535-11ec-a40d-1f7bee26e2c0' - ) - ); - - return; - } - - if (!$entityWorkflow->getCurrentStep()->getAllDestUser()->contains($this->security->getUser())) { - if (!$event->getMarking()->has('initial')) { - $event->addTransitionBlocker(new TransitionBlocker( - 'workflow.You are not allowed to apply a transition on this workflow. Only those users are allowed: %users%', - 'f3eeb57c-7532-11ec-9495-e7942a2ac7bc', - [ - '%users%' => implode( - ', ', - $entityWorkflow->getCurrentStep()->getAllDestUser()->map(fn (User $u) => $this->userRender->renderString($u, []))->toArray() - ), - ] - )); - } - } - } - public function markAsFinal(Event $event): void { + // NOTE: it is not possible to move this method to the marking store, because + // there is dependency between the Workflow definition and the MarkingStoreInterface (the workflow + // constructor need a MarkingStoreInterface) + if (!$event->getSubject() instanceof EntityWorkflow) { return; } @@ -125,18 +65,14 @@ class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterfac /** @var EntityWorkflow $entityWorkflow */ $entityWorkflow = $event->getSubject(); - $step = $entityWorkflow->getCurrentStep(); - $step - ->setTransitionAfter($event->getTransition()->getName()) - ->setTransitionAt(new \DateTimeImmutable('now')) - ->setTransitionBy($this->security->getUser()); + $user = $this->security->getUser(); $this->chillLogger->info('[workflow] apply transition on entityWorkflow', [ 'relatedEntityClass' => $entityWorkflow->getRelatedEntityClass(), 'relatedEntityId' => $entityWorkflow->getRelatedEntityId(), 'transition' => $event->getTransition()->getName(), - 'by_user' => $this->security->getUser(), + 'by_user' => $user instanceof User ? $user->getId() : (string) $user?->getUserIdentifier(), 'entityWorkflow' => $entityWorkflow->getId(), ]); } diff --git a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php index 07cf8cc14..d955d777f 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php +++ b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php @@ -23,9 +23,13 @@ use Symfony\Component\Workflow\Registry; class NotificationOnTransition implements EventSubscriberInterface { - public function __construct(private readonly EntityManagerInterface $entityManager, private readonly \Twig\Environment $engine, private readonly MetadataExtractor $metadataExtractor, private readonly Security $security, private readonly Registry $registry) - { - } + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly \Twig\Environment $engine, + private readonly MetadataExtractor $metadataExtractor, + private readonly Security $security, + private readonly Registry $registry, + ) {} public static function getSubscribedEvents(): array { @@ -87,7 +91,10 @@ class NotificationOnTransition implements EventSubscriberInterface 'dest' => $subscriber, 'place' => $place, 'workflow' => $workflow, - 'is_dest' => \in_array($subscriber->getId(), array_map(static fn (User $u) => $u->getId(), $entityWorkflow->futureDestUsers), true), + 'is_dest' => \in_array($subscriber->getId(), array_map( + static fn (User $u) => $u->getId(), + $entityWorkflow->getCurrentStep()->getDestUser()->toArray() + ), true), ]; $notification = new Notification(); diff --git a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/SendAccessKeyEventSubscriber.php b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/SendAccessKeyEventSubscriber.php index bd07a5a28..a7bae81d4 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/SendAccessKeyEventSubscriber.php +++ b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/SendAccessKeyEventSubscriber.php @@ -20,9 +20,13 @@ use Symfony\Component\Workflow\Registry; class SendAccessKeyEventSubscriber { - public function __construct(private readonly \Twig\Environment $engine, private readonly MetadataExtractor $metadataExtractor, private readonly Registry $registry, private readonly EntityWorkflowManager $entityWorkflowManager, private readonly MailerInterface $mailer) - { - } + public function __construct( + private readonly \Twig\Environment $engine, + private readonly MetadataExtractor $metadataExtractor, + private readonly Registry $registry, + private readonly EntityWorkflowManager $entityWorkflowManager, + private readonly MailerInterface $mailer, + ) {} public function postPersist(EntityWorkflowStep $step): void { @@ -34,7 +38,7 @@ class SendAccessKeyEventSubscriber ); $handler = $this->entityWorkflowManager->getHandler($entityWorkflow); - foreach ($entityWorkflow->futureDestEmails as $emailAddress) { + foreach ($step->getDestEmail() as $emailAddress) { $context = [ 'entity_workflow' => $entityWorkflow, 'dest' => $emailAddress, diff --git a/src/Bundle/ChillMainBundle/Workflow/Exception/HandlerNotFoundException.php b/src/Bundle/ChillMainBundle/Workflow/Exception/HandlerNotFoundException.php index f4280b50f..9d91b3357 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Exception/HandlerNotFoundException.php +++ b/src/Bundle/ChillMainBundle/Workflow/Exception/HandlerNotFoundException.php @@ -11,6 +11,4 @@ declare(strict_types=1); namespace Chill\MainBundle\Workflow\Exception; -class HandlerNotFoundException extends \RuntimeException -{ -} +class HandlerNotFoundException extends \RuntimeException {} diff --git a/src/Bundle/ChillMainBundle/Workflow/Helper/MetadataExtractor.php b/src/Bundle/ChillMainBundle/Workflow/Helper/MetadataExtractor.php index 8f0caa62e..f99449dc3 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Helper/MetadataExtractor.php +++ b/src/Bundle/ChillMainBundle/Workflow/Helper/MetadataExtractor.php @@ -19,9 +19,7 @@ use Symfony\Component\Workflow\WorkflowInterface; class MetadataExtractor { - public function __construct(private readonly Registry $registry, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly Registry $registry, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function availableWorkflowFor(string $relatedEntityClass, ?int $relatedEntityId = 0): array { diff --git a/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php b/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php index 9302cf7f9..c9ba7cf79 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php +++ b/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php @@ -20,9 +20,7 @@ use Symfony\Component\Security\Core\Security; class WorkflowNotificationHandler implements NotificationHandlerInterface { - public function __construct(private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly EntityWorkflowManager $entityWorkflowManager, private readonly Security $security) - { - } + public function __construct(private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly EntityWorkflowManager $entityWorkflowManager, private readonly Security $security) {} public function getTemplate(Notification $notification, array $options = []): string { diff --git a/src/Bundle/ChillMainBundle/Workflow/SignatureStepStateChanger.php b/src/Bundle/ChillMainBundle/Workflow/SignatureStepStateChanger.php new file mode 100644 index 000000000..3e2871810 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Workflow/SignatureStepStateChanger.php @@ -0,0 +1,112 @@ +setState(EntityWorkflowSignatureStateEnum::SIGNED) + ->setZoneSignatureIndex($atIndex) + ->setStateDate($this->clock->now()) + ; + + $this->logger->info(self::LOG_PREFIX.'Mark signature entity as signed', ['signatureId' => $signature->getId(), 'index' => (string) $atIndex]); + + if (!EntityWorkflowStepSignature::isAllSignatureNotPendingForStep($signature->getStep())) { + $this->logger->info(self::LOG_PREFIX.'This is not the last signature, skipping transition to another place', ['signatureId' => $signature->getId()]); + + return; + } + + $this->logger->debug(self::LOG_PREFIX.'Continuing the process to find a transition', ['signatureId' => $signature->getId()]); + + $entityWorkflow = $signature->getStep()->getEntityWorkflow(); + $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); + $metadataStore = $workflow->getMetadataStore(); + + // find a transition + $marking = $workflow->getMarking($entityWorkflow); + $places = $marking->getPlaces(); + + $transition = null; + foreach ($places as $place => $int) { + $metadata = $metadataStore->getPlaceMetadata($place); + if (array_key_exists('onSignatureCompleted', $metadata)) { + $transition = $metadata['onSignatureCompleted']['transitionName']; + } + } + + if (null === $transition) { + $this->logger->info(self::LOG_PREFIX.'The transition is not configured, will not apply a transition', ['signatureId' => $signature->getId()]); + + return; + } + + $previousUser = $this->getPreviousSender($signature->getStep()); + + if (null === $previousUser) { + $this->logger->info(self::LOG_PREFIX.'No previous user, will not apply a transition', ['signatureId' => $signature->getId()]); + + return; + } + + $transitionDto = new WorkflowTransitionContextDTO($entityWorkflow); + $transitionDto->futureDestUsers[] = $previousUser; + + $workflow->apply($entityWorkflow, $transition, [ + 'context' => $transitionDto, + 'transitionAt' => $this->clock->now(), + 'transition' => $transition, + ]); + + $this->logger->info(self::LOG_PREFIX.'Transition automatically applied', ['signatureId' => $signature->getId()]); + } + + private function getPreviousSender(EntityWorkflowStep $entityWorkflowStep): ?User + { + $stepsChained = $entityWorkflowStep->getEntityWorkflow()->getStepsChained(); + + foreach ($stepsChained as $stepChained) { + if ($stepChained === $entityWorkflowStep) { + if (null === $previous = $stepChained->getPrevious()) { + return null; + } + + if (null !== $previousUser = $previous->getTransitionBy()) { + return $previousUser; + } + + return $this->getPreviousSender($previous); + } + } + + throw new \LogicException('no same step found'); + } +} diff --git a/src/Bundle/ChillMainBundle/Workflow/Templating/WorkflowTwigExtensionRuntime.php b/src/Bundle/ChillMainBundle/Workflow/Templating/WorkflowTwigExtensionRuntime.php index e9edb11d9..f2b7d80db 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Templating/WorkflowTwigExtensionRuntime.php +++ b/src/Bundle/ChillMainBundle/Workflow/Templating/WorkflowTwigExtensionRuntime.php @@ -23,9 +23,7 @@ use Twig\Extension\RuntimeExtensionInterface; class WorkflowTwigExtensionRuntime implements RuntimeExtensionInterface { - public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly Registry $registry, private readonly EntityWorkflowRepository $repository, private readonly MetadataExtractor $metadataExtractor, private readonly NormalizerInterface $normalizer) - { - } + public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly Registry $registry, private readonly EntityWorkflowRepository $repository, private readonly MetadataExtractor $metadataExtractor, private readonly NormalizerInterface $normalizer) {} public function getTransitionByString(EntityWorkflow $entityWorkflow, string $key): ?Transition { diff --git a/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreation.php b/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreation.php index 7476d3273..34f024884 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreation.php +++ b/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreation.php @@ -17,9 +17,8 @@ namespace Chill\MainBundle\Workflow\Validator; * * a handler exists; * * a related entity does exists; * * a workflow can be associated with this entity. - * - * @Annotation */ +#[\Attribute(\Attribute::TARGET_CLASS)] class EntityWorkflowCreation extends \Symfony\Component\Validator\Constraint { public string $messageEntityNotFound = 'Related entity is not found'; diff --git a/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreationValidator.php b/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreationValidator.php index f6590c9d3..2020c7b52 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreationValidator.php +++ b/src/Bundle/ChillMainBundle/Workflow/Validator/EntityWorkflowCreationValidator.php @@ -21,9 +21,7 @@ use Symfony\Component\Workflow\WorkflowInterface; class EntityWorkflowCreationValidator extends \Symfony\Component\Validator\ConstraintValidator { - public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager) - { - } + public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager) {} /** * @param EntityWorkflow $value diff --git a/src/Bundle/ChillMainBundle/Workflow/WorkflowTransitionContextDTO.php b/src/Bundle/ChillMainBundle/Workflow/WorkflowTransitionContextDTO.php new file mode 100644 index 000000000..f675b9646 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Workflow/WorkflowTransitionContextDTO.php @@ -0,0 +1,87 @@ + + */ + public array $futurePersonSignatures = []; + + /** + * An eventual user which is requested to apply a signature. + */ + public ?User $futureUserSignature = null; + + public ?Transition $transition = null; + + public string $comment = ''; + + public function __construct( + public EntityWorkflow $entityWorkflow, + ) {} + + #[Assert\Callback()] + public function validateCCUserIsNotInDest(ExecutionContextInterface $context, $payload): void + { + foreach ($this->futureDestUsers as $u) { + if (in_array($u, $this->futureCcUsers, true)) { + $context + ->buildViolation('workflow.The user in cc cannot be a dest user in the same workflow step') + ->atPath('ccUsers') + ->addViolation(); + } + } + } +} diff --git a/src/Bundle/ChillMainBundle/chill.webpack.config.js b/src/Bundle/ChillMainBundle/chill.webpack.config.js index 35e88ed18..677adde04 100644 --- a/src/Bundle/ChillMainBundle/chill.webpack.config.js +++ b/src/Bundle/ChillMainBundle/chill.webpack.config.js @@ -1,10 +1,10 @@ -const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' ); const { styles } = require( '@ckeditor/ckeditor5-dev-utils' ); +const {CKEditorTranslationsPlugin} = require("@ckeditor/ckeditor5-dev-translations"); buildCKEditor = function(encore) { encore - .addPlugin( new CKEditorWebpackPlugin( { + .addPlugin( new CKEditorTranslationsPlugin( { language: 'fr', addMainLanguageTranslationsToAllAssets: true, verbose: !encore.isProduction(), @@ -52,12 +52,14 @@ module.exports = function(encore, entries) Tabs: __dirname + '/Resources/public/lib/tabs' }); + // Page entrypoints encore.addEntry('page_login', __dirname + '/Resources/public/page/login/index.js'); encore.addEntry('page_location', __dirname + '/Resources/public/page/location/index.js'); encore.addEntry('page_workflow_show', __dirname + '/Resources/public/page/workflow-show/index.js'); encore.addEntry('page_homepage_widget', __dirname + '/Resources/public/page/homepage_widget/index.js'); encore.addEntry('page_export', __dirname + '/Resources/public/page/export/index.js'); + encore.addEntry('page_download_exports', __dirname + '/Resources/public/page/export/download-export.js'); buildCKEditor(encore); @@ -65,7 +67,7 @@ module.exports = function(encore, entries) encore.addEntry('mod_collection', __dirname + '/Resources/public/module/collection/index.ts'); encore.addEntry('mod_forkawesome', __dirname + '/Resources/public/module/forkawesome/index.js'); encore.addEntry('mod_bootstrap', __dirname + '/Resources/public/module/bootstrap/index.js'); - encore.addEntry('mod_ckeditor5', __dirname + '/Resources/public/module/ckeditor5/index.js'); + encore.addEntry('mod_ckeditor5', __dirname + '/Resources/public/module/ckeditor5/index'); encore.addEntry('mod_disablebuttons', __dirname + '/Resources/public/module/disable-buttons/index.js'); encore.addEntry('mod_blur', __dirname + '/Resources/public/module/blur/index.js'); encore.addEntry('mod_input_address', __dirname + '/Resources/public/vuejs/Address/mod_input_address_index.js'); diff --git a/src/Bundle/ChillMainBundle/config/services/controller.yaml b/src/Bundle/ChillMainBundle/config/services/controller.yaml index 428147961..794923e65 100644 --- a/src/Bundle/ChillMainBundle/config/services/controller.yaml +++ b/src/Bundle/ChillMainBundle/config/services/controller.yaml @@ -30,8 +30,6 @@ services: tags: ['controller.service_arguments'] Chill\MainBundle\Controller\NotificationController: - arguments: - $security: '@Symfony\Component\Security\Core\Security' tags: ['controller.service_arguments'] Chill\MainBundle\Controller\RegroupmentController: diff --git a/src/Bundle/ChillMainBundle/config/services/form.yaml b/src/Bundle/ChillMainBundle/config/services/form.yaml index 226af2afe..f6b50cb57 100644 --- a/src/Bundle/ChillMainBundle/config/services/form.yaml +++ b/src/Bundle/ChillMainBundle/config/services/form.yaml @@ -93,17 +93,16 @@ services: Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer: ~ - chill.main.form.advanced_search_type: - class: Chill\MainBundle\Form\AdvancedSearchType - arguments: - - "@chill_main.search_provider" - tags: - - { name: form.type } + #chill.main.form.advanced_search_type: + # class: Chill\MainBundle\Form\AdvancedSearchType + # arguments: + # - "@chill_main.search_provider" + # tags: + # - { name: form.type } Chill\MainBundle\Form\UserPasswordType: arguments: $chillLogger: '@monolog.logger.chill' - $passwordEncoder: '@Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface' tags: - { name: form.type } @@ -134,6 +133,8 @@ services: Chill\MainBundle\Form\WorkflowStepType: ~ + Chill\MainBundle\Form\WorkflowSignatureMetadataType: ~ + Chill\MainBundle\Form\DataMapper\PrivateCommentDataMapper: autowire: true autoconfigure: true diff --git a/src/Bundle/ChillMainBundle/config/services/security.yaml b/src/Bundle/ChillMainBundle/config/services/security.yaml index 38089becf..6c3f1afc6 100644 --- a/src/Bundle/ChillMainBundle/config/services/security.yaml +++ b/src/Bundle/ChillMainBundle/config/services/security.yaml @@ -44,6 +44,8 @@ services: chill.main.role_provider: class: Chill\MainBundle\Security\RoleProvider + arguments: + $providers: !tagged_iterator chill_main.provide_role Chill\MainBundle\Security\RoleProvider: '@chill.main.role_provider' chill.main.user_provider: diff --git a/src/Bundle/ChillMainBundle/config/services/templating.yaml b/src/Bundle/ChillMainBundle/config/services/templating.yaml index 0baa91b69..281d4ad23 100644 --- a/src/Bundle/ChillMainBundle/config/services/templating.yaml +++ b/src/Bundle/ChillMainBundle/config/services/templating.yaml @@ -32,11 +32,16 @@ services: - { name: twig.extension } Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension: - arguments: - $renders: !tagged_iterator chill.render_entity tags: - { name: twig.extension } + Chill\MainBundle\Templating\Entity\ChillEntityRenderManager: + arguments: + $renders: !tagged_iterator chill.render_entity + + Chill\MainBundle\Templating\Entity\ChillEntityRenderManagerInterface: + alias: 'Chill\MainBundle\Templating\Entity\ChillEntityRenderManager' + Chill\MainBundle\Templating\Entity\CommentRender: tags: - { name: 'chill.render_entity' } diff --git a/src/Bundle/ChillMainBundle/migrations/Version20100000000000.php b/src/Bundle/ChillMainBundle/migrations/Version20100000000000.php index 5ae675b51..55f5a6420 100644 --- a/src/Bundle/ChillMainBundle/migrations/Version20100000000000.php +++ b/src/Bundle/ChillMainBundle/migrations/Version20100000000000.php @@ -16,9 +16,7 @@ use Doctrine\Migrations\AbstractMigration; class Version20100000000000 extends AbstractMigration { - public function down(Schema $schema): void - { - } + public function down(Schema $schema): void {} public function up(Schema $schema): void { diff --git a/src/Bundle/ChillMainBundle/migrations/Version20220513151853.php b/src/Bundle/ChillMainBundle/migrations/Version20220513151853.php index c46b40ee5..4bd9bd18f 100644 --- a/src/Bundle/ChillMainBundle/migrations/Version20220513151853.php +++ b/src/Bundle/ChillMainBundle/migrations/Version20220513151853.php @@ -16,9 +16,7 @@ use Doctrine\Migrations\AbstractMigration; final class Version20220513151853 extends AbstractMigration { - public function down(Schema $schema): void - { - } + public function down(Schema $schema): void {} public function getDescription(): string { diff --git a/src/Bundle/ChillMainBundle/migrations/Version20240628095159.php b/src/Bundle/ChillMainBundle/migrations/Version20240628095159.php new file mode 100644 index 000000000..4452530c6 --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20240628095159.php @@ -0,0 +1,51 @@ +addSql('CREATE SEQUENCE chill_main_workflow_entity_step_signature_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_main_workflow_entity_step_signature (id INT NOT NULL, step_id INT NOT NULL, '. + 'state VARCHAR(50) NOT NULL, stateDate TIMESTAMP(0) WITH TIME ZONE DEFAULT NULL, signatureMetadata JSON DEFAULT \'[]\' NOT NULL,'. + ' zoneSignatureIndex INT DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL,'. + ' userSigner_id INT DEFAULT NULL, personSigner_id INT DEFAULT NULL, createdBy_id INT DEFAULT NULL, updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_C47D4BA3D934E3A4 ON chill_main_workflow_entity_step_signature (userSigner_id)'); + $this->addSql('CREATE INDEX IDX_C47D4BA3ADFFA293 ON chill_main_workflow_entity_step_signature (personSigner_id)'); + $this->addSql('CREATE INDEX IDX_C47D4BA373B21E9C ON chill_main_workflow_entity_step_signature (step_id)'); + $this->addSql('CREATE INDEX IDX_C47D4BA33174800F ON chill_main_workflow_entity_step_signature (createdBy_id)'); + $this->addSql('CREATE INDEX IDX_C47D4BA365FF1AEC ON chill_main_workflow_entity_step_signature (updatedBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_main_workflow_entity_step_signature.stateDate IS \'(DC2Type:datetimetz_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_main_workflow_entity_step_signature.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_main_workflow_entity_step_signature.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_signature ADD CONSTRAINT FK_C47D4BA3D934E3A4 FOREIGN KEY (userSigner_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_signature ADD CONSTRAINT FK_C47D4BA3ADFFA293 FOREIGN KEY (personSigner_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_signature ADD CONSTRAINT FK_C47D4BA373B21E9C FOREIGN KEY (step_id) REFERENCES chill_main_workflow_entity_step (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_signature ADD CONSTRAINT FK_C47D4BA33174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_signature ADD CONSTRAINT FK_C47D4BA365FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_main_workflow_entity_step_signature_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_main_workflow_entity_step_signature'); + } +} diff --git a/src/Bundle/ChillMainBundle/migrations/Version20240807123801.php b/src/Bundle/ChillMainBundle/migrations/Version20240807123801.php new file mode 100644 index 000000000..1e95bd359 --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20240807123801.php @@ -0,0 +1,46 @@ +addSql('CREATE SEQUENCE chill_main_workflow_entity_step_hold_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_main_workflow_entity_step_hold (id INT NOT NULL, step_id INT NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, byUser_id INT NOT NULL, createdBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_1BE2E7C73B21E9C ON chill_main_workflow_entity_step_hold (step_id)'); + $this->addSql('CREATE INDEX IDX_1BE2E7CD23C0240 ON chill_main_workflow_entity_step_hold (byUser_id)'); + $this->addSql('CREATE INDEX IDX_1BE2E7C3174800F ON chill_main_workflow_entity_step_hold (createdBy_id)'); + $this->addSql('CREATE UNIQUE INDEX chill_main_workflow_hold_unique_idx ON chill_main_workflow_entity_step_hold (step_id, byUser_id)'); + $this->addSql('COMMENT ON COLUMN chill_main_workflow_entity_step_hold.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_hold ADD CONSTRAINT FK_1BE2E7C73B21E9C FOREIGN KEY (step_id) REFERENCES chill_main_workflow_entity_step (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_hold ADD CONSTRAINT FK_1BE2E7CD23C0240 FOREIGN KEY (byUser_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_hold ADD CONSTRAINT FK_1BE2E7C3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_main_workflow_entity_step_hold_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_hold DROP CONSTRAINT FK_1BE2E7C73B21E9C'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_hold DROP CONSTRAINT FK_1BE2E7CD23C0240'); + $this->addSql('ALTER TABLE chill_main_workflow_entity_step_hold DROP CONSTRAINT FK_1BE2E7C3174800F'); + $this->addSql('DROP TABLE chill_main_workflow_entity_step_hold'); + } +} diff --git a/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml index 96b2edd98..a0753f7a6 100644 --- a/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml +++ b/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml @@ -45,6 +45,9 @@ workflow: few {# workflows} other {# workflows} } + signature_zone: + has_signed_statement: 'A signé le {datetime, date, short} à {datetime, time, short}' + duration: minute: >- diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 421cac473..495b9a3bd 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -527,10 +527,33 @@ workflow: Access link copied: Lien d'accès copié This link grant any user to apply a transition: Le lien d'accès suivant permet d'appliquer une transition The workflow may be accssed through this link: Une transition peut être appliquée sur ce workflow grâce au lien d'accès suivant + Put on hold: Mettre en attente + Remove hold: Enlever la mise en attente + On hold: En attente + Automated transition: Transition automatique + waiting_for_signature: En attente de signature + Permissions: Workflows (suivi de décision) + + + signature_zone: + title: Signatures électroniques + button_sign: Signer + metadata: + sign_by: 'Signature pour %name%' + docType: Type de document + docNumber: Numéro de document + docExpiration: Date d'expiration + type of signature: Type de signature + person signatures: Selectionner usagers pour signer + user signature: Selectionner utilisateur pour signer + persons: Usagers + user: Utilisateur + already_signed_alert: La signature a déjà été appliquée Subscribe final: Recevoir une notification à l'étape finale Subscribe all steps: Recevoir une notification à chaque étape +CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION: Appliquer les transitions sur tous les workflows notification: Notification: Notification diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php index f65533958..64d2b8f12 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php @@ -22,9 +22,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class PersonAddressMoveEventSubscriber implements EventSubscriberInterface { - public function __construct(private readonly \Twig\Environment $engine, private readonly NotificationPersisterInterface $notificationPersister, private readonly Security $security, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly \Twig\Environment $engine, private readonly NotificationPersisterInterface $notificationPersister, private readonly Security $security, private readonly TranslatorInterface $translator) {} public static function getSubscribedEvents(): array { diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php index 297da8673..084fe8ff5 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php @@ -23,9 +23,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class UserRefEventSubscriber implements EventSubscriberInterface { - public function __construct(private readonly Security $security, private readonly TranslatorInterface $translator, private readonly \Twig\Environment $engine, private readonly NotificationPersisterInterface $notificationPersister) - { - } + public function __construct(private readonly Security $security, private readonly TranslatorInterface $translator, private readonly \Twig\Environment $engine, private readonly NotificationPersisterInterface $notificationPersister) {} public static function getSubscribedEvents() { diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeCronjob.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeCronjob.php index 73030f42c..27553444b 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeCronjob.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeCronjob.php @@ -20,8 +20,7 @@ readonly class AccompanyingPeriodStepChangeCronjob implements CronJobInterface public function __construct( private ClockInterface $clock, private AccompanyingPeriodStepChangeRequestor $requestor, - ) { - } + ) {} public function canRun(?CronJobExecution $cronJobExecution): bool { diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeMessageHandler.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeMessageHandler.php index 71d28c57f..534672efc 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeMessageHandler.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChangeMessageHandler.php @@ -23,8 +23,7 @@ class AccompanyingPeriodStepChangeMessageHandler implements MessageHandlerInterf public function __construct( private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly AccompanyingPeriodStepChanger $changer, - ) { - } + ) {} public function __invoke(AccompanyingPeriodStepChangeRequestMessage $message): void { diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChanger.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChanger.php index 7e9f87939..fe597a724 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChanger.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Lifecycle/AccompanyingPeriodStepChanger.php @@ -30,8 +30,7 @@ class AccompanyingPeriodStepChanger private readonly EntityManagerInterface $entityManager, private readonly LoggerInterface $logger, private readonly Registry $workflowRegistry, - ) { - } + ) {} public function __invoke(AccompanyingPeriod $period, string $transition, ?string $workflowName = null): void { diff --git a/src/Bundle/ChillPersonBundle/Actions/ActionEvent.php b/src/Bundle/ChillPersonBundle/Actions/ActionEvent.php index 88691e179..c8c1add72 100644 --- a/src/Bundle/ChillPersonBundle/Actions/ActionEvent.php +++ b/src/Bundle/ChillPersonBundle/Actions/ActionEvent.php @@ -52,8 +52,7 @@ class ActionEvent extends \Symfony\Contracts\EventDispatcher\Event * an array of key value data to describe the movement. */ protected $metadata = [], - ) { - } + ) {} /** * Add Sql which will be executed **after** the delete statement. diff --git a/src/Bundle/ChillPersonBundle/Actions/Remove/Handler/PersonMoveCenterHistoryHandler.php b/src/Bundle/ChillPersonBundle/Actions/Remove/Handler/PersonMoveCenterHistoryHandler.php index b2deb17ca..f08bd7dff 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Remove/Handler/PersonMoveCenterHistoryHandler.php +++ b/src/Bundle/ChillPersonBundle/Actions/Remove/Handler/PersonMoveCenterHistoryHandler.php @@ -19,8 +19,7 @@ class PersonMoveCenterHistoryHandler implements PersonMoveSqlHandlerInterface { public function __construct( private readonly PersonCenterHistoryRepository $centerHistoryRepository, - ) { - } + ) {} public function supports(string $className, string $field): bool { diff --git a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php index ce7ad467b..2ebae0457 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php +++ b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php @@ -33,8 +33,7 @@ class PersonMove private readonly EntityManagerInterface $em, private readonly PersonMoveManager $personMoveManager, private readonly EventDispatcherInterface $eventDispatcher, - ) { - } + ) {} /** * Return the sql used to move or delete entities associated to a person to diff --git a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMoveManager.php b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMoveManager.php index 230c2d4e2..0c9230d90 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMoveManager.php +++ b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMoveManager.php @@ -20,8 +20,7 @@ class PersonMoveManager * @var iterable */ private readonly iterable $handlers, - ) { - } + ) {} /** * @param class-string $className diff --git a/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php b/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php index 12df5a0f9..74f2d44fa 100644 --- a/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php +++ b/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php @@ -23,6 +23,17 @@ use Symfony\Component\HttpFoundation\Response; */ class EntityPersonCRUDController extends CRUDController { + public function __construct(protected readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} + + protected function generateTemplateParameter(string $action, mixed $entity, Request $request, array $defaultTemplateParameters = []) + { + $templateParameters = parent::generateTemplateParameter($action, $entity, $request, $defaultTemplateParameters); + + $templateParameters['person'] = $this->getPerson($request); + + return $templateParameters; + } + /** * Override the base method to add a filtering step to a person. * @@ -64,25 +75,6 @@ class EntityPersonCRUDController extends CRUDController return $qb; } - /** - * @throws \Exception - */ - protected function generateTemplateParameter(string $action, $entity, Request $request, array $defaultTemplateParameters = []): array - { - $person = $this->getPerson($request); - - if (null === $person) { - throw new \Exception('the `person_id` parameter is not set in the query. You should set it or override the current method to allow another behaviour: '.__METHOD__); - } - - return parent::generateTemplateParameter( - $action, - $entity, - $request, - \array_merge(['person' => $person], $defaultTemplateParameters) - ); - } - /** * Extract the person from the request. * @@ -102,7 +94,7 @@ class EntityPersonCRUDController extends CRUDController return null; } - $person = $this->getDoctrine() + $person = $this->managerRegistry ->getRepository(Person::class) ->find($request->query->getInt('person_id')); diff --git a/src/Bundle/ChillPersonBundle/CRUD/Controller/OneToOneEntityPersonCRUDController.php b/src/Bundle/ChillPersonBundle/CRUD/Controller/OneToOneEntityPersonCRUDController.php index a163e9bbd..55b788cc2 100644 --- a/src/Bundle/ChillPersonBundle/CRUD/Controller/OneToOneEntityPersonCRUDController.php +++ b/src/Bundle/ChillPersonBundle/CRUD/Controller/OneToOneEntityPersonCRUDController.php @@ -20,6 +20,8 @@ use Symfony\Component\HttpFoundation\Response; class OneToOneEntityPersonCRUDController extends CRUDController { + public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} + protected function generateRedirectOnCreateRoute($action, Request $request, $entity): string { throw new \BadMethodCallException('Not implemented yet.'); @@ -31,7 +33,7 @@ class OneToOneEntityPersonCRUDController extends CRUDController if (null === $entity) { $entity = $this->createEntity($action, $request); - $person = $this->getDoctrine() + $person = $this->managerRegistry ->getManager() ->getRepository(Person::class) ->find($id); @@ -58,7 +60,7 @@ class OneToOneEntityPersonCRUDController extends CRUDController protected function onPostFetchEntity($action, Request $request, $entity): ?Response { - if (false === $this->getDoctrine()->getManager()->contains($entity)) { + if (false === $this->managerRegistry->getManager()->contains($entity)) { return new RedirectResponse($this->generateRedirectOnCreateRoute($action, $request, $entity)); } @@ -67,6 +69,6 @@ class OneToOneEntityPersonCRUDController extends CRUDController protected function onPreFlush(string $action, $entity, FormInterface $form, Request $request) { - $this->getDoctrine()->getManager()->persist($entity); + $this->managerRegistry->getManager()->persist($entity); } } diff --git a/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php b/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php index 9e6608272..19d64c488 100644 --- a/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php +++ b/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php @@ -23,6 +23,8 @@ use Symfony\Component\Console\Output\OutputInterface; final class ChillPersonMoveCommand extends Command { + protected static $defaultDescription = 'Move all the associated entities on a "from" person to a "to" person and remove the old person'; + public function __construct( private readonly PersonMove $mover, private readonly EntityManagerInterface $em, @@ -53,7 +55,6 @@ final class ChillPersonMoveCommand extends Command { $this ->setName('chill:person:move') - ->setDescription('Move all the associated entities on a "from" person to a "to" person and remove the old person') ->addOption('from', 'f', InputOption::VALUE_REQUIRED, 'The person id to delete, all associated data will be moved before') ->addOption('to', 't', InputOption::VALUE_REQUIRED, 'The person id which will received data') ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'dump sql to stdout') @@ -99,7 +100,7 @@ final class ChillPersonMoveCommand extends Command $this->chillLogger->notice('Move a person from command line succeeded', $ctxt); } - return 0; + return Command::SUCCESS; } protected function interact(InputInterface $input, OutputInterface $output) diff --git a/src/Bundle/ChillPersonBundle/Command/ImportSocialWorkMetadata.php b/src/Bundle/ChillPersonBundle/Command/ImportSocialWorkMetadata.php index 53ea84deb..636330138 100644 --- a/src/Bundle/ChillPersonBundle/Command/ImportSocialWorkMetadata.php +++ b/src/Bundle/ChillPersonBundle/Command/ImportSocialWorkMetadata.php @@ -41,7 +41,6 @@ final class ImportSocialWorkMetadata extends Command ->setName('chill:person:import-socialwork') ->addOption('filepath', 'f', InputOption::VALUE_REQUIRED, 'The file to import.') ->addOption('language', 'l', InputOption::VALUE_OPTIONAL, 'The default language') - ->setDescription($description) ->setHelp($help); } diff --git a/src/Bundle/ChillPersonBundle/Command/RemoveOldDraftAccompanyingPeriodCommand.php b/src/Bundle/ChillPersonBundle/Command/RemoveOldDraftAccompanyingPeriodCommand.php index f826c4d17..43a74a5e1 100644 --- a/src/Bundle/ChillPersonBundle/Command/RemoveOldDraftAccompanyingPeriodCommand.php +++ b/src/Bundle/ChillPersonBundle/Command/RemoveOldDraftAccompanyingPeriodCommand.php @@ -20,6 +20,8 @@ use Symfony\Component\Console\Output\OutputInterface; class RemoveOldDraftAccompanyingPeriodCommand extends Command { + protected static $defaultDescription = 'Remove draft accompanying period which are still draft and unused'; + public function __construct(private readonly LoggerInterface $logger, private readonly OldDraftAccompanyingPeriodRemoverInterface $remover) { parent::__construct('chill:person:remove-old-draft-period'); @@ -28,7 +30,6 @@ class RemoveOldDraftAccompanyingPeriodCommand extends Command protected function configure(): void { $this - ->setDescription('Remove draft accompanying period which are still draft and unused') ->addArgument('interval', InputArgument::OPTIONAL, 'The interval for unactive periods', 'P15D'); } @@ -50,6 +51,6 @@ class RemoveOldDraftAccompanyingPeriodCommand extends Command $this->logger->info('['.$this->getName().'] end of command'); - return 0; + return Command::SUCCESS; } } diff --git a/src/Bundle/ChillPersonBundle/Config/ConfigPersonAltNamesHelper.php b/src/Bundle/ChillPersonBundle/Config/ConfigPersonAltNamesHelper.php index bbf21545b..4be480442 100644 --- a/src/Bundle/ChillPersonBundle/Config/ConfigPersonAltNamesHelper.php +++ b/src/Bundle/ChillPersonBundle/Config/ConfigPersonAltNamesHelper.php @@ -24,8 +24,7 @@ class ConfigPersonAltNamesHelper * the raw config, directly from the container parameter. */ private $config, - ) { - } + ) {} /** * get the choices as key => values. diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php index 8efe73d92..262a4a03d 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php @@ -46,9 +46,7 @@ use Symfony\Component\Workflow\Registry; final class AccompanyingCourseApiController extends ApiController { - public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly AccompanyingPeriodACLAwareRepository $accompanyingPeriodACLAwareRepository, private readonly EventDispatcherInterface $eventDispatcher, private readonly ReferralsSuggestionInterface $referralAvailable, private readonly Registry $registry, private readonly ValidatorInterface $validator) - { - } + public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly AccompanyingPeriodACLAwareRepository $accompanyingPeriodACLAwareRepository, private readonly EventDispatcherInterface $eventDispatcher, private readonly ReferralsSuggestionInterface $referralAvailable, private readonly Registry $registry, private readonly ValidatorInterface $validator, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} public function commentApi($id, Request $request, string $_format): Response { @@ -74,16 +72,14 @@ final class AccompanyingCourseApiController extends ApiController $workflow->apply($accompanyingPeriod, 'confirm'); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->json($accompanyingPeriod, Response::HTTP_OK, [], [ 'groups' => ['read'], ]); } - /** - * @Route("/api/1.0/person/accompanying-course/list/by-recent-attributions") - */ + #[Route(path: '/api/1.0/person/accompanying-course/list/by-recent-attributions')] public function findMyRecentCourseAttribution(Request $request): JsonResponse { $this->denyAccessUnlessGranted('ROLE_USER'); @@ -174,7 +170,7 @@ final class AccompanyingCourseApiController extends ApiController return $this->json($errors, 422); } - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->json($participation, 200, [], ['groups' => ['read']]); } @@ -222,7 +218,7 @@ final class AccompanyingCourseApiController extends ApiController return $this->json($errors, 422); } - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->json($accompanyingPeriod->getRequestor(), 200, [], ['groups' => ['read']]); } @@ -249,11 +245,7 @@ final class AccompanyingCourseApiController extends ApiController return $this->addRemoveSomething('socialissue', $id, $request, $_format, 'socialIssue', SocialIssue::class, ['groups' => ['read']]); } - /** - * @Route("/api/1.0/person/accompanying-course/{id}/referrers-suggested.{_format}", - * requirements={ "_format": "json"}, - * name="chill_api_person_accompanying_period_referrers_suggested") - */ + #[Route(path: '/api/1.0/person/accompanying-course/{id}/referrers-suggested.{_format}', requirements: ['_format' => 'json'], name: 'chill_api_person_accompanying_period_referrers_suggested')] public function suggestReferrals(AccompanyingPeriod $period, string $_format = 'json'): JsonResponse { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $period); @@ -280,10 +272,9 @@ final class AccompanyingCourseApiController extends ApiController } /** - * @Route("/api/1.0/person/accompanying-course/{id}/confidential.json", name="chill_api_person_accompanying_period_confidential") - * * @ParamConverter("accompanyingCourse", options={"id": "id"}) */ + #[Route(path: '/api/1.0/person/accompanying-course/{id}/confidential.json', name: 'chill_api_person_accompanying_period_confidential')] public function toggleConfidentialApi(AccompanyingPeriod $accompanyingCourse, mixed $id, Request $request) { if ('POST' === $request->getMethod()) { @@ -291,17 +282,16 @@ final class AccompanyingCourseApiController extends ApiController $accompanyingCourse->setConfidential(!$accompanyingCourse->isConfidential()); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); } return $this->json($accompanyingCourse->isConfidential(), Response::HTTP_OK, [], ['groups' => ['read']]); } /** - * @Route("/api/1.0/person/accompanying-course/{id}/intensity.json", name="chill_api_person_accompanying_period_intensity") - * * @ParamConverter("accompanyingCourse", options={"id": "id"}) */ + #[Route(path: '/api/1.0/person/accompanying-course/{id}/intensity.json', name: 'chill_api_person_accompanying_period_intensity')] public function toggleIntensityApi(AccompanyingPeriod $accompanyingCourse, Request $request) { if ('POST' === $request->getMethod()) { @@ -309,7 +299,7 @@ final class AccompanyingCourseApiController extends ApiController $status = 'regular' === $accompanyingCourse->getIntensity() ? 'occasional' : 'regular'; $accompanyingCourse->setIntensity($status); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); } return $this->json($accompanyingCourse->getIntensity(), Response::HTTP_OK, [], ['groups' => ['read']]); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php index 48e0e2cfa..f7622953d 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php @@ -16,6 +16,7 @@ use Chill\PersonBundle\Form\AccompanyingCourseCommentType; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\Persistence\ManagerRegistry; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\FormType; @@ -30,22 +31,24 @@ use Symfony\Contracts\Translation\TranslatorInterface; class AccompanyingCourseCommentController extends AbstractController { - public function __construct(private readonly EntityManagerInterface $entityManager, private readonly FormFactoryInterface $formFactory, private readonly TranslatorInterface $translator) - { - } + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly FormFactoryInterface $formFactory, + private readonly TranslatorInterface $translator, + private readonly ManagerRegistry $managerRegistry, + ) {} /** * Page of comments in Accompanying Course section. * - * @Route("/{_locale}/parcours/{accompanying_period_id}/comments", name="chill_person_accompanying_period_comment_list") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}/comments', name: 'chill_person_accompanying_period_comment_list')] public function commentAction(AccompanyingPeriod $accompanyingCourse, Request $request): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE_DETAILS, $accompanyingCourse); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $afterSuccessfulRedirectResponse = $this->redirectToRoute('chill_person_accompanying_period_comment_list', [ 'accompanying_period_id' => $accompanyingCourse->getId(), ]); @@ -114,12 +117,8 @@ class AccompanyingCourseCommentController extends AbstractController /** * Delete an existing comment. - * - * @Route( - * "/{_locale}/parcours/comment/{id}/delete", - * name="chill_person_accompanying_period_comment_delete" - * ) */ + #[Route(path: '/{_locale}/parcours/comment/{id}/delete', name: 'chill_person_accompanying_period_comment_delete')] public function deleteAction(AccompanyingPeriod\Comment $comment, Request $request): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodCommentVoter::DELETE, $comment); @@ -155,16 +154,14 @@ class AccompanyingCourseCommentController extends AbstractController ]); } - /** - * @Route("/{_locale}/parcours/comment/{id}/pin", name="chill_person_accompanying_period_comment_pin") - */ + #[Route(path: '/{_locale}/parcours/comment/{id}/pin', name: 'chill_person_accompanying_period_comment_pin')] public function pinComment(AccompanyingPeriod\Comment $comment): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $comment->getAccompanyingPeriod()); $comment->getAccompanyingPeriod()->setPinnedComment($comment); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans('accompanying_course.comment is pinned')); @@ -173,16 +170,14 @@ class AccompanyingCourseCommentController extends AbstractController ]); } - /** - * @Route("/{_locale}/parcours/comment/{id}/unpin", name="chill_person_accompanying_period_comment_unpin") - */ + #[Route(path: '/{_locale}/parcours/comment/{id}/unpin', name: 'chill_person_accompanying_period_comment_unpin')] public function unpinComment(AccompanyingPeriod\Comment $comment): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $comment->getAccompanyingPeriod()); $comment->getAccompanyingPeriod()->setPinnedComment(null); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans('accompanying_course.comment is unpinned')); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php index 6acca44e3..754be808a 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php @@ -12,40 +12,46 @@ declare(strict_types=1); namespace Chill\PersonBundle\Controller; use Chill\ActivityBundle\Entity\Activity; +use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Household\Household; -use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\AccompanyingCourseType; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; +use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; +use Chill\PersonBundle\Security\Authorization\PersonVoter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\Security\Core\Security; use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\Registry; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\Translation\TranslatorInterface; /** * Class AccompanyingCourseController. */ -class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController +final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController { - public function __construct(protected SerializerInterface $serializer, protected EventDispatcherInterface $dispatcher, protected ValidatorInterface $validator, private readonly AccompanyingPeriodWorkRepository $workRepository, private readonly Registry $registry, private readonly TranslatorInterface $translator) - { - } + public function __construct( + private readonly ValidatorInterface $validator, + private readonly AccompanyingPeriodWorkRepository $workRepository, + private readonly Registry $registry, + private readonly TranslatorInterface $translator, + private readonly Security $security, + private readonly PersonRepository $personRepository, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} /** - * @Route("/{_locale}/parcours/{accompanying_period_id}/close", name="chill_person_accompanying_course_close") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}/close', name: 'chill_person_accompanying_course_close')] public function closeAction(AccompanyingPeriod $accompanyingCourse, Request $request): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $accompanyingCourse); @@ -57,7 +63,7 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $workflow = $this->registry->get($accompanyingCourse); @@ -89,13 +95,12 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr /** * Delete page of Accompanying Course section. * - * @Route("/{_locale}/parcours/{accompanying_period_id}/delete", name="chill_person_accompanying_course_delete") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}/delete', name: 'chill_person_accompanying_course_delete')] public function deleteAction(Request $request, AccompanyingPeriod $accompanyingCourse) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $person_id = $request->query->get('person_id'); @@ -104,11 +109,10 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr 'accompanying_period_id' => $accompanyingCourse->getId(), 'person_id' => $person_id, ])) - ->setMethod('DELETE') ->add('submit', SubmitType::class, ['label' => 'Delete']) ->getForm(); - if (Request::METHOD_DELETE === $request->getMethod()) { + if (Request::METHOD_POST === $request->getMethod()) { $form->handleRequest($request); if ($form->isValid()) { @@ -146,10 +150,9 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr * * the page edit all blocks managed by vuejs component * - * @Route("/{_locale}/parcours/{accompanying_period_id}/edit", name="chill_person_accompanying_course_edit") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}/edit', name: 'chill_person_accompanying_course_edit')] public function editAction(AccompanyingPeriod $accompanyingCourse): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $accompanyingCourse); @@ -164,10 +167,9 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr * * the page show anti chronologic history with all actions, title of page is 'Accompanying Course History' * - * @Route("/{_locale}/parcours/{accompanying_period_id}/history", name="chill_person_accompanying_course_history") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}/history', name: 'chill_person_accompanying_course_history')] public function historyAction(AccompanyingPeriod $accompanyingCourse): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse); @@ -180,10 +182,9 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr /** * Homepage of Accompanying Course section. * - * @Route("/{_locale}/parcours/{accompanying_period_id}", name="chill_person_accompanying_course_index") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}', name: 'chill_person_accompanying_course_index')] public function indexAction(AccompanyingPeriod $accompanyingCourse): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse); @@ -198,7 +199,7 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr } } - $activities = $this->getDoctrine()->getManager()->getRepository(Activity::class)->findBy( + $activities = $this->managerRegistry->getManager()->getRepository(Activity::class)->findBy( ['accompanyingPeriod' => $accompanyingCourse], ['date' => 'DESC', 'id' => 'DESC'], ); @@ -220,31 +221,32 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr ]); } - /** - * @Route("/{_locale}/person/parcours/new", name="chill_person_accompanying_course_new") - */ + #[Route(path: '/{_locale}/person/parcours/new', name: 'chill_person_accompanying_course_new')] public function newAction(Request $request): Response { + $user = $this->security->getUser(); + + if (!$user instanceof User) { + throw new AccessDeniedHttpException(); + } + $period = new AccompanyingPeriod(); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); - if ($request->query->has('person_id')) { - $personIds = $request->query->get('person_id'); + $personIds = $request->query->all('person_id'); - if (false === \is_array($personIds)) { - throw new BadRequestHttpException('person_id parameter should be an array'); - } + foreach ($personIds as $personId) { + $person = $this->personRepository->find($personId); - foreach ($personIds as $personId) { - $person = $em->getRepository(Person::class)->find($personId); - - if (null !== $person) { - $period->addPerson($person); + if (null !== $person) { + if (!$this->isGranted(PersonVoter::SEE, $person)) { + throw new AccessDeniedHttpException(sprintf('person with id %d cannot be seen', $person->getId())); } + $period->addPerson($person); } } - $userLocation = $this->getUser()->getCurrentLocation(); + $userLocation = $user->getCurrentLocation(); $period->setAdministrativeLocation($userLocation); $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::CREATE, $period); @@ -257,13 +259,17 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr ]); } - /** - * @Route("/{_locale}/person/household/parcours/new", name="chill_household_accompanying_course_new") - */ + #[Route(path: '/{_locale}/person/household/parcours/new', name: 'chill_household_accompanying_course_new')] public function newHouseholdParcoursAction(Request $request): Response { + $user = $this->getUser(); + + if (!$user instanceof User || !$this->security->isGranted('ROLE_USER')) { + throw new AccessDeniedHttpException(); + } + $period = new AccompanyingPeriod(); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); if ($request->query->has('household_id')) { $householdId = $request->query->get('household_id'); @@ -278,8 +284,7 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr } } - $userLocation = $this->getUser()->getCurrentLocation(); - $period->setAdministrativeLocation($userLocation); + $period->setAdministrativeLocation($user->getCurrentLocation()); $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::CREATE, $period); @@ -292,10 +297,9 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr } /** - * @Route("/{_locale}/parcours/{accompanying_period_id}/open", name="chill_person_accompanying_course_reopen") - * * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ + #[Route(path: '/{_locale}/parcours/{accompanying_period_id}/open', name: 'chill_person_accompanying_course_reopen')] public function reOpenAction(AccompanyingPeriod $accompanyingCourse, Request $request): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse); @@ -309,7 +313,7 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr if ($form->isSubmitted() && $form->isValid()) { $accompanyingCourse->reOpen(); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->redirectToRoute('chill_person_accompanying_course_index', [ 'accompanying_period_id' => $accompanyingCourse->getId(), diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php index 47e46cb6b..98467a302 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php @@ -12,30 +12,38 @@ declare(strict_types=1); namespace Chill\PersonBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\MainBundle\Entity\User; use Chill\MainBundle\Serializer\Model\Collection; use Chill\MainBundle\Serializer\Model\Counter; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Security; class AccompanyingCourseWorkApiController extends ApiController { - public function __construct(private readonly AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository) - { - } + public function __construct( + private readonly AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository, + private readonly Security $security, + ) {} - /** - * @Route("/api/1.0/person/accompanying-period/work/my-near-end") - */ + #[Route(path: '/api/1.0/person/accompanying-period/work/my-near-end')] public function myWorksNearEndDate(Request $request): JsonResponse { + $user = $this->security->getUser(); + + if (!$user instanceof User) { + throw new AccessDeniedHttpException(); + } + $since = (new \DateTimeImmutable('now')) ->sub(new \DateInterval('P'.$request->query->getInt('since', 15).'D')); $until = (new \DateTimeImmutable('now')) ->add(new \DateInterval('P'.$request->query->getInt('since', 15).'D')); $total = $this->accompanyingPeriodWorkRepository - ->countNearEndDateByUser($this->getUser(), $since, $until); + ->countNearEndDateByUser($user, $since, $until); if ($request->query->getBoolean('countOnly', false)) { return $this->json( @@ -48,7 +56,7 @@ class AccompanyingCourseWorkApiController extends ApiController $paginator = $this->getPaginatorFactory()->create($total); $works = $this->accompanyingPeriodWorkRepository - ->findNearEndDateByUser($this->getUser(), $since, $until, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); + ->findNearEndDateByUser($user, $since, $until, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); $collection = new Collection($works, $paginator); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php index 59301419a..523d5a875 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php @@ -11,14 +11,12 @@ declare(strict_types=1); namespace Chill\PersonBundle\Controller; -use Chill\DocStoreBundle\Serializer\Normalizer\StoredObjectNormalizer; use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Templating\Listing\FilterOrderHelper; use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; -use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\SocialWork\SocialAction; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; @@ -42,16 +40,10 @@ final class AccompanyingCourseWorkController extends AbstractController private readonly LoggerInterface $chillLogger, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory, - ) { - } + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} - /** - * @Route( - * "{_locale}/person/accompanying-period/{id}/work/new", - * name="chill_person_accompanying_period_work_new", - * methods={"GET"} - * ) - */ + #[Route(path: '{_locale}/person/accompanying-period/{id}/work/new', name: 'chill_person_accompanying_period_work_new', methods: ['GET'])] public function createWork(AccompanyingPeriod $period): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::CREATE, $period); @@ -78,25 +70,19 @@ final class AccompanyingCourseWorkController extends AbstractController ]); } - /** - * @Route( - * "{_locale}/person/accompanying-period/work/{id}/delete", - * name="chill_person_accompanying_period_work_delete", - * methods={"GET", "POST", "DELETE"} - * ) - */ + #[Route(path: '{_locale}/person/accompanying-period/work/{id}/delete', name: 'chill_person_accompanying_period_work_delete', methods: ['GET', 'POST', 'DELETE'])] public function deleteWork(AccompanyingPeriodWork $work, Request $request): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $form = $this->createDeleteForm($work->getId()); - if (Request::METHOD_DELETE === $request->getMethod()) { + if (Request::METHOD_POST === $request->getMethod()) { $form->handleRequest($request); - if ($form->isValid()) { + if ($form->isSubmitted() && $form->isValid()) { $this->chillLogger->notice('An accompanying period work has been removed', [ 'by_user' => $this->getUser()->getUsername(), 'work_id' => $work->getId(), @@ -124,18 +110,12 @@ final class AccompanyingCourseWorkController extends AbstractController ]); } - /** - * @Route( - * "{_locale}/person/accompanying-period/work/{id}/edit", - * name="chill_person_accompanying_period_work_edit", - * methods={"GET"} - * ) - */ + #[Route(path: '{_locale}/person/accompanying-period/work/{id}/edit', name: 'chill_person_accompanying_period_work_edit', methods: ['GET'])] public function editWork(AccompanyingPeriodWork $work): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work); - $json = $this->serializer->normalize($work, 'json', ['groups' => ['read', StoredObjectNormalizer::ADD_DAV_EDIT_LINK_CONTEXT]]); + $json = $this->serializer->normalize($work, 'json', ['groups' => ['read']]); return $this->render('@ChillPerson/AccompanyingCourseWork/edit.html.twig', [ 'accompanyingCourse' => $work->getAccompanyingPeriod(), @@ -144,13 +124,7 @@ final class AccompanyingCourseWorkController extends AbstractController ]); } - /** - * @Route( - * "{_locale}/person/accompanying-period/{id}/work", - * name="chill_person_accompanying_period_work_list", - * methods={"GET"} - * ) - */ + #[Route(path: '{_locale}/person/accompanying-period/{id}/work', name: 'chill_person_accompanying_period_work_list', methods: ['GET'])] public function listWorkByAccompanyingPeriod(AccompanyingPeriod $period): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::SEE, $period); @@ -182,13 +156,7 @@ final class AccompanyingCourseWorkController extends AbstractController ]); } - /** - * @Route( - * "{_locale}/person/accompanying-period/work/{id}/show", - * name="chill_person_accompanying_period_work_show", - * methods={"GET"} - * ) - */ + #[Route(path: '{_locale}/person/accompanying-period/work/{id}/show', name: 'chill_person_accompanying_period_work_show', methods: ['GET'])] public function showWork(AccompanyingPeriodWork $work): Response { if (null === $work) { @@ -210,7 +178,6 @@ final class AccompanyingCourseWorkController extends AbstractController return $this->createFormBuilder() ->setAction($this->generateUrl('chill_person_accompanying_period_work_delete', $params)) - ->setMethod('DELETE') ->add('submit', SubmitType::class, ['label' => 'Delete']) ->getForm(); } diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkEvaluationDocumentController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkEvaluationDocumentController.php index 5855692f1..677040484 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkEvaluationDocumentController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkEvaluationDocumentController.php @@ -20,17 +20,9 @@ use Symfony\Component\Security\Core\Security; class AccompanyingCourseWorkEvaluationDocumentController extends AbstractController { - public function __construct(private readonly Security $security) - { - } + public function __construct(private readonly Security $security) {} - /** - * @Route( - * "{_locale}/person/accompanying-period/work/evaluation/document/{id}/show", - * name="chill_person_accompanying_period_work_evaluation_document_show", - * methods={"GET"} - * ) - */ + #[Route(path: '{_locale}/person/accompanying-period/work/evaluation/document/{id}/show', name: 'chill_person_accompanying_period_work_evaluation_document_show', methods: ['GET'])] public function showAccompanyingCourseWork(AccompanyingPeriodWorkEvaluationDocument $document): Response { $work = $document->getAccompanyingPeriodWorkEvaluation()->getAccompanyingPeriodWork(); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodCommentApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodCommentApiController.php new file mode 100644 index 000000000..a8ede3399 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodCommentApiController.php @@ -0,0 +1,16 @@ +_getPerson($person_id); @@ -87,7 +86,7 @@ class AccompanyingPeriodController extends AbstractController '%name%' => $person->__toString(), ])); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->redirectToRoute('chill_person_accompanying_period_list', [ 'person_id' => $person->getId(), @@ -123,9 +122,7 @@ class AccompanyingPeriodController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/accompanying-period/create", name="chill_person_accompanying_period_create") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/accompanying-period/create', name: 'chill_person_accompanying_period_create')] public function createAction(int $person_id, Request $request): Response { $person = $this->_getPerson($person_id); @@ -160,7 +157,7 @@ class AccompanyingPeriodController extends AbstractController $form->isValid(['Default', 'closed']) && 0 === \count($errors) ) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->persist($accompanyingPeriod); $em->flush(); $flashBag->add( @@ -190,10 +187,9 @@ class AccompanyingPeriodController extends AbstractController } /** - * @ParamConverter("person", options={"id": "person_id"}) - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/accompanying-period", name="chill_person_accompanying_period_list") + * @ParamConverter("person", options={"id"="person_id"}) */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/accompanying-period', name: 'chill_person_accompanying_period_list')] public function listAction(Person $person): Response { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $person); @@ -218,9 +214,7 @@ class AccompanyingPeriodController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/accompanying-period/open", name="chill_person_accompanying_period_open") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/accompanying-period/open', name: 'chill_person_accompanying_period_open')] public function openAction(int $person_id, Request $request): Response { $person = $this->_getPerson($person_id); @@ -272,7 +266,7 @@ class AccompanyingPeriodController extends AbstractController ['%name%' => $person->__toString()] )); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->redirectToRoute('chill_person_accompanying_period_list', [ 'person_id' => $person->getId(), @@ -303,9 +297,7 @@ class AccompanyingPeriodController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/accompanying-period/{period_id}/re-open", name="chill_person_accompanying_period_re_open") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/accompanying-period/{period_id}/re-open', name: 'chill_person_accompanying_period_re_open')] public function reOpenAction(int $person_id, int $period_id, Request $request): Response { /** @var Person $person */ @@ -328,7 +320,7 @@ class AccompanyingPeriodController extends AbstractController $this->_validatePerson($person); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans( 'The period has been re-opened' @@ -353,12 +345,11 @@ class AccompanyingPeriodController extends AbstractController /** * @throws Exception - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/accompanying-period/{period_id}/update", name="chill_person_accompanying_period_update") */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/accompanying-period/{period_id}/update', name: 'chill_person_accompanying_period_update')] public function updateAction(int $person_id, int $period_id, Request $request): Response { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); /** @var AccompanyingPeriod $accompanyingPeriod */ $accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($period_id); @@ -431,7 +422,7 @@ class AccompanyingPeriodController extends AbstractController */ private function _getPerson(int $id): Person { - $person = $this->getDoctrine()->getManager() + $person = $this->managerRegistry->getManager() ->getRepository(Person::class)->find($id); if (null === $person) { diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodRegulationListController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodRegulationListController.php index 0c81e21b9..a3ce3ef13 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodRegulationListController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodRegulationListController.php @@ -31,13 +31,9 @@ use Symfony\Component\Security\Core\Security; class AccompanyingPeriodRegulationListController { - public function __construct(private readonly AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository, private readonly \Twig\Environment $engine, private readonly FormFactoryInterface $formFactory, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository, private readonly \Twig\Environment $engine, private readonly FormFactoryInterface $formFactory, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} - /** - * @Route("/{_locale}/person/periods/undispatched", name="chill_person_course_list_regulation") - */ + #[Route(path: '/{_locale}/person/periods/undispatched', name: 'chill_person_course_list_regulation')] public function listRegul(Request $request): Response { if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) { diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodResourceApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodResourceApiController.php new file mode 100644 index 000000000..d1a4da5d0 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodResourceApiController.php @@ -0,0 +1,16 @@ + 'json'])] public function listTemplateByEvaluation(Evaluation $evaluation, string $_format): JsonResponse { if ('json' !== $_format) { @@ -66,9 +61,7 @@ class AccompanyingPeriodWorkEvaluationApiController ), JsonResponse::HTTP_OK, [], true); } - /** - * @Route("/api/1.0/person/accompanying-period/work/evaluation/my-near-end") - */ + #[Route(path: '/api/1.0/person/accompanying-period/work/evaluation/my-near-end')] public function myWorksNearEndDate(Request $request): JsonResponse { $total = $this->accompanyingPeriodWorkEvaluationRepository diff --git a/src/Bundle/ChillPersonBundle/Controller/AdminController.php b/src/Bundle/ChillPersonBundle/Controller/AdminController.php index 7f973d50a..970010e20 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AdminController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AdminController.php @@ -19,33 +19,25 @@ use Symfony\Component\Routing\Annotation\Route; */ class AdminController extends AbstractController { - /** - * @Route("/{_locale}/admin/accompanying-course", name="chill_accompanying-course_admin_index") - */ + #[Route(path: '/{_locale}/admin/accompanying-course', name: 'chill_accompanying-course_admin_index')] public function indexAccompanyingCourseAdminAction() { return $this->render('@ChillPerson/Admin/indexAccompanyingCourse.html.twig'); } - /** - * @Route("/{_locale}/admin/household", name="chill_household_admin_index") - */ + #[Route(path: '/{_locale}/admin/household', name: 'chill_household_admin_index')] public function indexHouseholdAdminAction() { return $this->render('@ChillPerson/Admin/indexHousehold.html.twig'); } - /** - * @Route("/{_locale}/admin/person", name="chill_person_admin_index") - */ + #[Route(path: '/{_locale}/admin/person', name: 'chill_person_admin_index')] public function indexPersonAdminAction() { return $this->render('@ChillPerson/Admin/indexPerson.html.twig'); } - /** - * @Route("/{_locale}/admin/social-work", name="chill_social-work_admin_index") - */ + #[Route(path: '/{_locale}/admin/social-work', name: 'chill_social-work_admin_index')] public function indexSocialWorkAdminAction() { return $this->render('@ChillPerson/Admin/indexSocialWork.html.twig'); @@ -53,9 +45,8 @@ class AdminController extends AbstractController /** * @return \Symfony\Component\HttpFoundation\RedirectResponse - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/person_redirect_to_main", name="chill_person_admin_redirect_to_admin_index", options={null}) */ + #[Route(path: '/{_locale}/admin/person_redirect_to_main', name: 'chill_person_admin_redirect_to_admin_index', options: [null])] public function redirectToAdminIndexAction() { return $this->redirectToRoute('chill_main_admin_central'); diff --git a/src/Bundle/ChillPersonBundle/Controller/ClosingMotiveController.php b/src/Bundle/ChillPersonBundle/Controller/ClosingMotiveController.php index 2943615f5..0cea8d1f2 100644 --- a/src/Bundle/ChillPersonBundle/Controller/ClosingMotiveController.php +++ b/src/Bundle/ChillPersonBundle/Controller/ClosingMotiveController.php @@ -21,6 +21,8 @@ use Symfony\Component\HttpFoundation\Request; */ class ClosingMotiveController extends CRUDController { + public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} + /** * @param string $action */ @@ -31,7 +33,7 @@ class ClosingMotiveController extends CRUDController if ($request->query->has('parent_id')) { $parentId = $request->query->getInt('parent_id'); - $parent = $this->getDoctrine()->getManager() + $parent = $this->managerRegistry->getManager() ->getRepository($this->getEntityClass()) ->find($parentId); diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php index cea622fab..05e73ad2a 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php @@ -31,16 +31,12 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class HouseholdApiController extends ApiController { - public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly HouseholdRepository $householdRepository, private readonly HouseholdACLAwareRepositoryInterface $householdACLAwareRepository) - { - } + public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly HouseholdRepository $householdRepository, private readonly HouseholdACLAwareRepositoryInterface $householdACLAwareRepository, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} /** - * @Route("/api/1.0/person/household/by-address-reference/{id}.json", - * name="chill_api_person_household_by_address_reference") - * * @return \Symfony\Component\HttpFoundation\JsonResponse */ + #[Route(path: '/api/1.0/person/household/by-address-reference/{id}.json', name: 'chill_api_person_household_by_address_reference')] public function getHouseholdByAddressReference(AddressReference $addressReference): Response { $this->denyAccessUnlessGranted('ROLE_USER'); @@ -61,10 +57,8 @@ class HouseholdApiController extends ApiController /** * Add an address to a household. - * - * @Route("/api/1.0/person/household/{id}/address.{_format}", name="chill_api_single_household_address", - * methods={"POST"}, requirements={"_format": "json"}) */ + #[Route(path: '/api/1.0/person/household/{id}/address.{_format}', name: 'chill_api_single_household_address', methods: ['POST'], requirements: ['_format' => 'json'])] public function householdAddressApi(Household $household, Request $request, string $_format): Response { $this->denyAccessUnlessGranted(HouseholdVoter::EDIT, $household); @@ -95,7 +89,7 @@ class HouseholdApiController extends ApiController return $this->json($errors, 422); } - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->json( $address, @@ -106,15 +100,9 @@ class HouseholdApiController extends ApiController } /** - * @Route("/api/1.0/person/address/suggest/by-household/{household_id}.{_format}", - * name="chill_person_address_suggest_by_household", - * requirements={ - * "_format": "json" - * } - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/api/1.0/person/address/suggest/by-household/{household_id}.{_format}', name: 'chill_person_address_suggest_by_household', requirements: ['_format' => 'json'])] public function suggestAddressByHousehold(Household $household, string $_format) { // TODO add acl diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php index 796ad979e..789adf471 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php @@ -44,12 +44,9 @@ class HouseholdCompositionController extends AbstractController private readonly TranslatorInterface $translator, private readonly \Twig\Environment $engine, private readonly UrlGeneratorInterface $urlGenerator, - ) { - } + ) {} - /** - * @Route("/{_locale}/person/household/{household_id}/composition/{composition_id}/delete", name="chill_person_household_composition_delete") - */ + #[Route(path: '/{_locale}/person/household/{household_id}/composition/{composition_id}/delete', name: 'chill_person_household_composition_delete')] public function deleteAction(Request $request, mixed $household_id, mixed $composition_id): Response { $composition = $this->householdCompositionRepository->find($composition_id); @@ -66,11 +63,10 @@ class HouseholdCompositionController extends AbstractController 'composition_id' => $composition_id, 'household_id' => $household_id, ])) - ->setMethod('DELETE') ->add('submit', SubmitType::class, ['label' => 'Delete']) ->getForm(); - if (Request::METHOD_DELETE === $request->getMethod()) { + if (Request::METHOD_POST === $request->getMethod()) { $form->handleRequest($request); if ($form->isValid()) { @@ -96,9 +92,7 @@ class HouseholdCompositionController extends AbstractController ); } - /** - * @Route("/{_locale}/person/household/{id}/composition/index", name="chill_person_household_composition_index") - */ + #[Route(path: '/{_locale}/person/household/{id}/composition/index', name: 'chill_person_household_composition_index')] public function index(Household $household, Request $request): Response { if (!$this->security->isGranted(HouseholdVoter::SEE, $household)) { @@ -123,9 +117,7 @@ class HouseholdCompositionController extends AbstractController )); } - /** - * @Route("/{_locale}/person/household/{id}/composition/new", name="chill_person_household_composition_new") - */ + #[Route(path: '/{_locale}/person/household/{id}/composition/new', name: 'chill_person_household_composition_new')] public function newAction(Household $household, Request $request): Response { if ($this->security->isGranted(HouseholdVoter::EDIT, $household)) { diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php index 0c488dba5..d63c5aea9 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php @@ -29,24 +29,15 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Contracts\Translation\TranslatorInterface; -/** - * @Route("/{_locale}/person/household") - */ +#[Route(path: '/{_locale}/person/household')] class HouseholdController extends AbstractController { - public function __construct(private readonly TranslatorInterface $translator, private readonly PositionRepository $positionRepository, private readonly SerializerInterface $serializer, private readonly Security $security) - { - } + public function __construct(private readonly TranslatorInterface $translator, private readonly PositionRepository $positionRepository, private readonly SerializerInterface $serializer, private readonly Security $security, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} /** - * @Route( - * "/{household_id}/accompanying-period", - * name="chill_person_household_accompanying_period", - * methods={"GET", "HEAD"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/accompanying-period', name: 'chill_person_household_accompanying_period', methods: ['GET', 'HEAD'])] public function accompanyingPeriod(Request $request, Household $household) { $currentMembers = $household->getCurrentPersons(); @@ -94,20 +85,15 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/address/edit", - * name="chill_person_household_address_edit", - * methods={"GET", "HEAD", "POST"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/address/edit', name: 'chill_person_household_address_edit', methods: ['GET', 'HEAD', 'POST'])] public function addressEdit(Request $request, Household $household) { // TODO ACL $address_id = $request->query->get('address_id'); - $address = $this->getDoctrine()->getManager() + $address = $this->managerRegistry->getManager() ->getRepository(Address::class) ->find($address_id); @@ -121,14 +107,9 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/addresses", - * name="chill_person_household_addresses", - * methods={"GET", "HEAD"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/addresses', name: 'chill_person_household_addresses', methods: ['GET', 'HEAD'])] public function addresses(Request $request, Household $household) { // TODO ACL @@ -152,14 +133,9 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/address/move", - * name="chill_person_household_address_move", - * methods={"GET", "HEAD", "POST"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/address/move', name: 'chill_person_household_address_move', methods: ['GET', 'HEAD', 'POST'])] public function addressMove(Request $request, Household $household) { // TODO ACL @@ -173,14 +149,9 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/address/edit_valid_from", - * name="chill_person_household_address_valid_from_edit", - * methods={"GET", "HEAD", "POST"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/address/edit_valid_from', name: 'chill_person_household_address_valid_from_edit', methods: ['GET', 'HEAD', 'POST'])] public function addressValidFromEdit(Request $request, Household $household) { $this->denyAccessUnlessGranted(HouseholdVoter::EDIT, $household); @@ -212,7 +183,7 @@ class HouseholdController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $household->makeAddressConsistent(); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); return $this->redirectToRoute('chill_person_household_addresses', [ 'household_id' => $household->getId(), @@ -230,14 +201,9 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/members/metadata/edit", - * name="chill_person_household_members_metadata_edit", - * methods={"GET", "POST"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/members/metadata/edit', name: 'chill_person_household_members_metadata_edit', methods: ['GET', 'POST'])] public function editHouseholdMetadata(Request $request, Household $household) { // TODO ACL @@ -246,7 +212,7 @@ class HouseholdController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator->trans('household.data_saved')); @@ -254,6 +220,12 @@ class HouseholdController extends AbstractController 'household_id' => $household->getId(), ]); } + if ($form->isSubmitted() && !$form->isValid()) { + $this->addFlash('error', $this->translator->trans('This form contains errors')); + foreach ($form->getErrors() as $error) { + $this->addFlash('error', $error->getMessage()); + } + } return $this->render('@ChillPerson/Household/edit_member_metadata.html.twig', [ 'household' => $household, @@ -262,14 +234,9 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/relationship", - * name="chill_person_household_relationship", - * methods={"GET", "HEAD"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/relationship', name: 'chill_person_household_relationship', methods: ['GET', 'HEAD'])] public function showRelationship(Request $request, Household $household) { $jsonString = $this->serializer->serialize( @@ -288,14 +255,9 @@ class HouseholdController extends AbstractController } /** - * @Route( - * "/{household_id}/summary", - * name="chill_person_household_summary", - * methods={"GET", "HEAD"} - * ) - * * @ParamConverter("household", options={"id": "household_id"}) */ + #[Route(path: '/{household_id}/summary', name: 'chill_person_household_summary', methods: ['GET', 'HEAD'])] public function summary(Request $request, Household $household) { // TODO ACL @@ -319,7 +281,7 @@ class HouseholdController extends AbstractController [ 'household' => $household, 'positions' => $positions, - 'form' => null !== $form ? $form->createView() : null, + 'form' => $form?->createView(), ] ); } diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php index c37cf63c0..07ab6da70 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php @@ -14,32 +14,40 @@ namespace Chill\PersonBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\PersonBundle\Entity\Household\Household; use Chill\PersonBundle\Entity\Household\HouseholdMember; -use Chill\PersonBundle\Entity\Household\Position; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\HouseholdMemberType; use Chill\PersonBundle\Household\MembersEditor; use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; +use Chill\PersonBundle\Repository\Household\HouseholdRepository; +use Chill\PersonBundle\Repository\Household\PositionRepository; +use Chill\PersonBundle\Repository\PersonRepository; +use Chill\PersonBundle\Security\Authorization\HouseholdVoter; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Exception; use Symfony\Contracts\Translation\TranslatorInterface; class HouseholdMemberController extends ApiController { - public function __construct(private readonly UrlGeneratorInterface $generator, private readonly TranslatorInterface $translator, private readonly AccompanyingPeriodRepository $periodRepository) - { - } + public function __construct( + private readonly UrlGeneratorInterface $generator, + private readonly TranslatorInterface $translator, + private readonly AccompanyingPeriodRepository $periodRepository, + private readonly PersonRepository $personRepository, + private readonly HouseholdRepository $householdRepository, + private readonly Security $security, + private readonly PositionRepository $positionRepository, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} - /** - * @Route( - * "/{_locale}/person/household/member/{id}/edit", - * name="chill_person_household_member_edit" - * ) - */ + #[Route(path: '/{_locale}/person/household/member/{id}/edit', name: 'chill_person_household_member_edit')] public function editMembership(Request $request, HouseholdMember $member): Response { // TODO ACL @@ -50,7 +58,7 @@ class HouseholdMemberController extends ApiController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator ->trans('household.successfully saved member')); @@ -77,51 +85,54 @@ class HouseholdMemberController extends ApiController * * household: the id of the destination household * * allow_leave_without_household: if present, the editor will allow * to leave household without joining another - * - * @Route( - * "/{_locale}/person/household/members/editor", - * name="chill_person_household_members_editor" - * ) */ + #[Route(path: '/{_locale}/person/household/members/editor', name: 'chill_person_household_members_editor')] public function editor(Request $request) { - $em = $this->getDoctrine()->getManager(); + $ids = $request->query->all('persons'); - if ($request->query->has('persons')) { - $ids = $request->query->get('persons', []); + if ([] !== $ids) { + $persons = []; - if (0 === \count($ids)) { - throw new BadRequestHttpException('parameters persons in query is not an array or empty'); - } + foreach ($ids as $id) { + if (!is_numeric($id)) { + throw new BadRequestHttpException(sprintf('persons with id %s is not numeric', $id)); + } - $persons = $em->getRepository(Person::class) - ->findById($ids); + $person = $this->personRepository->find((int) $id); + + if (null === $person) { + throw new NotFoundHttpException(sprintf('person with id %d not found', $id)); + } - foreach ($persons as $person) { $this->denyAccessUnlessGranted( PersonVoter::SEE, $person, "You are not allowed to see person with id {$person->getId()}" ); + + $persons[] = $person; } } if ($request->query->has('household')) { $householdId = $request->query->get('household', false); - $household = $em->getRepository(Household::class) + $household = $this->householdRepository ->find($householdId); $allowHouseholdCreate = false; $allowHouseholdSearch = false; $allowLeaveWithoutHousehold = false; if (null === $household) { - throw $this->createNotFoundException('household not found'); + throw new NotFoundHttpException('household not found'); + } + + if (!$this->security->isGranted(HouseholdVoter::EDIT, $household)) { + throw new AccessDeniedHttpException('not allowed to edit this household'); } - // TODO ACL on household } - $positions = $this->getDoctrine()->getManager() - ->getRepository(Position::class) + $positions = $this->positionRepository ->findAll(); $data = [ @@ -142,10 +153,8 @@ class HouseholdMemberController extends ApiController ); if (null === $period) { - throw $this->createNotFoundException('period not found'); + throw new NotFoundHttpException('accompanying period not found'); } - - // TODO add acl on accompanying Course } return $this->render('@ChillPerson/Household/members_editor.html.twig', [ @@ -155,12 +164,7 @@ class HouseholdMemberController extends ApiController ]); } - /** - * @Route( - * "/api/1.0/person/household/members/move.{_format}", - * name="chill_api_person_household_members_move" - * ) - */ + #[Route(path: '/api/1.0/person/household/members/move.{_format}', name: 'chill_api_person_household_members_move')] public function move(Request $request, mixed $_format): Response { try { @@ -187,7 +191,7 @@ class HouseholdMemberController extends ApiController // launch events on post move $editor->postMove(); - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); // if new household, persist it if ( diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php b/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php index c6ffd1fec..13b1fc7ca 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php @@ -29,16 +29,12 @@ class PersonAddressController extends AbstractController /** * PersonAddressController constructor. */ - public function __construct(private readonly ValidatorInterface $validator, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly ValidatorInterface $validator, private readonly TranslatorInterface $translator, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/address/create", name="chill_person_address_create", methods={"POST"}) - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/address/create', name: 'chill_person_address_create', methods: ['POST'])] public function createAction(mixed $person_id, Request $request) { - $person = $this->getDoctrine()->getManager() + $person = $this->managerRegistry->getManager() ->getRepository(Person::class) ->find($person_id); @@ -67,7 +63,7 @@ class PersonAddressController extends AbstractController $this->addFlash('error', $error->getMessage()); } } elseif ($form->isValid()) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->flush(); $this->addFlash( @@ -90,12 +86,10 @@ class PersonAddressController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/address/{address_id}/edit", name="chill_person_address_edit") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/address/{address_id}/edit', name: 'chill_person_address_edit')] public function editAction(mixed $person_id, mixed $address_id) { - $person = $this->getDoctrine()->getManager() + $person = $this->managerRegistry->getManager() ->getRepository(Person::class) ->find($person_id); @@ -120,12 +114,10 @@ class PersonAddressController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/address/list", name="chill_person_address_list") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/address/list', name: 'chill_person_address_list')] public function listAction(mixed $person_id) { - $person = $this->getDoctrine()->getManager() + $person = $this->managerRegistry->getManager() ->getRepository(Person::class) ->find($person_id); @@ -144,12 +136,10 @@ class PersonAddressController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/address/new", name="chill_person_address_new") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/address/new', name: 'chill_person_address_new')] public function newAction(mixed $person_id) { - $person = $this->getDoctrine()->getManager() + $person = $this->managerRegistry->getManager() ->getRepository(Person::class) ->find($person_id); @@ -173,12 +163,10 @@ class PersonAddressController extends AbstractController ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/address/{address_id}/update", name="chill_person_address_update") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/address/{address_id}/update', name: 'chill_person_address_update')] public function updateAction(mixed $person_id, mixed $address_id, Request $request) { - $person = $this->getDoctrine()->getManager() + $person = $this->managerRegistry->getManager() ->getRepository(Person::class) ->find($person_id); @@ -205,7 +193,7 @@ class PersonAddressController extends AbstractController $this->addFlash('error', $error->getMessage()); } } elseif ($form->isValid()) { - $this->getDoctrine()->getManager() + $this->managerRegistry->getManager() ->flush(); $this->addFlash('success', $this->translator->trans( @@ -278,7 +266,7 @@ class PersonAddressController extends AbstractController */ protected function findAddressById(Person $person, $address_id) { - $address = $this->getDoctrine()->getManager() + $address = $this->managerRegistry->getManager() ->getRepository(Address::class) ->find($address_id); diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php b/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php index 23ec47309..ffe3295d9 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php @@ -36,11 +36,7 @@ class PersonApiController extends ApiController $this->showCenters = $parameterBag->get('chill_main')['acl']['form_show_centers']; } - /** - * @Route("/api/1.0/person/creation/authorized-centers", - * name="chill_person_person_creation_authorized_centers" - * ) - */ + #[Route(path: '/api/1.0/person/creation/authorized-centers', name: 'chill_person_person_creation_authorized_centers')] public function authorizedCentersForCreation(): Response { $centers = $this->authorizedCenterOnPersonCreation->getCenters(); @@ -53,14 +49,7 @@ class PersonApiController extends ApiController ); } - /** - * @Route("/api/1.0/person/config/alt_names.{_format}", - * name="chill_person_config_alt_names", - * requirements={ - * "_format": "json" - * } - * ) - */ + #[Route(path: '/api/1.0/person/config/alt_names.{_format}', name: 'chill_person_config_alt_names', requirements: ['_format' => 'json'])] public function configAltNames(Request $request, string $_format): Response { $configAltNamesChoices = $this->configPersonAltNameHelper->getChoices(); @@ -83,15 +72,9 @@ class PersonApiController extends ApiController } /** - * @Route("/api/1.0/person/address/suggest/by-person/{person_id}.{_format}", - * name="chill_person_address_suggest_by_person", - * requirements={ - * "_format": "json" - * } - * ) - * * @ParamConverter("person", options={"id": "person_id"}) */ + #[Route(path: '/api/1.0/person/address/suggest/by-person/{person_id}.{_format}', name: 'chill_person_address_suggest_by_person', requirements: ['_format' => 'json'])] public function suggestAddress(Person $person, Request $request, string $_format): Response { $this->denyAccessUnlessGranted(PersonVoter::SEE, $person); diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonController.php b/src/Bundle/ChillPersonBundle/Controller/PersonController.php index 99c3899e6..9f35e1b5c 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonController.php @@ -47,12 +47,9 @@ final class PersonController extends AbstractController private readonly ConfigPersonAltNamesHelper $configPersonAltNameHelper, private readonly ValidatorInterface $validator, private readonly EntityManagerInterface $em, - ) { - } + ) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/general/edit", name="chill_person_general_edit") - */ + #[Route(path: '/{_locale}/person/{person_id}/general/edit', name: 'chill_person_general_edit')] public function editAction(int $person_id, Request $request) { $person = $this->_getPerson($person_id); @@ -117,14 +114,9 @@ final class PersonController extends AbstractController } /** - * @Route( - * "/{_locale}/person/household/{person_id}/history", - * name="chill_person_household_person_history", - * methods={"GET", "POST"} - * ) - * * @ParamConverter("person", options={"id": "person_id"}) */ + #[Route(path: '/{_locale}/person/household/{person_id}/history', name: 'chill_person_household_person_history', methods: ['GET', 'POST'])] public function householdHistoryByPerson(Request $request, Person $person): Response { $this->denyAccessUnlessGranted( @@ -147,14 +139,13 @@ final class PersonController extends AbstractController /** * Method for creating a new person. * - *The controller register data from a previous post on the form, and + * The controller register data from a previous post on the form, and * register it in the session. * * The next post compare the data with previous one and, if yes, show a * review page if there are "alternate persons". - * - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/new", name="chill_person_new") */ + #[Route(path: '/{_locale}/person/new', name: 'chill_person_new')] public function newAction(Request $request): Response { $person = new Person(); @@ -249,9 +240,7 @@ final class PersonController extends AbstractController ); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/general", name="chill_person_view") - */ + #[Route(path: '/{_locale}/person/{person_id}/general', name: 'chill_person_view')] public function viewAction(int $person_id) { $person = $this->_getPerson($person_id); diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php b/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php index 31965a498..b11390a46 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php @@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Controller; use Chill\ActivityBundle\Entity\Activity; use Chill\DocStoreBundle\Entity\PersonDocument; use Chill\EventBundle\Entity\Participation; +use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Actions\Remove\PersonMove; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\PersonNotDuplicate; @@ -24,25 +25,28 @@ use Chill\PersonBundle\Repository\PersonNotDuplicateRepository; use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Search\SimilarPersonMatcher; use Chill\TaskBundle\Entity\SingleTask; -use http\Exception\InvalidArgumentException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\Security\Core\Security; use function count; class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController { - public function __construct(private readonly SimilarPersonMatcher $similarPersonMatcher, private readonly TranslatorInterface $translator, private readonly PersonRepository $personRepository, private readonly PersonMove $personMove, private readonly EventDispatcherInterface $eventDispatcher) - { - } + public function __construct( + private readonly SimilarPersonMatcher $similarPersonMatcher, + private readonly PersonRepository $personRepository, + private readonly PersonMove $personMove, + private readonly EventDispatcherInterface $eventDispatcher, + private readonly Security $security, + private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + ) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person1_id}/duplicate/{person2_id}/confirm", name="chill_person_duplicate_confirm") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person1_id}/duplicate/{person2_id}/confirm', name: 'chill_person_duplicate_confirm')] public function confirmAction(mixed $person1_id, mixed $person2_id, Request $request) { if ($person1_id === $person2_id) { - throw new InvalidArgumentException('Can not merge same person'); + throw new \InvalidArgumentException('Can not merge same person'); } $person1 = $this->_getPerson($person1_id); @@ -79,7 +83,7 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll $sqls = $this->personMove->getSQL($person2, $person1); - $connection = $this->getDoctrine()->getConnection(); + $connection = $this->managerRegistry->getConnection(); $connection->beginTransaction(); @@ -98,9 +102,7 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/find-manually", name="chill_person_find_manually_duplicate") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/find-manually', name: 'chill_person_find_manually_duplicate')] public function findManuallyDuplicateAction(mixed $person_id, Request $request) { $person = $this->_getPerson($person_id); @@ -149,11 +151,15 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll ]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person1_id}/duplicate/{person2_id}/not-duplicate", name="chill_person_duplicate_not_duplicate") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person1_id}/duplicate/{person2_id}/not-duplicate', name: 'chill_person_duplicate_not_duplicate')] public function notDuplicateAction(mixed $person1_id, mixed $person2_id) { + $user = $this->security->getUser(); + + if (!$user instanceof User) { + throw new AccessDeniedHttpException(); + } + [$person1, $person2] = $this->_getPersonsByPriority($person1_id, $person2_id); $this->denyAccessUnlessGranted( @@ -162,25 +168,23 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll 'You are not allowed to see this person.' ); - $personNotDuplicate = $this->getDoctrine()->getRepository(PersonNotDuplicate::class) + $personNotDuplicate = $this->managerRegistry->getRepository(PersonNotDuplicate::class) ->findOneBy(['person1' => $person1, 'person2' => $person2]); if (!$personNotDuplicate instanceof PersonNotDuplicate) { $personNotDuplicate = new PersonNotDuplicate(); $personNotDuplicate->setPerson1($person1); $personNotDuplicate->setPerson2($person2); - $personNotDuplicate->setUser($this->getUser()); + $personNotDuplicate->setUser($user); - $this->getDoctrine()->getManager()->persist($personNotDuplicate); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->persist($personNotDuplicate); + $this->managerRegistry->getManager()->flush(); } return $this->redirectToRoute('chill_person_duplicate_view', ['person_id' => $person1->getId()]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person1_id}/duplicate/{person2_id}/remove-not-duplicate", name="chill_person_remove_duplicate_not_duplicate") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person1_id}/duplicate/{person2_id}/remove-not-duplicate', name: 'chill_person_remove_duplicate_not_duplicate')] public function removeNotDuplicateAction(mixed $person1_id, mixed $person2_id) { [$person1, $person2] = $this->_getPersonsByPriority($person1_id, $person2_id); @@ -191,20 +195,18 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll 'You are not allowed to see this person.' ); - $personNotDuplicate = $this->getDoctrine()->getRepository(PersonNotDuplicate::class) + $personNotDuplicate = $this->managerRegistry->getRepository(PersonNotDuplicate::class) ->findOneBy(['person1' => $person1, 'person2' => $person2]); if ($personNotDuplicate instanceof PersonNotDuplicate) { - $this->getDoctrine()->getManager()->remove($personNotDuplicate); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->remove($personNotDuplicate); + $this->managerRegistry->getManager()->flush(); } return $this->redirectToRoute('chill_person_duplicate_view', ['person_id' => $person1->getId()]); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/duplicate/view", name="chill_person_duplicate_view") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/duplicate/view', name: 'chill_person_duplicate_view')] public function viewAction(mixed $person_id, PersonNotDuplicateRepository $personNotDuplicateRepository) { $person = $this->_getPerson($person_id); @@ -233,7 +235,7 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll private function _getCounters($id): ?array { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $nb_activity = $em->getRepository(Activity::class)->findBy(['person' => $id]); $nb_document = $em->getRepository(PersonDocument::class)->findBy(['person' => $id]); @@ -261,7 +263,7 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll private function _getPersonsByPriority($person1_id, $person2_id) { if ($person1_id === $person2_id) { - throw new InvalidArgumentException('Can not merge same person'); + throw new \InvalidArgumentException('Can not merge same person'); } if ($person1_id > $person2_id) { diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php b/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php index 7a112371d..8332d468e 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php @@ -25,13 +25,9 @@ use Symfony\Contracts\Translation\TranslatorInterface; final class PersonResourceController extends AbstractController { - public function __construct(private readonly PersonResourceRepository $personResourceRepository, private readonly PersonRepository $personRepository, private readonly EntityManagerInterface $em, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly PersonResourceRepository $personResourceRepository, private readonly PersonRepository $personRepository, private readonly EntityManagerInterface $em, private readonly TranslatorInterface $translator) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/resources/{resource_id}/delete", name="chill_person_resource_delete") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/resources/{resource_id}/delete', name: 'chill_person_resource_delete')] public function deleteAction(Request $request, mixed $person_id, mixed $resource_id): Response { $personOwner = $this->personRepository->find($person_id); @@ -48,14 +44,13 @@ final class PersonResourceController extends AbstractController 'resource_id' => $resource_id, 'person_id' => $person_id, ])) - ->setMethod('DELETE') ->add('submit', SubmitType::class, ['label' => 'Delete']) ->getForm(); - if (Request::METHOD_DELETE === $request->getMethod()) { + if (Request::METHOD_POST === $request->getMethod()) { $form->handleRequest($request); - if ($form->isValid()) { + if ($form->isSubmitted() && $form->isValid()) { $this->em->remove($resource); $this->em->flush(); @@ -78,9 +73,7 @@ final class PersonResourceController extends AbstractController ); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/resources/{resource_id}/edit", name="chill_person_resource_edit") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/resources/{resource_id}/edit', name: 'chill_person_resource_edit')] public function editAction(Request $request, mixed $resource_id, mixed $person_id): Response { $resource = $this->personResourceRepository->find($resource_id); @@ -115,9 +108,7 @@ final class PersonResourceController extends AbstractController ); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/resources/list", name="chill_person_resource_list") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/resources/list', name: 'chill_person_resource_list')] public function listAction(Request $request, mixed $person_id) { $personOwner = $this->personRepository->find($person_id); @@ -135,9 +126,7 @@ final class PersonResourceController extends AbstractController ); } - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/resources/new", name="chill_person_resource_new") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/resources/new', name: 'chill_person_resource_new')] public function newAction(Request $request, mixed $person_id) { $personOwner = $this->personRepository->find($person_id); diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonSignatureController.php b/src/Bundle/ChillPersonBundle/Controller/PersonSignatureController.php new file mode 100644 index 000000000..aa9407c11 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/PersonSignatureController.php @@ -0,0 +1,60 @@ +denyAccessUnlessGranted(PersonVoter::SEE, $person); + + $signatures = $this->signatureRepository->findByPersonAndPendingState($person); + $signatureData = []; + + foreach ($signatures as $signature) { + $entityWorkflow = $signature->getStep()->getEntityWorkflow(); + $handler = $this->entityWorkflowManager->getHandler($entityWorkflow); + + $workflow = [ + 'handler_template' => $handler->getTemplate($entityWorkflow), + 'handler_template_data' => $handler->getTemplateData($entityWorkflow), + 'entity_workflow' => $entityWorkflow, + ]; + + $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow); + $signatureData[] = [ + 'signature' => $signature, + 'document' => $storedObject, + 'workflow' => $workflow, + ]; + } + + return $this->render('@ChillPerson/Person/signature_list.html.twig', [ + 'signatures' => $signatureData, + 'person' => $person, + ]); + } +} diff --git a/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php index f8e305552..6e3fa5117 100644 --- a/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php @@ -39,13 +39,9 @@ use Symfony\Component\Validator\Constraints\NotNull; class ReassignAccompanyingPeriodController extends AbstractController { - public function __construct(private readonly AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository, private readonly UserRepository $userRepository, private readonly AccompanyingPeriodRepository $courseRepository, private readonly \Twig\Environment $engine, private readonly FormFactoryInterface $formFactory, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly UserRender $userRender, private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository, private readonly UserRepository $userRepository, private readonly AccompanyingPeriodRepository $courseRepository, private readonly \Twig\Environment $engine, private readonly FormFactoryInterface $formFactory, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly UserRender $userRender, private readonly EntityManagerInterface $em) {} - /** - * @Route("/{_locale}/person/accompanying-periods/reassign", name="chill_course_list_reassign") - */ + #[Route(path: '/{_locale}/person/accompanying-periods/reassign', name: 'chill_course_list_reassign')] public function listAction(Request $request): Response { if (!$this->security->isGranted(AccompanyingPeriodVoter::REASSIGN_BULK)) { diff --git a/src/Bundle/ChillPersonBundle/Controller/RelationApiController.php b/src/Bundle/ChillPersonBundle/Controller/RelationApiController.php new file mode 100644 index 000000000..31eabb54a --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/RelationApiController.php @@ -0,0 +1,16 @@ +denyAccessUnlessGranted(PersonVoter::UPDATE, $residentialAddress->getPerson()); @@ -43,7 +39,7 @@ final class ResidentialAddressController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $this->getDoctrine()->getManager(); + $em = $this->managerRegistry->getManager(); $em->remove($residentialAddress); $em->flush(); @@ -59,9 +55,7 @@ final class ResidentialAddressController extends AbstractController ]); } - /** - * @Route("/{_locale}/person/residential-address/{id}/edit", name="chill_person_residential_address_edit") - */ + #[Route(path: '/{_locale}/person/residential-address/{id}/edit', name: 'chill_person_residential_address_edit')] public function editAction(Request $request, ResidentialAddress $residentialAddress): Response { if ($request->query->has('kind')) { @@ -77,7 +71,7 @@ final class ResidentialAddressController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator ->trans('The residential address was updated successfully')); @@ -95,9 +89,7 @@ final class ResidentialAddressController extends AbstractController ]); } - /** - * @Route("/{_locale}/person/{id}/residential-address/list", name="chill_person_residential_address_list") - */ + #[Route(path: '/{_locale}/person/{id}/residential-address/list', name: 'chill_person_residential_address_list')] public function listAction(Request $request, Person $person): Response { $this->denyAccessUnlessGranted(PersonVoter::SEE, $person); @@ -110,9 +102,7 @@ final class ResidentialAddressController extends AbstractController ]); } - /** - * @Route("/{_locale}/person/{id}/residential-address/new", name="chill_person_residential_address_new") - */ + #[Route(path: '/{_locale}/person/{id}/residential-address/new', name: 'chill_person_residential_address_new')] public function newAction(Request $request, Person $person): Response { $residentialAddress = new ResidentialAddress(); @@ -129,8 +119,8 @@ final class ResidentialAddressController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $this->getDoctrine()->getManager()->persist($residentialAddress); - $this->getDoctrine()->getManager()->flush(); + $this->managerRegistry->getManager()->persist($residentialAddress); + $this->managerRegistry->getManager()->flush(); $this->addFlash('success', $this->translator ->trans('The new residential address was created successfully')); diff --git a/src/Bundle/ChillPersonBundle/Controller/SocialWorkEvaluationApiController.php b/src/Bundle/ChillPersonBundle/Controller/SocialWorkEvaluationApiController.php index b6b7baf00..27a7acbf5 100644 --- a/src/Bundle/ChillPersonBundle/Controller/SocialWorkEvaluationApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/SocialWorkEvaluationApiController.php @@ -22,20 +22,12 @@ use Symfony\Component\Routing\Annotation\Route; class SocialWorkEvaluationApiController extends AbstractController { - public function __construct(private readonly PaginatorFactory $paginatorFactory) - { - } + public function __construct(private readonly PaginatorFactory $paginatorFactory) {} /** - * @Route("/api/1.0/person/social-work/evaluation/by-social-action/{action_id}.json", - * name="chill_person_evaluation_index_by_social_action", - * requirements={ - * "_format": "json" - * } - * ) - * * @ParamConverter("action", options={"id": "action_id"}) */ + #[Route(path: '/api/1.0/person/social-work/evaluation/by-social-action/{action_id}.json', name: 'chill_person_evaluation_index_by_social_action', requirements: ['_format' => 'json'])] public function listEvaluationBySocialAction(SocialAction $action): Response { $evaluations = $action->getEvaluations()->filter(static fn (Evaluation $eval) => $eval->isActive()); diff --git a/src/Bundle/ChillPersonBundle/Controller/SocialWorkGoalApiController.php b/src/Bundle/ChillPersonBundle/Controller/SocialWorkGoalApiController.php index cbbd9a748..2a7f39712 100644 --- a/src/Bundle/ChillPersonBundle/Controller/SocialWorkGoalApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/SocialWorkGoalApiController.php @@ -21,9 +21,7 @@ use Symfony\Component\HttpFoundation\Response; class SocialWorkGoalApiController extends ApiController { - public function __construct(private readonly GoalRepository $goalRepository, private readonly PaginatorFactory $paginator) - { - } + public function __construct(private readonly GoalRepository $goalRepository, private readonly PaginatorFactory $paginator) {} public function listBySocialAction(Request $request, SocialAction $action): Response { diff --git a/src/Bundle/ChillPersonBundle/Controller/SocialWorkResultApiController.php b/src/Bundle/ChillPersonBundle/Controller/SocialWorkResultApiController.php index aaedfd330..9b97d8129 100644 --- a/src/Bundle/ChillPersonBundle/Controller/SocialWorkResultApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/SocialWorkResultApiController.php @@ -21,9 +21,7 @@ use Symfony\Component\HttpFoundation\Response; class SocialWorkResultApiController extends ApiController { - public function __construct(private readonly ResultRepository $resultRepository) - { - } + public function __construct(private readonly ResultRepository $resultRepository) {} public function listByGoal(Request $request, Goal $goal): Response { diff --git a/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php b/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php index 5ecc41a4c..6b341e926 100644 --- a/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php @@ -26,8 +26,7 @@ final class SocialWorkSocialActionApiController extends ApiController private readonly SocialIssueRepository $socialIssueRepository, private readonly PaginatorFactory $paginator, private readonly ClockInterface $clock, - ) { - } + ) {} public function listBySocialIssueApi($id, Request $request) { diff --git a/src/Bundle/ChillPersonBundle/Controller/TimelinePersonController.php b/src/Bundle/ChillPersonBundle/Controller/TimelinePersonController.php index c271f22f4..0cd86eb5b 100644 --- a/src/Bundle/ChillPersonBundle/Controller/TimelinePersonController.php +++ b/src/Bundle/ChillPersonBundle/Controller/TimelinePersonController.php @@ -22,16 +22,12 @@ use Symfony\Component\HttpFoundation\Request; class TimelinePersonController extends AbstractController { - public function __construct(protected EventDispatcherInterface $eventDispatcher, protected TimelineBuilder $timelineBuilder, protected PaginatorFactory $paginatorFactory) - { - } + public function __construct(protected EventDispatcherInterface $eventDispatcher, protected TimelineBuilder $timelineBuilder, protected PaginatorFactory $paginatorFactory, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} - /** - * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/person/{person_id}/timeline", name="chill_person_timeline") - */ + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/person/{person_id}/timeline', name: 'chill_person_timeline')] public function personAction(Request $request, mixed $person_id) { - $person = $this->getDoctrine() + $person = $this->managerRegistry ->getRepository(Person::class) ->find($person_id); diff --git a/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php index 1667ea902..3a2b1be6e 100644 --- a/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php @@ -21,13 +21,9 @@ use Symfony\Component\Routing\Annotation\Route; class UserAccompanyingPeriodController extends AbstractController { - public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly PaginatorFactory $paginatorFactory) - { - } + public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly PaginatorFactory $paginatorFactory) {} - /** - * @Route("/{_locale}/person/accompanying-periods/my", name="chill_person_accompanying_period_user") - */ + #[Route(path: '/{_locale}/person/accompanying-periods/my', name: 'chill_person_accompanying_period_user')] public function listAction(Request $request): Response { $active = $request->query->getBoolean('active', true); @@ -58,9 +54,7 @@ class UserAccompanyingPeriodController extends AbstractController ]); } - /** - * @Route("/{_locale}/person/accompanying-periods/my/drafts", name="chill_person_accompanying_period_draft_user") - */ + #[Route(path: '/{_locale}/person/accompanying-periods/my/drafts', name: 'chill_person_accompanying_period_draft_user')] public function listDraftsAction(): Response { $total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => 'DRAFT']); diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php index 63000093e..44992ebef 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php @@ -26,9 +26,7 @@ class LoadAccompanyingPeriodWork extends \Doctrine\Bundle\FixturesBundle\Fixture */ private array $cacheEvaluations = []; - public function __construct(private readonly AccompanyingPeriodRepository $periodRepository, private readonly EvaluationRepository $evaluationRepository) - { - } + public function __construct(private readonly AccompanyingPeriodRepository $periodRepository, private readonly EvaluationRepository $evaluationRepository) {} public function getDependencies() { diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php index baf18cebc..2acbcbfbd 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php @@ -37,8 +37,7 @@ class LoadCustomFields extends AbstractFixture implements OrderedFixtureInterfac private readonly EntityManagerInterface $entityManager, private readonly CustomFieldChoice $customFieldChoice, private readonly CustomFieldText $customFieldText, - ) { - } + ) {} // put your code here public function getOrder() diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php index 8fff20a39..3efcc6386 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php @@ -24,9 +24,7 @@ class LoadRelationships extends Fixture implements DependentFixtureInterface { use PersonRandomHelper; - public function __construct(private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly EntityManagerInterface $em) {} public function getDependencies(): array { diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadSocialWorkMetadata.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadSocialWorkMetadata.php index 9c04d73cd..dc1e7b4dd 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadSocialWorkMetadata.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadSocialWorkMetadata.php @@ -19,9 +19,7 @@ use League\Csv\Reader; class LoadSocialWorkMetadata extends Fixture implements OrderedFixtureInterface { - public function __construct(private readonly SocialWorkMetadata $importer) - { - } + public function __construct(private readonly SocialWorkMetadata $importer) {} public function getOrder() { diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index ebbfedeb3..e9e1b79b5 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -13,7 +13,10 @@ namespace Chill\PersonBundle\DependencyInjection; use Chill\MainBundle\DependencyInjection\MissingBundleException; use Chill\MainBundle\Security\Authorization\ChillExportVoter; +use Chill\PersonBundle\Controller\AccompanyingPeriodCommentApiController; +use Chill\PersonBundle\Controller\AccompanyingPeriodResourceApiController; use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController; +use Chill\PersonBundle\Controller\RelationApiController; use Chill\PersonBundle\Doctrine\DQL\AddressPart; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter; @@ -537,6 +540,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], [ 'class' => AccompanyingPeriod\Comment::class, + 'controller' => AccompanyingPeriodCommentApiController::class, 'name' => 'accompanying_period_comment', 'base_path' => '/api/1.0/person/accompanying-period/comment', 'base_role' => 'ROLE_USER', @@ -556,6 +560,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], [ 'class' => AccompanyingPeriod\Resource::class, + 'controller' => AccompanyingPeriodResourceApiController::class, 'name' => 'accompanying_period_resource', 'base_path' => '/api/1.0/person/accompanying-period/resource', 'base_role' => 'ROLE_USER', @@ -874,6 +879,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], [ 'class' => \Chill\PersonBundle\Entity\Relationships\Relation::class, + 'controller' => RelationApiController::class, 'name' => 'relations', 'base_path' => '/api/1.0/relations/relation', 'base_role' => 'ROLE_USER', diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 569e3449a..85b80faf8 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -37,10 +37,10 @@ use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\LocationValidity use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ParticipationOverlap; use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ResourceDuplicateCheck; use Chill\ThirdPartyBundle\Entity\ThirdParty; -use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Order; use Doctrine\Common\Collections\ReadableCollection; use Doctrine\Common\Collections\Selectable; use Doctrine\ORM\Mapping as ORM; @@ -53,23 +53,14 @@ use UnexpectedValueException; /** * AccompanyingPeriod Class. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "accompanying_period": AccompanyingPeriod::class - * }) - * - * @Assert\GroupSequenceProvider - * - * @AccompanyingPeriodValidity(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) - * - * @LocationValidity(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) - * - * @ConfidentialCourseMustHaveReferrer(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period' => AccompanyingPeriod::class])] +#[Assert\GroupSequenceProvider] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period')] +#[AccompanyingPeriodValidity(groups: [AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED])] +#[LocationValidity(groups: [AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED])] +#[ConfidentialCourseMustHaveReferrer(groups: [AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED])] class AccompanyingPeriod implements GroupSequenceProviderInterface, HasCentersInterface, @@ -135,322 +126,179 @@ class AccompanyingPeriod implements */ final public const STEP_DRAFT = 'DRAFT'; - /** - * @ORM\ManyToOne( - * targetEntity=Address::class - * ) - */ + #[ORM\ManyToOne(targetEntity: Address::class)] private ?Address $addressLocation = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location") - * - * @Groups({"read", "write"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED}) - */ + #[Groups(['read', 'write'])] + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_CONFIRMED])] + #[ORM\ManyToOne(targetEntity: Location::class)] private ?Location $administrativeLocation = null; /** - * @var Collection&Selectable - * - * @ORM\OneToMany(targetEntity="Chill\CalendarBundle\Entity\Calendar", mappedBy="accompanyingPeriod") + * @var \Doctrine\Common\Collections\Collection&Selectable */ + #[ORM\OneToMany(mappedBy: 'accompanyingPeriod', targetEntity: Calendar::class)] private Collection&Selectable $calendars; - /** - * @ORM\Column(type="date", nullable=true) - * - * @Groups({"read", "write", "docgen:read"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CLOSED}) - * - * @Assert\GreaterThanOrEqual( - * propertyPath="openingDate", - * groups={AccompanyingPeriod::STEP_CLOSED}, - * message="The closing date must be later than the date of creation" - * ) - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_CLOSED])] + #[Assert\GreaterThanOrEqual(propertyPath: 'openingDate', message: 'The closing date must be later than the date of creation', groups: [AccompanyingPeriod::STEP_CLOSED])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)] private ?\DateTime $closingDate = null; - /** - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive") - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "write"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CLOSED}) - */ + #[Groups(['read', 'write'])] + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_CLOSED])] + #[ORM\ManyToOne(targetEntity: ClosingMotive::class)] + #[ORM\JoinColumn(nullable: true)] private ?ClosingMotive $closingMotive = null; /** - * @ORM\OneToMany(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Comment", - * mappedBy="accompanyingPeriod", - * cascade={"persist", "remove"}, - * orphanRemoval=true - * ) - * - * @ORM\OrderBy({"createdAt": "DESC", "id": "DESC"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_DRAFT}) - * - * @var Collection + * @var \Doctrine\Common\Collections\Collection */ + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_DRAFT])] + #[ORM\OneToMany(mappedBy: 'accompanyingPeriod', targetEntity: Comment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['createdAt' => Criteria::DESC, 'id' => 'DESC'])] private Collection $comments; - /** - * @ORM\Column(type="boolean", options={"default": false}) - * - * @Groups({"read", "write", "docgen:read"}) - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $confidential = false; - /** - * @ORM\Column(type="datetime", nullable=true, options={"default": NULL}) - * - * @Groups({"docgen:read"}) - */ + #[Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeInterface $createdAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $createdBy = null; - /** - * @ORM\Column(type="boolean", options={"default": false}) - * - * @Groups({"read", "write", "docgen:read"}) - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $emergency = false; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\Column(type="string", nullable=true) - * - * @Groups({"read"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED}) - */ + #[Groups(['read'])] + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_CONFIRMED])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] private ?string $intensity = self::INTENSITY_OCCASIONAL; - /** - * @ORM\ManyToOne( - * targetEntity=UserJob::class - * ) - * - * @Groups({"read", "write"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED}) - */ + #[Groups(['read', 'write'])] + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_CONFIRMED])] + #[ORM\ManyToOne(targetEntity: UserJob::class)] private ?UserJob $job = null; /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=AccompanyingPeriodLocationHistory::class, - * mappedBy="period", cascade={"persist", "remove"}, orphanRemoval=true) + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'period', targetEntity: AccompanyingPeriodLocationHistory::class, cascade: ['persist', 'remove'], orphanRemoval: true)] private Collection $locationHistories; - /** - * @ORM\Column(type="date") - * - * @Groups({"read", "write", "docgen:read"}) - * - * @Assert\LessThan(value="tomorrow", groups={AccompanyingPeriod::STEP_CONFIRMED}) - * - * @Assert\LessThanOrEqual(propertyPath="closingDate", groups={AccompanyingPeriod::STEP_CONFIRMED}) - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[Assert\LessThan(value: 'tomorrow', groups: [AccompanyingPeriod::STEP_CONFIRMED])] + #[Assert\LessThanOrEqual(propertyPath: 'closingDate', groups: [AccompanyingPeriod::STEP_CONFIRMED])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE)] private ?\DateTime $openingDate = null; - /** - * @ORM\ManyToOne(targetEntity=Origin::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "write"}) - * - * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED}) - */ + #[Groups(['read', 'write'])] + #[Assert\NotBlank(groups: [AccompanyingPeriod::STEP_CONFIRMED])] + #[ORM\ManyToOne(targetEntity: Origin::class)] + #[ORM\JoinColumn(nullable: true)] private ?Origin $origin = null; /** - * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, - * mappedBy="accompanyingPeriod", orphanRemoval=true, - * cascade={"persist", "refresh", "remove", "merge", "detach"}) - * - * @Groups({"read", "docgen:read"}) - * - * @ParticipationOverlap(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) - * - * @var Collection + * @var Collection */ + #[Groups(['read', 'docgen:read'])] + #[ORM\OneToMany(mappedBy: 'accompanyingPeriod', targetEntity: AccompanyingPeriodParticipation::class, cascade: ['persist', 'refresh', 'remove', 'merge', 'detach'], orphanRemoval: true)] + #[ParticipationOverlap(groups: [AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED])] private Collection $participations; - /** - * @ORM\ManyToOne( - * targetEntity=Person::class, - * inversedBy="periodLocatedOn" - * ) - */ + #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'periodLocatedOn')] private ?Person $personLocation = null; - /** - * @ORM\ManyToOne( - * targetEntity=Comment::class, - * cascade={"persist"}, - * ) - * - * @Groups({"read"}) - * - * @ORM\JoinColumn(onDelete="SET NULL") - */ + #[Groups(['read'])] + #[ORM\ManyToOne(targetEntity: Comment::class, cascade: ['persist'])] + #[ORM\JoinColumn(onDelete: 'SET NULL')] private ?Comment $pinnedComment = null; private bool $preventUserIsChangedNotification = false; - /** - * @ORM\Column(type="text") - * - * @Groups({"read", "write"}) - */ + #[Groups(['read', 'write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $remark = ''; - /** - * @ORM\Column(type="boolean", options={"default": false}) - * - * @Groups({"read", "write", "docgen:read"}) - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $requestorAnonymous = false; - /** - * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodRequested") - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'accompanyingPeriodRequested')] + #[ORM\JoinColumn(nullable: true)] private ?Person $requestorPerson = null; - /** - * @ORM\ManyToOne(targetEntity=ThirdParty::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: ThirdParty::class)] + #[ORM\JoinColumn(nullable: true)] private ?ThirdParty $requestorThirdParty = null; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Resource", - * mappedBy="accompanyingPeriod", - * cascade={"persist", "remove"}, - * orphanRemoval=true - * ) - * - * @Groups({"read", "docgen:read"}) - * - * @ResourceDuplicateCheck(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED, "Default", "default"}) + * @var Collection */ + #[Groups(['read', 'docgen:read'])] + #[ORM\OneToMany(targetEntity: AccompanyingPeriod\Resource::class, mappedBy: 'accompanyingPeriod', cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ResourceDuplicateCheck(groups: [AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED, 'Default', 'default'])] private Collection $resources; /** - * @var Collection - * - * @ORM\ManyToMany( - * targetEntity=Scope::class, - * cascade={} - * ) - * - * @ORM\JoinTable( - * name="accompanying_periods_scopes", - * joinColumns={@ORM\JoinColumn(name="accompanying_period_id", referencedColumnName="id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="scope_id", referencedColumnName="id")} - * ) - * - * @Groups({"read", "docgen:read"}) - * - * @Assert\Count(min=1, groups={AccompanyingPeriod::STEP_CONFIRMED}, minMessage="A course must be associated to at least one scope") + * @var Collection */ + #[Groups(['read', 'docgen:read'])] + #[Assert\Count(min: 1, groups: [AccompanyingPeriod::STEP_CONFIRMED], minMessage: 'A course must be associated to at least one scope')] + #[ORM\ManyToMany(targetEntity: Scope::class, cascade: [])] + #[ORM\JoinTable(name: 'accompanying_periods_scopes', joinColumns: [new ORM\JoinColumn(name: 'accompanying_period_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'scope_id', referencedColumnName: 'id')])] private Collection $scopes; /** - * @var Collection - * - * @ORM\ManyToMany( - * targetEntity=SocialIssue::class - * ) - * - * @ORM\JoinTable( - * name="chill_person_accompanying_period_social_issues" - * ) - * - * @Groups({"read", "docgen:read"}) - * - * @Assert\Count(min=1, groups={AccompanyingPeriod::STEP_CONFIRMED}, minMessage="A course must contains at least one social issue") + * @var Collection */ + #[Groups(['read', 'docgen:read'])] + #[Assert\Count(min: 1, groups: [AccompanyingPeriod::STEP_CONFIRMED], minMessage: 'A course must contains at least one social issue')] + #[ORM\ManyToMany(targetEntity: SocialIssue::class)] + #[ORM\JoinTable(name: 'chill_person_accompanying_period_social_issues')] private Collection $socialIssues; /** - * @ORM\Column(type="string", length=32, nullable=true) - * - * @Groups({"read"}) - * * @var AccompanyingPeriod::STEP_* */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 32, nullable: true)] private ?string $step = self::STEP_DRAFT; /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=AccompanyingPeriodStepHistory::class, - * mappedBy="period", cascade={"persist", "remove"}, orphanRemoval=true) + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'period', targetEntity: AccompanyingPeriodStepHistory::class, cascade: ['persist', 'remove'], orphanRemoval: true)] private Collection $stepHistories; - /** - * @ORM\Column(type="datetime", nullable=true, options={"default": NULL}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeInterface $updatedAt = null; - /** - * @ORM\ManyToOne( - * targetEntity=User::class - * ) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $updatedBy = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "write", "docgen:read"}) - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $user = null; /** - * @ORM\OneToMany(targetEntity=UserHistory::class, mappedBy="accompanyingPeriod", orphanRemoval=true, - * cascade={"persist", "remove"}) - * - * @var Collection + * @var Collection */ + #[ORM\OneToMany(targetEntity: UserHistory::class, mappedBy: 'accompanyingPeriod', orphanRemoval: true, cascade: ['persist', 'remove'])] private Collection $userHistories; private bool $userIsChanged = false; @@ -463,15 +311,10 @@ class AccompanyingPeriod implements private ?User $userPrevious = null; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriodWork::class, - * mappedBy="accompanyingPeriod" - * ) - * - * @Assert\Valid(traverse=true) + * @var Collection */ + #[Assert\Valid(traverse: true)] + #[ORM\OneToMany(mappedBy: 'accompanyingPeriod', targetEntity: AccompanyingPeriodWork::class)] private Collection $works; /** @@ -555,7 +398,7 @@ class AccompanyingPeriod implements // ensure continuity of histories $criteria = new Criteria(); - $criteria->orderBy(['startDate' => \Doctrine\Common\Collections\Order::Ascending, 'id' => \Doctrine\Common\Collections\Order::Ascending]); + $criteria->orderBy(['startDate' => Order::Ascending, 'id' => Order::Ascending]); /** @var \Iterator $locations */ $locations = $this->getLocationHistories()->matching($criteria)->getIterator(); @@ -584,7 +427,7 @@ class AccompanyingPeriod implements return $this; } - public function addResource(Resource $resource): self + public function addResource(AccompanyingPeriod\Resource $resource): self { $resource->setAccompanyingPeriod($this); $this->resources[] = $resource; @@ -749,10 +592,9 @@ class AccompanyingPeriod implements } /** - * @Groups({"read"}) - * - * @return ReadableCollection<(int|string), Comment> + * @return ReadableCollection */ + #[Groups(['read'])] public function getComments(): ReadableCollection { $pinnedComment = $this->pinnedComment; @@ -775,9 +617,7 @@ class AccompanyingPeriod implements return $this->createdBy; } - /** - * @Groups({"docgen:read"}) - */ + #[Groups(['docgen:read'])] public function getCurrentParticipations(): ReadableCollection { return $this->getOpenParticipations(); @@ -826,9 +666,8 @@ class AccompanyingPeriod implements /** * Get the location, taking precedence into account. - * - * @Groups({"read"}) */ + #[Groups(['read'])] public function getLocation(?\DateTimeImmutable $at = null): ?Address { if ($this->getPersonLocation() instanceof Person) { @@ -849,10 +688,9 @@ class AccompanyingPeriod implements /** * Get where the location is. * - * @Groups({"read"}) - * * @return 'person'|'address'|'none' */ + #[Groups(['read'])] public function getLocationStatus(): string { if ($this->getPersonLocation() instanceof Person) { @@ -954,9 +792,7 @@ class AccompanyingPeriod implements ); } - /** - * @Groups({"read"}) - */ + #[Groups(['read'])] public function getPersonLocation(): ?Person { return $this->personLocation; @@ -965,7 +801,7 @@ class AccompanyingPeriod implements /** * Get a list of all persons which are participating to this course. * - * @psalm-return Collection<(int|string), Person|null> + * @psalm-return Collection */ public function getPersons(): Collection { @@ -976,9 +812,7 @@ class AccompanyingPeriod implements ); } - /** - * @Groups({"read"}) - */ + #[Groups(['read'])] public function getPinnedComment(): ?Comment { return $this->pinnedComment; @@ -1031,9 +865,7 @@ class AccompanyingPeriod implements return $this->remark; } - /** - * @Groups({"read"}) - */ + #[Groups(['read'])] public function getRequestor(): Person|ThirdParty|null { return $this->requestorPerson ?? $this->requestorThirdParty; @@ -1065,6 +897,9 @@ class AccompanyingPeriod implements return $this->requestorThirdParty; } + /** + * @return Collection + */ public function getResources(): Collection { return $this->resources; @@ -1259,9 +1094,7 @@ class AccompanyingPeriod implements return $this; } - /** - * @Groups({"write"}) - */ + #[Groups(['write'])] public function setAddressLocation(?Address $addressLocation = null): self { if ($this->addressLocation !== $addressLocation) { @@ -1374,9 +1207,7 @@ class AccompanyingPeriod implements return $this; } - /** - * @Groups({"write"}) - */ + #[Groups(['write'])] public function setPersonLocation(?Person $person = null): self { if ($this->personLocation !== $person) { @@ -1396,9 +1227,7 @@ class AccompanyingPeriod implements return $this; } - /** - * @Groups({"write"}) - */ + #[Groups(['write'])] public function setPinnedComment(?Comment $comment = null): self { if (null !== $this->pinnedComment) { @@ -1426,9 +1255,8 @@ class AccompanyingPeriod implements * @param $requestor Person|ThirdParty * * @throw UnexpectedValueException if the requestor is not a Person or ThirdParty - * - * @Groups({"write"}) */ + #[Groups(['write'])] public function setRequestor($requestor): self { if ($requestor instanceof Person) { @@ -1551,7 +1379,7 @@ class AccompanyingPeriod implements { // ensure continuity of histories $criteria = new Criteria(); - $criteria->orderBy(['startDate' => \Doctrine\Common\Collections\Order::Ascending, 'id' => \Doctrine\Common\Collections\Order::Ascending]); + $criteria->orderBy(['startDate' => Order::Ascending, 'id' => Order::Ascending]); /** @var \Iterator $steps */ $steps = $this->getStepHistories()->matching($criteria)->getIterator(); diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodInfo.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodInfo.php index fe552dfe0..d8b5b3209 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodInfo.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodInfo.php @@ -24,66 +24,54 @@ use Doctrine\ORM\Mapping as ORM; * Usage: * * - get the user involved with an accompanying period - * - * @ORM\Entity() - * - * @ORM\Table(name="view_chill_person_accompanying_period_info") */ +#[ORM\Entity] +#[ORM\Table(name: 'view_chill_person_accompanying_period_info')] class AccompanyingPeriodInfo { public function __construct( /** * @var AccompanyingPeriod - * - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class)] public readonly AccompanyingPeriod $accompanyingPeriod, /** * @var string - * - * @ORM\Column(type="text") - * - * @ORM\Id */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] + #[ORM\Id] public readonly string $relatedEntity, /** * @var int - * - * @ORM\Column(type="integer") - * - * @ORM\Id */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\Id] public readonly int $relatedEntityId, /** * @var User - * - * @ORM\ManyToOne(targetEntity=User::class) */ + #[ORM\ManyToOne(targetEntity: User::class)] public readonly ?User $user, /** * @var \DateTimeImmutable - * - * @ORM\Column(type="datetime_immutable") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] public readonly \DateTimeImmutable $infoDate, /** * @var array - * - * @ORM\Column(type="json") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] public readonly array $metadata, /** * @var string - * - * @ORM\Column(type="text") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] public readonly string $discriminator, - ) { - } + ) {} } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php index 700076506..7f42f17e9 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php @@ -18,47 +18,30 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table("chill_person_accompanying_period_location_history") - */ +#[ORM\Entity] +#[ORM\Table('chill_person_accompanying_period_location_history')] class AccompanyingPeriodLocationHistory implements TrackCreationInterface { use TrackCreationTrait; - /** - * @ORM\ManyToOne(targetEntity=Address::class, cascade={"persist"}) - */ + #[ORM\ManyToOne(targetEntity: Address::class, cascade: ['persist'])] private ?Address $addressLocation = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class)] private AccompanyingPeriod $period; - /** - * @ORM\ManyToOne(targetEntity=Person::class) - */ + #[ORM\ManyToOne(targetEntity: Person::class)] private ?Person $personLocation = null; - /** - * @ORM\Column(type="date_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE)] private ?\DateTimeImmutable $startDate = null; public function getAddressLocation(): ?Address diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodStepHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodStepHistory.php index c25c11e69..550f4f0b4 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodStepHistory.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodStepHistory.php @@ -16,54 +16,35 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\PersonBundle\Entity\AccompanyingPeriod; -use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table("chill_person_accompanying_period_step_history") - */ +#[ORM\Entity] +#[ORM\Table('chill_person_accompanying_period_step_history')] class AccompanyingPeriodStepHistory implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class)] private AccompanyingPeriod $period; - /** - * @ORM\Column(type="date_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE)] private ?\DateTimeImmutable $startDate = null; - /** - * @ORM\Column(type="text", nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false)] private string $step; - /** - * @ORM\ManyToOne(targetEntity=ClosingMotive::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: ClosingMotive::class)] + #[ORM\JoinColumn(nullable: true)] private ?ClosingMotive $closingMotive = null; public function getEndDate(): ?\DateTimeImmutable diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index fbd1a54a3..af012c5ff 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -29,229 +29,125 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_work") - * - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "accompanying_period_work": AccompanyingPeriodWork::class - * } - * ) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_work' => AccompanyingPeriodWork::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_work')] class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface, TrackCreationInterface, TrackUpdateInterface { - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) - * - * @Serializer\Groups({"read", "read:accompanyingPeriodWork:light"}) - * - * @Serializer\Context(normalizationContext={"groups": {"read"}}, groups={"read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['read', 'read:accompanyingPeriodWork:light'])] + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class)] + #[Serializer\Context(normalizationContext: ['groups' => ['read']], groups: ['read:accompanyingPeriodWork:light'])] private ?AccompanyingPeriod $accompanyingPeriod = null; /** - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriodWorkEvaluation::class, - * mappedBy="accompanyingPeriodWork", - * cascade={"remove", "persist"}, - * orphanRemoval=true - * ) - * - * @Serializer\Groups({"read"}) - * - * @ORM\OrderBy({"startDate": "DESC", "id": "DESC"}) - * - * @var Collection + * @var Collection * * @internal the serialization for write evaluations is handled in `accompanyingperiodworkdenormalizer` * @internal the serialization for context docgen:read is handled in `accompanyingperiodworknormalizer` */ + #[Serializer\Groups(['read'])] + #[ORM\OneToMany(mappedBy: 'accompanyingPeriodWork', targetEntity: AccompanyingPeriodWorkEvaluation::class, cascade: ['remove', 'persist'], orphanRemoval: true)] + #[ORM\OrderBy(['startDate' => \Doctrine\Common\Collections\Criteria::DESC, 'id' => 'DESC'])] private Collection $accompanyingPeriodWorkEvaluations; - /** - * @ORM\Column(type="datetime_immutable") - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private ?\DateTimeImmutable $createdAt = null; - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $createdAutomatically = false; - /** - * @ORM\Column(type="text") - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $createdAutomaticallyReason = ''; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] private ?User $createdBy = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"accompanying_period_work:create"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - * - * @Assert\GreaterThanOrEqual(propertyPath="startDate", - * message="accompanying_course_work.The endDate should be greater or equal than the start date" - * ) - */ + #[Serializer\Groups(['accompanying_period_work:create', 'accompanying_period_work:edit', 'read', 'docgen:read', 'read:accompanyingPeriodWork:light'])] + #[Assert\GreaterThanOrEqual(propertyPath: 'startDate', message: 'accompanying_course_work.The endDate should be greater or equal than the start date')] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriodWorkGoal::class, - * mappedBy="accompanyingPeriodWork", - * cascade={"persist"}, - * orphanRemoval=true - * ) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) + * @var Collection */ + #[Serializer\Groups(['read', 'docgen:read', 'accompanying_period_work:edit'])] + #[ORM\OneToMany(mappedBy: 'accompanyingPeriodWork', targetEntity: AccompanyingPeriodWorkGoal::class, cascade: ['persist'], orphanRemoval: true)] private Collection $goals; - /** - * @ORM\ManyToOne(targetEntity=ThirdParty::class) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * - * In schema : traitant - */ + #[Serializer\Groups(['read', 'docgen:read', 'accompanying_period_work:edit'])] + #[ORM\ManyToOne(targetEntity: ThirdParty::class)] private ?ThirdParty $handlingThierParty = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light", "read:evaluation:include-work"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light', 'read:evaluation:include-work'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="text") - * - * @Serializer\Groups({"read", "accompanying_period_work:edit", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'accompanying_period_work:edit', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $note = ''; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Person::class) - * - * @ORM\JoinTable(name="chill_person_accompanying_period_work_person") - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"accompanying_period_work:create"}) + * @var Collection */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light', 'accompanying_period_work:edit', 'accompanying_period_work:create'])] + #[ORM\ManyToMany(targetEntity: Person::class)] + #[ORM\JoinTable(name: 'chill_person_accompanying_period_work_person')] private Collection $persons; - /** - * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable", columnPrefix="privateComment_") - * - * @Serializer\Groups({"read", "accompanying_period_work:edit"}) - */ + #[Serializer\Groups(['read', 'accompanying_period_work:edit'])] + #[ORM\Embedded(class: PrivateCommentEmbeddable::class, columnPrefix: 'privateComment_')] private PrivateCommentEmbeddable $privateComment; /** * @var Collection - * - * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork", orphanRemoval=true) */ + #[ORM\OneToMany(targetEntity: AccompanyingPeriodWorkReferrerHistory::class, cascade: ['persist', 'remove'], mappedBy: 'accompanyingPeriodWork', orphanRemoval: true)] private Collection $referrersHistory; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorks") - * - * @ORM\JoinTable(name="chill_person_accompanying_period_work_result") - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) + * @var Collection */ + #[Serializer\Groups(['read', 'docgen:read', 'accompanying_period_work:edit'])] + #[ORM\ManyToMany(targetEntity: Result::class, inversedBy: 'accompanyingPeriodWorks')] + #[ORM\JoinTable(name: 'chill_person_accompanying_period_work_result')] private Collection $results; - /** - * @ORM\ManyToOne(targetEntity=SocialAction::class) - * - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - * @Serializer\Groups({"accompanying_period_work:create"}) - * - * @Serializer\Context(normalizationContext={"groups": {"read"}}, groups={"read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'read:accompanyingPeriodWork:light', 'accompanying_period_work:create'])] + #[ORM\ManyToOne(targetEntity: SocialAction::class)] + #[Serializer\Context(normalizationContext: ['groups' => ['read']], groups: ['read:accompanyingPeriodWork:light'])] private ?SocialAction $socialAction = null; - /** - * @ORM\Column(type="date_immutable") - * - * @Serializer\Groups({"accompanying_period_work:create"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - */ + #[Serializer\Groups(['accompanying_period_work:create', 'accompanying_period_work:edit', 'read', 'docgen:read', 'read:accompanyingPeriodWork:light'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE)] private ?\DateTimeImmutable $startDate = null; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=ThirdParty::class) - * - * @ORM\JoinTable(name="chill_person_accompanying_period_work_third_party") - * - * In schema : intervenants - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) + * @var Collection */ + #[Serializer\Groups(['read', 'docgen:read', 'accompanying_period_work:edit'])] + #[ORM\ManyToMany(targetEntity: ThirdParty::class)] + #[ORM\JoinTable(name: 'chill_person_accompanying_period_work_third_party')] // In schema : intervenants private Collection $thirdParties; - /** - * @ORM\Column(type="datetime_immutable") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private ?\DateTimeImmutable $updatedAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] private ?User $updatedBy = null; - /** - * @ORM\Column(type="integer", nullable=false, options={"default": 1}) - * - * @Serializer\Groups({"read", "accompanying_period_work:edit"}) - * - * @ORM\Version - */ + #[Serializer\Groups(['read', 'accompanying_period_work:edit'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: false, options: ['default' => 1])] + #[ORM\Version] private int $version = 1; public function __construct() @@ -401,9 +297,8 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues * and returns them as a new ReadableCollection. * * @return ReadableCollection collection of active referrers - * - * @Serializer\Groups({"accompanying_period_work:edit"}) */ + #[Serializer\Groups(['accompanying_period_work:edit'])] public function getReferrers(): ReadableCollection { $users = $this->referrersHistory diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php index 7f2fc981c..748174e19 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php @@ -15,58 +15,31 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\SocialWork\Evaluation; -use DateInterval; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table("chill_person_accompanying_period_work_evaluation") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "accompanying_period_work_evaluation": AccompanyingPeriodWorkEvaluation::class, - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_work_evaluation' => AccompanyingPeriodWorkEvaluation::class])] +#[ORM\Entity] +#[ORM\Table('chill_person_accompanying_period_work_evaluation')] class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackUpdateInterface { - /** - * @ORM\ManyToOne( - * targetEntity=AccompanyingPeriodWork::class, - * inversedBy="accompanyingPeriodWorkEvaluations" - * ) - * - * @Serializer\Groups({"read:evaluation:include-work"}) - * - * @Serializer\Context(normalizationContext={"groups": {"read:accompanyingPeriodWork:light"}}, groups={"read:evaluation:include-work"}) - */ + #[Serializer\Groups(['read:evaluation:include-work'])] + #[ORM\ManyToOne(targetEntity: AccompanyingPeriodWork::class, inversedBy: 'accompanyingPeriodWorkEvaluations')] + #[Serializer\Context(normalizationContext: ['groups' => ['read:accompanyingPeriodWork:light']], groups: ['read:evaluation:include-work'])] private ?AccompanyingPeriodWork $accompanyingPeriodWork = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $comment = ''; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $createdAt = null; - /** - * @ORM\ManyToOne( - * targetEntity=User::class - * ) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $createdBy = null; /** @@ -74,49 +47,25 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU * * @see{Chill\PersonBundle\Serializer\Normalizer\AccompanyingPeriodWorkEvaluationDenormalizer} * - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriodWorkEvaluationDocument::class, - * mappedBy="accompanyingPeriodWorkEvaluation", - * cascade={"remove", "persist"}, - * orphanRemoval=true - * ) - * - * @ORM\OrderBy({"createdAt": "DESC", "id": "DESC"}) - * - * @Serializer\Groups({"read"}) - * - * @var Collection + * @var Collection */ + #[Serializer\Groups(['read'])] + #[ORM\OneToMany(mappedBy: 'accompanyingPeriodWorkEvaluation', targetEntity: AccompanyingPeriodWorkEvaluationDocument::class, cascade: ['remove', 'persist'], orphanRemoval: true)] + #[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::DESC, 'id' => 'DESC'])] private Collection $documents; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\ManyToOne( - * targetEntity=Evaluation::class - * ) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'accompanying_period_work_evaluation:create'])] + #[ORM\ManyToOne(targetEntity: Evaluation::class)] private ?Evaluation $evaluation = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; /** @@ -125,63 +74,32 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU * * This data is not persisted into database, but will appears on the data * normalized during the same request (like PUT/PATCH request) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ + #[Serializer\Groups(['read', 'write', 'accompanying_period_work_evaluation:create'])] private $key; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $maxDate = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $startDate = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $updatedAt = null; - /** - * @ORM\ManyToOne( - * targetEntity=User::class - * ) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $updatedBy = null; - /** - * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATEINTERVAL, nullable: true, options: ['default' => null])] private ?\DateInterval $warningInterval = null; - /** - * @ORM\Column(type="integer", nullable=true) - * - * @Serializer\Groups({"read", "docgen:read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'docgen:read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true)] private ?int $timeSpent = null; public function __construct() @@ -270,9 +188,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU return $this->updatedBy; } - /** - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] public function getWarningDate(): ?\DateTimeImmutable { if (null === $this->getEndDate() || null === $this->getWarningInterval()) { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php index e5ddc059a..ae0546516 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php @@ -19,43 +19,26 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table("chill_person_accompanying_period_work_evaluation_document") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "accompanying_period_work_evaluation_document": AccompanyingPeriodWorkEvaluationDocument::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_work_evaluation_document' => AccompanyingPeriodWorkEvaluationDocument::class])] +#[ORM\Entity] +#[ORM\Table('chill_person_accompanying_period_work_evaluation_document')] class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doctrine\Model\TrackCreationInterface, \Chill\MainBundle\Doctrine\Model\TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\ManyToOne( - * targetEntity=AccompanyingPeriodWorkEvaluation::class, - * inversedBy="documents" - * ) - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriodWorkEvaluation::class, inversedBy: 'documents')] private ?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation = null; /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * * @internal the default name exceeds 64 characters, we must set manually: - * - * @ORM\SequenceGenerator(sequenceName="chill_person_social_work_eval_doc_id_seq", allocationSize=1, initialValue=1000) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ + #[Serializer\Groups(['read', 'accompanying_period_work_evaluation:create'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\SequenceGenerator(sequenceName: 'chill_person_social_work_eval_doc_id_seq', allocationSize: 1, initialValue: 1000)] private ?int $id = null; /** @@ -64,43 +47,21 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct * * This data is not persisted into database, but will appears on the data * normalized during the same request (like PUT/PATCH request) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ + #[Serializer\Groups(['read', 'write', 'accompanying_period_work_evaluation:create'])] private $key; - /** - * @ORM\ManyToOne( - * targetEntity=StoredObject::class, - * ) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - * - * @Assert\Valid - */ + #[Serializer\Groups(['read', 'write', 'accompanying_period_work_evaluation:create'])] + #[Assert\Valid] + #[ORM\ManyToOne(targetEntity: StoredObject::class)] private ?StoredObject $storedObject = null; - /** - * @ORM\ManyToOne( - * targetEntity=DocGeneratorTemplate::class - * ) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'accompanying_period_work_evaluation:create'])] + #[ORM\ManyToOne(targetEntity: DocGeneratorTemplate::class)] private ?DocGeneratorTemplate $template = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"write"}) - * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) - */ + #[Serializer\Groups(['read', 'write', 'accompanying_period_work_evaluation:create'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private ?string $title = ''; public function getAccompanyingPeriodWorkEvaluation(): ?AccompanyingPeriodWorkEvaluation diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php index c0a1528ad..8e78f40fb 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php @@ -18,62 +18,34 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_work_goal") - * - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "accompanying_period_work_goal": AccompanyingPeriodWorkGoal::class - * } - * ) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_work_goal' => AccompanyingPeriodWorkGoal::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_work_goal')] class AccompanyingPeriodWorkGoal { - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriodWork::class, inversedBy="goals") - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriodWork::class, inversedBy: 'goals')] private ?AccompanyingPeriodWork $accompanyingPeriodWork = null; - /** - * @ORM\ManyToOne(targetEntity=Goal::class) - * - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['accompanying_period_work:edit', 'read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: Goal::class)] private ?Goal $goal = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="text") - * - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['accompanying_period_work:edit', 'read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $note = ''; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorkGoals") - * - * @ORM\JoinTable(name="chill_person_accompanying_period_work_goal_result") - * - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read", "docgen:read"}) + * @var Collection */ + #[Serializer\Groups(['accompanying_period_work:edit', 'read', 'docgen:read'])] + #[ORM\ManyToMany(targetEntity: Result::class, inversedBy: 'accompanyingPeriodWorkGoals')] + #[ORM\JoinTable(name: 'chill_person_accompanying_period_work_goal_result')] private Collection $results; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php index 1a83ac113..ac09a1433 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php @@ -18,49 +18,35 @@ use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\MainBundle\Entity\User; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_work_referrer") - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_work_referrer')] class AccompanyingPeriodWorkReferrerHistory implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; public function __construct( - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriodWork::class, inversedBy="referrersHistory") - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriodWork::class, inversedBy: 'referrersHistory')] private ?AccompanyingPeriodWork $accompanyingPeriodWork, /** * @var User - * - * @ORM\ManyToOne(targetEntity=User::class) */ + #[ORM\ManyToOne(targetEntity: User::class)] private User $user, /** * @var \DateTimeImmutable - * - * @ORM\Column(type="date_immutable", nullable=false) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)] private \DateTimeImmutable $startDate, - ) { - } + ) {} public function getId(): ?int { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php index 97938dafc..fc61aed9e 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php @@ -18,64 +18,40 @@ use Symfony\Component\Serializer\Annotation as Serializer; /** * ClosingMotive give an explanation why we closed the Accompanying period. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_closingmotive") */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_closingmotive')] class ClosingMotive { - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $active = true; /** * Child Accompanying periods. * - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive", - * mappedBy="parent") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'parent', targetEntity: ClosingMotive::class)] private Collection $children; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $name = []; - /** - * @ORM\Column(type="float") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] private float $ordering = 0.0; - /** - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive", - * inversedBy="children") - */ + #[ORM\ManyToOne(targetEntity: ClosingMotive::class, inversedBy: 'children')] private ?ClosingMotive $parent = null; - /** - * @ORM\Column(type="boolean", nullable=false, options={"default": false}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: false, options: ['default' => false])] private bool $isCanceledAccompanyingPeriod = false; /** @@ -206,11 +182,9 @@ class ClosingMotive /** * Set name. * - * @param array $name - * * @return ClosingMotive */ - public function setName($name) + public function setName(array $name) { $this->name = $name; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php index 509dcabb0..4d976396d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php @@ -20,78 +20,43 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_comment") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "accompanying_period_comment": Comment::class - * }) - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_comment' => Comment::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_comment')] class Comment implements TrackCreationInterface, TrackUpdateInterface { - /** - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", - * inversedBy="comments") - * - * @ORM\JoinColumn(nullable=false, onDelete="CASCADE") - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class, inversedBy: 'comments')] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] private ?AccompanyingPeriod $accompanyingPeriod = null; - /** - * @ORM\Column(type="text", nullable=false, options={"default":""}) - * - * @Groups({"read", "write", "docgen:read"}) - * - * @Assert\NotBlank - * - * @Assert\NotNull - */ + #[Groups(['read', 'write', 'docgen:read'])] + #[Assert\NotBlank] + #[Assert\NotNull] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] private string $content = ''; - /** - * @ORM\Column(type="datetime") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)] private ?\DateTimeInterface $createdAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] private ?User $creator = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="datetime") - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)] private ?\DateTimeInterface $updatedAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] private ?User $updatedBy = null; public function getAccompanyingPeriod(): ?AccompanyingPeriod diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php index 979fd4581..a551b8b75 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php @@ -14,44 +14,24 @@ namespace Chill\PersonBundle\Entity\AccompanyingPeriod; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_origin") - * - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "origin": Origin::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['origin' => Origin::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_origin')] class Origin { - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $label = []; - /** - * @ORM\Column(type="date_immutable", nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $noActiveAfter = null; public function getId(): ?int diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php index f0ff1d956..ddaecacd1 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php @@ -20,68 +20,38 @@ use Symfony\Component\Serializer\Annotation\Groups; /** * **About denormalization**: this operation is operated by @see{AccompanyingPeriodResourdeNormalizer}. - * - * @ORM\Entity - * - * @ORM\Table( - * name="chill_person_accompanying_period_resource", - * uniqueConstraints={ - * - * @ORM\UniqueConstraint(name="person_unique", columns={"person_id", "accompanyingperiod_id"}), - * @ORM\UniqueConstraint(name="thirdparty_unique", columns={"thirdparty_id", "accompanyingperiod_id"}) - * } - * ) - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "accompanying_period_resource": Resource::class - * }) */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_resource' => Resource::class])] +#[ORM\Entity] +#[ORM\UniqueConstraint(name: 'person_unique', columns: ['person_id', 'accompanyingperiod_id'])] // , +#[ORM\UniqueConstraint(name: 'thirdparty_unique', columns: ['thirdparty_id', 'accompanyingperiod_id'])] +#[ORM\Table(name: 'chill_person_accompanying_period_resource')] +#[ORM\UniqueConstraint(name: 'person_unique', columns: ['person_id', 'accompanyingperiod_id'])] +#[ORM\UniqueConstraint(name: 'thirdparty_unique', columns: ['thirdparty_id', 'accompanyingperiod_id'])] class Resource { - /** - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", - * inversedBy="resources" - * ) - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class, inversedBy: 'resources')] + #[ORM\JoinColumn(nullable: false)] private ?AccompanyingPeriod $accompanyingPeriod = null; - /** - * @ORM\Column(type="text", nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $comment = ''; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"docgen:read"}) - */ + #[Groups(['docgen:read'])] + #[ORM\ManyToOne(targetEntity: Person::class)] + #[ORM\JoinColumn(nullable: true)] private ?Person $person = null; - /** - * @ORM\ManyToOne(targetEntity=ThirdParty::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"docgen:read"}) - */ + #[Groups(['docgen:read'])] + #[ORM\ManyToOne(targetEntity: ThirdParty::class)] + #[ORM\JoinColumn(nullable: true)] private ?ThirdParty $thirdParty = null; public function getAccompanyingPeriod(): ?AccompanyingPeriod @@ -104,9 +74,7 @@ class Resource return $this->person; } - /** - * @Groups({"read"}) - */ + #[Groups(['read'])] public function getResource(): Person|ThirdParty|null { return $this->person ?? $this->thirdParty; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/UserHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/UserHistory.php index b968ccafb..b600ab0bf 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/UserHistory.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/UserHistory.php @@ -17,49 +17,30 @@ use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ORM\Table("chill_person_accompanying_period_user_history") - */ +#[ORM\Entity] +#[ORM\Table('chill_person_accompanying_period_user_history')] class UserHistory implements TrackCreationInterface { use TrackCreationTrait; - /** - * @ORM\Column(type="datetime_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; public function __construct( - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, inversedBy="userHistories") - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class, inversedBy: 'userHistories')] + #[ORM\JoinColumn(nullable: false)] private ?AccompanyingPeriod $accompanyingPeriod, - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] private User $user, - - /** - * @ORM\Column(type="datetime_immutable", nullable=false, options={"default": "now()"}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false, options: ['default' => 'now()'])] private \DateTimeImmutable $startDate = new \DateTimeImmutable('now'), - ) { - } + ) {} public function getAccompanyingPeriod(): AccompanyingPeriod { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php index 100057c76..498aa44e4 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php @@ -17,54 +17,31 @@ use Symfony\Component\Serializer\Annotation\Groups; /** * AccompanyingPeriodParticipation Class. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_accompanying_period_participation") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "accompanying_period_participation": AccompanyingPeriodParticipation::class - * }) */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['accompanying_period_participation' => AccompanyingPeriodParticipation::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_accompanying_period_participation')] class AccompanyingPeriodParticipation { - /** - * @ORM\Column(type="date", nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)] private ?\DateTime $endDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="date", nullable=false) - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: false)] private ?\DateTime $startDate = null; - public function __construct(/** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, inversedBy="participations", cascade={"persist"}) - * - * @ORM\JoinColumn(name="accompanyingperiod_id", referencedColumnName="id", nullable=false) - */ - private ?AccompanyingPeriod $accompanyingPeriod, /** - * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations") - * - * @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false) - * - * @Groups({"read", "docgen:read"}) - */ + public function __construct( + #[ORM\ManyToOne(targetEntity: AccompanyingPeriod::class, inversedBy: 'participations', cascade: ['persist'])] + #[ORM\JoinColumn(name: 'accompanyingperiod_id', referencedColumnName: 'id', nullable: false)] + private ?AccompanyingPeriod $accompanyingPeriod, + #[Groups(['read', 'docgen:read'])] #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'accompanyingPeriodParticipations')] #[ORM\JoinColumn(name: 'person_id', referencedColumnName: 'id', nullable: false)] private ?Person $person, ) { $this->startDate = new \DateTime('now'); diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php index cc0ff2d69..6ecc0366d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Entity\Household; use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; +use Chill\MainBundle\Entity\HasCentersInterface; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Validator\Constraints\Household\MaxHolder; use Doctrine\Common\Collections\ArrayCollection; @@ -20,99 +21,61 @@ use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Criteria; use Doctrine\Common\Collections\ReadableCollection; use Doctrine\Common\Collections\Selectable; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Context\ExecutionContextInterface; -/** - * @ORM\Entity - * - * @ORM\Table( - * name="chill_person_household" - * ) - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "household": Household::class - * }) - * - * @MaxHolder(groups={"household_memberships"}) - */ -class Household +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['household' => Household::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_household')] +#[MaxHolder(groups: ['household_memberships'])] +class Household implements HasCentersInterface { /** * Addresses. * - * @var Collection
    - * - * @ORM\ManyToMany( - * targetEntity="Chill\MainBundle\Entity\Address", - * cascade={"persist", "remove", "merge", "detach"}) - * - * @ORM\JoinTable(name="chill_person_household_to_addresses") - * - * @ORM\OrderBy({"validFrom": "DESC", "id": "DESC"}) - * - * @Serializer\Groups({"write"}) + * @var Collection */ + #[Serializer\Groups(['write'])] + #[ORM\ManyToMany(targetEntity: Address::class, cascade: ['persist', 'remove', 'merge', 'detach'])] + #[ORM\JoinTable(name: 'chill_person_household_to_addresses')] + #[ORM\OrderBy(['validFrom' => Criteria::DESC, 'id' => 'DESC'])] private Collection $addresses; - /** - * @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_members_") - */ + #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'comment_members_')] private CommentEmbeddable $commentMembers; /** - * @var Collection&Selectable - * - * @ORM\OneToMany( - * targetEntity=HouseholdComposition::class, - * mappedBy="household", - * orphanRemoval=true, - * cascade={"persist"} - * ) - * - * @ORM\OrderBy({"startDate": "DESC"}) - * - * @Assert\Valid(traverse=true, groups={"household_composition"}) + * @var \Doctrine\Common\Collections\Collection&Selectable */ + #[Assert\Valid(groups: ['household_composition'], traverse: true)] + #[ORM\OneToMany(mappedBy: 'household', targetEntity: HouseholdComposition::class, cascade: ['persist'], orphanRemoval: true)] + #[ORM\OrderBy(['startDate' => Criteria::DESC])] private Collection&Selectable $compositions; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] private ?int $id = null; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity=HouseholdMember::class, - * mappedBy="household" - * ) - * - * @Serializer\Groups({"read", "docgen:read"}) + * @var Collection */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\OneToMany(mappedBy: 'household', targetEntity: HouseholdMember::class)] private Collection $members; - /** - * @ORM\Column(type="boolean", name="waiting_for_birth", options={"default": false}) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(name: 'waiting_for_birth', type: Types::BOOLEAN, options: ['default' => false])] + #[Assert\Type('boolean', groups: ['household_metadata'])] private bool $waitingForBirth = false; - /** - * @ORM\Column(type="date_immutable", name="waiting_for_birth_date", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: Types::DATE_IMMUTABLE, name: 'waiting_for_birth_date', nullable: true, options: ['default' => null])] + #[Assert\Expression('this.getWaitingForBirth() == false or value != null', message: 'The waiting for birth date must be set', groups: ['household_metadata'])] private ?\DateTimeImmutable $waitingForBirthDate = null; public function __construct() @@ -159,8 +122,6 @@ class Household * By default, the addresses are ordered by date, descending (the most * recent first). * - * @Assert\Callback(methods={"validate"}) - * * @return Collection
    */ public function getAddresses(): Collection @@ -196,6 +157,19 @@ class Household return $addresses; } + public function getCenters(): ?iterable + { + $centers = []; + + foreach ($this->getCurrentPersons() as $person) { + if (null !== $center = $person->getCenter()) { + $centers[$center->getId() ?? spl_object_hash($center)] = $center; + } + } + + return array_values($centers); + } + public function getCommentMembers(): CommentEmbeddable { return $this->commentMembers; @@ -209,11 +183,8 @@ class Household return $this->compositions; } - /** - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\SerializedName("current_address") - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[Serializer\SerializedName('current_address')] public function getCurrentAddress(?\DateTime $at = null): ?Address { $at ??= new \DateTime('today'); @@ -229,11 +200,8 @@ class Household return null; } - /** - * @Serializer\Groups({"docgen:read"}) - * - * @Serializer\SerializedName("current_composition") - */ + #[Serializer\Groups(['docgen:read'])] + #[Serializer\SerializedName('current_composition')] public function getCurrentComposition(?\DateTimeImmutable $at = null): ?HouseholdComposition { $at ??= new \DateTimeImmutable('today'); @@ -259,9 +227,7 @@ class Household return null; } - /** - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] public function getCurrentMembers(?\DateTimeImmutable $now = null): Collection { return $this->getMembers()->matching($this->buildCriteriaCurrentMembers($now)); @@ -281,11 +247,9 @@ class Household * get current members ids. * * Used in serialization - * - * @Serializer\Groups({"read"}) - * - * @Serializer\SerializedName("current_members_id") */ + #[Serializer\Groups(['read'])] + #[Serializer\SerializedName('current_members_id')] public function getCurrentMembersIds(?\DateTimeImmutable $now = null): ReadableCollection { return $this->getCurrentMembers($now)->map( @@ -606,9 +570,8 @@ class Household * This will force the startDate's address on today. * * Used on household creation. - * - * @Serializer\Groups({"create"}) */ + #[Serializer\Groups(['create'])] public function setForceAddress(Address $address) { $address->setValidFrom(new \DateTime('today')); @@ -629,14 +592,16 @@ class Household return $this; } - public function validate(ExecutionContextInterface $context, $payload) + #[Assert\Callback] + public function validate(ExecutionContextInterface $context, $payload): void { - $addresses = $this->getAddresses(); - $cond = true; + $addresses = $this->getAddressesOrdered(); for ($i = 0; \count($addresses) - 1 > $i; ++$i) { - if ($addresses[$i]->getValidFrom() !== $addresses[$i + 1]->getValidTo()) { - $cond = false; + if (0 === $i) { + continue; + } + if ($addresses[$i - 1]->getValidTo() !== $addresses[$i]->getValidFrom()) { $context->buildViolation('The address are not sequentials. The validFrom date of one address should be equal to the validTo date of the previous address.') ->atPath('addresses') ->addViolation(); diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdComposition.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdComposition.php index d8eab9bef..4aea2129c 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdComposition.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdComposition.php @@ -20,82 +20,47 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table( - * name="chill_person_household_composition" - * ) - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "household_composition_type": HouseholdCompositionType::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['household_composition_type' => HouseholdCompositionType::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_household_composition')] class HouseholdComposition implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_") - */ + #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'comment_')] private CommentEmbeddable $comment; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Assert\GreaterThanOrEqual(propertyPath="startDate", groups={"Default", "household_composition"}) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Assert\GreaterThanOrEqual(propertyPath: 'startDate', groups: ['Default', 'household_composition'])] + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\ManyToOne(targetEntity=Household::class, inversedBy="compositions") - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: Household::class, inversedBy: 'compositions')] + #[ORM\JoinColumn(nullable: false)] private ?Household $household = null; - /** - * @ORM\ManyToOne(targetEntity=HouseholdCompositionType::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\ManyToOne(targetEntity: HouseholdCompositionType::class)] + #[ORM\JoinColumn(nullable: false)] private ?HouseholdCompositionType $householdCompositionType = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="integer", nullable=true, options={"default": null}) - * - * @Assert\NotNull - * - * @Assert\GreaterThanOrEqual(0, groups={"Default", "household_composition"}) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Assert\NotNull] + #[Assert\GreaterThanOrEqual(0, groups: ['Default', 'household_composition'])] + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])] private ?int $numberOfChildren = null; - /** - * @ORM\Column(type="date_immutable", nullable=false) - * - * @Assert\NotNull(groups={"Default", "household_composition"}) - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Assert\NotNull(groups: ['Default', 'household_composition'])] + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)] private ?\DateTimeImmutable $startDate = null; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdCompositionType.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdCompositionType.php index cb1fe2703..695105084 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdCompositionType.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdCompositionType.php @@ -14,42 +14,23 @@ namespace Chill\PersonBundle\Entity\Household; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table( - * name="chill_person_household_composition_type" - * ) - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "household_composition_type": HouseholdCompositionType::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['household_composition_type' => HouseholdCompositionType::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_household_composition_type')] class HouseholdCompositionType { - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $active = true; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $label = []; public function getId(): ?int diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php index 21c28f52e..76d9f0236 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php @@ -16,98 +16,51 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table( - * name="chill_person_household_members" - * ) - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_household_members')] class HouseholdMember { - /** - * @ORM\Column(type="string", length=255, nullable=true) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] private ?string $comment = null; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Assert\GreaterThanOrEqual( - * propertyPath="startDate", - * message="household_membership.The end date must be after start date", - * groups={"household_memberships"} - * ) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[Assert\GreaterThanOrEqual(propertyPath: 'startDate', message: 'household_membership.The end date must be after start date', groups: ['household_memberships'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Column(type="boolean", options={"default": false}) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private bool $holder = false; - /** - * @ORM\ManyToOne( - * targetEntity="\Chill\PersonBundle\Entity\Household\Household" - * ) - * - * @Assert\Valid(groups={"household_memberships"}) - * - * @Assert\NotNull(groups={"household_memberships"}) - */ + #[Assert\Valid(groups: ['household_memberships'])] + #[Assert\NotNull(groups: ['household_memberships'])] + #[ORM\ManyToOne(targetEntity: Household::class)] private ?Household $household = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne( - * targetEntity="\Chill\PersonBundle\Entity\Person" - * ) - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"docgen:person:with-household": false}) - * - * @Assert\Valid(groups={"household_memberships"}) - * - * @Assert\NotNull(groups={"household_memberships"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[Assert\Valid(groups: ['household_memberships'])] + #[Assert\NotNull(groups: ['household_memberships'])] + #[ORM\ManyToOne(targetEntity: Person::class)] + #[Serializer\Context(['docgen:person:with-household' => false])] private ?Person $person = null; - /** - * @ORM\ManyToOne(targetEntity=Position::class) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\ManyToOne(targetEntity: Position::class)] private ?Position $position = null; - /** - * @ORM\Column(type="boolean", name="sharedhousehold") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, name: 'sharedhousehold')] private bool $shareHousehold = true; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Assert\NotNull(groups={"household_memberships"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[Assert\NotNull(groups: ['household_memberships'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $startDate = null; public function getComment(): ?string @@ -140,9 +93,7 @@ class HouseholdMember return $this->position; } - /** - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] public function getShareHousehold(): ?bool { return $this->shareHousehold; diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php b/src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php index 529f3e0a6..f7d28eb67 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php @@ -38,48 +38,30 @@ use Doctrine\ORM\Mapping as ORM; * 1. 1st entity: from 2021-01-01 to 2021-06-01, household W, address Q; * 2. 2st entity: from 2021-06-01 to 2021-12-01, household W, address R; * 3. 3st entity: from 2021-12-01 to NULL, household V, address T; - * - * @ORM\Entity(readOnly=true) - * - * @ORM\Table(name="view_chill_person_household_address") */ +#[ORM\Entity(readOnly: true)] +#[ORM\Table(name: 'view_chill_person_household_address')] class PersonHouseholdAddress { - /** - * @ORM\Id - * - * @ORM\ManyToOne(targetEntity=Address::class) - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: Address::class)] + #[ORM\JoinColumn(nullable: false)] private ?Address $address = null; - /** - * @ORM\Id - * - * @ORM\ManyToOne(targetEntity=Household::class) - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: Household::class)] + #[ORM\JoinColumn(nullable: false)] private ?Household $household = null; - /** - * @ORM\Id - * - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: Person::class)] + #[ORM\JoinColumn(nullable: false)] private ?Person $person = null; - /** - * @ORM\Column(type="date_immutable") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE)] private $validFrom; - /** - * @ORM\Column(type="date_immutable", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true)] private $validTo; public function getAddress(): ?Address diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Position.php b/src/Bundle/ChillPersonBundle/Entity/Household/Position.php index 2252fca97..f35858636 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/Position.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Position.php @@ -14,56 +14,32 @@ namespace Chill\PersonBundle\Entity\Household; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_household_position") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "household_position": Position::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['household_position' => Position::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_household_position')] class Position { - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({ "read" }) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $allowHolder = false; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $label = []; - /** - * @ORM\Column(type="float") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] private float $ordering = 0.00; - /** - * @ORM\Column(type="boolean") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $shareHouseHold = true; public function getAllowHolder(): bool diff --git a/src/Bundle/ChillPersonBundle/Entity/MaritalStatus.php b/src/Bundle/ChillPersonBundle/Entity/MaritalStatus.php index 36834542a..b64416113 100644 --- a/src/Bundle/ChillPersonBundle/Entity/MaritalStatus.php +++ b/src/Bundle/ChillPersonBundle/Entity/MaritalStatus.php @@ -15,25 +15,17 @@ use Doctrine\ORM\Mapping as ORM; /** * MaritalStatus. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_marital_status") - * - * @ORM\HasLifecycleCallbacks */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'chill_person_marital_status')] class MaritalStatus { - /** - * @ORM\Id - * - * @ORM\Column(type="string", length=7) - */ + #[ORM\Id] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 7)] private ?string $id; - /** - * @ORM\Column(type="json") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $name; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index e5df9e0e0..0b4b54681 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -39,6 +39,7 @@ use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Selectable; use Doctrine\ORM\Mapping as ORM; use libphonenumber\PhoneNumber; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; @@ -47,34 +48,15 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; /** * Person Class. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_person", - * indexes={ - * - * @ORM\Index( - * name="person_names", - * columns={"firstName", "lastName"} - * ), - * @ORM\Index( - * name="person_birthdate", - * columns={"birthdate"} - * ) - * }) - * - * @ORM\HasLifecycleCallbacks - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "person": Person::class - * }) - * - * @PersonHasCenter - * - * @HouseholdMembershipSequential( - * groups={"household_memberships"} - * ) */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['person' => Person::class])] +#[ORM\Entity] +#[ORM\Index(name: 'person_names', columns: ['firstName', 'lastName'])] // , +#[ORM\Index(name: 'person_birthdate', columns: ['birthdate'])] // @ORM\HasLifecycleCallbacks +#[ORM\Table(name: 'chill_person_person')] +#[ORM\HasLifecycleCallbacks] +#[PersonHasCenter] +#[HouseholdMembershipSequential(groups: ['household_memberships'])] class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateInterface, \Stringable { final public const BOTH_GENDER = 'both'; @@ -92,171 +74,122 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI /** * Accept receiving email. - * - * @ORM\Column(type="boolean", options={"default": false}) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private ?bool $acceptEmail = false; /** * Accept short text message (aka SMS). - * - * @ORM\Column(type="boolean", options={"default": false}) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] private ?bool $acceptSMS = false; /** * The person's accompanying periods (when the person was accompanied by the center). * - * @var Collection - * - * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, - * mappedBy="person", - * cascade={"persist", "remove", "merge", "detach"}) - * - * @ORM\OrderBy({"startDate": "DESC"}) + * @var Collection */ + #[ORM\OneToMany(targetEntity: AccompanyingPeriodParticipation::class, mappedBy: 'person', cascade: ['persist', 'remove', 'merge', 'detach'])] + #[ORM\OrderBy(['startDate' => Criteria::DESC])] private Collection $accompanyingPeriodParticipations; /** * The accompanying period requested by the Person. * - * @ORM\OneToMany(targetEntity=AccompanyingPeriod::class, - * mappedBy="requestorPerson") - * - * @var Collection + * @var Collection */ + #[ORM\OneToMany(targetEntity: AccompanyingPeriod::class, mappedBy: 'requestorPerson')] private Collection $accompanyingPeriodRequested; /** * Addresses. * - * @var Collection
    - * - * @ORM\ManyToMany( - * targetEntity="Chill\MainBundle\Entity\Address", - * cascade={"persist", "remove", "merge", "detach"}) - * - * @ORM\JoinTable(name="chill_person_persons_to_addresses") - * - * @ORM\OrderBy({"validFrom": "DESC"}) + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Address::class, cascade: ['persist', 'remove', 'merge', 'detach'])] + #[ORM\JoinTable(name: 'chill_person_persons_to_addresses')] + #[ORM\OrderBy(['validFrom' => Criteria::DESC])] private Collection $addresses; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\PersonBundle\Entity\PersonAltName", - * mappedBy="person", - * cascade={"persist", "remove", "merge", "detach"}, - * orphanRemoval=true) + * @var Collection */ + #[ORM\OneToMany(targetEntity: PersonAltName::class, mappedBy: 'person', cascade: ['persist', 'remove', 'merge', 'detach'], orphanRemoval: true)] private Collection $altNames; /** * The person's birthdate. - * - * @ORM\Column(type="date", nullable=true) - * - * @Birthdate */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)] + #[Birthdate] private ?\DateTime $birthdate = null; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity=Charge::class, - * mappedBy="person" - * ) + * @var Collection */ + #[ORM\OneToMany(targetEntity: Charge::class, mappedBy: 'person')] private Collection $budgetCharges; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity=Resource::class, - * mappedBy="person" - * ) + * @var Collection */ + #[ORM\OneToMany(targetEntity: Resource::class, mappedBy: 'person')] private Collection $budgetResources; /** * @var Collection - * - * @ORM\ManyToMany( - * targetEntity="Chill\CalendarBundle\Entity\Calendar", - * mappedBy="persons" - * ) */ + #[ORM\ManyToMany(targetEntity: Calendar::class, mappedBy: 'persons')] private Collection $calendars; /** * The person's center. * - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Center") - * * @deprecated */ + #[ORM\ManyToOne(targetEntity: Center::class)] private ?Center $center = null; - /** - * @ORM\OneToOne(targetEntity=PersonCenterCurrent::class, mappedBy="person") - */ + #[ORM\OneToOne(mappedBy: 'person', targetEntity: PersonCenterCurrent::class)] private ?PersonCenterCurrent $centerCurrent = null; /** - * @ORM\OneToMany(targetEntity=PersonCenterHistory::class, mappedBy="person", cascade={"persist", "remove"}) - * - * @var Collection + * @var \Doctrine\Common\Collections\Collection&Selectable */ - private Collection $centerHistory; + #[ORM\OneToMany(mappedBy: 'person', targetEntity: PersonCenterHistory::class, cascade: ['persist', 'remove'])] + private Collection&Selectable $centerHistory; /** * Array where customfield's data are stored. - * - * @ORM\Column(type="json") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private ?array $cFData = null; /** * The marital status of the person. - * - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Civility") - * - * @ORM\JoinColumn(nullable=true) */ + #[ORM\ManyToOne(targetEntity: Civility::class)] + #[ORM\JoinColumn(nullable: true)] private ?Civility $civility = null; /** * Contact information for contacting the person. - * - * @ORM\Column(type="text", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $contactInfo = ''; /** * The person's country of birth. - * - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Country") - * - * sf4 check: option inversedBy="birthsIn" return error mapping !! - * - * @ORM\JoinColumn(nullable=true) */ + #[ORM\ManyToOne(targetEntity: Country::class)] // sf4 check: option inversedBy="birthsIn" return error mapping !! + #[ORM\JoinColumn(nullable: true)] private ?Country $countryOfBirth = null; - /** - * @ORM\Column(type="datetime", nullable=true, options={"default": NULL}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeInterface $createdAt = null; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=true) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] private ?User $createdBy = null; /** @@ -273,258 +206,180 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * The current person address. * * This is computed through database and is optimized on database side. - * - * @ORM\OneToOne(targetEntity=PersonCurrentAddress::class, mappedBy="person") */ + #[ORM\OneToOne(targetEntity: PersonCurrentAddress::class, mappedBy: 'person')] private ?PersonCurrentAddress $currentPersonAddress = null; /** * The person's deathdate. - * - * @ORM\Column(type="date_immutable", nullable=true) - * - * @Assert\Date - * - * @Assert\GreaterThanOrEqual(propertyPath="birthdate") - * - * @Assert\LessThanOrEqual("today") */ + #[Assert\Date] + #[Assert\GreaterThanOrEqual(propertyPath: 'birthdate')] + #[Assert\LessThanOrEqual('today')] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $deathdate = null; /** * The person's email. - * - * @ORM\Column(type="text", nullable=true) - * - * @Assert\Email() */ + #[Assert\Email] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $email = ''; /** * The person's first name. - * - * @ORM\Column(type="string", length=255) - * - * @Assert\NotBlank(message="The firstname cannot be empty") - * - * @Assert\Length( - * max=255, - * ) */ + #[Assert\NotBlank(message: 'The firstname cannot be empty')] + #[Assert\Length(max: 255)] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $firstName = ''; /** * fullname canonical. Read-only field, which is calculated by * the database. - * - * @ORM\Column(type="text", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $fullnameCanonical = ''; /** * The person's gender. - * - * @ORM\Column(type="string", length=9, nullable=true) - * - * @Assert\NotNull(message="The gender must be set") */ + #[Assert\NotNull(message: 'The gender must be set')] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 9, nullable: true)] private ?string $gender = null; /** * Comment on gender. - * - * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="genderComment_") */ + #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'genderComment_')] private CommentEmbeddable $genderComment; /** * Read-only field, computed by the database. * - * @var Collection - * - * @ORM\OneToMany( - * targetEntity=PersonHouseholdAddress::class, - * mappedBy="person" - * ) + * @var Collection */ + #[ORM\OneToMany(targetEntity: PersonHouseholdAddress::class, mappedBy: 'person')] private Collection $householdAddresses; /** - * @ORM\OneToMany( - * targetEntity=HouseholdMember::class, - * mappedBy="person" - * ) - * - * @var Collection + * @var Collection */ + #[ORM\OneToMany(targetEntity: HouseholdMember::class, mappedBy: 'person')] private Collection $householdParticipations; /** * The person's id. - * - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; /** * The person's last name. - * - * @ORM\Column(type="string", length=255) - * - * @Assert\NotBlank(message="The lastname cannot be empty") - * - * @Assert\Length( - * max=255, - * ) */ + #[Assert\NotBlank(message: 'The lastname cannot be empty')] + #[Assert\Length(max: 255)] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $lastName = ''; /** * The marital status of the person. - * - * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\MaritalStatus") - * - * @ORM\JoinColumn(nullable=true) */ + #[ORM\ManyToOne(targetEntity: MaritalStatus::class)] + #[ORM\JoinColumn(nullable: true)] private ?MaritalStatus $maritalStatus = null; /** * Comment on marital status. - * - * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="maritalStatusComment_") */ + #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'maritalStatusComment_')] private CommentEmbeddable $maritalStatusComment; /** * The date of the last marital status change of the person. - * - * @ORM\Column(type="date", nullable=true) - * - * @Assert\Date */ + #[Assert\Date] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)] private ?\DateTime $maritalStatusDate = null; /** * A remark over the person. - * - * @ORM\Column(type="text") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] private string $memo = ''; /** * The person's mobile phone number. - * - * @PhonenumberConstraint(type="mobile") - * - * @ORM\Column(type="phone_number", nullable=true) */ + #[ORM\Column(type: 'phone_number', nullable: true)] + #[PhonenumberConstraint(type: 'mobile')] private ?PhoneNumber $mobilenumber = null; /** * The person's nationality. - * - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Country") - * - * sf4 check: option inversedBy="nationals" return error mapping !! - * - * @ORM\JoinColumn(nullable=true) */ + #[ORM\ManyToOne(targetEntity: Country::class)] // sf4 check: option inversedBy="nationals" return error mapping !! + #[ORM\JoinColumn(nullable: true)] private ?Country $nationality = null; /** * Number of children. - * - * @ORM\Column(type="integer", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true)] private ?int $numberOfChildren = null; /** - * @var Collection - * - * @ORM\OneToMany( - * targetEntity="Chill\PersonBundle\Entity\PersonPhone", - * mappedBy="person", - * cascade={"persist", "remove", "merge", "detach"}, - * orphanRemoval=true - * ) - * - * @Assert\Valid( - * traverse=true, - * ) + * @var Collection */ + #[Assert\Valid(traverse: true)] + #[ORM\OneToMany(targetEntity: PersonPhone::class, mappedBy: 'person', cascade: ['persist', 'remove', 'merge', 'detach'], orphanRemoval: true)] private Collection $otherPhoneNumbers; /** - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriod::class, - * mappedBy="personLocation" - * ) - * - * @var Collection + * @var Collection */ + #[ORM\OneToMany(targetEntity: AccompanyingPeriod::class, mappedBy: 'personLocation')] private Collection $periodLocatedOn; /** * The person's phonenumber. - * - * @ORM\Column(type="phone_number", nullable=true) - * - * @PhonenumberConstraint( - * type="landline", - * ) */ + #[ORM\Column(type: 'phone_number', nullable: true)] + #[PhonenumberConstraint(type: 'landline')] private ?PhoneNumber $phonenumber = null; /** * The person's place of birth. - * - * @ORM\Column(type="string", length=255, name="place_of_birth") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, name: 'place_of_birth')] private string $placeOfBirth = ''; /** * @deprecated - * - * @ORM\Column(type="boolean") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $proxyAccompanyingPeriodOpenState = false; // TO-DELETE ? - /** - * @ORM\OneToMany(targetEntity=PersonResource::class, mappedBy="personOwner") - * - * @var Collection + * @var Collection */ + #[ORM\OneToMany(targetEntity: PersonResource::class, mappedBy: 'personOwner')] private Collection $resources; /** * The person's spoken languages. * - * @var Collection - * - * @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\Language") - * - * @ORM\JoinTable( - * name="persons_spoken_languages", - * joinColumns={@ORM\JoinColumn(name="person_id", referencedColumnName="id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="language_id", referencedColumnName="id")} - * ) + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Language::class)] + #[ORM\JoinTable(name: 'persons_spoken_languages', joinColumns: [new ORM\JoinColumn(name: 'person_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'language_id', referencedColumnName: 'id')])] private Collection $spokenLanguages; - /** - * @ORM\Column(type="datetime", nullable=true, options={"default": NULL}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeInterface $updatedAt = null; - /** - * @ORM\ManyToOne( - * targetEntity=User::class - * ) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $updatedBy = null; /** @@ -1410,11 +1265,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * Validation callback that checks if the accompanying periods are valid. * * This method add violation errors. - * - * @Assert\Callback( - * groups={"accompanying_period_consistent"} - * ) */ + #[Assert\Callback(groups: ['accompanying_period_consistent'])] public function isAccompanyingPeriodValid(ExecutionContextInterface $context) { $r = $this->checkAccompanyingPeriodsAreNotCollapsing(); @@ -1439,11 +1291,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * two addresses with the same validFrom date). * * This method add violation errors. - * - * @Assert\Callback( - * groups={"addresses_consistent"} - * ) */ + #[Assert\Callback(groups: ['addresses_consistent'])] public function isAddressesValid(ExecutionContextInterface $context) { if ($this->hasTwoAdressWithSameValidFromDate()) { @@ -1561,10 +1410,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - /** - * @param \DateTime $birthdate - */ - public function setBirthdate($birthdate): self + public function setBirthdate(?\DateTime $birthdate): self { $this->birthdate = $birthdate; @@ -1595,7 +1441,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - public function setCenterHistory(Collection $centerHistory): Person + public function setCenterHistory(Collection&Selectable $centerHistory): Person { $this->centerHistory = $centerHistory; @@ -1679,7 +1525,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - public function setFullnameCanonical($fullnameCanonical): self + public function setFullnameCanonical(?string $fullnameCanonical): self { $this->fullnameCanonical = $fullnameCanonical; @@ -1787,7 +1633,10 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - public function setSpokenLanguages(mixed $spokenLanguages): self + /** + * @param (Collection) $spokenLanguages + */ + public function setSpokenLanguages(Collection $spokenLanguages): self { $this->spokenLanguages = $spokenLanguages; diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/AbstractPersonResource.php b/src/Bundle/ChillPersonBundle/Entity/Person/AbstractPersonResource.php new file mode 100644 index 000000000..cfdf88555 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/Person/AbstractPersonResource.php @@ -0,0 +1,198 @@ +comment = new CommentEmbeddable(); + } + + public function getComment(): CommentEmbeddable + { + return $this->comment; + } + + public function getFreeText(): ?string + { + return $this->freeText; + } + + public function getKind(): ?PersonResourceKind + { + return $this->kind; + } + + public function getPerson(): ?Person + { + return $this->person; + } + + public function getPersonOwner(): ?Person + { + return $this->personOwner; + } + + /** + * @Groups({"read", "docgen:read"}) + */ + public function getResourceKind(): string + { + if ($this->getPerson() instanceof Person) { + return 'person'; + } + + if ($this->getThirdParty() instanceof ThirdParty) { + return 'thirdparty'; + } + + if (null !== $this->getFreeText()) { + return 'freetext'; + } + + return 'none'; + } + + public function getThirdParty(): ?ThirdParty + { + return $this->thirdParty; + } + + public function setComment(?CommentEmbeddable $comment): self + { + if (null === $comment) { + $this->comment->setComment(''); + + return $this; + } + + $this->comment = $comment; + + return $this; + } + + public function setFreeText(?string $freeText): self + { + $this->freeText = $freeText; + + if ('' !== $freeText && null !== $freeText) { + $this->setPerson(null); + $this->setThirdParty(null); + } + + if ('' === $freeText) { + $this->freeText = null; + } + + return $this; + } + + public function setKind(?PersonResourceKind $kind): self + { + $this->kind = $kind; + + return $this; + } + + public function setPerson(?Person $person): self + { + $this->person = $person; + + if (null !== $person) { + $this->setFreeText(''); + $this->setThirdParty(null); + } + + return $this; + } + + public function setPersonOwner(?Person $personOwner): self + { + $this->personOwner = $personOwner; + + return $this; + } + + public function setThirdParty(?ThirdParty $thirdParty): self + { + $this->thirdParty = $thirdParty; + + if (null !== $thirdParty) { + $this->setFreeText(''); + $this->setPerson(null); + } + + return $this; + } + + /** + * @Assert\Callback + */ + public function validate(ExecutionContextInterface $context, mixed $payload): void + { + if (null === $this->person && null === $this->thirdParty && (null === $this->freeText || '' === $this->freeText)) { + $context->buildViolation('You must associate at least one entity') + ->addViolation(); + } + + if (null !== $this->person && $this->person === $this->personOwner) { + $context->buildViolation('You cannot associate a resource with the same person') + ->addViolation(); + } + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php index 551f8fd03..5590f5329 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php @@ -21,39 +21,26 @@ use Doctrine\ORM\Mapping as ORM; * The process of selecting the current center is done on database side, * using a SQL view. * - * @ORM\Entity(readOnly=true) - * - * @ORM\Table(name="view_chill_person_person_center_history_current") - * * @psalm-internal Chill\PersonBundle\Entity */ +#[ORM\Entity(readOnly: true)] +#[ORM\Table(name: 'view_chill_person_person_center_history_current')] class PersonCenterCurrent { - /** - * @ORM\ManyToOne(targetEntity=Center::class) - */ + #[ORM\ManyToOne(targetEntity: Center::class)] private Center $center; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\OneToOne(targetEntity=Person::class, inversedBy="centerCurrent") - */ + #[ORM\OneToOne(targetEntity: Person::class, inversedBy: 'centerCurrent')] private Person $person; - /** - * @ORM\Column(type="date_immutable", nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)] private \DateTimeImmutable $startDate; /** diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php index cc95b5a20..6c5d19413 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php @@ -21,46 +21,31 @@ use Doctrine\ORM\Mapping as ORM; /** * Associate a Person with a Center. The association may change on date intervals. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_person_center_history") */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_person_center_history')] class PersonCenterHistory implements TrackCreationInterface, TrackUpdateInterface { use TrackCreationTrait; use TrackUpdateTrait; - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: true, options: ['default' => null])] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; public function __construct( - /** - * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerHistory") - */ + #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'centerHistory')] private ?Person $person = null, - /** - * @ORM\ManyToOne(targetEntity=Center::class) - */ + #[ORM\ManyToOne(targetEntity: Center::class)] private ?Center $center = null, - /** - * @ORM\Column(type="date_immutable", nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)] private ?\DateTimeImmutable $startDate = null, - ) { - } + ) {} public function getCenter(): ?Center { diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCurrentAddress.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCurrentAddress.php index 1ec28f423..4e4761987 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCurrentAddress.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCurrentAddress.php @@ -23,35 +23,23 @@ use Doctrine\ORM\Mapping as ORM; * * The validFrom and validTo properties are the intersection of * household membership and address validity. See @see{PersonHouseholdAddress} - * - * @ORM\Entity(readOnly=true) - * - * @ORM\Table("view_chill_person_current_address") */ +#[ORM\Entity(readOnly: true)] +#[ORM\Table('view_chill_person_current_address')] class PersonCurrentAddress { - /** - * @ORM\OneToOne(targetEntity=Address::class) - */ + #[ORM\OneToOne(targetEntity: Address::class)] protected Address $address; - /** - * @ORM\Id - * - * @ORM\OneToOne(targetEntity=Person::class, inversedBy="currentPersonAddress") - * - * @ORM\JoinColumn(name="person_id", referencedColumnName="id") - */ + #[ORM\Id] + #[ORM\OneToOne(targetEntity: Person::class, inversedBy: 'currentPersonAddress')] + #[ORM\JoinColumn(name: 'person_id', referencedColumnName: 'id')] protected Person $person; - /** - * @ORM\Column(name="valid_from", type="date_immutable") - */ + #[ORM\Column(name: 'valid_from', type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE)] protected \DateTimeImmutable $validFrom; - /** - * @ORM\Column(name="valid_to", type="date_immutable") - */ + #[ORM\Column(name: 'valid_to', type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE)] protected ?\DateTimeImmutable $validTo = null; public function getAddress(): Address diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonResource.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonResource.php index c5c2c8d08..4c86f8c4c 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/PersonResource.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonResource.php @@ -12,241 +12,24 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity\Person; use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; -use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; -use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; -use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; -use Chill\PersonBundle\Entity\Person; -use Chill\ThirdPartyBundle\Entity\ThirdParty; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation\Groups; -use Symfony\Component\Validator\Constraints as Assert; -use Symfony\Component\Validator\Context\ExecutionContextInterface; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_resource") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "personResource": personResource::class - * }) - */ -class PersonResource implements TrackCreationInterface, TrackUpdateInterface +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['personResource' => PersonResource::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_resource')] +class PersonResource extends AbstractPersonResource implements TrackCreationInterface, TrackUpdateInterface { - use TrackCreationTrait; - - use TrackUpdateTrait; - - /** - * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ - private CommentEmbeddable $comment; - - /** - * @ORM\Column(type="text", nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ - private ?string $freeText = null; - - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Groups({"read", "docgen:read"}) - */ + #[Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=PersonResourceKind::class, inversedBy="personResources") - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ - private ?PersonResourceKind $kind = null; - - /** - * The person which host the owner of this resource. - * - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ - private ?Person $person = null; - - /** - * The person linked with this resource. - * - * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="resources") - * - * @ORM\JoinColumn(nullable=false) - * - * @Groups({"read"}) - */ - private ?Person $personOwner = null; - - /** - * @ORM\ManyToOne(targetEntity=ThirdParty::class, inversedBy="personResources") - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read", "docgen:read"}) - */ - private ?ThirdParty $thirdParty = null; - - public function __construct() - { - $this->comment = new CommentEmbeddable(); - } - - public function getComment(): CommentEmbeddable - { - return $this->comment; - } - - public function getFreeText(): ?string - { - return $this->freeText; - } - - /** - * GETTERS. - */ public function getId(): ?int { return $this->id; } - - public function getKind(): ?PersonResourceKind - { - return $this->kind; - } - - public function getPerson(): ?Person - { - return $this->person; - } - - public function getPersonOwner(): ?Person - { - return $this->personOwner; - } - - /** - * @Groups({"read", "docgen:read"}) - */ - public function getResourceKind(): string - { - if ($this->getPerson() instanceof Person) { - return 'person'; - } - - if ($this->getThirdParty() instanceof ThirdParty) { - return 'thirdparty'; - } - - if (null !== $this->getFreeText()) { - return 'freetext'; - } - - return 'none'; - } - - public function getThirdParty(): ?ThirdParty - { - return $this->thirdParty; - } - - public function setComment(?CommentEmbeddable $comment): self - { - if (null === $comment) { - $this->comment->setComment(''); - - return $this; - } - - $this->comment = $comment; - - return $this; - } - - public function setFreeText(?string $freeText): self - { - $this->freeText = $freeText; - - if ('' !== $freeText && null !== $freeText) { - $this->setPerson(null); - $this->setThirdParty(null); - } - - if ('' === $freeText) { - $this->freeText = null; - } - - return $this; - } - - public function setKind(?PersonResourceKind $kind): self - { - $this->kind = $kind; - - return $this; - } - - public function setPerson(?Person $person): self - { - $this->person = $person; - - if (null !== $person) { - $this->setFreeText(''); - $this->setThirdParty(null); - } - - return $this; - } - - public function setPersonOwner(?Person $personOwner): self - { - $this->personOwner = $personOwner; - - return $this; - } - - public function setThirdParty(?ThirdParty $thirdParty): self - { - $this->thirdParty = $thirdParty; - - if (null !== $thirdParty) { - $this->setFreeText(''); - $this->setPerson(null); - } - - return $this; - } - - /** - * @Assert\Callback - */ - public function validate(ExecutionContextInterface $context, mixed $payload) - { - if (null === $this->person && null === $this->thirdParty && (null === $this->freeText || '' === $this->freeText)) { - $context->buildViolation('You must associate at least one entity') - ->addViolation(); - } - - if (null !== $this->person && $this->person === $this->personOwner) { - $context->buildViolation('You cannot associate a resource with the same person') - ->addViolation(); - } - } } diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonResourceKind.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonResourceKind.php index f036e4b4a..b0ce8f136 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/PersonResourceKind.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonResourceKind.php @@ -14,36 +14,22 @@ namespace Chill\PersonBundle\Entity\Person; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_resource_kind") - */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_resource_kind')] class PersonResourceKind { - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $isActive = true; - /** - * @ORM\Column(type="json", length=255) - * - * @Serializer\Groups({"docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, length: 255)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $title; public function getId(): ?int diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/ResidentialAddress.php b/src/Bundle/ChillPersonBundle/Entity/Person/ResidentialAddress.php index acd312190..d1379530f 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/ResidentialAddress.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/ResidentialAddress.php @@ -20,75 +20,44 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Context; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity(repositoryClass=ResidentialAddressRepository::class) - * - * @ORM\Table(name="chill_person_residential_address") - */ +#[ORM\Entity(repositoryClass: ResidentialAddressRepository::class)] +#[ORM\Table(name: 'chill_person_residential_address')] class ResidentialAddress { - /** - * @ORM\ManyToOne(targetEntity=Address::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\ManyToOne(targetEntity: Address::class)] + #[ORM\JoinColumn(nullable: true)] private ?Address $address = null; - /** - * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="residentialAddressComment_") - */ + #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'residentialAddressComment_')] private CommentEmbeddable $comment; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $endDate = null; - /** - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read"}) - * - * @Context(normalizationContext={"groups": {"minimal"}}) - */ + #[Groups(['read'])] + #[ORM\ManyToOne(targetEntity: Person::class)] + #[ORM\JoinColumn(nullable: true)] + #[Context(normalizationContext: ['groups' => ['minimal']])] private ?Person $hostPerson = null; - /** - * @ORM\ManyToOne(targetEntity=ThirdParty::class) - * - * @ORM\JoinColumn(nullable=true) - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\ManyToOne(targetEntity: ThirdParty::class)] + #[ORM\JoinColumn(nullable: true)] private ?ThirdParty $hostThirdParty = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: Person::class)] + #[ORM\JoinColumn(nullable: false)] private Person $person; - /** - * @ORM\Column(type="datetime_immutable") - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)] private ?\DateTimeImmutable $startDate = null; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/PersonAltName.php b/src/Bundle/ChillPersonBundle/Entity/PersonAltName.php index c17172882..4a4aaae1a 100644 --- a/src/Bundle/ChillPersonBundle/Entity/PersonAltName.php +++ b/src/Bundle/ChillPersonBundle/Entity/PersonAltName.php @@ -16,42 +16,25 @@ use Symfony\Component\Serializer\Annotation\Groups; /** * PersonAltName. - * - * @ORM\Table(name="chill_person_alt_name") - * - * @ORM\Entity */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_alt_name')] class PersonAltName { - /** - * @ORM\Column(name="id", type="integer") - * - * @ORM\Id - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\Column(name="key", type="string", length=255) - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(name: 'key', type: \Doctrine\DBAL\Types\Types::STRING, length: 255)] private string $key = ''; - /** - * @ORM\Column(name="label", type="text") - * - * @Groups({"write"}) - */ + #[Groups(['write'])] + #[ORM\Column(name: 'label', type: \Doctrine\DBAL\Types\Types::TEXT)] private string $label = ''; - /** - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\Person", - * inversedBy="altNames" - * ) - */ + #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'altNames')] private ?Person $person = null; /** diff --git a/src/Bundle/ChillPersonBundle/Entity/PersonNotDuplicate.php b/src/Bundle/ChillPersonBundle/Entity/PersonNotDuplicate.php index 7d296576c..323752e54 100644 --- a/src/Bundle/ChillPersonBundle/Entity/PersonNotDuplicate.php +++ b/src/Bundle/ChillPersonBundle/Entity/PersonNotDuplicate.php @@ -12,47 +12,33 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity; use Chill\MainBundle\Entity\User; -use DateTime; use Doctrine\ORM\Mapping as ORM; /** * PersonNotDuplicate. - * - * @ORM\Table(name="chill_person_not_duplicate") - * - * @ORM\Entity */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_not_duplicate')] class PersonNotDuplicate { - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)] private \DateTime $date; /** * The person's id. - * - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person") - */ + #[ORM\ManyToOne(targetEntity: Person::class)] private ?Person $person1 = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person") - */ + #[ORM\ManyToOne(targetEntity: Person::class)] private ?Person $person2 = null; - /** - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") - */ + #[ORM\ManyToOne(targetEntity: User::class)] private ?User $user = null; public function __construct() @@ -90,7 +76,7 @@ class PersonNotDuplicate $this->date = $date; } - public function setId($id) + public function setId(?int $id) { $this->id = $id; } diff --git a/src/Bundle/ChillPersonBundle/Entity/PersonPhone.php b/src/Bundle/ChillPersonBundle/Entity/PersonPhone.php index c994e487b..8edf4411a 100644 --- a/src/Bundle/ChillPersonBundle/Entity/PersonPhone.php +++ b/src/Bundle/ChillPersonBundle/Entity/PersonPhone.php @@ -11,58 +11,36 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity; -use DateTime; use Doctrine\ORM\Mapping as ORM; use libphonenumber\PhoneNumber; /** * Person Phones. - * - * @ORM\Entity - * - * @ORM\Table(name="chill_person_phone", - * indexes={ - * - * @ORM\Index(name="phonenumber", columns={"phonenumber"}) - * }) */ +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_phone')] +#[ORM\Index(name: 'phonenumber', columns: ['phonenumber'])] +#[ORM\Index(name: 'phonenumber', columns: ['phonenumber'])] class PersonPhone { - /** - * @ORM\Column(type="datetime", nullable=false) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: false)] private \DateTime $date; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $description = null; - /** - * @ORM\Id - * - * @ORM\Column(name="id", type="integer") - * - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\Person", - * inversedBy="otherPhoneNumbers" - * ) - */ + #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'otherPhoneNumbers')] private Person $person; - /** - * @ORM\Column(type="phone_number", nullable=false) - */ + #[ORM\Column(type: 'phone_number', nullable: false)] private ?PhoneNumber $phonenumber = null; - /** - * @ORM\Column(type="text", length=40, nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, length: 40, nullable: true)] private ?string $type = null; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php index a8c542622..56d051608 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php +++ b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php @@ -15,51 +15,29 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_relations") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "relation": Relation::class - * }) - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['relation' => Relation::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_relations')] class Relation { - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="boolean", nullable=true) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: true)] private bool $isActive = true; - /** - * @ORM\Column(type="json", nullable=true) - * - * @Serializer\Groups({"read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: true)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $reverseTitle = []; - /** - * @ORM\Column(type="json", nullable=true) - * - * @Serializer\Groups({"read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: true)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $title = []; public function getId(): ?int diff --git a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php index ce56fa013..2325f4221 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php +++ b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php @@ -12,8 +12,9 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity\Relationships; use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; +use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; -use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Validator\Constraints\Relationship\RelationshipNoDuplicate; use Doctrine\ORM\Mapping as ORM; @@ -23,109 +24,45 @@ use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_relationships") - * - * @DiscriminatorColumn(name="relation_id", type="integer") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "relationship": Relationship::class - * }) - * - * @RelationshipNoDuplicate - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['relationship' => Relationship::class])] +#[ORM\Entity] +#[DiscriminatorColumn(name: 'relation_id', type: 'integer')] +#[ORM\Table(name: 'chill_person_relationships')] +#[RelationshipNoDuplicate] class Relationship implements TrackCreationInterface, TrackUpdateInterface { - /** - * @ORM\Column(type="datetime_immutable") - */ - private ?\DateTimeImmutable $createdAt = null; + use TrackCreationTrait; + use TrackUpdateTrait; - /** - * @ORM\ManyToOne(targetEntity=User::class) - * - * @ORM\JoinColumn(nullable=false) - */ - private ?User $createdBy = null; - - /** - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Assert\NotNull - * - * @Serializer\Groups({"read", "write"}) - */ + #[Assert\NotNull] + #[Serializer\Groups(['read', 'write'])] + #[ORM\ManyToOne(targetEntity: Person::class)] + #[ORM\JoinColumn(nullable: false)] private ?Person $fromPerson = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=Relation::class) - * - * @ORM\JoinColumn(nullable=false, name="relation_id", referencedColumnName="id") - * - * @Assert\NotNull - * - * @Serializer\Groups({"read", "write"}) - */ + #[Assert\NotNull] + #[Serializer\Groups(['read', 'write'])] + #[ORM\ManyToOne(targetEntity: Relation::class)] + #[ORM\JoinColumn(nullable: false, name: 'relation_id', referencedColumnName: 'id')] private ?Relation $relation = null; - /** - * @ORM\Column(type="boolean") - * - * @Assert\Type( - * type="bool", - * message="This must be of type boolean" - * ) - * - * @Serializer\Groups({"read", "write"}) - */ + #[Assert\Type(type: 'bool', message: 'This must be of type boolean')] + #[Serializer\Groups(['read', 'write'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] private bool $reverse; - /** - * @ORM\ManyToOne(targetEntity=Person::class) - * - * @ORM\JoinColumn(nullable=false) - * - * @Assert\NotNull - * - * @Serializer\Groups({"read", "write"}) - */ + #[Assert\NotNull] + #[Serializer\Groups(['read', 'write'])] + #[ORM\ManyToOne(targetEntity: Person::class)] + #[ORM\JoinColumn(nullable: false)] private ?Person $toPerson = null; - /** - * @ORM\Column(type="datetime_immutable", nullable=true) - */ - private ?\DateTimeImmutable $updatedAt = null; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ - private ?User $updatedBy = null; - - public function getCreatedAt(): ?\DateTimeImmutable - { - return $this->createdAt; - } - - public function getCreatedBy(): ?User - { - return $this->createdBy; - } - public function getFromPerson(): ?Person { return $this->fromPerson; @@ -178,30 +115,6 @@ class Relationship implements TrackCreationInterface, TrackUpdateInterface return $this->toPerson; } - public function getUpdatedAt(): ?\DateTimeImmutable - { - return $this->updatedAt; - } - - public function getUpdatedBy(): ?User - { - return $this->updatedBy; - } - - public function setCreatedAt(\DateTimeInterface $createdAt): self - { - $this->createdAt = $createdAt; - - return $this; - } - - public function setCreatedBy(?User $user): self - { - $this->createdBy = $user; - - return $this; - } - public function setFromPerson(?Person $fromPerson): self { $this->fromPerson = $fromPerson; @@ -229,18 +142,4 @@ class Relationship implements TrackCreationInterface, TrackUpdateInterface return $this; } - - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self - { - $this->updatedAt = $updatedAt; - - return $this; - } - - public function setUpdatedBy(?User $updatedBy): self - { - $this->updatedBy = $updatedBy; - - return $this; - } } diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php index 4ec5bcf78..8a1fc1c9b 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php @@ -11,77 +11,46 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity\SocialWork; -use DateInterval; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_social_work_evaluation") - * - * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "social_work_evaluation": Evaluation::class - * }) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['social_work_evaluation' => Evaluation::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_social_work_evaluation')] class Evaluation { - /** - * @ORM\Column(type="boolean", nullable=false, options={"default": true}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: false, options: ['default' => true])] private bool $active = true; - /** - * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATEINTERVAL, nullable: true, options: ['default' => null])] private ?\DateInterval $delay = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) - * - * @Serializer\Groups({"read"}) - */ + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATEINTERVAL, nullable: true, options: ['default' => null])] private ?\DateInterval $notificationDelay = null; /** - * @var Collection - * - * @ORM\ManyToMany( - * targetEntity=SocialAction::class, - * mappedBy="evaluations" - * ) + * @var \Doctrine\Common\Collections\Collection */ + #[ORM\ManyToMany(targetEntity: SocialAction::class, mappedBy: 'evaluations')] private Collection $socialActions; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $title = []; - /** - * @ORM\Column(type="text", nullable=true) - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)] private ?string $url = null; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php index 856e565eb..2d297607e 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php @@ -16,59 +16,36 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_social_work_goal") - * - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "social_work_goal": Goal::class - * } - * ) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['social_work_goal' => Goal::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_social_work_goal')] class Goal { - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTimeInterface $desactivationDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="goals") - * - * @ORM\JoinTable(name="chill_person_social_work_goal_result") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Result::class, inversedBy: 'goals')] + #[ORM\JoinTable(name: 'chill_person_social_work_goal_result')] private Collection $results; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=SocialAction::class, mappedBy="goals") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: SocialAction::class, mappedBy: 'goals')] private Collection $socialActions; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $title = []; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php index c8afb0456..f5b8aaa92 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php @@ -13,77 +13,52 @@ namespace Chill\PersonBundle\Entity\SocialWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkGoal; -use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_social_work_result") - * - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "social_work_result": Result::class - * } - * ) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['social_work_result' => Result::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_social_work_result')] class Result { /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=AccompanyingPeriodWorkGoal::class, mappedBy="results") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: AccompanyingPeriodWorkGoal::class, mappedBy: 'results')] private Collection $accompanyingPeriodWorkGoals; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=AccompanyingPeriodWork::class, mappedBy="results") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: AccompanyingPeriodWork::class, mappedBy: 'results')] private Collection $accompanyingPeriodWorks; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTime $desactivationDate = null; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Goal::class, mappedBy="results") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Goal::class, mappedBy: 'results')] private Collection $goals; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - * - * @Serializer\Groups({"read", "docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=SocialAction::class, mappedBy="results") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: SocialAction::class, mappedBy: 'results')] private Collection $socialActions; - /** - * @ORM\Column(type="json") - * - * @Serializer\Groups({"read", "docgen:read"}) - * - * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) - */ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] private array $title = []; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php index 12b2c41f2..0d0a59c87 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php @@ -11,98 +11,65 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity\SocialWork; -use DateInterval; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ReadableCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_social_action") - * - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "social_work_social_action": SocialAction::class - * } - * ) - */ +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['social_work_social_action' => SocialAction::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_social_action')] class SocialAction { /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=SocialAction::class, mappedBy="parent") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'parent', targetEntity: SocialAction::class)] private Collection $children; - /** - * @ORM\Column(type="dateinterval", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATEINTERVAL, nullable: true)] private ?\DateInterval $defaultNotificationDelay = null; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTimeInterface $desactivationDate = null; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Evaluation::class, inversedBy="socialActions") - * - * @ORM\JoinTable(name="chill_person_social_work_evaluation_action") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Evaluation::class, inversedBy: 'socialActions')] + #[ORM\JoinTable(name: 'chill_person_social_work_evaluation_action')] private Collection $evaluations; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Goal::class, inversedBy="socialActions") - * - * @ORM\JoinTable(name="chill_person_social_action_goal") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Goal::class, inversedBy: 'socialActions')] + #[ORM\JoinTable(name: 'chill_person_social_action_goal')] private Collection $goals; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="socialActions") - */ + #[ORM\ManyToOne(targetEntity: SocialIssue::class, inversedBy: 'socialActions')] private ?SocialIssue $issue = null; - /** - * @ORM\Column(type="float", name="ordering", options={"default": 0.0}) - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', options: ['default' => '0.0'])] private float $ordering = 0.0; - /** - * @ORM\ManyToOne(targetEntity=SocialAction::class, inversedBy="children") - */ + #[ORM\ManyToOne(targetEntity: SocialAction::class, inversedBy: 'children')] private ?SocialAction $parent = null; /** - * @var Collection - * - * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="socialActions") - * - * @ORM\JoinTable(name="chill_person_social_action_result") + * @var Collection */ + #[ORM\ManyToMany(targetEntity: Result::class, inversedBy: 'socialActions')] + #[ORM\JoinTable(name: 'chill_person_social_action_result')] private Collection $results; - /** - * @ORM\Column(type="json") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $title = []; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php index 397e5a826..02c38a60a 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php @@ -13,64 +13,44 @@ namespace Chill\PersonBundle\Entity\SocialWork; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * - * @ORM\Table(name="chill_person_social_issue") - * - * @DiscriminatorMap(typeProperty="type", mapping={ - * "social_issue": SocialIssue::class - * }) - */ +#[DiscriminatorMap(typeProperty: 'type', mapping: ['social_issue' => SocialIssue::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_social_issue')] class SocialIssue { /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=SocialIssue::class, mappedBy="parent") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'parent', targetEntity: SocialIssue::class)] private Collection $children; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTimeInterface $desactivationDate = null; - /** - * @ORM\Id - * - * @ORM\GeneratedValue - * - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] private ?int $id = null; - /** - * @ORM\Column(type="float", name="ordering", options={"default": 0.0}) - */ + #[ORM\Column(name: 'ordering', type: Types::FLOAT, options: ['default' => '0.0'])] private float $ordering = 0.0; - /** - * @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="children") - */ + #[ORM\ManyToOne(targetEntity: SocialIssue::class, inversedBy: 'children')] private ?SocialIssue $parent = null; /** - * @var Collection - * - * @ORM\OneToMany(targetEntity=SocialAction::class, mappedBy="issue") + * @var Collection */ + #[ORM\OneToMany(mappedBy: 'issue', targetEntity: SocialAction::class)] private Collection $socialActions; - /** - * @ORM\Column(type="json") - * - * @Groups({"read"}) - */ + #[Groups(['read'])] + #[ORM\Column(type: Types::JSON)] private array $title = []; public function __construct() diff --git a/src/Bundle/ChillPersonBundle/Event/Person/PersonAddressMoveEvent.php b/src/Bundle/ChillPersonBundle/Event/Person/PersonAddressMoveEvent.php index a65f68102..cf15018fd 100644 --- a/src/Bundle/ChillPersonBundle/Event/Person/PersonAddressMoveEvent.php +++ b/src/Bundle/ChillPersonBundle/Event/Person/PersonAddressMoveEvent.php @@ -29,9 +29,7 @@ class PersonAddressMoveEvent extends Event private ?HouseholdMember $previousMembership = null; - public function __construct(private readonly Person $person) - { - } + public function __construct(private readonly Person $person) {} /** * Get the date of the move. diff --git a/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php b/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php index 60d521424..c6b366fc8 100644 --- a/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php +++ b/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php @@ -17,9 +17,7 @@ use Symfony\Component\Security\Core\Security; class AccompanyingPeriodWorkEventListener { - public function __construct(private readonly Security $security) - { - } + public function __construct(private readonly Security $security) {} public function prePersistAccompanyingPeriodWork(AccompanyingPeriodWork $work): void { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/AdministrativeLocationAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/AdministrativeLocationAggregator.php index 6d15566af..522b2ecdd 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/AdministrativeLocationAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/AdministrativeLocationAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; class AdministrativeLocationAggregator implements AggregatorInterface { - public function __construct(private readonly LocationRepository $locationRepository, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly LocationRepository $locationRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingMotiveAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingMotiveAggregator.php index 9ea9998b3..259d5fb66 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingMotiveAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingMotiveAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ClosingMotiveAggregator implements AggregatorInterface { - public function __construct(private readonly ClosingMotiveRepositoryInterface $motiveRepository, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly ClosingMotiveRepositoryInterface $motiveRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ConfidentialAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ConfidentialAggregator.php index 3c404c513..0e3e5f735 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ConfidentialAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ConfidentialAggregator.php @@ -19,9 +19,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class ConfidentialAggregator implements AggregatorInterface { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index cfcb04378..94202d958 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -27,8 +27,7 @@ class CreatorJobAggregator implements AggregatorInterface public function __construct( private readonly UserJobRepository $jobRepository, private readonly TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -79,9 +78,7 @@ class CreatorJobAggregator implements AggregatorInterface return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/DurationAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/DurationAggregator.php index f0dbec2c4..f5dc99115 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/DurationAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/DurationAggregator.php @@ -26,9 +26,7 @@ final readonly class DurationAggregator implements AggregatorInterface 'day', ]; - public function __construct(private TranslatorInterface $translator) - { - } + public function __construct(private TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php index c215eeb6a..0217166d2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php @@ -19,9 +19,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class EmergencyAggregator implements AggregatorInterface { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EvaluationAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EvaluationAggregator.php index de2f9305e..a90896ccd 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EvaluationAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EvaluationAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class EvaluationAggregator implements AggregatorInterface { - public function __construct(private EvaluationRepository $evaluationRepository, private TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private EvaluationRepository $evaluationRepository, private TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php index 6b8b77a88..fde825a88 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php @@ -28,12 +28,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class GeographicalUnitStatAggregator implements AggregatorInterface { - public function __construct( - private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, - private TranslatableStringHelperInterface $translatableStringHelper, - private RollingDateConverterInterface $rollingDateConverter, - ) { - } + public function __construct(private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private TranslatableStringHelperInterface $translatableStringHelper, private RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/IntensityAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/IntensityAggregator.php index d7dff6265..de42039c1 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/IntensityAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/IntensityAggregator.php @@ -19,9 +19,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class IntensityAggregator implements AggregatorInterface { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php index cfb9d53aa..bac34096f 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php @@ -28,8 +28,7 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface public function __construct( private UserJobRepositoryInterface $userJobRepository, private TranslatableStringHelperInterface $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -73,9 +72,7 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OriginAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OriginAggregator.php index 9b88a8513..070122f2e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OriginAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OriginAggregator.php @@ -20,13 +20,13 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -final class OriginAggregator implements AggregatorInterface +final readonly class OriginAggregator implements AggregatorInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct( EntityManagerInterface $em, - private readonly TranslatableStringHelper $translatableStringHelper, + private TranslatableStringHelper $translatableStringHelper, ) { $this->repository = $em->getRepository(Origin::class); } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/PersonParticipatingAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/PersonParticipatingAggregator.php index 632d0402d..3859eded5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/PersonParticipatingAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/PersonParticipatingAggregator.php @@ -23,8 +23,7 @@ final readonly class PersonParticipatingAggregator implements AggregatorInterfac public function __construct( private LabelPersonHelper $labelPersonHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php index d0776dbd2..2df724517 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php @@ -32,8 +32,7 @@ final readonly class ReferrerAggregator implements AggregatorInterface, DataTran private UserRepository $userRepository, private UserRender $userRender, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index 3525538fd..c5f274cc4 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -32,8 +32,7 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface, DataTrans private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelperInterface $translatableStringHelper, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/RequestorAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/RequestorAggregator.php index 824d7431f..ec168ceaf 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/RequestorAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/RequestorAggregator.php @@ -19,9 +19,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final readonly class RequestorAggregator implements AggregatorInterface { - public function __construct(private TranslatorInterface $translator) - { - } + public function __construct(private TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php index d7cdfbab1..06dbc906d 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class ScopeAggregator implements AggregatorInterface { - public function __construct(private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php index 23159cae8..dd33603b4 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php @@ -28,8 +28,7 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa public function __construct( private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelperInterface $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -73,9 +72,7 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialActionAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialActionAggregator.php index 4459d634a..7abad2602 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialActionAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialActionAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class SocialActionAggregator implements AggregatorInterface { - public function __construct(private SocialActionRender $actionRender, private SocialActionRepository $actionRepository) - { - } + public function __construct(private SocialActionRender $actionRender, private SocialActionRepository $actionRepository) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialIssueAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialIssueAggregator.php index 02746f82a..8c0cbfbd5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialIssueAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/SocialIssueAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class SocialIssueAggregator implements AggregatorInterface { - public function __construct(private SocialIssueRepository $issueRepository, private SocialIssueRender $issueRender) - { - } + public function __construct(private SocialIssueRepository $issueRepository, private SocialIssueRender $issueRender) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/StepAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/StepAggregator.php index 5623a7212..a9439a63f 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/StepAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/StepAggregator.php @@ -27,9 +27,7 @@ final readonly class StepAggregator implements AggregatorInterface private const P = 'acp_step_agg_date'; - public function __construct(private RollingDateConverterInterface $rollingDateConverter, private TranslatorInterface $translator) - { - } + public function __construct(private RollingDateConverterInterface $rollingDateConverter, private TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index a46fdc5b4..b5d6566e7 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -32,8 +32,7 @@ final readonly class UserJobAggregator implements AggregatorInterface, DataTrans private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php index b4bc40c10..321801e28 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php @@ -27,8 +27,7 @@ final readonly class UserWorkingOnCourseAggregator implements AggregatorInterfac public function __construct( private UserRender $userRender, private UserRepositoryInterface $userRepository, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByClosingMotiveAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByClosingMotiveAggregator.php index b5776ebeb..6b6a5ce4a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByClosingMotiveAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByClosingMotiveAggregator.php @@ -25,8 +25,7 @@ final readonly class ByClosingMotiveAggregator implements AggregatorInterface public function __construct( private ClosingMotiveRepositoryInterface $closingMotiveRepository, private ClosingMotiveRender $closingMotiveRender, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByStepAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByStepAggregator.php index 48161ee05..b3be83da2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByStepAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingPeriodStepHistoryAggregators/ByStepAggregator.php @@ -27,8 +27,7 @@ final readonly class ByStepAggregator implements AggregatorInterface public function __construct( private TranslatorInterface $translator, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/EvaluationTypeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/EvaluationTypeAggregator.php index 593e23420..9ff2ad50a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/EvaluationTypeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/EvaluationTypeAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; class EvaluationTypeAggregator implements AggregatorInterface { - public function __construct(private readonly EvaluationRepository $evaluationRepository, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly EvaluationRepository $evaluationRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/HavingEndDateAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/HavingEndDateAggregator.php index 8960cbd86..4dfddab81 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/HavingEndDateAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/EvaluationAggregators/HavingEndDateAggregator.php @@ -19,9 +19,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class HavingEndDateAggregator implements AggregatorInterface { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/ChildrenNumberAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/ChildrenNumberAggregator.php index 750841337..e013c2f0f 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/ChildrenNumberAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/ChildrenNumberAggregator.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ChildrenNumberAggregator implements AggregatorInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/CompositionAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/CompositionAggregator.php index 45263dd52..3dc3a1398 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/CompositionAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/HouseholdAggregators/CompositionAggregator.php @@ -24,9 +24,7 @@ use Symfony\Component\Form\FormBuilderInterface; class CompositionAggregator implements AggregatorInterface { - public function __construct(private readonly HouseholdCompositionTypeRepository $typeRepository, private readonly TranslatableStringHelper $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly HouseholdCompositionTypeRepository $typeRepository, private readonly TranslatableStringHelper $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/AgeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/AgeAggregator.php index 68ed28492..2ca286b57 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/AgeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/AgeAggregator.php @@ -24,8 +24,7 @@ final readonly class AgeAggregator implements AggregatorInterface, ExportElement { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/ByHouseholdCompositionAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/ByHouseholdCompositionAggregator.php index 06647dbc7..af1018f6e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/ByHouseholdCompositionAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/ByHouseholdCompositionAggregator.php @@ -27,9 +27,7 @@ class ByHouseholdCompositionAggregator implements AggregatorInterface { private const PREFIX = 'acp_by_household_compo_agg'; - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly HouseholdCompositionTypeRepositoryInterface $householdCompositionTypeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly HouseholdCompositionTypeRepositoryInterface $householdCompositionTypeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php index fd48bdb01..cd48a3f51 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php @@ -27,8 +27,7 @@ final readonly class CenterAggregator implements AggregatorInterface public function __construct( private CenterRepositoryInterface $centerRepository, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CountryOfBirthAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CountryOfBirthAggregator.php index e54714d7a..b8d204dc5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CountryOfBirthAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CountryOfBirthAggregator.php @@ -25,9 +25,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final readonly class CountryOfBirthAggregator implements AggregatorInterface, ExportElementValidatedInterface { - public function __construct(private CountryRepository $countriesRepository, private TranslatableStringHelper $translatableStringHelper, private TranslatorInterface $translator) - { - } + public function __construct(private CountryRepository $countriesRepository, private TranslatableStringHelper $translatableStringHelper, private TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php index 05a9273e5..0181c6e7b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php @@ -20,9 +20,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final readonly class GenderAggregator implements AggregatorInterface { - public function __construct(private TranslatorInterface $translator) - { - } + public function __construct(private TranslatorInterface $translator) {} public function addRole(): ?string { @@ -41,9 +39,7 @@ final readonly class GenderAggregator implements AggregatorInterface return Declarations::PERSON_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php index 8691f8cd3..8ce51a3ab 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php @@ -26,9 +26,7 @@ use Symfony\Component\Form\FormBuilderInterface; class GeographicalUnitAggregator implements AggregatorInterface { - public function __construct(private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/HouseholdPositionAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/HouseholdPositionAggregator.php index f44b949dc..eb1e52d9b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/HouseholdPositionAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/HouseholdPositionAggregator.php @@ -28,9 +28,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final readonly class HouseholdPositionAggregator implements AggregatorInterface, ExportElementValidatedInterface { - public function __construct(private TranslatorInterface $translator, private TranslatableStringHelper $translatableStringHelper, private PositionRepository $positionRepository, private RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private TranslatorInterface $translator, private TranslatableStringHelper $translatableStringHelper, private PositionRepository $positionRepository, private RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php index c0f86ea25..1555a5a12 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class MaritalStatusAggregator implements AggregatorInterface { - public function __construct(private MaritalStatusRepository $maritalStatusRepository, private TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private MaritalStatusRepository $maritalStatusRepository, private TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php index bc11565e4..9daca5b34 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php @@ -24,9 +24,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final readonly class NationalityAggregator implements AggregatorInterface, ExportElementValidatedInterface { - public function __construct(private CountryRepository $countriesRepository, private TranslatableStringHelper $translatableStringHelper, private TranslatorInterface $translator) - { - } + public function __construct(private CountryRepository $countriesRepository, private TranslatableStringHelper $translatableStringHelper, private TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/PostalCodeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/PostalCodeAggregator.php index aa06fff61..a8ec614d4 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/PostalCodeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/PostalCodeAggregator.php @@ -26,8 +26,7 @@ final readonly class PostalCodeAggregator implements AggregatorInterface public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php index 901bd1cb6..9abf5c1e7 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class ActionTypeAggregator implements AggregatorInterface { - public function __construct(private SocialActionRepository $socialActionRepository, private SocialActionRender $actionRender, private SocialIssueRender $socialIssueRender, private SocialIssueRepository $socialIssueRepository) - { - } + public function __construct(private SocialActionRepository $socialActionRepository, private SocialActionRender $actionRender, private SocialIssueRender $socialIssueRender, private SocialIssueRepository $socialIssueRepository) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorAggregator.php index b8ecf5898..46cc85de6 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorAggregator.php @@ -25,8 +25,7 @@ class CreatorAggregator implements AggregatorInterface public function __construct( private readonly UserRepository $userRepository, private readonly UserRender $userRender, - ) { - } + ) {} public function addRole(): ?string { @@ -47,9 +46,7 @@ class CreatorAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorJobAggregator.php index 3dfea37d2..c1b7c248b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorJobAggregator.php @@ -27,8 +27,7 @@ class CreatorJobAggregator implements AggregatorInterface public function __construct( private readonly UserJobRepository $jobRepository, private readonly TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -64,9 +63,7 @@ class CreatorJobAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorScopeAggregator.php index 232404e28..b38096079 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CreatorScopeAggregator.php @@ -27,8 +27,7 @@ class CreatorScopeAggregator implements AggregatorInterface public function __construct( private readonly ScopeRepository $scopeRepository, private readonly TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -64,9 +63,7 @@ class CreatorScopeAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CurrentActionAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CurrentActionAggregator.php index 95e1b8518..a9f8e020a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CurrentActionAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/CurrentActionAggregator.php @@ -19,9 +19,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; class CurrentActionAggregator implements AggregatorInterface { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalAggregator.php index 84367578e..ce1e381f2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class GoalAggregator implements AggregatorInterface { - public function __construct(private GoalRepository $goalRepository, private TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private GoalRepository $goalRepository, private TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalResultAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalResultAggregator.php index de4e1d46e..e1549f315 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalResultAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/GoalResultAggregator.php @@ -21,9 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface; class GoalResultAggregator implements AggregatorInterface { - public function __construct(private readonly ResultRepository $resultRepository, private readonly GoalRepository $goalRepository, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly ResultRepository $resultRepository, private readonly GoalRepository $goalRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/HandlingThirdPartyAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/HandlingThirdPartyAggregator.php index f02e05f4f..f58246a25 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/HandlingThirdPartyAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/HandlingThirdPartyAggregator.php @@ -25,9 +25,7 @@ final readonly class HandlingThirdPartyAggregator implements AggregatorInterface { private const PREFIX = 'acpw_handling3party_agg'; - public function __construct(private LabelThirdPartyHelper $labelThirdPartyHelper) - { - } + public function __construct(private LabelThirdPartyHelper $labelThirdPartyHelper) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php index 7aa29c9c0..282a36db4 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php @@ -28,8 +28,7 @@ final readonly class JobAggregator implements AggregatorInterface public function __construct( private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -59,9 +58,7 @@ final readonly class JobAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php index c587fadd6..7543da857 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php @@ -29,8 +29,7 @@ final readonly class ReferrerAggregator implements AggregatorInterface private UserRepository $userRepository, private UserRender $userRender, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ResultAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ResultAggregator.php index 53628d329..63a037f21 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ResultAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ResultAggregator.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class ResultAggregator implements AggregatorInterface { - public function __construct(private ResultRepository $resultRepository, private TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private ResultRepository $resultRepository, private TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php index 68d7e9697..0bedaf267 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php @@ -28,8 +28,7 @@ final readonly class ScopeAggregator implements AggregatorInterface public function __construct( private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { @@ -59,9 +58,7 @@ final readonly class ScopeAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnAccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnAccompanyingPeriod.php index de70bf92f..18a0c54b0 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnAccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnAccompanyingPeriod.php @@ -34,9 +34,7 @@ class AvgDurationAPWorkPersonAssociatedOnAccompanyingPeriod implements ExportInt $this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnWork.php b/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnWork.php index 20dc894bc..a8750e42c 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnWork.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/AvgDurationAPWorkPersonAssociatedOnWork.php @@ -34,9 +34,7 @@ class AvgDurationAPWorkPersonAssociatedOnWork implements ExportInterface, Groupe $this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php index c5c66cd01..0cbe7b3e8 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php @@ -35,9 +35,7 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface $this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriod.php index 6c9efcfc3..7d0e52169 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriod.php @@ -34,8 +34,7 @@ final readonly class ListAccompanyingPeriod implements ListInterface, GroupedExp private RollingDateConverterInterface $rollingDateConverter, private ListAccompanyingPeriodHelper $listAccompanyingPeriodHelper, private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod.php index eb9f1c525..8f63b1584 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod.php @@ -91,8 +91,7 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeri private readonly AggregateStringHelper $aggregateStringHelper, private readonly SocialActionRepository $socialActionRepository, private readonly FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnWork.php b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnWork.php index d05e22af3..fe200ca02 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnWork.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWorkAssociatePersonOnWork.php @@ -91,8 +91,7 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnWork implements private readonly AggregateStringHelper $aggregateStringHelper, private readonly SocialActionRepository $socialActionRepository, private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php index fe707d56a..71d9924be 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php @@ -81,8 +81,7 @@ final readonly class ListEvaluation implements ListInterface, GroupedExportInter private readonly AggregateStringHelper $aggregateStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter, private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php b/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php index 37b7ca7d7..2b8bfad20 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php @@ -23,10 +23,8 @@ use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Export\Helper\ListPersonHelper; use Chill\PersonBundle\Security\Authorization\PersonVoter; -use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Query; -use PhpOffice\PhpSpreadsheet\Shared\Date; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\FormBuilderInterface; @@ -41,7 +39,7 @@ class ListPerson implements ListInterface, GroupedExportInterface public function __construct( private readonly CustomFieldProvider $customFieldProvider, private readonly ListPersonHelper $listPersonHelper, - private readonly EntityManagerInterface $entityManager, + protected readonly EntityManagerInterface $entityManager, private readonly TranslatableStringHelper $translatableStringHelper, ParameterBagInterface $parameterBag, ) { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php b/src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php index 82bccc6d6..69d00a612 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php @@ -135,9 +135,7 @@ class ListPersonDuplicate implements DirectExportInterface, ExportElementValidat return PersonVoter::DUPLICATE; } - public function validateForm($data, ExecutionContextInterface $context) - { - } + public function validateForm($data, ExecutionContextInterface $context) {} protected function getHeaders(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriodDetails.php b/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriodDetails.php index 81cc09c8d..42a2205a1 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriodDetails.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriodDetails.php @@ -41,8 +41,7 @@ final readonly class ListPersonWithAccompanyingPeriodDetails implements ListInte private EntityManagerInterface $entityManager, private RollingDateConverterInterface $rollingDateConverter, private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder) { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php index d34eb7a15..6bcb4f8b8 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ActiveOnDateFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilter.php index fb5d6dc02..3b7c4fe25 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilter.php @@ -21,9 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ActiveOneDayBetweenDatesFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilter.php index c79f94daf..915a2c9e6 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilter.php @@ -20,9 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; class AdministrativeLocationFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php index 442dc505b..7fb032050 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ClosingMotiveFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ConfidentialFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ConfidentialFilter.php index 230267904..4c8baf147 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ConfidentialFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ConfidentialFilter.php @@ -28,9 +28,7 @@ class ConfidentialFilter implements FilterInterface private const DEFAULT_CHOICE = 'false'; - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php index a23d2c2c3..dd1264bd2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php @@ -29,8 +29,7 @@ class CreatorJobFilter implements FilterInterface public function __construct( private readonly TranslatableStringHelper $translatableStringHelper, private readonly UserJobRepositoryInterface $userJobRepository, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php index 10528a007..671b87407 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php @@ -28,9 +28,7 @@ class EmergencyFilter implements FilterInterface private const DEFAULT_CHOICE = 'false'; - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php index 95dcb5c62..bec01c249 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class EvaluationFilter implements FilterInterface { - public function __construct(private readonly EvaluationRepositoryInterface $evaluationRepository, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly EvaluationRepositoryInterface $evaluationRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php index 62417bd42..7d6d90e64 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php @@ -38,8 +38,7 @@ class GeographicalUnitStatFilter implements FilterInterface private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HandlingThirdPartyFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HandlingThirdPartyFilter.php index 818f7567a..8a9f734aa 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HandlingThirdPartyFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HandlingThirdPartyFilter.php @@ -26,8 +26,7 @@ final readonly class HandlingThirdPartyFilter implements FilterInterface public function __construct( private ThirdPartyRender $thirdPartyRender, - ) { - } + ) {} public function getTitle() { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasNoReferrerFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasNoReferrerFilter.php index 7df3ff0d2..72bcce39e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasNoReferrerFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasNoReferrerFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class HasNoReferrerFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasTemporaryLocationFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasTemporaryLocationFilter.php index 741a19961..778e4181a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasTemporaryLocationFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HasTemporaryLocationFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class HasTemporaryLocationFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HavingAnAccompanyingPeriodInfoWithinDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HavingAnAccompanyingPeriodInfoWithinDatesFilter.php index b6a05a466..d6436f8b4 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HavingAnAccompanyingPeriodInfoWithinDatesFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/HavingAnAccompanyingPeriodInfoWithinDatesFilter.php @@ -29,8 +29,7 @@ final readonly class HavingAnAccompanyingPeriodInfoWithinDatesFilter implements { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder): void { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/IntensityFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/IntensityFilter.php index d1d3de19d..3eb8bbb24 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/IntensityFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/IntensityFilter.php @@ -28,9 +28,7 @@ class IntensityFilter implements FilterInterface private const DEFAULT_CHOICE = 'occasional'; - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php index 73d5a02c9..622aa5801 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php @@ -39,8 +39,7 @@ readonly class JobWorkingOnCourseFilter implements FilterInterface private UserJobRepositoryInterface $userJobRepository, private RollingDateConverterInterface $rollingDateConverter, private TranslatableStringHelperInterface $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/NotAssociatedWithAReferenceAddressFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/NotAssociatedWithAReferenceAddressFilter.php index 72197234c..60486371e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/NotAssociatedWithAReferenceAddressFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/NotAssociatedWithAReferenceAddressFilter.php @@ -26,8 +26,7 @@ final readonly class NotAssociatedWithAReferenceAddressFilter implements FilterI { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function getTitle() { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php index 2427b1637..1b85f6cd7 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class OpenBetweenDatesFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OriginFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OriginFilter.php index 7ded268f6..617577cde 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OriginFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OriginFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class OriginFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php index 22a4b560f..30f67f664 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php @@ -28,9 +28,7 @@ class ReferrerFilter implements FilterInterface private const PU = 'acp_referrer_filter_users'; - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilterBetweenDates.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilterBetweenDates.php index 424f1d36b..6116e968b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilterBetweenDates.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilterBetweenDates.php @@ -42,8 +42,7 @@ final readonly class ReferrerFilterBetweenDates implements FilterInterface public function __construct( private RollingDateConverterInterface $rollingDateConverter, private UserRender $userRender, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/RequestorFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/RequestorFilter.php index 90f6953f1..0b7ce6994 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/RequestorFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/RequestorFilter.php @@ -31,9 +31,7 @@ final readonly class RequestorFilter implements FilterInterface 'no requestor' => 'no_requestor', ]; - public function __construct(private TranslatorInterface $translator, private EntityManagerInterface $em) - { - } + public function __construct(private TranslatorInterface $translator, private EntityManagerInterface $em) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php index 554023f1a..63d93805f 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php @@ -39,8 +39,7 @@ readonly class ScopeWorkingOnCourseFilter implements FilterInterface private ScopeRepositoryInterface $scopeRepository, private RollingDateConverterInterface $rollingDateConverter, private TranslatableStringHelperInterface $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php index 87d482ed9..545c35f5e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php @@ -31,8 +31,7 @@ final readonly class SocialActionFilter implements FilterInterface private SocialActionRender $actionRender, private RollingDateConverterInterface $rollingDateConverter, private TranslatorInterface $translator, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterBetweenDates.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterBetweenDates.php index 8b0a4c085..dfd627eda 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterBetweenDates.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterBetweenDates.php @@ -39,9 +39,7 @@ class StepFilterBetweenDates implements FilterInterface 'course.inactive_long' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG, ]; - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterOnDate.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterOnDate.php index c88bf1e34..8b36b1b5b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterOnDate.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/StepFilterOnDate.php @@ -43,9 +43,7 @@ class StepFilterOnDate implements FilterInterface 'course.inactive_long' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG, ]; - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index c958272fc..c328e9b21 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -35,8 +35,7 @@ final readonly class UserJobFilter implements FilterInterface, DataTransformerIn private TranslatableStringHelper $translatableStringHelper, private UserJobRepositoryInterface $userJobRepository, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 5b8ff7526..3489b8cb3 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -35,8 +35,7 @@ final readonly class UserScopeFilter implements FilterInterface, DataTransformer private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelper $translatableStringHelper, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserWorkingOnCourseFilter.php index af7674570..85d5db9d6 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserWorkingOnCourseFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserWorkingOnCourseFilter.php @@ -34,8 +34,7 @@ final readonly class UserWorkingOnCourseFilter implements FilterInterface public function __construct( private UserRender $userRender, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder): void { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByDateFilter.php index e15537864..84a5814b3 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByDateFilter.php @@ -33,8 +33,7 @@ final readonly class ByDateFilter implements FilterInterface { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function getTitle() { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByStepFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByStepFilter.php index 337b27e8a..337c30a89 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByStepFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodStepHistoryFilters/ByStepFilter.php @@ -23,8 +23,7 @@ final readonly class ByStepFilter implements FilterInterface { public function __construct( private TranslatorInterface $translator, - ) { - } + ) {} public function getTitle() { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByEndDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByEndDateFilter.php index 3bb8eb417..a0d8d0033 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByEndDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByEndDateFilter.php @@ -21,9 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ByEndDateFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByStartDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByStartDateFilter.php index 8c46fbfc2..401cd79a5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByStartDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/ByStartDateFilter.php @@ -21,9 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ByStartDateFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php index fce1600d1..20472420c 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class EvaluationTypeFilter implements FilterInterface { - public function __construct(private TranslatableStringHelper $translatableStringHelper, private EvaluationRepositoryInterface $evaluationRepository) - { - } + public function __construct(private TranslatableStringHelper $translatableStringHelper, private EvaluationRepositoryInterface $evaluationRepository) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/MaxDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/MaxDateFilter.php index 8555fbac9..6094d56ee 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/MaxDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/MaxDateFilter.php @@ -25,9 +25,7 @@ class MaxDateFilter implements FilterInterface 'maxdate is not specified' => false, ]; - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php index b84a354c7..b9f9075ed 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php @@ -28,8 +28,7 @@ readonly class CompositionFilter implements FilterInterface public function __construct( private TranslatableStringHelper $translatableStringHelper, private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AddressRefStatusFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AddressRefStatusFilter.php index 7c79f473a..8cd675abe 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AddressRefStatusFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AddressRefStatusFilter.php @@ -23,9 +23,7 @@ use Symfony\Component\Form\FormBuilderInterface; class AddressRefStatusFilter implements \Chill\MainBundle\Export\FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AgeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AgeFilter.php index 1c34f90ee..aa97ad54c 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AgeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/AgeFilter.php @@ -25,9 +25,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; class AgeFilter implements ExportElementValidatedInterface, FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/BirthdateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/BirthdateFilter.php index 45d190eee..dd14c71ef 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/BirthdateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/BirthdateFilter.php @@ -24,9 +24,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; class BirthdateFilter implements ExportElementValidatedInterface, FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ByHouseholdCompositionFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ByHouseholdCompositionFilter.php index 77f4f758f..e873a6598 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ByHouseholdCompositionFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ByHouseholdCompositionFilter.php @@ -29,9 +29,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ByHouseholdCompositionFilter implements FilterInterface { - public function __construct(private readonly HouseholdCompositionTypeRepositoryInterface $householdCompositionTypeRepository, private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly HouseholdCompositionTypeRepositoryInterface $householdCompositionTypeRepository, private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeadOrAliveFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeadOrAliveFilter.php index 3cbd46a7b..82cda25ed 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeadOrAliveFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeadOrAliveFilter.php @@ -23,9 +23,7 @@ use Symfony\Component\Form\FormBuilderInterface; class DeadOrAliveFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php index 8caf64fbf..1bc32d9bb 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php @@ -24,9 +24,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; class DeathdateFilter implements ExportElementValidatedInterface, FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php index a0aefe75b..e2041c3fa 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php @@ -27,9 +27,7 @@ use Symfony\Component\Form\FormBuilderInterface; class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface { - public function __construct(private readonly GeographicalUnitRepositoryInterface $geographicalUnitRepository, private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly GeographicalUnitRepositoryInterface $geographicalUnitRepository, private readonly GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php index d6af8204d..6c4cdf802 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php @@ -19,9 +19,7 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType; class MaritalStatusFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/NationalityFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/NationalityFilter.php index 556be8188..4c83fafe3 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/NationalityFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/NationalityFilter.php @@ -26,9 +26,7 @@ class NationalityFilter implements ExportElementValidatedInterface, FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilter.php index ff511fe91..ea8e01baf 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilter.php @@ -26,9 +26,7 @@ use Symfony\Component\Form\FormBuilderInterface; class ResidentialAddressAtThirdpartyFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter, private readonly TranslatableStringHelper $translatableStringHelper) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtUserFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtUserFilter.php index acd5ede84..3c2d7a3a6 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtUserFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/ResidentialAddressAtUserFilter.php @@ -23,9 +23,7 @@ use Doctrine\ORM\QueryBuilder; class ResidentialAddressAtUserFilter implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithParticipationBetweenDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithParticipationBetweenDatesFilter.php index 1df656a00..289af5f07 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithParticipationBetweenDatesFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithParticipationBetweenDatesFilter.php @@ -25,8 +25,7 @@ final readonly class WithParticipationBetweenDatesFilter implements FilterInterf { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutHouseholdComposition.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutHouseholdComposition.php index 079040b7f..c34c7eb40 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutHouseholdComposition.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutHouseholdComposition.php @@ -24,9 +24,7 @@ use Symfony\Component\Form\FormBuilderInterface; class WithoutHouseholdComposition implements FilterInterface { - public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private readonly RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutParticipationBetweenDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutParticipationBetweenDatesFilter.php new file mode 100644 index 000000000..d1e3e9b2f --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/WithoutParticipationBetweenDatesFilter.php @@ -0,0 +1,90 @@ +andWhere( + $qb->expr()->not( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class." {$p}_acp JOIN {$p}_acp.accompanyingPeriod {$p}_acpp ". + "WHERE {$p}_acp.person = person ". + "AND OVERLAPSI({$p}_acp.startDate, {$p}_acp.endDate), (:{$p}_date_after, :{$p}_date_before) = TRUE ". + "AND OVERLAPSI({$p}_acpp.openingDate, {$p}_acpp.closingDate), (:{$p}_date_after, :{$p}_date_before) = TRUE" + ) + ) + ) + ->setParameter("{$p}_date_after", $this->rollingDateConverter->convert($data['date_after']), Types::DATE_IMMUTABLE) + ->setParameter("{$p}_date_before", $this->rollingDateConverter->convert($data['date_before']), Types::DATE_IMMUTABLE); + } + + public function applyOn(): string + { + return Declarations::PERSON_TYPE; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('date_after', PickRollingDateType::class, [ + 'label' => 'export.filter.person.without_participation_between_dates.date_after', + ]); + + $builder->add('date_before', PickRollingDateType::class, [ + 'label' => 'export.filter.person.without_participation_between_dates.date_before', + ]); + } + + public function getFormDefaultData(): array + { + return [ + 'date_after' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'date_before' => new RollingDate(RollingDate::T_TODAY), + ]; + } + + public function describeAction($data, $format = 'string') + { + return ['exports.filter.person.without_participation_between_dates.Filtered by having no participations during period: between', [ + 'dateafter' => $this->rollingDateConverter->convert($data['date_after']), + 'datebefore' => $this->rollingDateConverter->convert($data['date_before']), + ]]; + } + + public function getTitle() + { + return 'export.filter.person.without_participation_between_dates.title'; + } +} diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkEndDateBetweenDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkEndDateBetweenDateFilter.php index 38ca39320..05d4633e2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkEndDateBetweenDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkEndDateBetweenDateFilter.php @@ -24,8 +24,7 @@ final readonly class AccompanyingPeriodWorkEndDateBetweenDateFilter implements F { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder): void { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkStartDateBetweenDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkStartDateBetweenDateFilter.php index 7b404796e..880543355 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkStartDateBetweenDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkStartDateBetweenDateFilter.php @@ -24,8 +24,7 @@ final readonly class AccompanyingPeriodWorkStartDateBetweenDateFilter implements { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder): void { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkWithEvaluationBetweenDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkWithEvaluationBetweenDatesFilter.php index 439cb47ca..e0c4da1e9 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkWithEvaluationBetweenDatesFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/AccompanyingPeriodWorkWithEvaluationBetweenDatesFilter.php @@ -24,8 +24,7 @@ final readonly class AccompanyingPeriodWorkWithEvaluationBetweenDatesFilter impl { public function __construct( private RollingDateConverterInterface $rollingDateConverter, - ) { - } + ) {} public function buildForm(FormBuilderInterface $builder): void { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorJobFilter.php index 84f6b2447..3087d156e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorJobFilter.php @@ -29,8 +29,7 @@ class CreatorJobFilter implements FilterInterface public function __construct( private readonly UserJobRepository $userJobRepository, private readonly TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorScopeFilter.php index 9201b9788..414740c7a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/CreatorScopeFilter.php @@ -29,8 +29,7 @@ class CreatorScopeFilter implements FilterInterface public function __construct( private readonly ScopeRepository $scopeRepository, private readonly TranslatableStringHelper $translatableStringHelper, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php index bb54f288b..25e762a9c 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php @@ -31,8 +31,7 @@ class JobFilter implements FilterInterface protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper, private readonly UserJobRepositoryInterface $userJobRepository, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php index 3997139c2..4d456fdb2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php @@ -24,9 +24,7 @@ final readonly class ReferrerFilter implements FilterInterface { private const PREFIX = 'acpw_referrer_filter'; - public function __construct(private RollingDateConverterInterface $rollingDateConverter) - { - } + public function __construct(private RollingDateConverterInterface $rollingDateConverter) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php index c09cc418e..9f2041aaa 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php @@ -31,8 +31,7 @@ class ScopeFilter implements FilterInterface protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper, private readonly ScopeRepositoryInterface $scopeRepository, - ) { - } + ) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php index 7204e6e11..c84ed7f40 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php @@ -26,9 +26,7 @@ use Symfony\Component\Form\FormBuilderInterface; class SocialWorkTypeFilter implements FilterInterface { - public function __construct(private readonly SocialActionRender $socialActionRender, private readonly TranslatableStringHelper $translatableStringHelper, private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly SocialActionRender $socialActionRender, private readonly TranslatableStringHelper $translatableStringHelper, private readonly EntityManagerInterface $em) {} public function addRole(): ?string { diff --git a/src/Bundle/ChillPersonBundle/Export/Helper/LabelPersonHelper.php b/src/Bundle/ChillPersonBundle/Export/Helper/LabelPersonHelper.php index 2b3c3674e..9dd9a7399 100644 --- a/src/Bundle/ChillPersonBundle/Export/Helper/LabelPersonHelper.php +++ b/src/Bundle/ChillPersonBundle/Export/Helper/LabelPersonHelper.php @@ -16,9 +16,7 @@ use Chill\PersonBundle\Templating\Entity\PersonRenderInterface; class LabelPersonHelper { - public function __construct(private readonly PersonRepository $personRepository, private readonly PersonRenderInterface $personRender) - { - } + public function __construct(private readonly PersonRepository $personRepository, private readonly PersonRenderInterface $personRender) {} public function getLabel(string $key, array $values, string $header): callable { diff --git a/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php b/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php index a74e44f0f..f66a8b039 100644 --- a/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php +++ b/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php @@ -88,8 +88,7 @@ final readonly class ListAccompanyingPeriodHelper private UserHelper $userHelper, private LabelPersonHelper $labelPersonHelper, private CenterRepository $centerRepository, - ) { - } + ) {} public function getQueryKeys($data) { diff --git a/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php b/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php index 2ffc3940f..393d246ea 100644 --- a/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php +++ b/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php @@ -84,8 +84,7 @@ final readonly class ListPersonHelper * @var iterable */ private iterable $customPersonHelpers, - ) { - } + ) {} /** * Those keys are the "direct" keys, which are created when we decide to use to list all the keys. diff --git a/src/Bundle/ChillPersonBundle/Form/ClosingMotiveType.php b/src/Bundle/ChillPersonBundle/Form/ClosingMotiveType.php index 5116ff1b0..fd7ef3ecb 100644 --- a/src/Bundle/ChillPersonBundle/Form/ClosingMotiveType.php +++ b/src/Bundle/ChillPersonBundle/Form/ClosingMotiveType.php @@ -26,9 +26,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class ClosingMotiveType extends AbstractType { - public function __construct(private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly TranslatorInterface $translator) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php b/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php index 0fc25eefe..3a2a61cad 100644 --- a/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php +++ b/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php @@ -19,7 +19,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; class PersonAltNameDataMapper implements DataMapperInterface { - public function mapDataToForms($viewData, $forms) + public function mapDataToForms($viewData, \Traversable $forms): void { if (null === $viewData) { return; @@ -43,11 +43,7 @@ class PersonAltNameDataMapper implements DataMapperInterface } } - /** - * @param FormInterface[] $forms - * @param Collection $viewData - */ - public function mapFormsToData($forms, &$viewData) + public function mapFormsToData(\Traversable $forms, &$viewData): void { $mapIndexToKey = []; diff --git a/src/Bundle/ChillPersonBundle/Form/HouseholdCompositionType.php b/src/Bundle/ChillPersonBundle/Form/HouseholdCompositionType.php index 0fe60cbe9..2df66039f 100644 --- a/src/Bundle/ChillPersonBundle/Form/HouseholdCompositionType.php +++ b/src/Bundle/ChillPersonBundle/Form/HouseholdCompositionType.php @@ -22,9 +22,7 @@ use Symfony\Component\Form\FormBuilderInterface; class HouseholdCompositionType extends AbstractType { - public function __construct(private readonly HouseholdCompositionTypeRepository $householdCompositionTypeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(private readonly HouseholdCompositionTypeRepository $householdCompositionTypeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/HouseholdType.php b/src/Bundle/ChillPersonBundle/Form/HouseholdType.php index 4a949bb92..ae9bcb45f 100644 --- a/src/Bundle/ChillPersonBundle/Form/HouseholdType.php +++ b/src/Bundle/ChillPersonBundle/Form/HouseholdType.php @@ -43,6 +43,7 @@ class HouseholdType extends AbstractType { $resolver->setDefaults([ 'data_class' => Household::class, + 'validation_groups' => ['household_metadata'], ]); } } diff --git a/src/Bundle/ChillPersonBundle/Form/PersonResourceType.php b/src/Bundle/ChillPersonBundle/Form/PersonResourceType.php index a4946b52d..2063b0e21 100644 --- a/src/Bundle/ChillPersonBundle/Form/PersonResourceType.php +++ b/src/Bundle/ChillPersonBundle/Form/PersonResourceType.php @@ -29,9 +29,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final class PersonResourceType extends AbstractType { - public function __construct(private readonly ResourceKindRender $resourceKindRender, private readonly PersonRenderInterface $personRender, private readonly ThirdPartyRender $thirdPartyRender, private readonly TranslatorInterface $translator) - { - } + public function __construct(private readonly ResourceKindRender $resourceKindRender, private readonly PersonRenderInterface $personRender, private readonly ThirdPartyRender $thirdPartyRender, private readonly TranslatorInterface $translator) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/SocialWork/SocialIssueType.php b/src/Bundle/ChillPersonBundle/Form/SocialWork/SocialIssueType.php index cce3ca46d..0d7a3bb4b 100644 --- a/src/Bundle/ChillPersonBundle/Form/SocialWork/SocialIssueType.php +++ b/src/Bundle/ChillPersonBundle/Form/SocialWork/SocialIssueType.php @@ -23,9 +23,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class SocialIssueType extends AbstractType { - public function __construct(protected TranslatableStringHelperInterface $translatableStringHelper) - { - } + public function __construct(protected TranslatableStringHelperInterface $translatableStringHelper) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PersonAltNameType.php b/src/Bundle/ChillPersonBundle/Form/Type/PersonAltNameType.php index 17aad8bd0..6d983be37 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PersonAltNameType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PersonAltNameType.php @@ -21,9 +21,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PersonAltNameType extends AbstractType { - public function __construct(private readonly ConfigPersonAltNamesHelper $configHelper, private readonly TranslatableStringHelper $translatableStringHelper) - { - } + public function __construct(private readonly ConfigPersonAltNamesHelper $configHelper, private readonly TranslatableStringHelper $translatableStringHelper) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php b/src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php index a55721011..0e84bfc83 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php @@ -24,9 +24,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PersonPhoneType extends AbstractType { - public function __construct(private readonly PhonenumberHelper $phonenumberHelper, private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly PhonenumberHelper $phonenumberHelper, private readonly EntityManagerInterface $em) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php index 71fd36225..01e3b3585 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php @@ -26,9 +26,7 @@ use Symfony\Component\Serializer\SerializerInterface; */ class PickPersonDynamicType extends AbstractType { - public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly SerializerInterface $serializer, private readonly NormalizerInterface $normalizer) - { - } + public function __construct(private readonly DenormalizerInterface $denormalizer, private readonly SerializerInterface $serializer, private readonly NormalizerInterface $normalizer) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php index 79c3547af..9ddee9c7e 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Form\Type; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\GroupCenter; +use Chill\MainBundle\Entity\User; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\ChoiceLoader\PersonChoiceLoader; @@ -25,7 +26,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\Role\Role; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -41,46 +41,15 @@ use Symfony\Contracts\Translation\TranslatorInterface; * - with the `role` option, only the people belonging to the reachable center for the * given role are displayed. */ -class PickPersonType extends AbstractType +final class PickPersonType extends AbstractType { - /** - * @var AuthorizationHelper - */ - protected $authorizationHelper; - - /** - * @var PersonRepository - */ - protected $personRepository; - - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var UrlGeneratorInterface - */ - protected $urlGenerator; - - /** - * @var \Chill\MainBundle\Entity\User - */ - protected $user; - public function __construct( - PersonRepository $personRepository, - TokenStorageInterface $tokenStorage, - AuthorizationHelper $authorizationHelper, - UrlGeneratorInterface $urlGenerator, - TranslatorInterface $translator, - ) { - $this->personRepository = $personRepository; - $this->user = $tokenStorage->getToken()->getUser(); - $this->authorizationHelper = $authorizationHelper; - $this->urlGenerator = $urlGenerator; - $this->translator = $translator; - } + private readonly PersonRepository $personRepository, + private readonly TokenStorageInterface $tokenStorage, + private readonly AuthorizationHelper $authorizationHelper, + private readonly UrlGeneratorInterface $urlGenerator, + private readonly TranslatorInterface $translator, + ) {} public function buildView(\Symfony\Component\Form\FormView $view, \Symfony\Component\Form\FormInterface $form, array $options) { @@ -130,11 +99,16 @@ class PickPersonType extends AbstractType protected function filterCentersfom(Options $options) { + $user = $this->tokenStorage->getToken()->getUser(); + if (!$user instanceof User) { + throw new \UnexpectedValueException('user should be an instance of '.User::class); + } + if (null === $options['role']) { - $centers = array_map(static fn (GroupCenter $g) => $g->getCenter(), $this->user->getGroupCenters()->toArray()); + $centers = array_map(static fn (GroupCenter $g) => $g->getCenter(), $user->getGroupCenters()->toArray()); } else { $centers = $this->authorizationHelper - ->getReachableCenters($this->user, $options['role']->getRole()); + ->getReachableCenters($user, $options['role']->getRole()); } if (null === $options['centers']) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickSocialActionType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickSocialActionType.php index 0fe09e56a..19258f23d 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PickSocialActionType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickSocialActionType.php @@ -20,9 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PickSocialActionType extends AbstractType { - public function __construct(private readonly SocialActionRender $actionRender, private readonly SocialActionRepository $actionRepository) - { - } + public function __construct(private readonly SocialActionRender $actionRender, private readonly SocialActionRepository $actionRepository) {} public function configureOptions(OptionsResolver $resolver) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickSocialIssueType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickSocialIssueType.php index 3e6ae1e97..b61343423 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PickSocialIssueType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickSocialIssueType.php @@ -20,9 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class PickSocialIssueType extends AbstractType { - public function __construct(private readonly SocialIssueRender $issueRender, private readonly SocialIssueRepository $issueRepository) - { - } + public function __construct(private readonly SocialIssueRender $issueRender, private readonly SocialIssueRepository $issueRepository) {} public function configureOptions(OptionsResolver $resolver) { diff --git a/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php b/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php index c33244635..2016fb80a 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php @@ -25,9 +25,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; */ class Select2MaritalStatusType extends AbstractType { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly EntityManagerInterface $em) - { - } + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly EntityManagerInterface $em) {} public function buildForm(FormBuilderInterface $builder, array $options) { diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php index dd860780a..d5e1dfe59 100644 --- a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php +++ b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php @@ -42,8 +42,7 @@ class MembersEditor private readonly ValidatorInterface $validator, private readonly ?Household $household, private readonly EventDispatcherInterface $eventDispatcher, - ) { - } + ) {} /** * Add a person to the household. diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php b/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php index cb6f7d4ea..071866b96 100644 --- a/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php +++ b/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php @@ -17,9 +17,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class MembersEditorFactory { - public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly ValidatorInterface $validator) - { - } + public function __construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly ValidatorInterface $validator) {} public function createEditor(?Household $household = null): MembersEditor { diff --git a/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php index 1984c4c93..f9973a4cf 100644 --- a/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Menu; +use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureACLAwareRepository; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Repository\ResidentialAddressRepository; @@ -43,6 +44,7 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface private readonly Security $security, protected TranslatorInterface $translator, private readonly ResidentialAddressRepository $residentialAddressRepo, + private readonly EntityWorkflowStepSignatureACLAwareRepository $entityWorkflowStepSignatureRepository, ) { $this->showAccompanyingPeriod = $parameterBag->get('chill_person.accompanying_period'); } @@ -125,6 +127,21 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface ? $nbAccompanyingPeriod : null, ]); } + + $nbSignatures = count($this->entityWorkflowStepSignatureRepository->findByPersonAndPendingState($parameters['person'])); + + if ($nbSignatures > 0) { + $menu->addChild($this->translator->trans('workflow.signature_list.menu'), [ + 'route' => 'chill_person_signature_list', + 'routeParameters' => [ + 'id' => $parameters['person']->getId(), + ], + ]) + ->setExtras([ + 'order' => 110, + 'counter' => $nbSignatures, + ]); + } } public static function getMenuIds(): array diff --git a/src/Bundle/ChillPersonBundle/Menu/PersonQuickMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/PersonQuickMenuBuilder.php index 5534791e4..f6b857b90 100644 --- a/src/Bundle/ChillPersonBundle/Menu/PersonQuickMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/PersonQuickMenuBuilder.php @@ -18,9 +18,7 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; final readonly class PersonQuickMenuBuilder implements LocalMenuBuilderInterface { - public function __construct(private AuthorizationCheckerInterface $authorizationChecker) - { - } + public function __construct(private AuthorizationCheckerInterface $authorizationChecker) {} public static function getMenuIds(): array { diff --git a/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php index 870f021f5..c82038b40 100644 --- a/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php @@ -28,9 +28,7 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface /** * SectionMenuBuilder constructor. */ - public function __construct(protected ParameterBagInterface $parameterBag, private readonly Security $security, protected TranslatorInterface $translator) - { - } + public function __construct(protected ParameterBagInterface $parameterBag, private readonly Security $security, protected TranslatorInterface $translator) {} public function buildMenu($menuId, MenuItem $menu, array $parameters) { diff --git a/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodNotificationHandler.php b/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodNotificationHandler.php index 4f1146391..668f868ae 100644 --- a/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodNotificationHandler.php +++ b/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodNotificationHandler.php @@ -18,9 +18,7 @@ use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; final readonly class AccompanyingPeriodNotificationHandler implements NotificationHandlerInterface { - public function __construct(private AccompanyingPeriodRepository $accompanyingPeriodRepository) - { - } + public function __construct(private AccompanyingPeriodRepository $accompanyingPeriodRepository) {} public function getTemplate(Notification $notification, array $options = []): string { diff --git a/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkEvaluationDocumentNotificationHandler.php b/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkEvaluationDocumentNotificationHandler.php index f69c49071..40aff8570 100644 --- a/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkEvaluationDocumentNotificationHandler.php +++ b/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkEvaluationDocumentNotificationHandler.php @@ -18,9 +18,7 @@ use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvalu final readonly class AccompanyingPeriodWorkEvaluationDocumentNotificationHandler implements NotificationHandlerInterface { - public function __construct(private AccompanyingPeriodWorkEvaluationDocumentRepository $accompanyingPeriodWorkEvaluationDocumentRepository) - { - } + public function __construct(private AccompanyingPeriodWorkEvaluationDocumentRepository $accompanyingPeriodWorkEvaluationDocumentRepository) {} public function getTemplate(Notification $notification, array $options = []): string { diff --git a/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkNotificationHandler.php b/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkNotificationHandler.php index abb8123bc..e147fa520 100644 --- a/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkNotificationHandler.php +++ b/src/Bundle/ChillPersonBundle/Notification/AccompanyingPeriodWorkNotificationHandler.php @@ -18,9 +18,7 @@ use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepos final readonly class AccompanyingPeriodWorkNotificationHandler implements NotificationHandlerInterface { - public function __construct(private AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository) - { - } + public function __construct(private AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository) {} public function getTemplate(Notification $notification, array $options = []): string { diff --git a/src/Bundle/ChillPersonBundle/Privacy/AccompanyingPeriodPrivacyEvent.php b/src/Bundle/ChillPersonBundle/Privacy/AccompanyingPeriodPrivacyEvent.php index f6619317f..739387941 100644 --- a/src/Bundle/ChillPersonBundle/Privacy/AccompanyingPeriodPrivacyEvent.php +++ b/src/Bundle/ChillPersonBundle/Privacy/AccompanyingPeriodPrivacyEvent.php @@ -37,9 +37,7 @@ class AccompanyingPeriodPrivacyEvent extends \Symfony\Contracts\EventDispatcher\ { final public const ACCOMPANYING_PERIOD_PRIVACY_EVENT = 'chill_person.accompanying_period_privacy_event'; - public function __construct(protected $period, protected $args = []) - { - } + public function __construct(protected $period, protected $args = []) {} public function getArgs(): array { diff --git a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php index 4e728c635..df57a08fd 100644 --- a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php +++ b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php @@ -48,9 +48,7 @@ class PrivacyEvent extends \Symfony\Contracts\EventDispatcher\Event /** * PrivacyEvent constructor. */ - public function __construct(private readonly Person $person, private readonly array $args = ['action' => 'show']) - { - } + public function __construct(private readonly Person $person, private readonly array $args = ['action' => 'show']) {} public function addPerson(Person $person) { diff --git a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php index 88eb2b172..7dfa9cb4b 100644 --- a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php +++ b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php @@ -31,31 +31,21 @@ namespace Chill\PersonBundle\Privacy; * along with this program. If not, see . */ +use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\Person; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -class PrivacyEventSubscriber implements EventSubscriberInterface +final readonly class PrivacyEventSubscriber implements EventSubscriberInterface { - /** - * @var LoggerInterface - */ - protected $logger; - - /** - * @var TokenStorageInterface - */ - protected $token; - /** * PrivacyEventSubscriber constructor. */ - public function __construct(LoggerInterface $logger, TokenStorageInterface $token) - { - $this->logger = $logger; - $this->token = $token; - } + public function __construct( + private LoggerInterface $logger, + private TokenStorageInterface $token, + ) {} public static function getSubscribedEvents() { @@ -109,11 +99,20 @@ class PrivacyEventSubscriber implements EventSubscriberInterface ); } - protected function getInvolved(): array + private function getInvolved(): array { + $user = $this->token->getToken()->getUser(); + + if ($user instanceof User) { + return [ + 'by_user' => $user->getUserIdentifier(), + 'by_user_id' => $user->getId(), + ]; + } + return [ - 'by_user' => $this->token->getToken()->getUser()->getUsername(), - 'by_user_id' => $this->token->getToken()->getUser()->getId(), + 'by_user' => $user->getUsername(), + 'by_user_id' => $user->getUserIdentifier(), ]; } } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php index 59bb3f915..e3a484f0b 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php @@ -11,14 +11,17 @@ declare(strict_types=1); namespace Chill\PersonBundle\Repository\AccompanyingPeriod; +use Chill\DocStoreBundle\Entity\StoredObject; +use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\NonUniqueResultException; use Doctrine\Persistence\ObjectRepository; -class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectRepository +readonly class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectRepository, AssociatedEntityToStoredObjectInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $em) { @@ -58,4 +61,18 @@ class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectReposi { return AccompanyingPeriodWorkEvaluationDocument::class; } + + /** + * @throws NonUniqueResultException + */ + public function findAssociatedEntityToStoredObject(StoredObject $storedObject): ?AccompanyingPeriodWorkEvaluationDocument + { + $qb = $this->repository->createQueryBuilder('acpwed'); + $query = $qb + ->where('acpwed.storedObject = :storedObject') + ->setParameter('storedObject', $storedObject) + ->getQuery(); + + return $query->getOneOrNullResult(); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkGoalRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkGoalRepository.php index 4e092beb0..7c24b8a61 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkGoalRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkGoalRepository.php @@ -21,9 +21,9 @@ use Doctrine\ORM\EntityRepository; * @method AccompanyingPeriodWorkGoal[] findAll() * @method AccompanyingPeriodWorkGoal[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -final class AccompanyingPeriodWorkGoalRepository +final readonly class AccompanyingPeriodWorkGoalRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php index 3759cf2cd..5ad717d0c 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class CommentRepository +final readonly class CommentRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php index 1668b456e..2e50386c8 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class OriginRepository +final readonly class OriginRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php index a5dbf4b69..66a2daea5 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class ResourceRepository +final readonly class ResourceRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php index a3a98eb20..ebd72e0b4 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php @@ -40,8 +40,7 @@ final readonly class AccompanyingPeriodACLAwareRepository implements Accompanyin private Security $security, private AuthorizationHelperForCurrentUserInterface $authorizationHelper, private CenterResolverManagerInterface $centerResolver, - ) { - } + ) {} public function buildQueryOpenedAccompanyingCourseByUserAndPostalCodes(?User $user, array $postalCodes = []): QueryBuilder { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php index 616c56eb0..0a2d00bcd 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class AccompanyingPeriodParticipationRepository +final readonly class AccompanyingPeriodParticipationRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php index 7b681a8f5..73f1beecb 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php @@ -18,9 +18,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class AccompanyingPeriodRepository implements ObjectRepository +final readonly class AccompanyingPeriodRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdACLAwareRepository.php index a98c28dcd..89a1c4e82 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdACLAwareRepository.php @@ -21,9 +21,7 @@ use Symfony\Component\Security\Core\Security; final readonly class HouseholdACLAwareRepository implements HouseholdACLAwareRepositoryInterface { - public function __construct(private EntityManagerInterface $em, private AuthorizationHelper $authorizationHelper, private Security $security) - { - } + public function __construct(private EntityManagerInterface $em, private AuthorizationHelper $authorizationHelper, private Security $security) {} public function addACL(QueryBuilder $qb, string $alias = 'h'): QueryBuilder { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionRepository.php index 5a0dee15d..1bd72fd35 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionRepository.php @@ -16,9 +16,9 @@ use Chill\PersonBundle\Entity\Household\HouseholdComposition; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class HouseholdCompositionRepository implements HouseholdCompositionRepositoryInterface +final readonly class HouseholdCompositionRepository implements HouseholdCompositionRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionTypeRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionTypeRepository.php index 2b748865b..666895696 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionTypeRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdCompositionTypeRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\Household\HouseholdCompositionType; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class HouseholdCompositionTypeRepository implements HouseholdCompositionTypeRepositoryInterface +final readonly class HouseholdCompositionTypeRepository implements HouseholdCompositionTypeRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdMembersRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdMembersRepository.php index e76e88fc3..777b14cdd 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdMembersRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdMembersRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\Household\HouseholdMember; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class HouseholdMembersRepository +final readonly class HouseholdMembersRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php index 2904ffb61..271883080 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php @@ -18,7 +18,7 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Persistence\ObjectRepository; -final class HouseholdRepository implements ObjectRepository +final readonly class HouseholdRepository implements ObjectRepository { private const SQL_BY_ACCOMPANYING_PERIOD_PARTICIPATION = <<<'SQL' WITH participations AS ( @@ -40,9 +40,9 @@ final class HouseholdRepository implements ObjectRepository SELECT {select} FROM households {limits} SQL; - private readonly EntityManagerInterface $em; + private EntityManagerInterface $em; - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/PersonHouseholdAddressRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/PersonHouseholdAddressRepository.php index ebcfabe4f..f9132c2bd 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/PersonHouseholdAddressRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/PersonHouseholdAddressRepository.php @@ -16,9 +16,9 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectRepository; -final class PersonHouseholdAddressRepository implements ObjectRepository +final readonly class PersonHouseholdAddressRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $em) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php index 32ca5b8fa..585f2aedb 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php @@ -18,9 +18,9 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectRepository; -final class PositionRepository implements ObjectRepository +final readonly class PositionRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php index c1bb427fd..fc5d0606d 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php +++ b/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php @@ -13,6 +13,4 @@ namespace Chill\PersonBundle\Repository\Person; use Doctrine\Persistence\ObjectRepository; -interface PersonCenterHistoryInterface extends ObjectRepository -{ -} +interface PersonCenterHistoryInterface extends ObjectRepository {} diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index 73b9d5854..9e76dd374 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -25,9 +25,7 @@ use Symfony\Component\Security\Core\Security; final readonly class PersonACLAwareRepository implements PersonACLAwareRepositoryInterface { - public function __construct(private Security $security, private EntityManagerInterface $em, private CountryRepository $countryRepository, private AuthorizationHelperInterface $authorizationHelper) - { - } + public function __construct(private Security $security, private EntityManagerInterface $em, private CountryRepository $countryRepository, private AuthorizationHelperInterface $authorizationHelper) {} public function buildAuthorizedQuery( ?string $default = null, diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonAltNameRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonAltNameRepository.php index 4a1ee1dd6..8a8bf0e7c 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonAltNameRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonAltNameRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\PersonAltName; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class PersonAltNameRepository +final readonly class PersonAltNameRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonNotDuplicateRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonNotDuplicateRepository.php index 6694f0e32..f1946bd37 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonNotDuplicateRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonNotDuplicateRepository.php @@ -16,9 +16,9 @@ use Chill\PersonBundle\Entity\PersonNotDuplicate; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class PersonNotDuplicateRepository +final readonly class PersonNotDuplicateRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonResourceRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonResourceRepository.php index b2bff2ce5..3caae8444 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonResourceRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonResourceRepository.php @@ -17,9 +17,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class PersonResourceRepository implements ObjectRepository +final readonly class PersonResourceRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/EvaluationRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/EvaluationRepository.php index a7b739f7d..1c89a98f6 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/EvaluationRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/EvaluationRepository.php @@ -15,9 +15,9 @@ use Chill\PersonBundle\Entity\SocialWork\Evaluation; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -final class EvaluationRepository implements EvaluationRepositoryInterface +final readonly class EvaluationRepository implements EvaluationRepositoryInterface { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/GoalRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/GoalRepository.php index f99bd54a5..ec89c597d 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/GoalRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/GoalRepository.php @@ -18,9 +18,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class GoalRepository implements ObjectRepository +final readonly class GoalRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php index 786c6635a..0d470d2d7 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php @@ -19,9 +19,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class ResultRepository implements ObjectRepository +final readonly class ResultRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialActionRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialActionRepository.php index da6bfcc46..fe530e84b 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialActionRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialActionRepository.php @@ -17,9 +17,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class SocialActionRepository implements ObjectRepository +final readonly class SocialActionRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php index 21f06afd1..c9bb3a189 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php @@ -17,9 +17,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final class SocialIssueRepository implements ObjectRepository +final readonly class SocialIssueRepository implements ObjectRepository { - private readonly EntityRepository $repository; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue index 8ae7dfff4..d6c438cd9 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue @@ -52,7 +52,7 @@