From 52327da82c0e4da2296c9da71e71cca44510a4f1 Mon Sep 17 00:00:00 2001
From: Giovanni Francesco Luigi Catania
Date: Thu, 23 Apr 2026 09:30:58 +0200
Subject: [PATCH] caricata WA
---
README.md | 3 +-
idrocap_wa/.htaccess | 12 +
idrocap_wa/Dockerfile | 20 +
idrocap_wa/README.md | 61 +
idrocap_wa/bin/bash_completion.sh | 47 +
idrocap_wa/bin/cake | 75 +
idrocap_wa/bin/cake.bat | 27 +
idrocap_wa/bin/cake.php | 10 +
idrocap_wa/composer.json | 67 +
idrocap_wa/composer.lock | 7466 +++
idrocap_wa/config/.env.example | 38 +
idrocap_wa/config/app.php | 436 +
idrocap_wa/config/app_local.example.php | 94 +
idrocap_wa/config/app_local.php | 94 +
idrocap_wa/config/bootstrap.php | 231 +
idrocap_wa/config/bootstrap_cli.php | 35 +
idrocap_wa/config/cakelte.php | 43 +
idrocap_wa/config/keys/private.key | 52 +
idrocap_wa/config/keys/public.key | 15 +
idrocap_wa/config/paths.php | 94 +
idrocap_wa/config/plugins.php | 15 +
idrocap_wa/config/routes.php | 357 +
idrocap_wa/config/schema/i18n.sql | 18 +
idrocap_wa/config/schema/sessions.sql | 15 +
idrocap_wa/dockerfiles/cake | 152 +
idrocap_wa/dockerfiles/run | 93 +
idrocap_wa/dockerfiles/www.conf | 453 +
idrocap_wa/index.php | 16 +
.../jixel-background-task-handler/Dockerfile | 39 +
.../jixel-background-task-handler/jbth.py | 152 +
.../jixel-background-task-handler/jbth.sh | 9 +
.../jixel-background-task-handler/jgprc.py | 169 +
.../jixel-background-task-handler/jgprc.sh | 26 +
.../jixel-background-task-handler.sh | 12 +
.../jixel-cron.log | 0
.../jixel-cron.sh | 5 +
.../jixel-cron.txt | 6 +
.../jixel-general-purpose-rabbit-consumer.sh | 12 +
idrocap_wa/phpcs.xml | 12 +
idrocap_wa/phpstan.neon | 6 +
idrocap_wa/phpunit.xml.dist | 37 +
idrocap_wa/plugins/.gitkeep | 0
idrocap_wa/psalm.xml | 15 +
idrocap_wa/resources/.gitkeep | 0
idrocap_wa/resources/locales/cake.pot | 279 +
idrocap_wa/resources/locales/default.pot | 1709 +
idrocap_wa/resources/locales/en/default.po | 1709 +
.../resources/locales/en/previous_default.po | 1709 +
idrocap_wa/resources/locales/it/cake.po | 279 +
idrocap_wa/src/Application.php | 268 +
.../Command/AddCadastralCodeToUsesCommand.php | 95 +
.../AddDerivationCoordinatesCommand.php | 44 +
...ingAntimafiaCertificateRequestsCommand.php | 57 +
.../src/Command/CopyTranslationsCommand.php | 144 +
.../IntendedUseVegetationCheckCommand.php | 107 +
.../NormalizeApplicantProvinceCommand.php | 65 +
.../Command/NotificationsHandlerCommand.php | 65 +
...kWaterDrawingPaperworkSnapshotsCommand.php | 98 +
idrocap_wa/src/Console/Installer.php | 250 +
.../src/Controller/AiServicesController.php | 91 +
.../src/Controller/Api/AppController.php | 74 +
.../Controller/Api/AttachmentsController.php | 53 +
.../src/Controller/Api/ErrorController.php | 70 +
.../Api/NotificationsController.php | 156 +
.../Api/OrganisationTypesController.php | 31 +
.../Api/OrganisationsController.php | 157 +
.../Api/SubscriptionsController.php | 67 +
.../src/Controller/Api/UsersController.php | 230 +
.../Api/WaterDrawingDerivationsController.php | 75 +
.../WaterDrawingMeasurementsController.php | 47 +
.../Api/WaterDrawingPaperworksController.php | 170 +
idrocap_wa/src/Controller/AppController.php | 424 +
.../src/Controller/ApplicantsController.php | 112 +
.../src/Controller/AttachmentsController.php | 98 +
.../src/Controller/CapabilitiesController.php | 205 +
idrocap_wa/src/Controller/Component/.gitkeep | 0
.../Component/StreamableCsvExportTrait.php | 103 +
.../ControllableObjectsController.php | 56 +
.../src/Controller/DashboardController.php | 35 +
.../src/Controller/DeliveriesController.php | 185 +
.../src/Controller/DistrictsController.php | 66 +
.../src/Controller/EmailsController.php | 78 +
idrocap_wa/src/Controller/ErrorController.php | 70 +
idrocap_wa/src/Controller/FaxesController.php | 78 +
.../src/Controller/FiltersController.php | 25 +
.../src/Controller/GroupsController.php | 236 +
idrocap_wa/src/Controller/MapsController.php | 187 +
.../src/Controller/MobilePhonesController.php | 79 +
.../Controller/NotificationsController.php | 97 +
.../Controller/OrganisationsController.php | 204 +
idrocap_wa/src/Controller/PecsController.php | 78 +
.../src/Controller/PhonesController.php | 78 +
.../src/Controller/PrivacyController.php | 174 +
idrocap_wa/src/Controller/TagsController.php | 91 +
.../Controller/TelegramChatsController.php | 76 +
idrocap_wa/src/Controller/UsersController.php | 624 +
.../WaterDrawingArticlesController.php | 124 +
.../WaterDrawingDerivationsController.php | 123 +
.../Controller/WaterDrawingFeesController.php | 174 +
.../WaterDrawingIntendedUsesController.php | 108 +
.../WaterDrawingMeasurementsController.php | 124 +
.../WaterDrawingMetersController.php | 97 +
.../WaterDrawingPaperworkPecsController.php | 148 +
.../WaterDrawingPaperworksController.php | 1775 +
.../WaterDrawingPaymentsController.php | 256 +
.../WaterDrawingReturnPointsController.php | 112 +
idrocap_wa/src/Error/AppExceptionRenderer.php | 27 +
.../Identifier/JixelPasswordIdentifier.php | 198 +
...rTimezoneDatetimeRequestDataMiddleware.php | 37 +
idrocap_wa/src/Model/Behavior/.gitkeep | 0
.../Model/Behavior/AttachmentsBehavior.php | 165 +
.../ControllableObjectInterfaceBehavior.php | 42 +
idrocap_wa/src/Model/Entity/Actor.php | 302 +
idrocap_wa/src/Model/Entity/ActorType.php | 35 +
idrocap_wa/src/Model/Entity/Applicant.php | 81 +
.../ApplicantsWaterDrawingPaperwork.php | 37 +
idrocap_wa/src/Model/Entity/Attachment.php | 86 +
.../src/Model/Entity/BackgroundTask.php | 43 +
.../src/Model/Entity/CadastralCropType.php | 31 +
.../src/Model/Entity/CapabilitiesMenuItem.php | 35 +
.../Model/Entity/CapabilitiesMenuSection.php | 35 +
idrocap_wa/src/Model/Entity/Capability.php | 53 +
.../src/Model/Entity/CapabilityGroup.php | 35 +
.../src/Model/Entity/ControllableObject.php | 297 +
.../Entity/ControllableObjectInterface.php | 35 +
.../ControllableObjectInterfaceType.php | 34 +
.../Model/Entity/ControllableObjectType.php | 33 +
idrocap_wa/src/Model/Entity/County.php | 52 +
idrocap_wa/src/Model/Entity/Delivery.php | 53 +
idrocap_wa/src/Model/Entity/DeliveryType.php | 31 +
.../src/Model/Entity/DispatchingTask.php | 47 +
.../src/Model/Entity/DispatchingTaskItem.php | 47 +
.../Model/Entity/DispatchingTaskStatus.php | 31 +
idrocap_wa/src/Model/Entity/District.php | 52 +
idrocap_wa/src/Model/Entity/Email.php | 43 +
.../src/Model/Entity/EmailDescription.php | 33 +
idrocap_wa/src/Model/Entity/Fax.php | 41 +
.../src/Model/Entity/FaxDescription.php | 33 +
idrocap_wa/src/Model/Entity/Filter.php | 43 +
idrocap_wa/src/Model/Entity/Group.php | 53 +
idrocap_wa/src/Model/Entity/GroupsGroup.php | 33 +
idrocap_wa/src/Model/Entity/Language.php | 33 +
idrocap_wa/src/Model/Entity/Location.php | 56 +
.../src/Model/Entity/LocationAttribute.php | 43 +
idrocap_wa/src/Model/Entity/Map.php | 43 +
idrocap_wa/src/Model/Entity/MenuItem.php | 82 +
idrocap_wa/src/Model/Entity/MenuSection.php | 35 +
idrocap_wa/src/Model/Entity/Message.php | 61 +
idrocap_wa/src/Model/Entity/MessageStatus.php | 31 +
idrocap_wa/src/Model/Entity/MessageType.php | 32 +
.../src/Model/Entity/MobileComponent.php | 35 +
idrocap_wa/src/Model/Entity/MobilePhone.php | 43 +
.../Model/Entity/MobilePhoneDescription.php | 33 +
idrocap_wa/src/Model/Entity/Notification.php | 51 +
.../src/Model/Entity/NotificationType.php | 31 +
idrocap_wa/src/Model/Entity/Organisation.php | 259 +
.../src/Model/Entity/OrganisationType.php | 32 +
idrocap_wa/src/Model/Entity/Pec.php | 43 +
.../src/Model/Entity/PecDescription.php | 33 +
idrocap_wa/src/Model/Entity/Permission.php | 34 +
idrocap_wa/src/Model/Entity/Phone.php | 39 +
.../src/Model/Entity/PhoneDescription.php | 33 +
idrocap_wa/src/Model/Entity/Privacy.php | 32 +
idrocap_wa/src/Model/Entity/PrivacyUser.php | 37 +
.../src/Model/Entity/PushNotification.php | 37 +
idrocap_wa/src/Model/Entity/Snapshot.php | 47 +
idrocap_wa/src/Model/Entity/Tag.php | 56 +
idrocap_wa/src/Model/Entity/TelegramChat.php | 41 +
.../src/Model/Entity/TelegramContact.php | 51 +
.../UnpackedWaterDrawingPaperworkSnapshot.php | 55 +
idrocap_wa/src/Model/Entity/User.php | 643 +
.../UserTimezoneDatetimeEntityTrait.php | 32 +
...erDrawingAntimafiaCertificationRequest.php | 43 +
...ingAntimafiaCertificationRequestStatus.php | 31 +
.../src/Model/Entity/WaterDrawingArticle.php | 32 +
.../Model/Entity/WaterDrawingDerivation.php | 67 +
.../Entity/WaterDrawingDerivationType.php | 31 +
.../src/Model/Entity/WaterDrawingFee.php | 65 +
.../Model/Entity/WaterDrawingIntendedUse.php | 55 +
.../Entity/WaterDrawingIntendedUseType.php | 31 +
.../Model/Entity/WaterDrawingMeasurement.php | 39 +
.../src/Model/Entity/WaterDrawingMeter.php | 45 +
.../Model/Entity/WaterDrawingPaperwork.php | 479 +
.../Entity/WaterDrawingPaperworkHistory.php | 54 +
.../Model/Entity/WaterDrawingPaperworkPec.php | 53 +
.../Entity/WaterDrawingPaperworkStatus.php | 33 +
.../src/Model/Entity/WaterDrawingPayment.php | 56 +
.../Model/Entity/WaterDrawingPaymentType.php | 31 +
.../Model/Entity/WaterDrawingReturnPoint.php | 43 +
.../src/Model/Entity/WaterDrawingToolType.php | 31 +
.../Entity/WaterDrawingWateringSystem.php | 31 +
.../src/Model/Table/ActorTypesTable.php | 81 +
idrocap_wa/src/Model/Table/ActorsTable.php | 126 +
.../src/Model/Table/ApplicantsTable.php | 208 +
.../ApplicantsWaterDrawingPaperworksTable.php | 100 +
.../src/Model/Table/AttachmentsTable.php | 133 +
.../src/Model/Table/BackgroundTasksTable.php | 103 +
.../Model/Table/CadastralCropTypesTable.php | 69 +
.../Table/CapabilitiesMenuItemsTable.php | 91 +
.../Table/CapabilitiesMenuSectionsTable.php | 91 +
.../src/Model/Table/CapabilitiesTable.php | 145 +
.../src/Model/Table/CapabilityGroupsTable.php | 79 +
.../ControllableObjectInterfaceTypesTable.php | 77 +
.../ControllableObjectInterfacesTable.php | 95 +
.../Table/ControllableObjectTypesTable.php | 74 +
.../Model/Table/ControllableObjectsTable.php | 167 +
idrocap_wa/src/Model/Table/CountiesTable.php | 165 +
.../src/Model/Table/DeliveriesTable.php | 145 +
.../src/Model/Table/DeliveryTypesTable.php | 65 +
.../Model/Table/DispatchingTaskItemsTable.php | 111 +
.../Table/DispatchingTaskStatusesTable.php | 65 +
.../src/Model/Table/DispatchingTasksTable.php | 113 +
idrocap_wa/src/Model/Table/DistrictsTable.php | 136 +
.../Model/Table/EmailDescriptionsTable.php | 74 +
idrocap_wa/src/Model/Table/EmailsTable.php | 111 +
.../src/Model/Table/FaxDescriptionsTable.php | 73 +
idrocap_wa/src/Model/Table/FaxesTable.php | 107 +
idrocap_wa/src/Model/Table/FiltersTable.php | 105 +
.../src/Model/Table/GroupsGroupsTable.php | 94 +
idrocap_wa/src/Model/Table/GroupsTable.php | 157 +
idrocap_wa/src/Model/Table/LanguagesTable.php | 71 +
.../Model/Table/LocationAttributesTable.php | 116 +
idrocap_wa/src/Model/Table/LocationsTable.php | 118 +
idrocap_wa/src/Model/Table/MapsTable.php | 88 +
idrocap_wa/src/Model/Table/MenuItemsTable.php | 135 +
.../src/Model/Table/MenuSectionsTable.php | 80 +
.../src/Model/Table/MessageStatusesTable.php | 65 +
.../src/Model/Table/MessageTypesTable.php | 69 +
idrocap_wa/src/Model/Table/MessagesTable.php | 150 +
.../src/Model/Table/MobileComponentsTable.php | 77 +
.../Table/MobilePhoneDescriptionsTable.php | 74 +
.../src/Model/Table/MobilePhonesTable.php | 111 +
.../Model/Table/NotificationTypesTable.php | 65 +
.../src/Model/Table/NotificationsTable.php | 122 +
.../Model/Table/OrganisationTypesTable.php | 69 +
.../src/Model/Table/OrganisationsTable.php | 286 +
.../src/Model/Table/PecDescriptionsTable.php | 74 +
idrocap_wa/src/Model/Table/PecsTable.php | 111 +
.../src/Model/Table/PermissionsTable.php | 85 +
.../Model/Table/PhoneDescriptionsTable.php | 73 +
idrocap_wa/src/Model/Table/PhonesTable.php | 103 +
idrocap_wa/src/Model/Table/PrivacyTable.php | 90 +
.../src/Model/Table/PrivacyUsersTable.php | 123 +
.../Model/Table/PushNotificationsTable.php | 101 +
idrocap_wa/src/Model/Table/SnapshotsTable.php | 118 +
idrocap_wa/src/Model/Table/TagsTable.php | 94 +
.../src/Model/Table/TelegramChatsTable.php | 99 +
.../src/Model/Table/TelegramContactsTable.php | 116 +
...kedWaterDrawingPaperworkSnapshotsTable.php | 137 +
idrocap_wa/src/Model/Table/UsersTable.php | 476 +
...mafiaCertificationRequestStatusesTable.php | 67 +
...ingAntimafiaCertificationRequestsTable.php | 107 +
.../Model/Table/WaterDrawingArticlesTable.php | 76 +
.../WaterDrawingDerivationTypesTable.php | 66 +
.../Table/WaterDrawingDerivationsTable.php | 206 +
.../src/Model/Table/WaterDrawingFeesTable.php | 124 +
.../WaterDrawingIntendedUseTypesTable.php | 67 +
.../Table/WaterDrawingIntendedUsesTable.php | 147 +
.../Table/WaterDrawingMeasurementsTable.php | 108 +
.../Model/Table/WaterDrawingMetersTable.php | 118 +
.../WaterDrawingPaperworkHistoriesTable.php | 170 +
.../Table/WaterDrawingPaperworkPecsTable.php | 136 +
.../WaterDrawingPaperworkStatusesTable.php | 70 +
.../Table/WaterDrawingPaperworksTable.php | 383 +
.../Table/WaterDrawingPaymentTypesTable.php | 67 +
.../Model/Table/WaterDrawingPaymentsTable.php | 149 +
.../Table/WaterDrawingReturnPointsTable.php | 120 +
.../Table/WaterDrawingToolTypesTable.php | 67 +
.../WaterDrawingWateringSystemsTable.php | 67 +
idrocap_wa/src/View/AjaxView.php | 46 +
idrocap_wa/src/View/AppView.php | 52 +
idrocap_wa/src/View/Cell/.gitkeep | 0
.../src/View/Cell/DistrictProvinceCell.php | 68 +
idrocap_wa/src/View/Cell/FilterInputCell.php | 51 +
idrocap_wa/src/View/Cell/FiltersCell.php | 50 +
idrocap_wa/src/View/Cell/IntendedUsesCell.php | 33 +
idrocap_wa/src/View/Cell/MapCell.php | 234 +
idrocap_wa/src/View/CustomCsvView.php | 100 +
.../src/View/Helper/BreadcrumbHelper.php | 67 +
idrocap_wa/src/View/Helper/MenuHelper.php | 108 +
.../src/View/Helper/NotificationsHelper.php | 87 +
idrocap_wa/src/View/Helper/SectionsHelper.php | 55 +
.../src/WGS/Auth/OpenIdConnectClient.php | 163 +
.../src/WGS/FileStorage/FileStorage.php | 14 +
.../WGS/FileStorage/FileStorageFactory.php | 37 +
.../src/WGS/FileStorage/HadoopFileStorage.php | 116 +
.../WGS/FileStorage/S3MinioFileStorage.php | 180 +
idrocap_wa/src/WGS/Geo/CadastralUtils.php | 61 +
.../Geo/ExtGeoResourceAttributesRetriever.php | 40 +
idrocap_wa/src/WGS/Geo/GeoValidation.php | 61 +
idrocap_wa/src/WGS/Geo/Geocoding.php | 84 +
.../Geo/IntGeoResourceAttributesRetriever.php | 57 +
.../WGS/Geo/LocationAttributesRetriever.php | 65 +
.../NotificationsHandler/MessagingHandler.php | 631 +
.../NotificationGenerator.php | 169 +
.../NotificationsHandler.php | 243 +
.../RecipientsDetector.php | 119 +
.../SystemNotificationsDispatcher.php | 122 +
.../WGS/SnapshotsHandler/SnapshotsHandler.php | 304 +
.../Utils/Attachments/AttachmentChecker.php | 27 +
.../Utils/Attachments/AttachmentConverter.php | 39 +
.../Attachments/SignedAttachmentChecker.php | 133 +
.../DistrictCellDto.php | 25 +
.../ProvinceCellDto.php | 25 +
.../Dto/Users/CitizenRegistrationDTO.php | 81 +
.../src/WGS/Utils/Enum/InputFieldType.php | 8 +
.../WGS/Utils/Enum/ProvinceDistrictFields.php | 12 +
idrocap_wa/src/WGS/Utils/Enum/Regions.php | 6 +
.../src/WGS/Utils/Enum/SicilyProvinces.php | 33 +
.../Helper/ProvinceDistrictFieldHelper.php | 44 +
...ntendedUseVegetationCheckCommandSender.php | 28 +
.../templates/Applicants/citizen_add.php | 49 +
.../templates/Applicants/citizen_edit.php | 49 +
.../templates/Applicants/citizen_view.php | 63 +
idrocap_wa/templates/Applicants/edit.php | 71 +
idrocap_wa/templates/Applicants/view.php | 72 +
idrocap_wa/templates/Capabilities/index.php | 85 +
.../ControllableObjects/get_attachments.php | 119 +
idrocap_wa/templates/Dashboard/index.php | 32 +
idrocap_wa/templates/Deliveries/index.php | 284 +
idrocap_wa/templates/Emails/add.php | 54 +
idrocap_wa/templates/Emails/edit.php | 54 +
idrocap_wa/templates/Error/error400.php | 49 +
idrocap_wa/templates/Error/error500.php | 53 +
idrocap_wa/templates/Faxes/add.php | 54 +
idrocap_wa/templates/Faxes/edit.php | 54 +
.../templates/Filters/get_filter_input.php | 1 +
idrocap_wa/templates/Groups/add.php | 61 +
idrocap_wa/templates/Groups/edit.php | 66 +
.../templates/Groups/handle_capabilities.php | 75 +
idrocap_wa/templates/Groups/index.php | 63 +
idrocap_wa/templates/Groups/view.php | 45 +
idrocap_wa/templates/Maps/index.php | 149 +
idrocap_wa/templates/MobilePhones/add.php | 54 +
idrocap_wa/templates/MobilePhones/edit.php | 54 +
idrocap_wa/templates/Notifications/index.php | 4 +
.../templates/Notifications/read_all.php | 5 +
idrocap_wa/templates/Organisations/add.php | 197 +
idrocap_wa/templates/Organisations/edit.php | 118 +
idrocap_wa/templates/Organisations/index.php | 75 +
idrocap_wa/templates/Organisations/view.php | 99 +
idrocap_wa/templates/Pecs/add.php | 54 +
idrocap_wa/templates/Pecs/edit.php | 54 +
idrocap_wa/templates/Phones/add.php | 53 +
idrocap_wa/templates/Phones/edit.php | 53 +
.../templates/Privacy/accept_privacy.php | 29 +
idrocap_wa/templates/Privacy/edit.php | 24 +
idrocap_wa/templates/Privacy/view.php | 19 +
idrocap_wa/templates/Privacy/view_public.php | 10 +
idrocap_wa/templates/Tags/add.php | 54 +
idrocap_wa/templates/Tags/edit.php | 55 +
idrocap_wa/templates/Tags/index.php | 63 +
idrocap_wa/templates/Tags/view.php | 52 +
idrocap_wa/templates/TelegramChats/add.php | 53 +
idrocap_wa/templates/TelegramChats/edit.php | 53 +
idrocap_wa/templates/Users/add.php | 108 +
idrocap_wa/templates/Users/add_citizen.php | 256 +
.../templates/Users/choose_new_password.php | 10 +
idrocap_wa/templates/Users/edit.php | 112 +
idrocap_wa/templates/Users/index.php | 71 +
idrocap_wa/templates/Users/login.php | 27 +
.../templates/Users/one_time_password.php | 8 +
.../templates/Users/password_recovery.php | 9 +
idrocap_wa/templates/Users/view.php | 72 +
.../templates/WaterDrawingArticles/add.php | 45 +
.../templates/WaterDrawingArticles/edit.php | 45 +
.../templates/WaterDrawingArticles/index.php | 65 +
.../templates/WaterDrawingArticles/view.php | 55 +
.../templates/WaterDrawingDerivations/add.php | 250 +
.../WaterDrawingDerivations/edit.php | 235 +
.../WaterDrawingDerivations/index.php | 72 +
.../WaterDrawingDerivations/view.php | 104 +
idrocap_wa/templates/WaterDrawingFees/add.php | 46 +
.../templates/WaterDrawingFees/edit.php | 46 +
.../templates/WaterDrawingFees/index.php | 76 +
.../templates/WaterDrawingFees/view.php | 91 +
.../WaterDrawingIntendedUses/add.php | 37 +
.../WaterDrawingIntendedUses/edit.php | 42 +
.../WaterDrawingIntendedUses/index.php | 60 +
.../WaterDrawingIntendedUses/view.php | 64 +
.../WaterDrawingMeasurements/add.php | 51 +
.../WaterDrawingMeasurements/index.php | 73 +
.../templates/WaterDrawingMeters/add.php | 66 +
.../templates/WaterDrawingMeters/dismiss.php | 67 +
.../templates/WaterDrawingMeters/edit.php | 66 +
.../templates/WaterDrawingMeters/view.php | 103 +
.../WaterDrawingPaperworkPecs/add.php | 62 +
.../WaterDrawingPaperworkPecs/edit.php | 62 +
.../WaterDrawingPaperworkPecs/index.php | 81 +
.../WaterDrawingPaperworkPecs/view.php | 61 +
.../templates/WaterDrawingPaperworks/add.php | 632 +
.../WaterDrawingPaperworks/add_scan.php | 49 +
.../antimafia_request_to_anac.php | 49 +
...ts_water_drawing_paperworks_item_block.php | 5 +
.../WaterDrawingPaperworks/assign.php | 48 +
.../citizen_documentation_index.php | 115 +
.../citizen_documentation_requested.php | 376 +
.../citizen_request_paperwork.php | 35 +
.../citizen_submission_index.php | 73 +
.../citizen_submit_paperwork.php | 46 +
.../citizen_upload_attachment.php | 60 +
.../citizen_upload_payment_receipt.php | 58 +
.../templates/WaterDrawingPaperworks/edit.php | 641 +
.../WaterDrawingPaperworks/edit_scan.php | 667 +
.../WaterDrawingPaperworks/index.php | 81 +
.../index_snapshots.php | 80 +
.../index_snapshots_all.php | 77 +
...es_water_drawing_paperworks_item_block.php | 1 +
.../upload_antimafia_attachment.php | 49 +
.../upload_attachment.php | 50 +
.../upload_attachment_scan.php | 50 +
.../WaterDrawingPaperworks/validate.php | 713 +
.../WaterDrawingPaperworks/validate_index.php | 71 +
.../WaterDrawingPaperworks/validate_scan.php | 728 +
.../templates/WaterDrawingPaperworks/view.php | 768 +
.../WaterDrawingPaperworks/view_scan.php | 727 +
.../WaterDrawingPaperworks/view_snapshot.php | 641 +
.../templates/WaterDrawingPayments/add.php | 93 +
.../templates/WaterDrawingPayments/edit.php | 92 +
.../templates/WaterDrawingPayments/index.php | 83 +
.../templates/WaterDrawingPayments/view.php | 95 +
.../WaterDrawingReturnPoints/add.php | 125 +
.../WaterDrawingReturnPoints/edit.php | 124 +
.../WaterDrawingReturnPoints/index.php | 54 +
.../WaterDrawingReturnPoints/view.php | 128 +
idrocap_wa/templates/cell/.gitkeep | 1 +
.../cell/DistrictProvince/display.php | 41 +
.../templates/cell/FilterInput/display.php | 12 +
idrocap_wa/templates/cell/Filters/display.php | 152 +
.../templates/cell/IntendedUses/display.php | 1 +
idrocap_wa/templates/cell/Map/display.php | 13 +
idrocap_wa/templates/element/Map.php | 622 +
.../element/MapCore/MapPrimitives.php | 373 +
.../WaterDrawingPaperworks/applicants.php | 196 +
.../WaterDrawingPaperworks/intended_uses.php | 151 +
.../templates/element/attachmentPreview.php | 41 +
idrocap_wa/templates/element/attachments.php | 341 +
.../templates/element/districtSelect.php | 210 +
.../templates/element/flash/default.php | 15 +
idrocap_wa/templates/element/flash/error.php | 11 +
idrocap_wa/templates/element/flash/info.php | 11 +
.../templates/element/flash/success.php | 11 +
.../templates/element/flash/warning.php | 11 +
.../templates/element/provinceSelect.php | 145 +
idrocap_wa/templates/email/html/default.php | 22 +
idrocap_wa/templates/email/text/default.php | 18 +
idrocap_wa/templates/layout/ajax.php | 17 +
idrocap_wa/templates/layout/default.php | 47 +
.../templates/layout/email/html/default.php | 25 +
.../templates/layout/email/text/default.php | 17 +
idrocap_wa/templates/layout/error.php | 41 +
idrocap_wa/templates/layout/view_public.php | 68 +
.../BootstrapUI/element/flash/default.php | 30 +
.../plugin/CakeLte/element/footer/main.php | 14 +
.../plugin/CakeLte/element/header/main.php | 21 +
.../plugin/CakeLte/element/header/menu.php | 2 +
.../CakeLte/element/header/notifications.php | 51 +
.../plugin/CakeLte/element/sidebar/main.php | 6 +
.../plugin/CakeLte/element/sidebar/menu.php | 33 +
.../plugin/CakeLte/layout/default.php | 108 +
.../templates/plugin/CakeLte/layout/login.php | 111 +
idrocap_wa/tests/Fixture/.gitkeep | 0
idrocap_wa/tests/TestCase/ApplicationTest.php | 85 +
.../TestCase/Controller/Component/.gitkeep | 0
.../Controller/PagesControllerTest.php | 115 +
.../tests/TestCase/Model/Behavior/.gitkeep | 0
.../tests/TestCase/View/Helper/.gitkeep | 0
idrocap_wa/tests/bootstrap.php | 66 +
idrocap_wa/tests/schema.sql | 4 +
idrocap_wa/webroot/.gitignore | 3 +
idrocap_wa/webroot/.htaccess | 5 +
idrocap_wa/webroot/adminlte | 1 +
idrocap_wa/webroot/bower.json | 17 +
idrocap_wa/webroot/css/cake.css | 299 +
.../webroot/css/citizen-registration.css | 14 +
idrocap_wa/webroot/css/fonts.css | 80 +
idrocap_wa/webroot/css/home.css | 75 +
idrocap_wa/webroot/css/idrocap-styles.css | 33 +
idrocap_wa/webroot/css/jixel_ol.css | 66 +
idrocap_wa/webroot/css/milligram.min.css | 9 +
idrocap_wa/webroot/css/normalize.min.css | 8 +
idrocap_wa/webroot/favicon.ico | Bin 0 -> 227390 bytes
idrocap_wa/webroot/favicon2.ico | Bin 0 -> 15086 bytes
idrocap_wa/webroot/font/Raleway-License.txt | 51 +
.../webroot/font/cakedingbats-webfont.eot | Bin 0 -> 75538 bytes
.../webroot/font/cakedingbats-webfont.svg | 78 +
.../webroot/font/cakedingbats-webfont.ttf | Bin 0 -> 75412 bytes
.../webroot/font/cakedingbats-webfont.woff | Bin 0 -> 43484 bytes
.../webroot/font/cakedingbats-webfont.woff2 | Bin 0 -> 35456 bytes
.../font/raleway-400-cyrillic-ext.woff2 | Bin 0 -> 22516 bytes
.../webroot/font/raleway-400-cyrillic.woff2 | Bin 0 -> 21768 bytes
.../webroot/font/raleway-400-latin-ext.woff2 | Bin 0 -> 25652 bytes
.../webroot/font/raleway-400-latin.woff2 | Bin 0 -> 41852 bytes
.../webroot/font/raleway-400-vietnamese.woff2 | Bin 0 -> 7648 bytes
.../font/raleway-700-cyrillic-ext.woff2 | Bin 0 -> 22516 bytes
.../webroot/font/raleway-700-cyrillic.woff2 | Bin 0 -> 21768 bytes
.../webroot/font/raleway-700-latin-ext.woff2 | Bin 0 -> 25652 bytes
.../webroot/font/raleway-700-latin.woff2 | Bin 0 -> 41852 bytes
.../webroot/font/raleway-700-vietnamese.woff2 | Bin 0 -> 7648 bytes
idrocap_wa/webroot/img/cake-logo.png | Bin 0 -> 2683 bytes
idrocap_wa/webroot/img/cake.icon.png | Bin 0 -> 943 bytes
idrocap_wa/webroot/img/cake.icon.svg | 7 +
idrocap_wa/webroot/img/cake.logo.svg | 41 +
idrocap_wa/webroot/img/cake.power.gif | Bin 0 -> 201 bytes
.../webroot/img/logo-autorita-dibacino.png | Bin 0 -> 14539 bytes
idrocap_wa/webroot/img/logo-fsc.png | Bin 0 -> 11329 bytes
idrocap_wa/webroot/img/logo-poa.png | Bin 0 -> 13583 bytes
.../webroot/img/logo-regione-sicilia.png | Bin 0 -> 379241 bytes
idrocap_wa/webroot/img/logo_mite.png | Bin 0 -> 26664 bytes
idrocap_wa/webroot/img/user2-160x160.jpg | Bin 0 -> 7070 bytes
idrocap_wa/webroot/index.php | 37 +
idrocap_wa/webroot/js/.gitkeep | 0
.../dist/entrypoints/content.js | 27 +
.../utils/Autocomplete/AutocompleteHandler.js | 69 +
.../entrypoints/utils/Clients/BaseClient.js | 38 +
.../entrypoints/utils/Clients/OpenAIClient.js | 39 +
.../entrypoints/utils/Clients/WgsAIClient.js | 10 +
.../utils/Interfaces/PromptInterface.js | 1 +
.../utils/Services/AutoCompleteService.js | 34 +
.../dist/entrypoints/utils/TaskFlow.js | 15 +
.../utils/Utility/DataFormatter.js | 55 +
.../utils/Utility/DomElementHandler.js | 26 +
.../entrypoints/utils/Utility/EventHandler.js | 5 +
.../entrypoints/utils/Utility/FormAnalyzer.js | 137 +
.../utils/Utility/FormExclusions.js | 25 +
.../entrypoints/utils/Utility/FormFiller.js | 112 +
.../js/ia-form-filler/styles/style.css | 228 +
idrocap_wa/webroot/js/init_tiny_mce.js | 62 +
idrocap_wa/webroot/js/jixel-primitives.js | 45 +
idrocap_wa/webroot/js/moment.js | 5685 +++
.../js/tinymce/icons/default/icons.min.js | 1 +
idrocap_wa/webroot/js/tinymce/langs/README.md | 3 +
idrocap_wa/webroot/js/tinymce/langs/it.js | 1 +
idrocap_wa/webroot/js/tinymce/license.md | 6 +
.../js/tinymce/models/dom/model.min.js | 4 +
.../tinymce/plugins/accordion/plugin.min.js | 4 +
.../js/tinymce/plugins/advlist/plugin.min.js | 4 +
.../js/tinymce/plugins/anchor/plugin.min.js | 4 +
.../js/tinymce/plugins/autolink/plugin.min.js | 4 +
.../tinymce/plugins/autoresize/plugin.min.js | 4 +
.../js/tinymce/plugins/autosave/plugin.min.js | 4 +
.../js/tinymce/plugins/charmap/plugin.min.js | 4 +
.../js/tinymce/plugins/code/plugin.min.js | 4 +
.../tinymce/plugins/codesample/plugin.min.js | 4 +
.../plugins/directionality/plugin.min.js | 4 +
.../plugins/emoticons/js/emojiimages.js | 1 +
.../plugins/emoticons/js/emojiimages.min.js | 3 +
.../js/tinymce/plugins/emoticons/js/emojis.js | 1 +
.../plugins/emoticons/js/emojis.min.js | 2 +
.../tinymce/plugins/emoticons/plugin.min.js | 4 +
.../tinymce/plugins/fullscreen/plugin.min.js | 4 +
.../tinymce/plugins/help/js/i18n/keynav/ar.js | 93 +
.../plugins/help/js/i18n/keynav/bg_BG.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/ca.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/cs.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/da.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/de.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/el.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/en.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/es.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/eu.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/fa.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/fi.js | 93 +
.../plugins/help/js/i18n/keynav/fr_FR.js | 93 +
.../plugins/help/js/i18n/keynav/he_IL.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/hi.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/hr.js | 93 +
.../plugins/help/js/i18n/keynav/hu_HU.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/id.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/it.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/ja.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/kk.js | 93 +
.../plugins/help/js/i18n/keynav/ko_KR.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/ms.js | 93 +
.../plugins/help/js/i18n/keynav/nb_NO.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/nl.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/pl.js | 93 +
.../plugins/help/js/i18n/keynav/pt_BR.js | 93 +
.../plugins/help/js/i18n/keynav/pt_PT.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/ro.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/ru.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/sk.js | 93 +
.../plugins/help/js/i18n/keynav/sl_SI.js | 93 +
.../plugins/help/js/i18n/keynav/sv_SE.js | 93 +
.../plugins/help/js/i18n/keynav/th_TH.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/tr.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/uk.js | 93 +
.../tinymce/plugins/help/js/i18n/keynav/vi.js | 93 +
.../plugins/help/js/i18n/keynav/zh_CN.js | 87 +
.../plugins/help/js/i18n/keynav/zh_TW.js | 93 +
.../js/tinymce/plugins/help/plugin.min.js | 4 +
.../js/tinymce/plugins/image/plugin.min.js | 4 +
.../tinymce/plugins/importcss/plugin.min.js | 4 +
.../plugins/insertdatetime/plugin.min.js | 4 +
.../js/tinymce/plugins/link/plugin.min.js | 4 +
.../js/tinymce/plugins/lists/plugin.min.js | 4 +
.../js/tinymce/plugins/media/plugin.min.js | 4 +
.../tinymce/plugins/nonbreaking/plugin.min.js | 4 +
.../tinymce/plugins/pagebreak/plugin.min.js | 4 +
.../js/tinymce/plugins/preview/plugin.min.js | 4 +
.../tinymce/plugins/quickbars/plugin.min.js | 4 +
.../js/tinymce/plugins/save/plugin.min.js | 4 +
.../plugins/searchreplace/plugin.min.js | 4 +
.../js/tinymce/plugins/table/plugin.min.js | 4 +
.../plugins/visualblocks/plugin.min.js | 4 +
.../tinymce/plugins/visualchars/plugin.min.js | 4 +
.../tinymce/plugins/wordcount/plugin.min.js | 4 +
.../js/tinymce/skins/content/dark/content.js | 1 +
.../skins/content/dark/content.min.css | 1 +
.../tinymce/skins/content/default/content.js | 1 +
.../skins/content/default/content.min.css | 1 +
.../tinymce/skins/content/document/content.js | 1 +
.../skins/content/document/content.min.css | 1 +
.../skins/content/tinymce-5-dark/content.js | 1 +
.../content/tinymce-5-dark/content.min.css | 1 +
.../skins/content/tinymce-5/content.js | 1 +
.../skins/content/tinymce-5/content.min.css | 1 +
.../tinymce/skins/content/writer/content.js | 1 +
.../skins/content/writer/content.min.css | 1 +
.../skins/ui/oxide-dark/content.inline.js | 1 +
.../ui/oxide-dark/content.inline.min.css | 1 +
.../js/tinymce/skins/ui/oxide-dark/content.js | 1 +
.../skins/ui/oxide-dark/content.min.css | 1 +
.../js/tinymce/skins/ui/oxide-dark/skin.js | 1 +
.../tinymce/skins/ui/oxide-dark/skin.min.css | 1 +
.../skins/ui/oxide-dark/skin.shadowdom.js | 1 +
.../ui/oxide-dark/skin.shadowdom.min.css | 1 +
.../tinymce/skins/ui/oxide/content.inline.js | 1 +
.../skins/ui/oxide/content.inline.min.css | 1 +
.../js/tinymce/skins/ui/oxide/content.js | 1 +
.../js/tinymce/skins/ui/oxide/content.min.css | 1 +
.../webroot/js/tinymce/skins/ui/oxide/skin.js | 1 +
.../js/tinymce/skins/ui/oxide/skin.min.css | 1 +
.../tinymce/skins/ui/oxide/skin.shadowdom.js | 1 +
.../skins/ui/oxide/skin.shadowdom.min.css | 1 +
.../skins/ui/tinymce-5-dark/content.inline.js | 1 +
.../ui/tinymce-5-dark/content.inline.min.css | 1 +
.../skins/ui/tinymce-5-dark/content.js | 1 +
.../skins/ui/tinymce-5-dark/content.min.css | 1 +
.../tinymce/skins/ui/tinymce-5-dark/skin.js | 1 +
.../skins/ui/tinymce-5-dark/skin.min.css | 1 +
.../skins/ui/tinymce-5-dark/skin.shadowdom.js | 1 +
.../ui/tinymce-5-dark/skin.shadowdom.min.css | 1 +
.../skins/ui/tinymce-5/content.inline.js | 1 +
.../skins/ui/tinymce-5/content.inline.min.css | 1 +
.../js/tinymce/skins/ui/tinymce-5/content.js | 1 +
.../skins/ui/tinymce-5/content.min.css | 1 +
.../js/tinymce/skins/ui/tinymce-5/skin.js | 1 +
.../tinymce/skins/ui/tinymce-5/skin.min.css | 1 +
.../skins/ui/tinymce-5/skin.shadowdom.js | 1 +
.../skins/ui/tinymce-5/skin.shadowdom.min.css | 1 +
.../js/tinymce/themes/silver/theme.min.js | 4 +
idrocap_wa/webroot/js/tinymce/tinymce.d.ts | 3254 ++
idrocap_wa/webroot/js/tinymce/tinymce.min.js | 4 +
idrocap_wa/webroot/ol-ext/extra/Cloud.js | 196 +
.../webroot/ol-ext/extra/Exif2Geojson.js | 76 +
idrocap_wa/webroot/ol-ext/extra/ExportMap.js | 84 +
.../webroot/ol-ext/extra/FontAwesome5Def.js | 681 +
.../webroot/ol-ext/extra/FontAwesomeDef.js | 681 +
.../webroot/ol-ext/extra/FontMaki2Def.js | 171 +
.../webroot/ol-ext/extra/FontMakiDef.js | 131 +
idrocap_wa/webroot/ol-ext/extra/IFrameAPI.js | 107 +
.../webroot/ol-ext/extra/MapIFrameAPI.js | 159 +
.../webroot/ol-ext/extra/TextureImage.js | 16 +
idrocap_wa/webroot/ol-ext/extra/WSynchro.js | 71 +
idrocap_wa/webroot/ol-ext/ol-ext.css | 6828 +++
idrocap_wa/webroot/ol-ext/ol-ext.js | 42128 ++++++++++++++++
idrocap_wa/webroot/ol-ext/ol-ext.min.css | 1 +
idrocap_wa/webroot/ol-ext/ol-ext.min.js | 9 +
idrocap_wa/webroot/package-lock.json | 443 +
idrocap_wa/webroot/package.json | 5 +
.../webroot/sounds/all_notification_read.mp3 | Bin 0 -> 116192 bytes
.../webroot/sounds/new_notification.mp3 | Bin 0 -> 108669 bytes
673 files changed, 126346 insertions(+), 1 deletion(-)
create mode 100644 idrocap_wa/.htaccess
create mode 100644 idrocap_wa/Dockerfile
create mode 100644 idrocap_wa/README.md
create mode 100644 idrocap_wa/bin/bash_completion.sh
create mode 100755 idrocap_wa/bin/cake
create mode 100644 idrocap_wa/bin/cake.bat
create mode 100644 idrocap_wa/bin/cake.php
create mode 100644 idrocap_wa/composer.json
create mode 100644 idrocap_wa/composer.lock
create mode 100644 idrocap_wa/config/.env.example
create mode 100644 idrocap_wa/config/app.php
create mode 100644 idrocap_wa/config/app_local.example.php
create mode 100644 idrocap_wa/config/app_local.php
create mode 100644 idrocap_wa/config/bootstrap.php
create mode 100644 idrocap_wa/config/bootstrap_cli.php
create mode 100644 idrocap_wa/config/cakelte.php
create mode 100644 idrocap_wa/config/keys/private.key
create mode 100644 idrocap_wa/config/keys/public.key
create mode 100644 idrocap_wa/config/paths.php
create mode 100644 idrocap_wa/config/plugins.php
create mode 100644 idrocap_wa/config/routes.php
create mode 100644 idrocap_wa/config/schema/i18n.sql
create mode 100644 idrocap_wa/config/schema/sessions.sql
create mode 100755 idrocap_wa/dockerfiles/cake
create mode 100755 idrocap_wa/dockerfiles/run
create mode 100644 idrocap_wa/dockerfiles/www.conf
create mode 100644 idrocap_wa/index.php
create mode 100755 idrocap_wa/jixel-background-task-handler/Dockerfile
create mode 100755 idrocap_wa/jixel-background-task-handler/jbth.py
create mode 100755 idrocap_wa/jixel-background-task-handler/jbth.sh
create mode 100755 idrocap_wa/jixel-background-task-handler/jgprc.py
create mode 100755 idrocap_wa/jixel-background-task-handler/jgprc.sh
create mode 100755 idrocap_wa/jixel-background-task-handler/jixel-background-task-handler.sh
create mode 100644 idrocap_wa/jixel-background-task-handler/jixel-cron.log
create mode 100755 idrocap_wa/jixel-background-task-handler/jixel-cron.sh
create mode 100644 idrocap_wa/jixel-background-task-handler/jixel-cron.txt
create mode 100755 idrocap_wa/jixel-background-task-handler/jixel-general-purpose-rabbit-consumer.sh
create mode 100644 idrocap_wa/phpcs.xml
create mode 100644 idrocap_wa/phpstan.neon
create mode 100644 idrocap_wa/phpunit.xml.dist
create mode 100644 idrocap_wa/plugins/.gitkeep
create mode 100644 idrocap_wa/psalm.xml
create mode 100644 idrocap_wa/resources/.gitkeep
create mode 100644 idrocap_wa/resources/locales/cake.pot
create mode 100644 idrocap_wa/resources/locales/default.pot
create mode 100644 idrocap_wa/resources/locales/en/default.po
create mode 100644 idrocap_wa/resources/locales/en/previous_default.po
create mode 100644 idrocap_wa/resources/locales/it/cake.po
create mode 100644 idrocap_wa/src/Application.php
create mode 100644 idrocap_wa/src/Command/AddCadastralCodeToUsesCommand.php
create mode 100644 idrocap_wa/src/Command/AddDerivationCoordinatesCommand.php
create mode 100644 idrocap_wa/src/Command/CheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand.php
create mode 100644 idrocap_wa/src/Command/CopyTranslationsCommand.php
create mode 100644 idrocap_wa/src/Command/IntendedUseVegetationCheckCommand.php
create mode 100644 idrocap_wa/src/Command/NormalizeApplicantProvinceCommand.php
create mode 100644 idrocap_wa/src/Command/NotificationsHandlerCommand.php
create mode 100644 idrocap_wa/src/Command/UnpackWaterDrawingPaperworkSnapshotsCommand.php
create mode 100644 idrocap_wa/src/Console/Installer.php
create mode 100644 idrocap_wa/src/Controller/AiServicesController.php
create mode 100644 idrocap_wa/src/Controller/Api/AppController.php
create mode 100644 idrocap_wa/src/Controller/Api/AttachmentsController.php
create mode 100644 idrocap_wa/src/Controller/Api/ErrorController.php
create mode 100644 idrocap_wa/src/Controller/Api/NotificationsController.php
create mode 100644 idrocap_wa/src/Controller/Api/OrganisationTypesController.php
create mode 100644 idrocap_wa/src/Controller/Api/OrganisationsController.php
create mode 100644 idrocap_wa/src/Controller/Api/SubscriptionsController.php
create mode 100644 idrocap_wa/src/Controller/Api/UsersController.php
create mode 100644 idrocap_wa/src/Controller/Api/WaterDrawingDerivationsController.php
create mode 100644 idrocap_wa/src/Controller/Api/WaterDrawingMeasurementsController.php
create mode 100644 idrocap_wa/src/Controller/Api/WaterDrawingPaperworksController.php
create mode 100644 idrocap_wa/src/Controller/AppController.php
create mode 100644 idrocap_wa/src/Controller/ApplicantsController.php
create mode 100644 idrocap_wa/src/Controller/AttachmentsController.php
create mode 100644 idrocap_wa/src/Controller/CapabilitiesController.php
create mode 100644 idrocap_wa/src/Controller/Component/.gitkeep
create mode 100644 idrocap_wa/src/Controller/Component/StreamableCsvExportTrait.php
create mode 100644 idrocap_wa/src/Controller/ControllableObjectsController.php
create mode 100644 idrocap_wa/src/Controller/DashboardController.php
create mode 100644 idrocap_wa/src/Controller/DeliveriesController.php
create mode 100644 idrocap_wa/src/Controller/DistrictsController.php
create mode 100644 idrocap_wa/src/Controller/EmailsController.php
create mode 100644 idrocap_wa/src/Controller/ErrorController.php
create mode 100644 idrocap_wa/src/Controller/FaxesController.php
create mode 100644 idrocap_wa/src/Controller/FiltersController.php
create mode 100644 idrocap_wa/src/Controller/GroupsController.php
create mode 100644 idrocap_wa/src/Controller/MapsController.php
create mode 100644 idrocap_wa/src/Controller/MobilePhonesController.php
create mode 100644 idrocap_wa/src/Controller/NotificationsController.php
create mode 100644 idrocap_wa/src/Controller/OrganisationsController.php
create mode 100644 idrocap_wa/src/Controller/PecsController.php
create mode 100644 idrocap_wa/src/Controller/PhonesController.php
create mode 100644 idrocap_wa/src/Controller/PrivacyController.php
create mode 100644 idrocap_wa/src/Controller/TagsController.php
create mode 100644 idrocap_wa/src/Controller/TelegramChatsController.php
create mode 100644 idrocap_wa/src/Controller/UsersController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingArticlesController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingDerivationsController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingFeesController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingIntendedUsesController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingMeasurementsController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingMetersController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingPaperworkPecsController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingPaperworksController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingPaymentsController.php
create mode 100644 idrocap_wa/src/Controller/WaterDrawingReturnPointsController.php
create mode 100755 idrocap_wa/src/Error/AppExceptionRenderer.php
create mode 100644 idrocap_wa/src/Identifier/JixelPasswordIdentifier.php
create mode 100644 idrocap_wa/src/Middleware/UserTimezoneDatetimeRequestDataMiddleware.php
create mode 100644 idrocap_wa/src/Model/Behavior/.gitkeep
create mode 100644 idrocap_wa/src/Model/Behavior/AttachmentsBehavior.php
create mode 100644 idrocap_wa/src/Model/Behavior/ControllableObjectInterfaceBehavior.php
create mode 100644 idrocap_wa/src/Model/Entity/Actor.php
create mode 100644 idrocap_wa/src/Model/Entity/ActorType.php
create mode 100644 idrocap_wa/src/Model/Entity/Applicant.php
create mode 100644 idrocap_wa/src/Model/Entity/ApplicantsWaterDrawingPaperwork.php
create mode 100644 idrocap_wa/src/Model/Entity/Attachment.php
create mode 100644 idrocap_wa/src/Model/Entity/BackgroundTask.php
create mode 100644 idrocap_wa/src/Model/Entity/CadastralCropType.php
create mode 100644 idrocap_wa/src/Model/Entity/CapabilitiesMenuItem.php
create mode 100644 idrocap_wa/src/Model/Entity/CapabilitiesMenuSection.php
create mode 100644 idrocap_wa/src/Model/Entity/Capability.php
create mode 100644 idrocap_wa/src/Model/Entity/CapabilityGroup.php
create mode 100644 idrocap_wa/src/Model/Entity/ControllableObject.php
create mode 100644 idrocap_wa/src/Model/Entity/ControllableObjectInterface.php
create mode 100644 idrocap_wa/src/Model/Entity/ControllableObjectInterfaceType.php
create mode 100644 idrocap_wa/src/Model/Entity/ControllableObjectType.php
create mode 100644 idrocap_wa/src/Model/Entity/County.php
create mode 100644 idrocap_wa/src/Model/Entity/Delivery.php
create mode 100644 idrocap_wa/src/Model/Entity/DeliveryType.php
create mode 100644 idrocap_wa/src/Model/Entity/DispatchingTask.php
create mode 100644 idrocap_wa/src/Model/Entity/DispatchingTaskItem.php
create mode 100644 idrocap_wa/src/Model/Entity/DispatchingTaskStatus.php
create mode 100644 idrocap_wa/src/Model/Entity/District.php
create mode 100644 idrocap_wa/src/Model/Entity/Email.php
create mode 100644 idrocap_wa/src/Model/Entity/EmailDescription.php
create mode 100644 idrocap_wa/src/Model/Entity/Fax.php
create mode 100644 idrocap_wa/src/Model/Entity/FaxDescription.php
create mode 100644 idrocap_wa/src/Model/Entity/Filter.php
create mode 100644 idrocap_wa/src/Model/Entity/Group.php
create mode 100644 idrocap_wa/src/Model/Entity/GroupsGroup.php
create mode 100644 idrocap_wa/src/Model/Entity/Language.php
create mode 100644 idrocap_wa/src/Model/Entity/Location.php
create mode 100644 idrocap_wa/src/Model/Entity/LocationAttribute.php
create mode 100644 idrocap_wa/src/Model/Entity/Map.php
create mode 100644 idrocap_wa/src/Model/Entity/MenuItem.php
create mode 100644 idrocap_wa/src/Model/Entity/MenuSection.php
create mode 100644 idrocap_wa/src/Model/Entity/Message.php
create mode 100644 idrocap_wa/src/Model/Entity/MessageStatus.php
create mode 100644 idrocap_wa/src/Model/Entity/MessageType.php
create mode 100644 idrocap_wa/src/Model/Entity/MobileComponent.php
create mode 100644 idrocap_wa/src/Model/Entity/MobilePhone.php
create mode 100644 idrocap_wa/src/Model/Entity/MobilePhoneDescription.php
create mode 100644 idrocap_wa/src/Model/Entity/Notification.php
create mode 100644 idrocap_wa/src/Model/Entity/NotificationType.php
create mode 100644 idrocap_wa/src/Model/Entity/Organisation.php
create mode 100644 idrocap_wa/src/Model/Entity/OrganisationType.php
create mode 100644 idrocap_wa/src/Model/Entity/Pec.php
create mode 100644 idrocap_wa/src/Model/Entity/PecDescription.php
create mode 100644 idrocap_wa/src/Model/Entity/Permission.php
create mode 100644 idrocap_wa/src/Model/Entity/Phone.php
create mode 100644 idrocap_wa/src/Model/Entity/PhoneDescription.php
create mode 100644 idrocap_wa/src/Model/Entity/Privacy.php
create mode 100644 idrocap_wa/src/Model/Entity/PrivacyUser.php
create mode 100644 idrocap_wa/src/Model/Entity/PushNotification.php
create mode 100644 idrocap_wa/src/Model/Entity/Snapshot.php
create mode 100644 idrocap_wa/src/Model/Entity/Tag.php
create mode 100644 idrocap_wa/src/Model/Entity/TelegramChat.php
create mode 100644 idrocap_wa/src/Model/Entity/TelegramContact.php
create mode 100644 idrocap_wa/src/Model/Entity/UnpackedWaterDrawingPaperworkSnapshot.php
create mode 100644 idrocap_wa/src/Model/Entity/User.php
create mode 100644 idrocap_wa/src/Model/Entity/UserTimezoneDatetimeEntityTrait.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequest.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequestStatus.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingArticle.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingDerivation.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingDerivationType.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingFee.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingIntendedUse.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingIntendedUseType.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingMeasurement.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingMeter.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingPaperwork.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingPaperworkHistory.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingPaperworkPec.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingPaperworkStatus.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingPayment.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingPaymentType.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingReturnPoint.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingToolType.php
create mode 100644 idrocap_wa/src/Model/Entity/WaterDrawingWateringSystem.php
create mode 100644 idrocap_wa/src/Model/Table/ActorTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/ActorsTable.php
create mode 100644 idrocap_wa/src/Model/Table/ApplicantsTable.php
create mode 100644 idrocap_wa/src/Model/Table/ApplicantsWaterDrawingPaperworksTable.php
create mode 100644 idrocap_wa/src/Model/Table/AttachmentsTable.php
create mode 100644 idrocap_wa/src/Model/Table/BackgroundTasksTable.php
create mode 100644 idrocap_wa/src/Model/Table/CadastralCropTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/CapabilitiesMenuItemsTable.php
create mode 100644 idrocap_wa/src/Model/Table/CapabilitiesMenuSectionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/CapabilitiesTable.php
create mode 100644 idrocap_wa/src/Model/Table/CapabilityGroupsTable.php
create mode 100644 idrocap_wa/src/Model/Table/ControllableObjectInterfaceTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/ControllableObjectInterfacesTable.php
create mode 100644 idrocap_wa/src/Model/Table/ControllableObjectTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/ControllableObjectsTable.php
create mode 100644 idrocap_wa/src/Model/Table/CountiesTable.php
create mode 100644 idrocap_wa/src/Model/Table/DeliveriesTable.php
create mode 100644 idrocap_wa/src/Model/Table/DeliveryTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/DispatchingTaskItemsTable.php
create mode 100644 idrocap_wa/src/Model/Table/DispatchingTaskStatusesTable.php
create mode 100644 idrocap_wa/src/Model/Table/DispatchingTasksTable.php
create mode 100644 idrocap_wa/src/Model/Table/DistrictsTable.php
create mode 100644 idrocap_wa/src/Model/Table/EmailDescriptionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/EmailsTable.php
create mode 100644 idrocap_wa/src/Model/Table/FaxDescriptionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/FaxesTable.php
create mode 100644 idrocap_wa/src/Model/Table/FiltersTable.php
create mode 100644 idrocap_wa/src/Model/Table/GroupsGroupsTable.php
create mode 100644 idrocap_wa/src/Model/Table/GroupsTable.php
create mode 100644 idrocap_wa/src/Model/Table/LanguagesTable.php
create mode 100644 idrocap_wa/src/Model/Table/LocationAttributesTable.php
create mode 100644 idrocap_wa/src/Model/Table/LocationsTable.php
create mode 100644 idrocap_wa/src/Model/Table/MapsTable.php
create mode 100644 idrocap_wa/src/Model/Table/MenuItemsTable.php
create mode 100644 idrocap_wa/src/Model/Table/MenuSectionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/MessageStatusesTable.php
create mode 100644 idrocap_wa/src/Model/Table/MessageTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/MessagesTable.php
create mode 100644 idrocap_wa/src/Model/Table/MobileComponentsTable.php
create mode 100644 idrocap_wa/src/Model/Table/MobilePhoneDescriptionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/MobilePhonesTable.php
create mode 100644 idrocap_wa/src/Model/Table/NotificationTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/NotificationsTable.php
create mode 100644 idrocap_wa/src/Model/Table/OrganisationTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/OrganisationsTable.php
create mode 100644 idrocap_wa/src/Model/Table/PecDescriptionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/PecsTable.php
create mode 100644 idrocap_wa/src/Model/Table/PermissionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/PhoneDescriptionsTable.php
create mode 100644 idrocap_wa/src/Model/Table/PhonesTable.php
create mode 100644 idrocap_wa/src/Model/Table/PrivacyTable.php
create mode 100644 idrocap_wa/src/Model/Table/PrivacyUsersTable.php
create mode 100644 idrocap_wa/src/Model/Table/PushNotificationsTable.php
create mode 100644 idrocap_wa/src/Model/Table/SnapshotsTable.php
create mode 100644 idrocap_wa/src/Model/Table/TagsTable.php
create mode 100644 idrocap_wa/src/Model/Table/TelegramChatsTable.php
create mode 100644 idrocap_wa/src/Model/Table/TelegramContactsTable.php
create mode 100644 idrocap_wa/src/Model/Table/UnpackedWaterDrawingPaperworkSnapshotsTable.php
create mode 100644 idrocap_wa/src/Model/Table/UsersTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestStatusesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestsTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingArticlesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingDerivationTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingDerivationsTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingFeesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingIntendedUseTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingIntendedUsesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingMeasurementsTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingMetersTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingPaperworkHistoriesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingPaperworkPecsTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingPaperworkStatusesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingPaperworksTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingPaymentTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingPaymentsTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingReturnPointsTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingToolTypesTable.php
create mode 100644 idrocap_wa/src/Model/Table/WaterDrawingWateringSystemsTable.php
create mode 100644 idrocap_wa/src/View/AjaxView.php
create mode 100644 idrocap_wa/src/View/AppView.php
create mode 100644 idrocap_wa/src/View/Cell/.gitkeep
create mode 100644 idrocap_wa/src/View/Cell/DistrictProvinceCell.php
create mode 100644 idrocap_wa/src/View/Cell/FilterInputCell.php
create mode 100755 idrocap_wa/src/View/Cell/FiltersCell.php
create mode 100644 idrocap_wa/src/View/Cell/IntendedUsesCell.php
create mode 100755 idrocap_wa/src/View/Cell/MapCell.php
create mode 100644 idrocap_wa/src/View/CustomCsvView.php
create mode 100644 idrocap_wa/src/View/Helper/BreadcrumbHelper.php
create mode 100644 idrocap_wa/src/View/Helper/MenuHelper.php
create mode 100644 idrocap_wa/src/View/Helper/NotificationsHelper.php
create mode 100644 idrocap_wa/src/View/Helper/SectionsHelper.php
create mode 100644 idrocap_wa/src/WGS/Auth/OpenIdConnectClient.php
create mode 100755 idrocap_wa/src/WGS/FileStorage/FileStorage.php
create mode 100755 idrocap_wa/src/WGS/FileStorage/FileStorageFactory.php
create mode 100755 idrocap_wa/src/WGS/FileStorage/HadoopFileStorage.php
create mode 100755 idrocap_wa/src/WGS/FileStorage/S3MinioFileStorage.php
create mode 100644 idrocap_wa/src/WGS/Geo/CadastralUtils.php
create mode 100644 idrocap_wa/src/WGS/Geo/ExtGeoResourceAttributesRetriever.php
create mode 100644 idrocap_wa/src/WGS/Geo/GeoValidation.php
create mode 100644 idrocap_wa/src/WGS/Geo/Geocoding.php
create mode 100644 idrocap_wa/src/WGS/Geo/IntGeoResourceAttributesRetriever.php
create mode 100644 idrocap_wa/src/WGS/Geo/LocationAttributesRetriever.php
create mode 100644 idrocap_wa/src/WGS/NotificationsHandler/MessagingHandler.php
create mode 100644 idrocap_wa/src/WGS/NotificationsHandler/NotificationGenerator.php
create mode 100644 idrocap_wa/src/WGS/NotificationsHandler/NotificationsHandler.php
create mode 100644 idrocap_wa/src/WGS/NotificationsHandler/RecipientsDetector.php
create mode 100644 idrocap_wa/src/WGS/NotificationsHandler/SystemNotificationsDispatcher.php
create mode 100644 idrocap_wa/src/WGS/SnapshotsHandler/SnapshotsHandler.php
create mode 100644 idrocap_wa/src/WGS/Utils/Attachments/AttachmentChecker.php
create mode 100644 idrocap_wa/src/WGS/Utils/Attachments/AttachmentConverter.php
create mode 100644 idrocap_wa/src/WGS/Utils/Attachments/SignedAttachmentChecker.php
create mode 100644 idrocap_wa/src/WGS/Utils/Dto/ProvinceDistrictCellDto/DistrictCellDto.php
create mode 100644 idrocap_wa/src/WGS/Utils/Dto/ProvinceDistrictCellDto/ProvinceCellDto.php
create mode 100644 idrocap_wa/src/WGS/Utils/Dto/Users/CitizenRegistrationDTO.php
create mode 100644 idrocap_wa/src/WGS/Utils/Enum/InputFieldType.php
create mode 100644 idrocap_wa/src/WGS/Utils/Enum/ProvinceDistrictFields.php
create mode 100644 idrocap_wa/src/WGS/Utils/Enum/Regions.php
create mode 100644 idrocap_wa/src/WGS/Utils/Enum/SicilyProvinces.php
create mode 100644 idrocap_wa/src/WGS/Utils/Helper/ProvinceDistrictFieldHelper.php
create mode 100644 idrocap_wa/src/WGS/Utils/RabbitMQSenders/IntendedUseVegetationCheckCommandSender.php
create mode 100644 idrocap_wa/templates/Applicants/citizen_add.php
create mode 100644 idrocap_wa/templates/Applicants/citizen_edit.php
create mode 100644 idrocap_wa/templates/Applicants/citizen_view.php
create mode 100644 idrocap_wa/templates/Applicants/edit.php
create mode 100644 idrocap_wa/templates/Applicants/view.php
create mode 100644 idrocap_wa/templates/Capabilities/index.php
create mode 100755 idrocap_wa/templates/ControllableObjects/get_attachments.php
create mode 100644 idrocap_wa/templates/Dashboard/index.php
create mode 100644 idrocap_wa/templates/Deliveries/index.php
create mode 100644 idrocap_wa/templates/Emails/add.php
create mode 100644 idrocap_wa/templates/Emails/edit.php
create mode 100644 idrocap_wa/templates/Error/error400.php
create mode 100644 idrocap_wa/templates/Error/error500.php
create mode 100644 idrocap_wa/templates/Faxes/add.php
create mode 100644 idrocap_wa/templates/Faxes/edit.php
create mode 100644 idrocap_wa/templates/Filters/get_filter_input.php
create mode 100644 idrocap_wa/templates/Groups/add.php
create mode 100644 idrocap_wa/templates/Groups/edit.php
create mode 100644 idrocap_wa/templates/Groups/handle_capabilities.php
create mode 100644 idrocap_wa/templates/Groups/index.php
create mode 100644 idrocap_wa/templates/Groups/view.php
create mode 100644 idrocap_wa/templates/Maps/index.php
create mode 100644 idrocap_wa/templates/MobilePhones/add.php
create mode 100644 idrocap_wa/templates/MobilePhones/edit.php
create mode 100644 idrocap_wa/templates/Notifications/index.php
create mode 100644 idrocap_wa/templates/Notifications/read_all.php
create mode 100644 idrocap_wa/templates/Organisations/add.php
create mode 100644 idrocap_wa/templates/Organisations/edit.php
create mode 100644 idrocap_wa/templates/Organisations/index.php
create mode 100644 idrocap_wa/templates/Organisations/view.php
create mode 100644 idrocap_wa/templates/Pecs/add.php
create mode 100644 idrocap_wa/templates/Pecs/edit.php
create mode 100644 idrocap_wa/templates/Phones/add.php
create mode 100644 idrocap_wa/templates/Phones/edit.php
create mode 100644 idrocap_wa/templates/Privacy/accept_privacy.php
create mode 100644 idrocap_wa/templates/Privacy/edit.php
create mode 100644 idrocap_wa/templates/Privacy/view.php
create mode 100644 idrocap_wa/templates/Privacy/view_public.php
create mode 100644 idrocap_wa/templates/Tags/add.php
create mode 100644 idrocap_wa/templates/Tags/edit.php
create mode 100644 idrocap_wa/templates/Tags/index.php
create mode 100644 idrocap_wa/templates/Tags/view.php
create mode 100644 idrocap_wa/templates/TelegramChats/add.php
create mode 100644 idrocap_wa/templates/TelegramChats/edit.php
create mode 100644 idrocap_wa/templates/Users/add.php
create mode 100644 idrocap_wa/templates/Users/add_citizen.php
create mode 100644 idrocap_wa/templates/Users/choose_new_password.php
create mode 100644 idrocap_wa/templates/Users/edit.php
create mode 100644 idrocap_wa/templates/Users/index.php
create mode 100644 idrocap_wa/templates/Users/login.php
create mode 100644 idrocap_wa/templates/Users/one_time_password.php
create mode 100644 idrocap_wa/templates/Users/password_recovery.php
create mode 100644 idrocap_wa/templates/Users/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingArticles/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingArticles/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingArticles/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingArticles/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingDerivations/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingDerivations/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingDerivations/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingDerivations/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingFees/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingFees/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingFees/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingFees/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingIntendedUses/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingIntendedUses/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingIntendedUses/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingIntendedUses/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingMeasurements/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingMeasurements/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingMeters/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingMeters/dismiss.php
create mode 100644 idrocap_wa/templates/WaterDrawingMeters/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingMeters/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworkPecs/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworkPecs/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworkPecs/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworkPecs/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/add_scan.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/antimafia_request_to_anac.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/applicants_water_drawing_paperworks_item_block.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/assign.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_index.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_requested.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_request_paperwork.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_submission_index.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_submit_paperwork.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_attachment.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_payment_receipt.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/edit_scan.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots_all.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/intended_uses_water_drawing_paperworks_item_block.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/upload_antimafia_attachment.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment_scan.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/validate.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/validate_index.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/validate_scan.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/view_scan.php
create mode 100644 idrocap_wa/templates/WaterDrawingPaperworks/view_snapshot.php
create mode 100644 idrocap_wa/templates/WaterDrawingPayments/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingPayments/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingPayments/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingPayments/view.php
create mode 100644 idrocap_wa/templates/WaterDrawingReturnPoints/add.php
create mode 100644 idrocap_wa/templates/WaterDrawingReturnPoints/edit.php
create mode 100644 idrocap_wa/templates/WaterDrawingReturnPoints/index.php
create mode 100644 idrocap_wa/templates/WaterDrawingReturnPoints/view.php
create mode 100644 idrocap_wa/templates/cell/.gitkeep
create mode 100644 idrocap_wa/templates/cell/DistrictProvince/display.php
create mode 100644 idrocap_wa/templates/cell/FilterInput/display.php
create mode 100755 idrocap_wa/templates/cell/Filters/display.php
create mode 100644 idrocap_wa/templates/cell/IntendedUses/display.php
create mode 100755 idrocap_wa/templates/cell/Map/display.php
create mode 100755 idrocap_wa/templates/element/Map.php
create mode 100644 idrocap_wa/templates/element/MapCore/MapPrimitives.php
create mode 100644 idrocap_wa/templates/element/WaterDrawingPaperworks/applicants.php
create mode 100644 idrocap_wa/templates/element/WaterDrawingPaperworks/intended_uses.php
create mode 100755 idrocap_wa/templates/element/attachmentPreview.php
create mode 100755 idrocap_wa/templates/element/attachments.php
create mode 100644 idrocap_wa/templates/element/districtSelect.php
create mode 100644 idrocap_wa/templates/element/flash/default.php
create mode 100644 idrocap_wa/templates/element/flash/error.php
create mode 100644 idrocap_wa/templates/element/flash/info.php
create mode 100644 idrocap_wa/templates/element/flash/success.php
create mode 100644 idrocap_wa/templates/element/flash/warning.php
create mode 100644 idrocap_wa/templates/element/provinceSelect.php
create mode 100644 idrocap_wa/templates/email/html/default.php
create mode 100644 idrocap_wa/templates/email/text/default.php
create mode 100644 idrocap_wa/templates/layout/ajax.php
create mode 100644 idrocap_wa/templates/layout/default.php
create mode 100644 idrocap_wa/templates/layout/email/html/default.php
create mode 100644 idrocap_wa/templates/layout/email/text/default.php
create mode 100644 idrocap_wa/templates/layout/error.php
create mode 100644 idrocap_wa/templates/layout/view_public.php
create mode 100644 idrocap_wa/templates/plugin/BootstrapUI/element/flash/default.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/element/footer/main.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/element/header/main.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/element/header/menu.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/element/header/notifications.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/element/sidebar/main.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/element/sidebar/menu.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/layout/default.php
create mode 100644 idrocap_wa/templates/plugin/CakeLte/layout/login.php
create mode 100644 idrocap_wa/tests/Fixture/.gitkeep
create mode 100644 idrocap_wa/tests/TestCase/ApplicationTest.php
create mode 100644 idrocap_wa/tests/TestCase/Controller/Component/.gitkeep
create mode 100644 idrocap_wa/tests/TestCase/Controller/PagesControllerTest.php
create mode 100644 idrocap_wa/tests/TestCase/Model/Behavior/.gitkeep
create mode 100644 idrocap_wa/tests/TestCase/View/Helper/.gitkeep
create mode 100644 idrocap_wa/tests/bootstrap.php
create mode 100644 idrocap_wa/tests/schema.sql
create mode 100644 idrocap_wa/webroot/.gitignore
create mode 100644 idrocap_wa/webroot/.htaccess
create mode 120000 idrocap_wa/webroot/adminlte
create mode 100644 idrocap_wa/webroot/bower.json
create mode 100644 idrocap_wa/webroot/css/cake.css
create mode 100644 idrocap_wa/webroot/css/citizen-registration.css
create mode 100644 idrocap_wa/webroot/css/fonts.css
create mode 100644 idrocap_wa/webroot/css/home.css
create mode 100644 idrocap_wa/webroot/css/idrocap-styles.css
create mode 100644 idrocap_wa/webroot/css/jixel_ol.css
create mode 100644 idrocap_wa/webroot/css/milligram.min.css
create mode 100644 idrocap_wa/webroot/css/normalize.min.css
create mode 100644 idrocap_wa/webroot/favicon.ico
create mode 100644 idrocap_wa/webroot/favicon2.ico
create mode 100644 idrocap_wa/webroot/font/Raleway-License.txt
create mode 100644 idrocap_wa/webroot/font/cakedingbats-webfont.eot
create mode 100644 idrocap_wa/webroot/font/cakedingbats-webfont.svg
create mode 100644 idrocap_wa/webroot/font/cakedingbats-webfont.ttf
create mode 100644 idrocap_wa/webroot/font/cakedingbats-webfont.woff
create mode 100644 idrocap_wa/webroot/font/cakedingbats-webfont.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-400-cyrillic-ext.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-400-cyrillic.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-400-latin-ext.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-400-latin.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-400-vietnamese.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-700-cyrillic-ext.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-700-cyrillic.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-700-latin-ext.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-700-latin.woff2
create mode 100644 idrocap_wa/webroot/font/raleway-700-vietnamese.woff2
create mode 100644 idrocap_wa/webroot/img/cake-logo.png
create mode 100644 idrocap_wa/webroot/img/cake.icon.png
create mode 100644 idrocap_wa/webroot/img/cake.icon.svg
create mode 100644 idrocap_wa/webroot/img/cake.logo.svg
create mode 100644 idrocap_wa/webroot/img/cake.power.gif
create mode 100644 idrocap_wa/webroot/img/logo-autorita-dibacino.png
create mode 100644 idrocap_wa/webroot/img/logo-fsc.png
create mode 100644 idrocap_wa/webroot/img/logo-poa.png
create mode 100644 idrocap_wa/webroot/img/logo-regione-sicilia.png
create mode 100644 idrocap_wa/webroot/img/logo_mite.png
create mode 100644 idrocap_wa/webroot/img/user2-160x160.jpg
create mode 100644 idrocap_wa/webroot/index.php
create mode 100644 idrocap_wa/webroot/js/.gitkeep
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/content.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Autocomplete/AutocompleteHandler.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Clients/BaseClient.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Clients/OpenAIClient.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Clients/WgsAIClient.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Interfaces/PromptInterface.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Services/AutoCompleteService.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/TaskFlow.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Utility/DataFormatter.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Utility/DomElementHandler.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Utility/EventHandler.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Utility/FormAnalyzer.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Utility/FormExclusions.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/dist/entrypoints/utils/Utility/FormFiller.js
create mode 100644 idrocap_wa/webroot/js/ia-form-filler/styles/style.css
create mode 100644 idrocap_wa/webroot/js/init_tiny_mce.js
create mode 100644 idrocap_wa/webroot/js/jixel-primitives.js
create mode 100644 idrocap_wa/webroot/js/moment.js
create mode 100644 idrocap_wa/webroot/js/tinymce/icons/default/icons.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/langs/README.md
create mode 100644 idrocap_wa/webroot/js/tinymce/langs/it.js
create mode 100644 idrocap_wa/webroot/js/tinymce/license.md
create mode 100644 idrocap_wa/webroot/js/tinymce/models/dom/model.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/accordion/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/advlist/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/anchor/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/autolink/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/autoresize/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/autosave/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/charmap/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/code/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/codesample/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/directionality/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/emoticons/js/emojiimages.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/emoticons/js/emojiimages.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/emoticons/js/emojis.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/emoticons/js/emojis.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/emoticons/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/fullscreen/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ar.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/bg_BG.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ca.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/cs.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/da.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/de.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/el.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/en.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/es.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/eu.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/fa.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/fi.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/fr_FR.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/he_IL.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/hi.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/hr.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/hu_HU.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/id.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/it.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ja.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/kk.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ko_KR.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ms.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/nb_NO.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/nl.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/pl.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/pt_BR.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/pt_PT.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ro.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/ru.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/sk.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/sl_SI.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/sv_SE.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/th_TH.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/tr.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/uk.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/vi.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/zh_CN.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/js/i18n/keynav/zh_TW.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/help/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/image/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/importcss/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/insertdatetime/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/link/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/lists/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/media/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/nonbreaking/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/pagebreak/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/preview/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/quickbars/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/save/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/searchreplace/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/table/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/visualblocks/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/visualchars/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/plugins/wordcount/plugin.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/dark/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/dark/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/default/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/default/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/document/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/document/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/tinymce-5-dark/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/tinymce-5-dark/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/tinymce-5/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/tinymce-5/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/writer/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/content/writer/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/content.inline.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/content.inline.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/skin.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/skin.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/skin.shadowdom.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/content.inline.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/content.inline.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/skin.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/skin.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/skin.shadowdom.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/oxide/skin.shadowdom.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/content.inline.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/skin.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/skin.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/content.inline.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/content.inline.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/content.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/content.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/skin.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/skin.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/skin.shadowdom.js
create mode 100644 idrocap_wa/webroot/js/tinymce/skins/ui/tinymce-5/skin.shadowdom.min.css
create mode 100644 idrocap_wa/webroot/js/tinymce/themes/silver/theme.min.js
create mode 100644 idrocap_wa/webroot/js/tinymce/tinymce.d.ts
create mode 100644 idrocap_wa/webroot/js/tinymce/tinymce.min.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/Cloud.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/Exif2Geojson.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/ExportMap.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/FontAwesome5Def.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/FontAwesomeDef.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/FontMaki2Def.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/FontMakiDef.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/IFrameAPI.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/MapIFrameAPI.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/TextureImage.js
create mode 100755 idrocap_wa/webroot/ol-ext/extra/WSynchro.js
create mode 100755 idrocap_wa/webroot/ol-ext/ol-ext.css
create mode 100755 idrocap_wa/webroot/ol-ext/ol-ext.js
create mode 100755 idrocap_wa/webroot/ol-ext/ol-ext.min.css
create mode 100755 idrocap_wa/webroot/ol-ext/ol-ext.min.js
create mode 100644 idrocap_wa/webroot/package-lock.json
create mode 100644 idrocap_wa/webroot/package.json
create mode 100644 idrocap_wa/webroot/sounds/all_notification_read.mp3
create mode 100644 idrocap_wa/webroot/sounds/new_notification.mp3
diff --git a/README.md b/README.md
index 9daeafb..c57fdec 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
-test
+idrocap_wa -> Web Application
+
diff --git a/idrocap_wa/.htaccess b/idrocap_wa/.htaccess
new file mode 100644
index 0000000..e029162
--- /dev/null
+++ b/idrocap_wa/.htaccess
@@ -0,0 +1,12 @@
+# Uncomment the following to prevent the httpoxy vulnerability
+# See: https://httpoxy.org/
+#
+# RequestHeader unset Proxy
+#
+
+
+ RewriteEngine on
+ RewriteRule ^(\.well-known/.*)$ $1 [L]
+ RewriteRule ^$ webroot/ [L]
+ RewriteRule (.*) webroot/$1 [L]
+
\ No newline at end of file
diff --git a/idrocap_wa/Dockerfile b/idrocap_wa/Dockerfile
new file mode 100644
index 0000000..4a3d615
--- /dev/null
+++ b/idrocap_wa/Dockerfile
@@ -0,0 +1,20 @@
+FROM registrywgs.webgenesis.it/webgenesys/jixel/jixel-dockers/almalinux9.5-php8.4.4:latest-master
+RUN dnf -y install npm
+RUN npm install -g bower
+RUN dnf -y install git
+RUN mkdir /var/www/jixel
+COPY . /var/www/jixel
+WORKDIR /var/www/jixel
+RUN composer install --no-interaction
+WORKDIR /var/www/jixel/webroot
+RUN npm install
+RUN bower install
+EXPOSE 443
+EXPOSE 80
+WORKDIR /var/www/jixel
+RUN mkdir /run/php-fpm
+COPY ./dockerfiles/run /usr/local/bin/run
+RUN chmod 500 /usr/local/bin/run
+COPY ./dockerfiles/cake /var/www/jixel/bin/cake
+RUN chmod 500 /var/www/jixel/bin/cake
+CMD ["run"]
diff --git a/idrocap_wa/README.md b/idrocap_wa/README.md
new file mode 100644
index 0000000..dae0f2f
--- /dev/null
+++ b/idrocap_wa/README.md
@@ -0,0 +1,61 @@
+# IDROCAP Jixel repository
+
+Jixel core for IDROCAP developing. Based on [CakePHP](https://cakephp.org) 5.x.
+
+The framework source code can be found here: [cakephp/cakephp](https://github.com/cakephp/cakephp).
+
+Before you run the docker stack:
+make sure you have a few configs keys under in `config/app_local.php`:
+
+```php
+ 'Custom' => [
+ 'background_tasks' => [
+ 'notifications' => [
+ 'channel' => 'newjixel_background_tasks',
+ ]
+ ],
+ ],
+```
+and:
+
+```php
+ 'Datasources' => [
+ 'default' => [
+ 'host' => 'mysql8',
+ 'username' => 'jixel',
+ 'password' => 'jixel2023',
+ 'database' => 'jixel',
+ 'url' => env('DATABASE_URL', null),
+ ],
+ 'geo' => [
+ 'host' => 'mysql-geo',
+ 'port' => '3307',
+ 'username' => 'gecos',
+ 'password' => 'gecos2015',
+ 'database' => 'geo',
+ ],
+ 'test' => [
+ 'host' => 'localhost',
+ 'username' => 'my_app',
+ 'password' => 'secret',
+ 'database' => 'test_myapp',
+ 'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tests.sqlite'),
+ ],
+ ],
+````
+
+First bootstrap only (and only if you are mapping in your host machine, idrocapjixel repository):
+
+enter the container:
+`docker exec -it -u jixel`
+
+install vendor packages:
+`composer install -n`
+
+install vendor front end packages:
+`cd webroot`
+`npm install -y`
+`bower install -y`
+
+
+
diff --git a/idrocap_wa/bin/bash_completion.sh b/idrocap_wa/bin/bash_completion.sh
new file mode 100644
index 0000000..a3d3feb
--- /dev/null
+++ b/idrocap_wa/bin/bash_completion.sh
@@ -0,0 +1,47 @@
+#
+# Bash completion file for CakePHP console.
+# Copy this file to a file named `cake` under `/etc/bash_completion.d/`.
+# For more info check https://book.cakephp.org/4/en/console-commands/completion.html#how-to-enable-bash-autocompletion-for-the-cakephp-console
+#
+
+_cake()
+{
+ local cur prev opts cake
+ COMPREPLY=()
+ cake="${COMP_WORDS[0]}"
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+ if [[ "$cur" == -* ]] ; then
+ if [[ ${COMP_CWORD} = 1 ]] ; then
+ opts=$(${cake} completion options)
+ elif [[ ${COMP_CWORD} = 2 ]] ; then
+ opts=$(${cake} completion options "${COMP_WORDS[1]}")
+ else
+ opts=$(${cake} completion options "${COMP_WORDS[1]}" "${COMP_WORDS[2]}")
+ fi
+
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+
+ if [[ ${COMP_CWORD} = 1 ]] ; then
+ opts=$(${cake} completion commands)
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+
+ if [[ ${COMP_CWORD} = 2 ]] ; then
+ opts=$(${cake} completion subcommands $prev)
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ if [[ $COMPREPLY = "" ]] ; then
+ _filedir
+ return 0
+ fi
+ return 0
+ fi
+
+ return 0
+}
+
+complete -F _cake cake bin/cake
diff --git a/idrocap_wa/bin/cake b/idrocap_wa/bin/cake
new file mode 100755
index 0000000..4b696c8
--- /dev/null
+++ b/idrocap_wa/bin/cake
@@ -0,0 +1,75 @@
+#!/usr/bin/env sh
+################################################################################
+#
+# Cake is a shell script for invoking CakePHP shell commands
+#
+# CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+#
+# Licensed under The MIT License
+# For full copyright and license information, please see the LICENSE.txt
+# Redistributions of files must retain the above copyright notice.
+#
+# @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+# @link https://cakephp.org CakePHP(tm) Project
+# @since 1.2.0
+# @license https://opensource.org/licenses/mit-license.php MIT License
+#
+################################################################################
+
+# Canonicalize by following every symlink of the given name recursively
+canonicalize() {
+ NAME="$1"
+ if [ -f "$NAME" ]
+ then
+ DIR=$(dirname -- "$NAME")
+ NAME=$(cd -P "$DIR" > /dev/null && pwd -P)/$(basename -- "$NAME")
+ fi
+ while [ -h "$NAME" ]; do
+ DIR=$(dirname -- "$NAME")
+ SYM=$(readlink "$NAME")
+ NAME=$(cd "$DIR" > /dev/null && cd "$(dirname -- "$SYM")" > /dev/null && pwd)/$(basename -- "$SYM")
+ done
+ echo "$NAME"
+}
+
+# Find a CLI version of PHP
+findCliPhp() {
+ for TESTEXEC in php php-cli /usr/local/bin/php
+ do
+ SAPI=$(echo "= PHP_SAPI ?>" | $TESTEXEC 2>/dev/null)
+ if [ "$SAPI" = "cli" ]
+ then
+ echo $TESTEXEC
+ return
+ fi
+ done
+ echo "Failed to find a CLI version of PHP; falling back to system standard php executable" >&2
+ echo "php";
+}
+
+# If current path is a symlink, resolve to real path
+realname="$0"
+if [ -L "$realname" ]
+then
+ realname=$(readlink -f "$0")
+fi
+
+CONSOLE=$(dirname -- "$(canonicalize "$realname")")
+APP=$(dirname "$CONSOLE")
+
+# If your CLI PHP is somewhere that this doesn't find, you can define a PHP environment
+# variable with the correct path in it.
+if [ -z "$PHP" ]
+then
+ PHP=$(findCliPhp)
+fi
+
+if [ "$(basename "$realname")" != 'cake' ]
+then
+ exec "$PHP" "$CONSOLE"/cake.php "$(basename "$realname")" "$@"
+else
+ exec "$PHP" "$CONSOLE"/cake.php "$@"
+fi
+
+exit
diff --git a/idrocap_wa/bin/cake.bat b/idrocap_wa/bin/cake.bat
new file mode 100644
index 0000000..a8a9af2
--- /dev/null
+++ b/idrocap_wa/bin/cake.bat
@@ -0,0 +1,27 @@
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Cake is a Windows batch script for invoking CakePHP shell commands
+::
+:: CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+:: Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+::
+:: Licensed under The MIT License
+:: Redistributions of files must retain the above copyright notice.
+::
+:: @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+:: @link https://cakephp.org CakePHP(tm) Project
+:: @since 2.0.0
+:: @license https://opensource.org/licenses/mit-license.php MIT License
+::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+@echo off
+
+SET app=%0
+SET lib=%~dp0
+
+php "%lib%cake.php" %*
+
+echo.
+
+exit /B %ERRORLEVEL%
diff --git a/idrocap_wa/bin/cake.php b/idrocap_wa/bin/cake.php
new file mode 100644
index 0000000..aab8d9f
--- /dev/null
+++ b/idrocap_wa/bin/cake.php
@@ -0,0 +1,10 @@
+#!/usr/bin/php -q
+run($argv));
diff --git a/idrocap_wa/composer.json b/idrocap_wa/composer.json
new file mode 100644
index 0000000..086c0c3
--- /dev/null
+++ b/idrocap_wa/composer.json
@@ -0,0 +1,67 @@
+{
+ "name": "cakephp/app",
+ "description": "CakePHP skeleton app",
+ "homepage": "https://cakephp.org",
+ "type": "project",
+ "license": "MIT",
+ "require": {
+ "php": ">=8.1",
+ "arodu/cakelte": "^2.0",
+ "aws/aws-sdk-php": "^3.301",
+ "cakephp/authentication": "^3.0",
+ "cakephp/cakephp": "^5.0.1",
+ "cakephp/migrations": "^4.0.0",
+ "cakephp/plugin-installer": "^2.0",
+ "firebase/php-jwt": "^6.10",
+ "friendsofcake/cakephp-csvview": "^5.0",
+ "lordsimal/cakephp-sentry": "^3.0",
+ "mobiledetect/mobiledetectlib": "^3.74",
+ "muffin/trash": "^4.0",
+ "php-amqplib/php-amqplib": "^3.6",
+ "simpleenergy/php-webhdfs": "^1.0"
+ },
+ "require-dev": {
+ "cakephp/bake": "^3.0.0",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "cakephp/debug_kit": "^5.0.0",
+ "josegonzalez/dotenv": "^4.0",
+ "phpunit/phpunit": "^10.1.0"
+ },
+ "suggest": {
+ "markstory/asset_compress": "An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.",
+ "dereuromark/cakephp-ide-helper": "After baking your code, this keeps your annotations in sync with the code evolving from there on for maximum IDE and PHPStan/Psalm compatibility.",
+ "phpstan/phpstan": "PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.",
+ "cakephp/repl": "Console tools for a REPL interface for CakePHP applications."
+ },
+ "autoload": {
+ "psr-4": {
+ "App\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "App\\Test\\": "tests/",
+ "Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
+ }
+ },
+ "scripts": {
+ "post-install-cmd": "App\\Console\\Installer::postInstall",
+ "post-create-project-cmd": "App\\Console\\Installer::postInstall",
+ "check": [
+ "@test",
+ "@cs-check"
+ ],
+ "cs-check": "phpcs --colors -p",
+ "cs-fix": "phpcbf --colors -p",
+ "stan": "phpstan analyse",
+ "test": "phpunit --colors=always"
+ },
+ "config": {
+ "platform-check": true,
+ "sort-packages": true,
+ "allow-plugins": {
+ "cakephp/plugin-installer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
+ }
+}
diff --git a/idrocap_wa/composer.lock b/idrocap_wa/composer.lock
new file mode 100644
index 0000000..3da6955
--- /dev/null
+++ b/idrocap_wa/composer.lock
@@ -0,0 +1,7466 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "e213713928c919df6ae66477bb3a0300",
+ "packages": [
+ {
+ "name": "almasaeed2010/adminlte",
+ "version": "v3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ColorlibHQ/AdminLTE.git",
+ "reference": "bd4d9c72931f1dd28601b6bfb387554a381ad540"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ColorlibHQ/AdminLTE/zipball/bd4d9c72931f1dd28601b6bfb387554a381ad540",
+ "reference": "bd4d9c72931f1dd28601b6bfb387554a381ad540",
+ "shasum": ""
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Colorlib"
+ }
+ ],
+ "description": "AdminLTE - admin control panel and dashboard that's based on Bootstrap 4",
+ "homepage": "https://adminlte.io/",
+ "keywords": [
+ "JS",
+ "admin",
+ "back-end",
+ "css",
+ "less",
+ "responsive",
+ "template",
+ "theme",
+ "web"
+ ],
+ "support": {
+ "issues": "https://github.com/ColorlibHQ/AdminLTE/issues",
+ "source": "https://github.com/ColorlibHQ/AdminLTE/tree/v3.2.0"
+ },
+ "time": "2022-02-07T20:33:09+00:00"
+ },
+ {
+ "name": "arodu/cakelte",
+ "version": "v2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/arodu/cakelte.git",
+ "reference": "0077bdd47e848122d665f55fa391cad067e8b454"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/arodu/cakelte/zipball/0077bdd47e848122d665f55fa391cad067e8b454",
+ "reference": "0077bdd47e848122d665f55fa391cad067e8b454",
+ "shasum": ""
+ },
+ "require": {
+ "almasaeed2010/adminlte": "^3.2",
+ "cakephp/cakephp": "^5.0",
+ "friendsofcake/bootstrap-ui": "^5.0"
+ },
+ "require-dev": {
+ "cakedc/cakephp-phpstan": "^3.1",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.1.0"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "CakeLte\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "CakeLTE: AdminLTE plugin for CakePHP",
+ "support": {
+ "issues": "https://github.com/arodu/cakelte/issues",
+ "source": "https://github.com/arodu/cakelte/tree/v2.0.1"
+ },
+ "time": "2024-03-05T11:41:23+00:00"
+ },
+ {
+ "name": "aws/aws-crt-php",
+ "version": "v1.2.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/awslabs/aws-crt-php.git",
+ "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e",
+ "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5",
+ "yoast/phpunit-polyfills": "^1.0"
+ },
+ "suggest": {
+ "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality."
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "AWS SDK Common Runtime Team",
+ "email": "aws-sdk-common-runtime@amazon.com"
+ }
+ ],
+ "description": "AWS Common Runtime for PHP",
+ "homepage": "https://github.com/awslabs/aws-crt-php",
+ "keywords": [
+ "amazon",
+ "aws",
+ "crt",
+ "sdk"
+ ],
+ "support": {
+ "issues": "https://github.com/awslabs/aws-crt-php/issues",
+ "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7"
+ },
+ "time": "2024-10-18T22:15:13+00:00"
+ },
+ {
+ "name": "aws/aws-sdk-php",
+ "version": "3.340.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/aws/aws-sdk-php.git",
+ "reference": "22cee29c0ca8d93a7a9c03d13739217373a21fcc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/22cee29c0ca8d93a7a9c03d13739217373a21fcc",
+ "reference": "22cee29c0ca8d93a7a9c03d13739217373a21fcc",
+ "shasum": ""
+ },
+ "require": {
+ "aws/aws-crt-php": "^1.2.3",
+ "ext-json": "*",
+ "ext-pcre": "*",
+ "ext-simplexml": "*",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/promises": "^2.0",
+ "guzzlehttp/psr7": "^2.4.5",
+ "mtdowling/jmespath.php": "^2.8.0",
+ "php": ">=8.1",
+ "psr/http-message": "^2.0"
+ },
+ "require-dev": {
+ "andrewsville/php-token-reflection": "^1.4",
+ "aws/aws-php-sns-message-validator": "~1.0",
+ "behat/behat": "~3.0",
+ "composer/composer": "^2.7.8",
+ "dms/phpunit-arraysubset-asserts": "^0.4.0",
+ "doctrine/cache": "~1.4",
+ "ext-dom": "*",
+ "ext-openssl": "*",
+ "ext-pcntl": "*",
+ "ext-sockets": "*",
+ "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
+ "psr/cache": "^2.0 || ^3.0",
+ "psr/simple-cache": "^2.0 || ^3.0",
+ "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0",
+ "symfony/filesystem": "^v6.4.0 || ^v7.1.0",
+ "yoast/phpunit-polyfills": "^2.0"
+ },
+ "suggest": {
+ "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
+ "doctrine/cache": "To use the DoctrineCacheAdapter",
+ "ext-curl": "To send requests using cURL",
+ "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
+ "ext-sockets": "To use client-side monitoring"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Aws\\": "src/"
+ },
+ "exclude-from-classmap": [
+ "src/data/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Amazon Web Services",
+ "homepage": "http://aws.amazon.com"
+ }
+ ],
+ "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
+ "homepage": "http://aws.amazon.com/sdkforphp",
+ "keywords": [
+ "amazon",
+ "aws",
+ "cloud",
+ "dynamodb",
+ "ec2",
+ "glacier",
+ "s3",
+ "sdk"
+ ],
+ "support": {
+ "forum": "https://github.com/aws/aws-sdk-php/discussions",
+ "issues": "https://github.com/aws/aws-sdk-php/issues",
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.340.2"
+ },
+ "time": "2025-02-26T19:28:12+00:00"
+ },
+ {
+ "name": "cakephp/authentication",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/authentication.git",
+ "reference": "3583745feb37c5069930cd1661bb0723a8f64f99"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/authentication/zipball/3583745feb37c5069930cd1661bb0723a8f64f99",
+ "reference": "3583745feb37c5069930cd1661bb0723a8f64f99",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/http": "^5.0",
+ "laminas/laminas-diactoros": "^3.0",
+ "psr/http-client": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "psr/http-server-handler": "^1.0",
+ "psr/http-server-middleware": "^1.0"
+ },
+ "require-dev": {
+ "cakephp/cakephp": "^5.1.0",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "firebase/php-jwt": "^6.2",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "suggest": {
+ "cakephp/cakephp": "Install full core to use \"CookieAuthenticator\".",
+ "cakephp/orm": "To use \"OrmResolver\" (Not needed separately if using full CakePHP framework).",
+ "cakephp/utility": "Provides CakePHP security methods. Required for the JWT adapter and Legacy password hasher.",
+ "ext-ldap": "Make sure this php extension is installed and enabled on your system if you want to use the built-in LDAP adapter for \"LdapIdentifier\".",
+ "firebase/php-jwt": "If you want to use the JWT adapter add this dependency"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "Authentication\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/authentication/graphs/contributors"
+ }
+ ],
+ "description": "Authentication plugin for CakePHP",
+ "homepage": "https://cakephp.org",
+ "keywords": [
+ "Authentication",
+ "auth",
+ "cakephp",
+ "middleware"
+ ],
+ "support": {
+ "docs": "https://book.cakephp.org/authentication/3/en/",
+ "forum": "https://discourse.cakephp.org/",
+ "issues": "https://github.com/cakephp/authentication/issues",
+ "source": "https://github.com/cakephp/authentication"
+ },
+ "time": "2024-10-18T15:48:32+00:00"
+ },
+ {
+ "name": "cakephp/cakephp",
+ "version": "5.1.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/cakephp.git",
+ "reference": "4b8915cf32949cac5c798af2ff65f688c4d76d21"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/cakephp/zipball/4b8915cf32949cac5c798af2ff65f688c4d76d21",
+ "reference": "4b8915cf32949cac5c798af2ff65f688c4d76d21",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/chronos": "^3.1",
+ "composer/ca-bundle": "^1.5",
+ "ext-intl": "*",
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "laminas/laminas-diactoros": "^3.3",
+ "laminas/laminas-httphandlerrunner": "^2.6",
+ "league/container": "^4.2",
+ "php": ">=8.1",
+ "psr/container": "^1.1 || ^2.0",
+ "psr/http-client": "^1.0.2",
+ "psr/http-factory": "^1.1",
+ "psr/http-message": "^1.1 || ^2.0",
+ "psr/http-server-handler": "^1.0.2",
+ "psr/http-server-middleware": "^1.0.2",
+ "psr/log": "^3.0",
+ "psr/simple-cache": "^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/container-implementation": "^2.0",
+ "psr/http-client-implementation": "^1.0",
+ "psr/http-factory-implementation": "^1.0",
+ "psr/http-server-handler-implementation": "^1.0",
+ "psr/http-server-middleware-implementation": "^1.0",
+ "psr/log-implementation": "^3.0",
+ "psr/simple-cache-implementation": "^3.0"
+ },
+ "replace": {
+ "cakephp/cache": "self.version",
+ "cakephp/collection": "self.version",
+ "cakephp/console": "self.version",
+ "cakephp/core": "self.version",
+ "cakephp/database": "self.version",
+ "cakephp/datasource": "self.version",
+ "cakephp/event": "self.version",
+ "cakephp/form": "self.version",
+ "cakephp/http": "self.version",
+ "cakephp/i18n": "self.version",
+ "cakephp/log": "self.version",
+ "cakephp/orm": "self.version",
+ "cakephp/utility": "self.version",
+ "cakephp/validation": "self.version"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "http-interop/http-factory-tests": "^2.0",
+ "mikey179/vfsstream": "^1.6.10",
+ "mockery/mockery": "^1.6",
+ "paragonie/csp-builder": "^2.3 || ^3.0",
+ "phpstan/extension-installer": "^1.3",
+ "phpstan/phpstan": "1.12.7",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3",
+ "symplify/phpstan-rules": "^12.4"
+ },
+ "suggest": {
+ "ext-curl": "To enable more efficient network calls in Http\\Client.",
+ "ext-openssl": "To use Security::encrypt() or have secure CSRF token generation.",
+ "paragonie/csp-builder": "CSP builder, to use the CSP Middleware"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Core/functions.php",
+ "src/Error/functions.php",
+ "src/Collection/functions.php",
+ "src/I18n/functions.php",
+ "src/ORM/bootstrap.php",
+ "src/Routing/functions.php",
+ "src/Utility/bootstrap.php"
+ ],
+ "psr-4": {
+ "Cake\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/cakephp/graphs/contributors"
+ }
+ ],
+ "description": "The CakePHP framework",
+ "homepage": "https://cakephp.org",
+ "keywords": [
+ "conventions over configuration",
+ "dry",
+ "form",
+ "framework",
+ "mvc",
+ "orm",
+ "psr-7",
+ "rapid-development",
+ "validation"
+ ],
+ "support": {
+ "forum": "https://discourse.cakephp.org/",
+ "issues": "https://github.com/cakephp/cakephp/issues",
+ "source": "https://github.com/cakephp/cakephp"
+ },
+ "time": "2025-02-23T20:09:05+00:00"
+ },
+ {
+ "name": "cakephp/chronos",
+ "version": "3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/chronos.git",
+ "reference": "786d69e1ee4b735765cbdb5521b9603e9b98d650"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/chronos/zipball/786d69e1ee4b735765cbdb5521b9603e9b98d650",
+ "reference": "786d69e1ee4b735765cbdb5521b9603e9b98d650",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/clock": "^1.0"
+ },
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "phpunit/phpunit": "^10.1.0 || ^11.1.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Cake\\Chronos\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "http://nesbot.com"
+ },
+ {
+ "name": "The CakePHP Team",
+ "homepage": "https://cakephp.org"
+ }
+ ],
+ "description": "A simple API extension for DateTime.",
+ "homepage": "https://cakephp.org",
+ "keywords": [
+ "date",
+ "datetime",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/cakephp/chronos/issues",
+ "source": "https://github.com/cakephp/chronos"
+ },
+ "time": "2024-07-18T03:18:04+00:00"
+ },
+ {
+ "name": "cakephp/migrations",
+ "version": "4.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/migrations.git",
+ "reference": "675b494235a3d3d8b76fda6a684f4ab38b5a6f7f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/migrations/zipball/675b494235a3d3d8b76fda6a684f4ab38b5a6f7f",
+ "reference": "675b494235a3d3d8b76fda6a684f4ab38b5a6f7f",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/cache": "^5.0",
+ "cakephp/orm": "^5.0",
+ "php": ">=8.1",
+ "robmorgan/phinx": "^0.16.0"
+ },
+ "require-dev": {
+ "cakephp/bake": "dev-3.next",
+ "cakephp/cakephp": "dev-5.next as 5.1.0",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "suggest": {
+ "cakephp/bake": "If you want to generate migrations.",
+ "dereuromark/cakephp-ide-helper": "If you want to have IDE suggest/autocomplete when creating migrations."
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "Migrations\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/migrations/graphs/contributors"
+ }
+ ],
+ "description": "Database Migration plugin for CakePHP based on Phinx",
+ "homepage": "https://github.com/cakephp/migrations",
+ "keywords": [
+ "cakephp",
+ "migrations"
+ ],
+ "support": {
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "issues": "https://github.com/cakephp/migrations/issues",
+ "source": "https://github.com/cakephp/migrations"
+ },
+ "time": "2025-01-16T15:21:04+00:00"
+ },
+ {
+ "name": "cakephp/plugin-installer",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/plugin-installer.git",
+ "reference": "5420701fd47d82fe81805ebee34fbbcef34c52ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/plugin-installer/zipball/5420701fd47d82fe81805ebee34fbbcef34c52ba",
+ "reference": "5420701fd47d82fe81805ebee34fbbcef34c52ba",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "composer/composer": "^2.0",
+ "phpunit/phpunit": "^10.1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "Cake\\Composer\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "Cake\\Composer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://cakephp.org"
+ }
+ ],
+ "description": "A composer installer for CakePHP 3.0+ plugins.",
+ "support": {
+ "issues": "https://github.com/cakephp/plugin-installer/issues",
+ "source": "https://github.com/cakephp/plugin-installer/tree/2.0.1"
+ },
+ "time": "2023-09-10T10:02:44+00:00"
+ },
+ {
+ "name": "composer/ca-bundle",
+ "version": "1.5.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/ca-bundle.git",
+ "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/08c50d5ec4c6ced7d0271d2862dec8c1033283e6",
+ "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "ext-pcre": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^8 || ^9",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\CaBundle\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
+ "keywords": [
+ "cabundle",
+ "cacert",
+ "certificate",
+ "ssl",
+ "tls"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/ca-bundle/issues",
+ "source": "https://github.com/composer/ca-bundle/tree/1.5.5"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-08T16:17:16+00:00"
+ },
+ {
+ "name": "firebase/php-jwt",
+ "version": "v6.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/firebase/php-jwt.git",
+ "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/8f718f4dfc9c5d5f0c994cdfd103921b43592712",
+ "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^2.0||^3.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
+ },
+ "suggest": {
+ "ext-sodium": "Support EdDSA (Ed25519) signatures",
+ "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Firebase\\JWT\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Neuman Vong",
+ "email": "neuman+pear@twilio.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Anant Narayanan",
+ "email": "anant@php.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
+ "homepage": "https://github.com/firebase/php-jwt",
+ "keywords": [
+ "jwt",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/firebase/php-jwt/issues",
+ "source": "https://github.com/firebase/php-jwt/tree/v6.11.0"
+ },
+ "time": "2025-01-23T05:11:06+00:00"
+ },
+ {
+ "name": "friendsofcake/bootstrap-ui",
+ "version": "5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FriendsOfCake/bootstrap-ui.git",
+ "reference": "3bd2963c13ff2d829010270669f0a259537acd6a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FriendsOfCake/bootstrap-ui/zipball/3bd2963c13ff2d829010270669f0a259537acd6a",
+ "reference": "3bd2963c13ff2d829010270669f0a259537acd6a",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/cakephp": "^5.1.4"
+ },
+ "require-dev": {
+ "cakephp/bake": "^3.0",
+ "cakephp/cakephp-codesniffer": "^5.1",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "BootstrapUI\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jad Bitar",
+ "homepage": "http://jadb.io",
+ "role": "Author"
+ },
+ {
+ "name": "Others",
+ "homepage": "https://github.com/friendsofcake/bootstrap-ui/graphs/contributors"
+ }
+ ],
+ "description": "Bootstrap front-end framework support for CakePHP",
+ "homepage": "http://github.com/friendsofcake/bootstrap-ui",
+ "keywords": [
+ "bootstrap",
+ "cakephp",
+ "front-end"
+ ],
+ "support": {
+ "issues": "http://github.com/friendsofcake/bootstrap-ui/issues",
+ "source": "http://github.com/friendsofcake/bootstrap-ui"
+ },
+ "time": "2024-12-13T06:20:08+00:00"
+ },
+ {
+ "name": "friendsofcake/cakephp-csvview",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FriendsOfCake/cakephp-csvview.git",
+ "reference": "c2e539c6e8a53c4fcbc27bfa3776f535dea96dc1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FriendsOfCake/cakephp-csvview/zipball/c2e539c6e8a53c4fcbc27bfa3776f535dea96dc1",
+ "reference": "c2e539c6e8a53c4fcbc27bfa3776f535dea96dc1",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/cakephp": "^5.0"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "phpunit/phpunit": "^10.1"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "CsvView\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jose Diaz-Gonzalez",
+ "email": "email@josediazgonzalez.com",
+ "homepage": "https://josediazgonzalez.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "ADmad",
+ "homepage": "https://github.com/admad",
+ "role": "Contributor"
+ },
+ {
+ "name": "Mark Scherer",
+ "homepage": "https://github.com/dereuromark",
+ "role": "Contributor"
+ },
+ {
+ "name": "Joshua Paling",
+ "homepage": "https://github.com/joshuapaling",
+ "role": "Contributor"
+ },
+ {
+ "name": "Gaurish Sharma",
+ "homepage": "https://github.com/gaurish",
+ "role": "Contributor"
+ },
+ {
+ "name": "Gregory Gaskill",
+ "homepage": "https://github.com/chronon",
+ "role": "Contributor"
+ }
+ ],
+ "description": "A CSV View class for CakePHP",
+ "homepage": "https://github.com/friendsofcake/cakephp-csvview",
+ "keywords": [
+ "cakephp",
+ "csv",
+ "export",
+ "view"
+ ],
+ "support": {
+ "issues": "https://github.com/friendsofcake/cakephp-csvview/issues",
+ "source": "https://github.com/friendsofcake/cakephp-csvview"
+ },
+ "time": "2023-10-13T18:16:38+00:00"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.9.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "d281ed313b989f213357e3be1a179f02196ac99b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
+ "reference": "d281ed313b989f213357e3be1a179f02196ac99b",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.3",
+ "guzzlehttp/psr7": "^2.7.0",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "guzzle/client-integration-tests": "3.0.2",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.9.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-24T11:22:20+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
+ "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-10-17T10:06:22+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "ralouphie/getallheaders": "^3.0"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "http-interop/http-factory-tests": "0.9.0",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.7.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-18T11:15:46+00:00"
+ },
+ {
+ "name": "jean85/pretty-package-versions",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Jean85/pretty-package-versions.git",
+ "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
+ "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2.1.0",
+ "php": "^7.4|^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "jean85/composer-provided-replaced-stub-package": "^1.0",
+ "phpstan/phpstan": "^1.4",
+ "phpunit/phpunit": "^7.5|^8.5|^9.6",
+ "vimeo/psalm": "^4.3 || ^5.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Jean85\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alessandro Lai",
+ "email": "alessandro.lai85@gmail.com"
+ }
+ ],
+ "description": "A library to get pretty versions strings of installed dependencies",
+ "keywords": [
+ "composer",
+ "package",
+ "release",
+ "versions"
+ ],
+ "support": {
+ "issues": "https://github.com/Jean85/pretty-package-versions/issues",
+ "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0"
+ },
+ "time": "2024-11-18T16:19:46+00:00"
+ },
+ {
+ "name": "laminas/laminas-diactoros",
+ "version": "3.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laminas/laminas-diactoros.git",
+ "reference": "143a16306602ce56b8b092a7914fef03c37f9ed2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/143a16306602ce56b8b092a7914fef03c37f9ed2",
+ "reference": "143a16306602ce56b8b092a7914fef03c37f9ed2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
+ "psr/http-factory": "^1.1",
+ "psr/http-message": "^1.1 || ^2.0"
+ },
+ "conflict": {
+ "amphp/amp": "<2.6.4"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "^1.0",
+ "psr/http-message-implementation": "^1.1 || ^2.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "ext-dom": "*",
+ "ext-gd": "*",
+ "ext-libxml": "*",
+ "http-interop/http-factory-tests": "^2.2.0",
+ "laminas/laminas-coding-standard": "~2.5.0",
+ "php-http/psr7-integration-tests": "^1.4.0",
+ "phpunit/phpunit": "^10.5.36",
+ "psalm/plugin-phpunit": "^0.19.0",
+ "vimeo/psalm": "^5.26.1"
+ },
+ "type": "library",
+ "extra": {
+ "laminas": {
+ "module": "Laminas\\Diactoros",
+ "config-provider": "Laminas\\Diactoros\\ConfigProvider"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions/create_uploaded_file.php",
+ "src/functions/marshal_headers_from_sapi.php",
+ "src/functions/marshal_method_from_sapi.php",
+ "src/functions/marshal_protocol_version_from_sapi.php",
+ "src/functions/normalize_server.php",
+ "src/functions/normalize_uploaded_files.php",
+ "src/functions/parse_cookie_header.php"
+ ],
+ "psr-4": {
+ "Laminas\\Diactoros\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "PSR HTTP Message implementations",
+ "homepage": "https://laminas.dev",
+ "keywords": [
+ "http",
+ "laminas",
+ "psr",
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "chat": "https://laminas.dev/chat",
+ "docs": "https://docs.laminas.dev/laminas-diactoros/",
+ "forum": "https://discourse.laminas.dev",
+ "issues": "https://github.com/laminas/laminas-diactoros/issues",
+ "rss": "https://github.com/laminas/laminas-diactoros/releases.atom",
+ "source": "https://github.com/laminas/laminas-diactoros"
+ },
+ "funding": [
+ {
+ "url": "https://funding.communitybridge.org/projects/laminas-project",
+ "type": "community_bridge"
+ }
+ ],
+ "time": "2024-10-14T11:59:49+00:00"
+ },
+ {
+ "name": "laminas/laminas-httphandlerrunner",
+ "version": "2.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laminas/laminas-httphandlerrunner.git",
+ "reference": "c428d9f67f280d155637cbe2b7245b5188c8cdae"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laminas/laminas-httphandlerrunner/zipball/c428d9f67f280d155637cbe2b7245b5188c8cdae",
+ "reference": "c428d9f67f280d155637cbe2b7245b5188c8cdae",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
+ "psr/http-message": "^1.0 || ^2.0",
+ "psr/http-message-implementation": "^1.0 || ^2.0",
+ "psr/http-server-handler": "^1.0"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~3.0.0",
+ "laminas/laminas-diactoros": "^3.4.0",
+ "phpunit/phpunit": "^10.5.36",
+ "psalm/plugin-phpunit": "^0.19.0",
+ "vimeo/psalm": "^5.26.1"
+ },
+ "type": "library",
+ "extra": {
+ "laminas": {
+ "config-provider": "Laminas\\HttpHandlerRunner\\ConfigProvider"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laminas\\HttpHandlerRunner\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Execute PSR-15 RequestHandlerInterface instances and emit responses they generate.",
+ "homepage": "https://laminas.dev",
+ "keywords": [
+ "components",
+ "laminas",
+ "mezzio",
+ "psr-15",
+ "psr-7"
+ ],
+ "support": {
+ "chat": "https://laminas.dev/chat",
+ "docs": "https://docs.laminas.dev/laminas-httphandlerrunner/",
+ "forum": "https://discourse.laminas.dev",
+ "issues": "https://github.com/laminas/laminas-httphandlerrunner/issues",
+ "rss": "https://github.com/laminas/laminas-httphandlerrunner/releases.atom",
+ "source": "https://github.com/laminas/laminas-httphandlerrunner"
+ },
+ "funding": [
+ {
+ "url": "https://funding.communitybridge.org/projects/laminas-project",
+ "type": "community_bridge"
+ }
+ ],
+ "time": "2024-10-17T20:37:17+00:00"
+ },
+ {
+ "name": "league/container",
+ "version": "4.2.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/container.git",
+ "reference": "7ea728b013b9a156c409c6f0fc3624071b742dec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/container/zipball/7ea728b013b9a156c409c6f0fc3624071b742dec",
+ "reference": "7ea728b013b9a156c409c6f0fc3624071b742dec",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0",
+ "psr/container": "^1.1 || ^2.0"
+ },
+ "provide": {
+ "psr/container-implementation": "^1.0"
+ },
+ "replace": {
+ "orno/di": "~2.0"
+ },
+ "require-dev": {
+ "nette/php-generator": "^3.4",
+ "nikic/php-parser": "^4.10",
+ "phpstan/phpstan": "^0.12.47",
+ "phpunit/phpunit": "^8.5.17",
+ "roave/security-advisories": "dev-latest",
+ "scrutinizer/ocular": "^1.8",
+ "squizlabs/php_codesniffer": "^3.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-1.x": "1.x-dev",
+ "dev-2.x": "2.x-dev",
+ "dev-3.x": "3.x-dev",
+ "dev-4.x": "4.x-dev",
+ "dev-master": "4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Container\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Phil Bennett",
+ "email": "mail@philbennett.co.uk",
+ "role": "Developer"
+ }
+ ],
+ "description": "A fast and intuitive dependency injection container.",
+ "homepage": "https://github.com/thephpleague/container",
+ "keywords": [
+ "container",
+ "dependency",
+ "di",
+ "injection",
+ "league",
+ "provider",
+ "service"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/container/issues",
+ "source": "https://github.com/thephpleague/container/tree/4.2.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/philipobenito",
+ "type": "github"
+ }
+ ],
+ "time": "2024-11-10T12:42:13+00:00"
+ },
+ {
+ "name": "lordsimal/cakephp-sentry",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/LordSimal/cakephp-sentry.git",
+ "reference": "de9640aeee76c50a7a5e0bc2346e295c7adb292f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/LordSimal/cakephp-sentry/zipball/de9640aeee76c50a7a5e0bc2346e295c7adb292f",
+ "reference": "de9640aeee76c50a7a5e0bc2346e295c7adb292f",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/cakephp": "^5.1.0",
+ "php": "^8.1",
+ "sentry/sentry": "^4.0"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "mockery/mockery": "^1.6",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "CakeSentry\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kevin Pfeifer",
+ "email": "info@pfeiferkevin.at",
+ "role": "Maintainer"
+ }
+ ],
+ "description": "Sentry plugin for CakePHP",
+ "support": {
+ "issues": "https://github.com/LordSimal/cakephp-sentry/issues",
+ "source": "https://github.com/LordSimal/cakephp-sentry/tree/3.2.0"
+ },
+ "time": "2024-12-31T19:23:16+00:00"
+ },
+ {
+ "name": "mobiledetect/mobiledetectlib",
+ "version": "3.74.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/serbanghita/Mobile-Detect.git",
+ "reference": "39582ab62f86b40e4edb698159f895929a29c346"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/39582ab62f86b40e4edb698159f895929a29c346",
+ "reference": "39582ab62f86b40e4edb698159f895929a29c346",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.14",
+ "phpunit/phpunit": "^9.6",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Detection\\": "src/"
+ },
+ "classmap": [
+ "src/MobileDetect.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Serban Ghita",
+ "email": "serbanghita@gmail.com",
+ "homepage": "https://mobiledetect.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.",
+ "homepage": "https://github.com/serbanghita/Mobile-Detect",
+ "keywords": [
+ "detect mobile devices",
+ "mobile",
+ "mobile detect",
+ "mobile detector",
+ "php mobile detect"
+ ],
+ "support": {
+ "issues": "https://github.com/serbanghita/Mobile-Detect/issues",
+ "source": "https://github.com/serbanghita/Mobile-Detect/tree/3.74.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/serbanghita",
+ "type": "github"
+ }
+ ],
+ "time": "2023-10-27T16:28:04+00:00"
+ },
+ {
+ "name": "mtdowling/jmespath.php",
+ "version": "2.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jmespath/jmespath.php.git",
+ "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc",
+ "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "symfony/polyfill-mbstring": "^1.17"
+ },
+ "require-dev": {
+ "composer/xdebug-handler": "^3.0.3",
+ "phpunit/phpunit": "^8.5.33"
+ },
+ "bin": [
+ "bin/jp.php"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/JmesPath.php"
+ ],
+ "psr-4": {
+ "JmesPath\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Declaratively specify how to extract elements from a JSON document",
+ "keywords": [
+ "json",
+ "jsonpath"
+ ],
+ "support": {
+ "issues": "https://github.com/jmespath/jmespath.php/issues",
+ "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0"
+ },
+ "time": "2024-09-04T18:46:31+00:00"
+ },
+ {
+ "name": "muffin/trash",
+ "version": "4.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/UseMuffin/Trash.git",
+ "reference": "bbdaab7b2f1848fbce9111daadda1146ef1122a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/UseMuffin/Trash/zipball/bbdaab7b2f1848fbce9111daadda1146ef1122a2",
+ "reference": "bbdaab7b2f1848fbce9111daadda1146ef1122a2",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/orm": "^5.0.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "cakephp/cakephp": "^5.0.0",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "phpunit/phpunit": "^10.1.0"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "Muffin\\Trash\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jad Bitar",
+ "homepage": "http://jadb.io",
+ "role": "Author"
+ },
+ {
+ "name": "ADmad",
+ "homepage": "https://github.com/ADmad",
+ "role": "Author"
+ },
+ {
+ "name": "Others",
+ "homepage": "https://github.com/usemuffin/trash/graphs/contributors"
+ }
+ ],
+ "description": "Adds soft delete support to CakePHP ORM tables.",
+ "homepage": "https://github.com/usemuffin/trash",
+ "keywords": [
+ "cakephp",
+ "muffin",
+ "orm",
+ "trash"
+ ],
+ "support": {
+ "issues": "https://github.com/usemuffin/trash/issues",
+ "source": "https://github.com/usemuffin/trash"
+ },
+ "time": "2025-02-04T07:09:14+00:00"
+ },
+ {
+ "name": "paragonie/constant_time_encoding",
+ "version": "v3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
+ "reference": "df1e7fde177501eee2037dd159cf04f5f301a512"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512",
+ "reference": "df1e7fde177501eee2037dd159cf04f5f301a512",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9",
+ "vimeo/psalm": "^4|^5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base16",
+ "base32",
+ "base32_decode",
+ "base32_encode",
+ "base64",
+ "base64_decode",
+ "base64_encode",
+ "bin2hex",
+ "encoding",
+ "hex",
+ "hex2bin",
+ "rfc4648"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
+ "source": "https://github.com/paragonie/constant_time_encoding"
+ },
+ "time": "2024-05-08T12:36:18+00:00"
+ },
+ {
+ "name": "paragonie/random_compat",
+ "version": "v9.99.100",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">= 7"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*",
+ "vimeo/psalm": "^1"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "polyfill",
+ "pseudorandom",
+ "random"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/random_compat/issues",
+ "source": "https://github.com/paragonie/random_compat"
+ },
+ "time": "2020-10-15T08:29:30+00:00"
+ },
+ {
+ "name": "php-amqplib/php-amqplib",
+ "version": "v3.7.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-amqplib/php-amqplib.git",
+ "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9f50fe69a9f1a19e2cb25596a354d705de36fe59",
+ "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-sockets": "*",
+ "php": "^7.2||^8.0",
+ "phpseclib/phpseclib": "^2.0|^3.0"
+ },
+ "conflict": {
+ "php": "7.4.0 - 7.4.1"
+ },
+ "replace": {
+ "videlalvaro/php-amqplib": "self.version"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "nategood/httpful": "^0.2.20",
+ "phpunit/phpunit": "^7.5|^9.5",
+ "squizlabs/php_codesniffer": "^3.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpAmqpLib\\": "PhpAmqpLib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-2.1-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Alvaro Videla",
+ "role": "Original Maintainer"
+ },
+ {
+ "name": "Raúl Araya",
+ "email": "nubeiro@gmail.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Luke Bakken",
+ "email": "luke@bakken.io",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Ramūnas Dronga",
+ "email": "github@ramuno.lt",
+ "role": "Maintainer"
+ }
+ ],
+ "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.",
+ "homepage": "https://github.com/php-amqplib/php-amqplib/",
+ "keywords": [
+ "message",
+ "queue",
+ "rabbitmq"
+ ],
+ "support": {
+ "issues": "https://github.com/php-amqplib/php-amqplib/issues",
+ "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.7.3"
+ },
+ "time": "2025-02-18T20:11:13+00:00"
+ },
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "3.0.43",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "709ec107af3cb2f385b9617be72af8cf62441d02"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02",
+ "reference": "709ec107af3cb2f385b9617be72af8cf62441d02",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/constant_time_encoding": "^1|^2|^3",
+ "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
+ "php": ">=5.6.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "suggest": {
+ "ext-dom": "Install the DOM extension to load XML formatted public keys.",
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib3\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "homepage": "http://phpseclib.sourceforge.net",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ],
+ "support": {
+ "issues": "https://github.com/phpseclib/phpseclib/issues",
+ "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/terrafrost",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/phpseclib",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-12-14T21:12:59+00:00"
+ },
+ {
+ "name": "psr/clock",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/clock.git",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Clock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for reading the clock.",
+ "homepage": "https://github.com/php-fig/clock",
+ "keywords": [
+ "clock",
+ "now",
+ "psr",
+ "psr-20",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/clock/issues",
+ "source": "https://github.com/php-fig/clock/tree/1.0.0"
+ },
+ "time": "2022-11-25T14:36:26+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client"
+ },
+ "time": "2023-09-23T14:17:50+00:00"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "time": "2024-04-15T12:06:14+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
+ },
+ "time": "2023-04-04T09:54:51+00:00"
+ },
+ {
+ "name": "psr/http-server-handler",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-server-handler.git",
+ "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4",
+ "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Server\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP server-side request handler",
+ "keywords": [
+ "handler",
+ "http",
+ "http-interop",
+ "psr",
+ "psr-15",
+ "psr-7",
+ "request",
+ "response",
+ "server"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-server-handler/tree/1.0.2"
+ },
+ "time": "2023-04-10T20:06:20+00:00"
+ },
+ {
+ "name": "psr/http-server-middleware",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-server-middleware.git",
+ "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829",
+ "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0",
+ "psr/http-message": "^1.0 || ^2.0",
+ "psr/http-server-handler": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Server\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP server-side middleware",
+ "keywords": [
+ "http",
+ "http-interop",
+ "middleware",
+ "psr",
+ "psr-15",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/http-server-middleware/issues",
+ "source": "https://github.com/php-fig/http-server-middleware/tree/1.0.2"
+ },
+ "time": "2023-04-11T06:14:47+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "time": "2024-09-11T13:17:53+00:00"
+ },
+ {
+ "name": "psr/simple-cache",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
+ "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
+ },
+ "time": "2021-10-29T13:26:27+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "time": "2019-03-08T08:55:37+00:00"
+ },
+ {
+ "name": "robmorgan/phinx",
+ "version": "0.16.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/phinx.git",
+ "reference": "5bad10934336e8cf45d50d529cabfcbe7fe287c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/phinx/zipball/5bad10934336e8cf45d50d529cabfcbe7fe287c5",
+ "reference": "5bad10934336e8cf45d50d529cabfcbe7fe287c5",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/database": "^5.0.2",
+ "composer-runtime-api": "^2.0",
+ "php-64bit": ">=8.1",
+ "psr/container": "^1.1|^2.0",
+ "symfony/config": "^3.4|^4.0|^5.0|^6.0|^7.0",
+ "symfony/console": "^6.0|^7.0"
+ },
+ "require-dev": {
+ "cakephp/cakephp": "^5.0.2",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "ext-json": "*",
+ "ext-pdo": "*",
+ "phpunit/phpunit": "^9.5.19",
+ "symfony/yaml": "^3.4|^4.0|^5.0|^6.0|^7.0"
+ },
+ "suggest": {
+ "ext-json": "Install if using JSON configuration format",
+ "ext-pdo": "PDO extension is needed",
+ "symfony/yaml": "Install if using YAML configuration format"
+ },
+ "bin": [
+ "bin/phinx"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Phinx\\": "src/Phinx/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Rob Morgan",
+ "email": "robbym@gmail.com",
+ "homepage": "https://robmorgan.id.au",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Woody Gilk",
+ "email": "woody.gilk@gmail.com",
+ "homepage": "https://shadowhand.me",
+ "role": "Developer"
+ },
+ {
+ "name": "Richard Quadling",
+ "email": "rquadling@gmail.com",
+ "role": "Developer"
+ },
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/phinx/graphs/contributors",
+ "role": "Developer"
+ }
+ ],
+ "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.",
+ "homepage": "https://phinx.org",
+ "keywords": [
+ "database",
+ "database migrations",
+ "db",
+ "migrations",
+ "phinx"
+ ],
+ "support": {
+ "issues": "https://github.com/cakephp/phinx/issues",
+ "source": "https://github.com/cakephp/phinx/tree/0.16.6"
+ },
+ "time": "2024-12-20T23:02:54+00:00"
+ },
+ {
+ "name": "sentry/sentry",
+ "version": "4.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/getsentry/sentry-php.git",
+ "reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2af937d47d8aadb8dab0b1d7b9557e495dd12856",
+ "reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "guzzlehttp/psr7": "^1.8.4|^2.1.1",
+ "jean85/pretty-package-versions": "^1.5|^2.0.4",
+ "php": "^7.2|^8.0",
+ "psr/log": "^1.0|^2.0|^3.0",
+ "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0"
+ },
+ "conflict": {
+ "raven/raven": "*"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.4",
+ "guzzlehttp/promises": "^2.0.3",
+ "guzzlehttp/psr7": "^1.8.4|^2.1.1",
+ "monolog/monolog": "^1.6|^2.0|^3.0",
+ "phpbench/phpbench": "^1.0",
+ "phpstan/phpstan": "^1.3",
+ "phpunit/phpunit": "^8.5|^9.6",
+ "symfony/phpunit-bridge": "^5.2|^6.0|^7.0",
+ "vimeo/psalm": "^4.17"
+ },
+ "suggest": {
+ "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Sentry\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Sentry",
+ "email": "accounts@sentry.io"
+ }
+ ],
+ "description": "PHP SDK for Sentry (http://sentry.io)",
+ "homepage": "http://sentry.io",
+ "keywords": [
+ "crash-reporting",
+ "crash-reports",
+ "error-handler",
+ "error-monitoring",
+ "log",
+ "logging",
+ "profiling",
+ "sentry",
+ "tracing"
+ ],
+ "support": {
+ "issues": "https://github.com/getsentry/sentry-php/issues",
+ "source": "https://github.com/getsentry/sentry-php/tree/4.10.0"
+ },
+ "funding": [
+ {
+ "url": "https://sentry.io/",
+ "type": "custom"
+ },
+ {
+ "url": "https://sentry.io/pricing/",
+ "type": "custom"
+ }
+ ],
+ "time": "2024-11-06T07:44:19+00:00"
+ },
+ {
+ "name": "simpleenergy/php-webhdfs",
+ "version": "1.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/michaelbutler/php-WebHDFS.git",
+ "reference": "3212b98e9444e55aab7d129f002247bdcd0c26c8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/michaelbutler/php-WebHDFS/zipball/3212b98e9444e55aab7d129f002247bdcd0c26c8",
+ "reference": "3212b98e9444e55aab7d129f002247bdcd0c26c8",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.4.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "org\\apache\\hadoop\\": "src/",
+ "org\\apache\\hadoop\\tools": "app/models/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "tranch-xiao",
+ "homepage": "https://github.com/tranch-xiao"
+ },
+ {
+ "name": "dshap",
+ "homepage": "https://github.com/dshap"
+ },
+ {
+ "name": "jacobko",
+ "homepage": "https://github.com/jacobko"
+ },
+ {
+ "name": "yosshi",
+ "homepage": "https://github.com/yosshi"
+ },
+ {
+ "name": "Sebastian Lagemann",
+ "email": "sebastian@iqu.com"
+ }
+ ],
+ "description": "PHP WebHDFS, forked from https://github.com/simpleenergy/php-WebHDFS",
+ "support": {
+ "issues": "https://github.com/michaelbutler/php-WebHDFS/issues",
+ "source": "https://github.com/michaelbutler/php-WebHDFS/tree/1.0.8"
+ },
+ "time": "2024-04-22T23:58:10+00:00"
+ },
+ {
+ "name": "symfony/config",
+ "version": "v7.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/config.git",
+ "reference": "7716594aaae91d9141be080240172a92ecca4d44"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/config/zipball/7716594aaae91d9141be080240172a92ecca4d44",
+ "reference": "7716594aaae91d9141be080240172a92ecca4d44",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/filesystem": "^7.1",
+ "symfony/polyfill-ctype": "~1.8"
+ },
+ "conflict": {
+ "symfony/finder": "<6.4",
+ "symfony/service-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Config\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/config/tree/v7.2.3"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-22T12:07:01+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v7.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
+ "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<6.4",
+ "symfony/dotenv": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/process": "<6.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/console/tree/v7.2.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-12-11T03:49:26+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-25T14:20:29+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v7.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
+ "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "require-dev": {
+ "symfony/process": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides basic utilities for the filesystem",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/filesystem/tree/v7.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-10-25T15:15:23+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v7.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
+ "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v7.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-11-20T11:17:29+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
+ "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v3.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+ "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/service-contracts/tree/v3.5.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-25T14:20:29+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v7.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82",
+ "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/emoji": "^7.1",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v7.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-11-13T13:31:26+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "brick/varexporter",
+ "version": "0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/brick/varexporter.git",
+ "reference": "84b2a7a91f69aa5d079aec5a0a7256ebf2dceb6b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/brick/varexporter/zipball/84b2a7a91f69aa5d079aec5a0a7256ebf2dceb6b",
+ "reference": "84b2a7a91f69aa5d079aec5a0a7256ebf2dceb6b",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.2",
+ "phpunit/phpunit": "^9.3",
+ "psalm/phar": "5.21.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Brick\\VarExporter\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A powerful alternative to var_export(), which can export closures and objects without __set_state()",
+ "keywords": [
+ "var_export"
+ ],
+ "support": {
+ "issues": "https://github.com/brick/varexporter/issues",
+ "source": "https://github.com/brick/varexporter/tree/0.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/BenMorel",
+ "type": "github"
+ }
+ ],
+ "time": "2024-05-10T17:15:19+00:00"
+ },
+ {
+ "name": "cakephp/bake",
+ "version": "3.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/bake.git",
+ "reference": "165e2bd9cc407b0ea19f8a3b48927c10607f3963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/bake/zipball/165e2bd9cc407b0ea19f8a3b48927c10607f3963",
+ "reference": "165e2bd9cc407b0ea19f8a3b48927c10607f3963",
+ "shasum": ""
+ },
+ "require": {
+ "brick/varexporter": "^0.5.0",
+ "cakephp/cakephp": "^5.1",
+ "cakephp/twig-view": "^2.0.0",
+ "nikic/php-parser": "^5.0.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0.0",
+ "cakephp/debug_kit": "^5.0.0",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "Bake\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/bake/graphs/contributors"
+ }
+ ],
+ "description": "Bake plugin for CakePHP",
+ "homepage": "https://github.com/cakephp/bake",
+ "keywords": [
+ "bake",
+ "cakephp"
+ ],
+ "support": {
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "issues": "https://github.com/cakephp/bake/issues",
+ "source": "https://github.com/cakephp/bake"
+ },
+ "time": "2025-01-17T14:18:00+00:00"
+ },
+ {
+ "name": "cakephp/cakephp-codesniffer",
+ "version": "5.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/cakephp-codesniffer.git",
+ "reference": "6d0168a18c9fb6802103b41579abdcfba7021790"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/cakephp-codesniffer/zipball/6d0168a18c9fb6802103b41579abdcfba7021790",
+ "reference": "6d0168a18c9fb6802103b41579abdcfba7021790",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1.0",
+ "phpstan/phpdoc-parser": "^1.4.5",
+ "slevomat/coding-standard": "^8.15",
+ "squizlabs/php_codesniffer": "^3.9"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3.4"
+ },
+ "type": "phpcodesniffer-standard",
+ "autoload": {
+ "psr-4": {
+ "CakePHP\\": "CakePHP/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/cakephp-codesniffer/graphs/contributors"
+ }
+ ],
+ "description": "CakePHP CodeSniffer Standards",
+ "homepage": "https://cakephp.org",
+ "keywords": [
+ "codesniffer",
+ "framework"
+ ],
+ "support": {
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "issues": "https://github.com/cakephp/cakephp-codesniffer/issues",
+ "source": "https://github.com/cakephp/cakephp-codesniffer"
+ },
+ "time": "2024-12-18T21:15:44+00:00"
+ },
+ {
+ "name": "cakephp/debug_kit",
+ "version": "5.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/debug_kit.git",
+ "reference": "b83ec9e0c62480f7cc9639e01cb9310bb7f0816d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/debug_kit/zipball/b83ec9e0c62480f7cc9639e01cb9310bb7f0816d",
+ "reference": "b83ec9e0c62480f7cc9639e01cb9310bb7f0816d",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/cakephp": "^5.1",
+ "composer/composer": "^2.0",
+ "doctrine/sql-formatter": "^1.1.3",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "cakephp/authorization": "^3.0",
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "suggest": {
+ "ext-pdo_sqlite": "DebugKit needs to store panel data in a database. SQLite is simple and easy to use."
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "DebugKit\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Story",
+ "homepage": "https://mark-story.com",
+ "role": "Author"
+ },
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/debug_kit/graphs/contributors"
+ }
+ ],
+ "description": "CakePHP Debug Kit",
+ "homepage": "https://github.com/cakephp/debug_kit",
+ "keywords": [
+ "cakephp",
+ "debug",
+ "dev",
+ "kit"
+ ],
+ "support": {
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "issues": "https://github.com/cakephp/debug_kit/issues",
+ "source": "https://github.com/cakephp/debug_kit"
+ },
+ "time": "2024-12-30T18:48:17+00:00"
+ },
+ {
+ "name": "cakephp/twig-view",
+ "version": "2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cakephp/twig-view.git",
+ "reference": "b11df8e8734ae556d98b143192377dbc6a6f5360"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cakephp/twig-view/zipball/b11df8e8734ae556d98b143192377dbc6a6f5360",
+ "reference": "b11df8e8734ae556d98b143192377dbc6a6f5360",
+ "shasum": ""
+ },
+ "require": {
+ "cakephp/cakephp": "^5.0.0",
+ "jasny/twig-extensions": "^1.3",
+ "twig/markdown-extra": "^3.0",
+ "twig/twig": "^3.11.1"
+ },
+ "conflict": {
+ "wyrihaximus/twig-view": "*"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^5.0",
+ "cakephp/debug_kit": "^5.0",
+ "michelf/php-markdown": "^1.9",
+ "mikey179/vfsstream": "^1.6.10",
+ "phpunit/phpunit": "^10.5.5 || ^11.1.3"
+ },
+ "type": "cakephp-plugin",
+ "autoload": {
+ "psr-4": {
+ "Cake\\TwigView\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/cakephp/graphs/contributors"
+ }
+ ],
+ "description": "Twig powered View for CakePHP",
+ "keywords": [
+ "cakephp",
+ "template",
+ "twig",
+ "view"
+ ],
+ "support": {
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "issues": "https://github.com/cakephp/twig-view/issues",
+ "source": "https://github.com/cakephp/twig-view"
+ },
+ "time": "2024-10-11T07:53:08+00:00"
+ },
+ {
+ "name": "composer/class-map-generator",
+ "version": "1.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/class-map-generator.git",
+ "reference": "ffe442c5974c44a9343e37a0abcb1cc37319f5b9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/class-map-generator/zipball/ffe442c5974c44a9343e37a0abcb1cc37319f5b9",
+ "reference": "ffe442c5974c44a9343e37a0abcb1cc37319f5b9",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^2.1 || ^3.1",
+ "php": "^7.2 || ^8.0",
+ "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-deprecation-rules": "^1 || ^2",
+ "phpstan/phpstan-phpunit": "^1 || ^2",
+ "phpstan/phpstan-strict-rules": "^1.1 || ^2",
+ "phpunit/phpunit": "^8",
+ "symfony/filesystem": "^5.4 || ^6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\ClassMapGenerator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Utilities to scan PHP code and generate class maps.",
+ "keywords": [
+ "classmap"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/class-map-generator/issues",
+ "source": "https://github.com/composer/class-map-generator/tree/1.6.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-05T10:05:34+00:00"
+ },
+ {
+ "name": "composer/composer",
+ "version": "2.8.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/composer.git",
+ "reference": "937c775a644bd7d2c3dfbb352747488463a6e673"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/composer/zipball/937c775a644bd7d2c3dfbb352747488463a6e673",
+ "reference": "937c775a644bd7d2c3dfbb352747488463a6e673",
+ "shasum": ""
+ },
+ "require": {
+ "composer/ca-bundle": "^1.5",
+ "composer/class-map-generator": "^1.4.0",
+ "composer/metadata-minifier": "^1.0",
+ "composer/pcre": "^2.2 || ^3.2",
+ "composer/semver": "^3.3",
+ "composer/spdx-licenses": "^1.5.7",
+ "composer/xdebug-handler": "^2.0.2 || ^3.0.3",
+ "justinrainbow/json-schema": "^5.3",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "react/promise": "^2.11 || ^3.2",
+ "seld/jsonlint": "^1.4",
+ "seld/phar-utils": "^1.2",
+ "seld/signal-handler": "^2.0",
+ "symfony/console": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "symfony/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "symfony/finder": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "symfony/polyfill-php73": "^1.24",
+ "symfony/polyfill-php80": "^1.24",
+ "symfony/polyfill-php81": "^1.24",
+ "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11.8",
+ "phpstan/phpstan-deprecation-rules": "^1.2.0",
+ "phpstan/phpstan-phpunit": "^1.4.0",
+ "phpstan/phpstan-strict-rules": "^1.6.0",
+ "phpstan/phpstan-symfony": "^1.4.0",
+ "symfony/phpunit-bridge": "^6.4.3 || ^7.0.1"
+ },
+ "suggest": {
+ "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
+ "ext-zip": "Enabling the zip extension allows you to unzip archives",
+ "ext-zlib": "Allow gzip compression of HTTP requests"
+ },
+ "bin": [
+ "bin/composer"
+ ],
+ "type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "phpstan/rules.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "2.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\": "src/Composer/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "https://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.",
+ "homepage": "https://getcomposer.org/",
+ "keywords": [
+ "autoload",
+ "dependency",
+ "package"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/composer/issues",
+ "security": "https://github.com/composer/composer/security/policy",
+ "source": "https://github.com/composer/composer/tree/2.8.6"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-25T12:03:50+00:00"
+ },
+ {
+ "name": "composer/metadata-minifier",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/metadata-minifier.git",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2",
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\MetadataMinifier\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Small utility library that handles metadata minification and expansion.",
+ "keywords": [
+ "composer",
+ "compression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/metadata-minifier/issues",
+ "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-04-07T13:37:33+00:00"
+ },
+ {
+ "name": "composer/pcre",
+ "version": "3.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<1.11.10"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-strict-rules": "^1 || ^2",
+ "phpunit/phpunit": "^8 || ^9"
+ },
+ "type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Pcre\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
+ "keywords": [
+ "PCRE",
+ "preg",
+ "regex",
+ "regular expression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/pcre/issues",
+ "source": "https://github.com/composer/pcre/tree/3.3.2"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-11-12T16:29:46+00:00"
+ },
+ {
+ "name": "composer/semver",
+ "version": "3.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
+ "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11",
+ "symfony/phpunit-bridge": "^3 || ^7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/semver/issues",
+ "source": "https://github.com/composer/semver/tree/3.4.3"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-19T14:15:21+00:00"
+ },
+ {
+ "name": "composer/spdx-licenses",
+ "version": "1.5.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/spdx-licenses.git",
+ "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a",
+ "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Spdx\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "SPDX licenses list and validation library.",
+ "keywords": [
+ "license",
+ "spdx",
+ "validator"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/spdx-licenses/issues",
+ "source": "https://github.com/composer/spdx-licenses/tree/1.5.8"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-11-20T07:44:33+00:00"
+ },
+ {
+ "name": "composer/xdebug-handler",
+ "version": "3.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^1 || ^2 || ^3",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1 || ^2 || ^3"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Composer\\XdebugHandler\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
+ }
+ ],
+ "description": "Restarts a process without Xdebug.",
+ "keywords": [
+ "Xdebug",
+ "performance"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/xdebug-handler/issues",
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-05-06T16:37:16+00:00"
+ },
+ {
+ "name": "dealerdirect/phpcodesniffer-composer-installer",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/composer-installer.git",
+ "reference": "4be43904336affa5c2f70744a348312336afd0da"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da",
+ "reference": "4be43904336affa5c2f70744a348312336afd0da",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^1.0 || ^2.0",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
+ },
+ "require-dev": {
+ "composer/composer": "*",
+ "ext-json": "*",
+ "ext-zip": "*",
+ "php-parallel-lint/php-parallel-lint": "^1.3.1",
+ "phpcompatibility/php-compatibility": "^9.0",
+ "yoast/phpunit-polyfills": "^1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Franck Nijhof",
+ "email": "franck.nijhof@dealerdirect.com",
+ "homepage": "http://www.frenck.nl",
+ "role": "Developer / IT Manager"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
+ "homepage": "http://www.dealerdirect.com",
+ "keywords": [
+ "PHPCodeSniffer",
+ "PHP_CodeSniffer",
+ "code quality",
+ "codesniffer",
+ "composer",
+ "installer",
+ "phpcbf",
+ "phpcs",
+ "plugin",
+ "qa",
+ "quality",
+ "standard",
+ "standards",
+ "style guide",
+ "stylecheck",
+ "tests"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
+ "source": "https://github.com/PHPCSStandards/composer-installer"
+ },
+ "time": "2023-01-05T11:28:13+00:00"
+ },
+ {
+ "name": "doctrine/sql-formatter",
+ "version": "1.5.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/sql-formatter.git",
+ "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d6d00aba6fd2957fe5216fe2b7673e9985db20c8",
+ "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "ergebnis/phpunit-slow-test-detector": "^2.14",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.5"
+ },
+ "bin": [
+ "bin/sql-formatter"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\SqlFormatter\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jeremy Dorn",
+ "email": "jeremy@jeremydorn.com",
+ "homepage": "https://jeremydorn.com/"
+ }
+ ],
+ "description": "a PHP SQL highlighting library",
+ "homepage": "https://github.com/doctrine/sql-formatter/",
+ "keywords": [
+ "highlight",
+ "sql"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/sql-formatter/issues",
+ "source": "https://github.com/doctrine/sql-formatter/tree/1.5.2"
+ },
+ "time": "2025-01-24T11:45:48+00:00"
+ },
+ {
+ "name": "jasny/twig-extensions",
+ "version": "v1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jasny/twig-extensions.git",
+ "reference": "8a5ca5f49317bf421a519556ad2e876820d41e01"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jasny/twig-extensions/zipball/8a5ca5f49317bf421a519556ad2e876820d41e01",
+ "reference": "8a5ca5f49317bf421a519556ad2e876820d41e01",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0",
+ "twig/twig": "^2.7 | ^3.0"
+ },
+ "require-dev": {
+ "ext-intl": "*",
+ "ext-json": "*",
+ "ext-pcre": "*",
+ "phpstan/phpstan": "^1.12.0",
+ "phpunit/phpunit": "^9.6",
+ "squizlabs/php_codesniffer": "^3.10"
+ },
+ "suggest": {
+ "ext-intl": "Required for the use of the LocalDate Twig extension",
+ "ext-pcre": "Required for the use of the PCRE Twig extension"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Jasny\\Twig\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arnold Daniels",
+ "email": "arnold@jasny.net",
+ "homepage": "http://www.jasny.net"
+ }
+ ],
+ "description": "A set of useful Twig filters",
+ "homepage": "http://github.com/jasny/twig-extensions#README",
+ "keywords": [
+ "PCRE",
+ "array",
+ "date",
+ "datetime",
+ "preg",
+ "regex",
+ "templating",
+ "text",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/jasny/twig-extensions/issues",
+ "source": "https://github.com/jasny/twig-extensions"
+ },
+ "time": "2024-09-03T09:04:53+00:00"
+ },
+ {
+ "name": "josegonzalez/dotenv",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/josegonzalez/php-dotenv.git",
+ "reference": "e97dbd3db53508dcd536e73ec787a7f11458d41d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/josegonzalez/php-dotenv/zipball/e97dbd3db53508dcd536e73ec787a7f11458d41d",
+ "reference": "e97dbd3db53508dcd536e73ec787a7f11458d41d",
+ "shasum": ""
+ },
+ "require": {
+ "m1/env": "2.*",
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "~2.0",
+ "php-mock/php-mock-phpunit": "~1.1||~2.0",
+ "squizlabs/php_codesniffer": "~2.9||~3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "josegonzalez\\Dotenv": [
+ "src",
+ "tests"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jose Diaz-Gonzalez",
+ "email": "dotenv@josegonzalez.com",
+ "homepage": "http://josediazgonzalez.com",
+ "role": "Maintainer"
+ }
+ ],
+ "description": "dotenv file parsing for PHP",
+ "homepage": "https://github.com/josegonzalez/php-dotenv",
+ "keywords": [
+ "configuration",
+ "dotenv",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/josegonzalez/php-dotenv/issues",
+ "source": "https://github.com/josegonzalez/php-dotenv/tree/4.0.0"
+ },
+ "time": "2023-05-29T22:49:26+00:00"
+ },
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "5.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jsonrainbow/json-schema.git",
+ "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8",
+ "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1",
+ "json-schema/json-schema-test-suite": "1.2.0",
+ "phpunit/phpunit": "^4.8.35"
+ },
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "JsonSchema\\": "src/JsonSchema/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/justinrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ],
+ "support": {
+ "issues": "https://github.com/jsonrainbow/json-schema/issues",
+ "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0"
+ },
+ "time": "2024-07-06T21:00:26+00:00"
+ },
+ {
+ "name": "m1/env",
+ "version": "2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/m1/Env.git",
+ "reference": "5c296e3e13450a207e12b343f3af1d7ab569f6f3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/m1/Env/zipball/5c296e3e13450a207e12b343f3af1d7ab569f6f3",
+ "reference": "5c296e3e13450a207e12b343f3af1d7ab569f6f3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*",
+ "scrutinizer/ocular": "~1.1",
+ "squizlabs/php_codesniffer": "^2.3"
+ },
+ "suggest": {
+ "josegonzalez/dotenv": "For loading of .env",
+ "m1/vars": "For loading of configs"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "M1\\Env\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Miles Croxford",
+ "email": "hello@milescroxford.com",
+ "homepage": "http://milescroxford.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Env is a lightweight library bringing .env file parser compatibility to PHP. In short - it enables you to read .env files with PHP.",
+ "homepage": "https://github.com/m1/Env",
+ "keywords": [
+ ".env",
+ "config",
+ "dotenv",
+ "env",
+ "loader",
+ "m1",
+ "parser",
+ "support"
+ ],
+ "support": {
+ "issues": "https://github.com/m1/Env/issues",
+ "source": "https://github.com/m1/Env/tree/2.2.0"
+ },
+ "time": "2020-02-19T09:02:13+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.13.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "024473a478be9df5fdaca2c793f2232fe788e414"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
+ "reference": "024473a478be9df5fdaca2c793f2232fe788e414",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpspec/prophecy": "^1.10",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-12T12:17:51+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "447a020a1f875a434d62f2a401f53b82a396e494"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494",
+ "reference": "447a020a1f875a434d62f2a401f53b82a396e494",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0"
+ },
+ "time": "2024-12-30T11:07:19+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpstan/phpdoc-parser",
+ "version": "1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpdoc-parser.git",
+ "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140",
+ "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^2.0",
+ "nikic/php-parser": "^4.15",
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpstan/phpstan-strict-rules": "^1.0",
+ "phpunit/phpunit": "^9.5",
+ "symfony/process": "^5.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\PhpDocParser\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PHPDoc parser with support for nullable, intersection and generic types",
+ "support": {
+ "issues": "https://github.com/phpstan/phpdoc-parser/issues",
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0"
+ },
+ "time": "2024-10-13T11:25:22+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "10.1.16",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "7e308268858ed6baedc8704a304727d20bc07c77"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77",
+ "reference": "7e308268858ed6baedc8704a304727d20bc07c77",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^4.19.1 || ^5.1.0",
+ "php": ">=8.1",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "sebastian/code-unit-reverse-lookup": "^3.0.0",
+ "sebastian/complexity": "^3.2.0",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/lines-of-code": "^2.0.2",
+ "sebastian/version": "^4.0.1",
+ "theseer/tokenizer": "^1.2.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.1"
+ },
+ "suggest": {
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "10.1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-08-22T04:31:57+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "4.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-08-31T06:24:48+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^10.0"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:56:09+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-08-31T14:07:24+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:57:52+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "10.5.45",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "bd68a781d8e30348bc297449f5234b3458267ae8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bd68a781d8e30348bc297449f5234b3458267ae8",
+ "reference": "bd68a781d8e30348bc297449f5234b3458267ae8",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.12.1",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.1",
+ "phpunit/php-code-coverage": "^10.1.16",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-invoker": "^4.0.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "phpunit/php-timer": "^6.0.0",
+ "sebastian/cli-parser": "^2.0.1",
+ "sebastian/code-unit": "^2.0.0",
+ "sebastian/comparator": "^5.0.3",
+ "sebastian/diff": "^5.1.1",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/exporter": "^5.1.2",
+ "sebastian/global-state": "^6.0.2",
+ "sebastian/object-enumerator": "^5.0.0",
+ "sebastian/recursion-context": "^5.0.0",
+ "sebastian/type": "^4.0.0",
+ "sebastian/version": "^4.0.1"
+ },
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "10.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.45"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-06T16:08:12+00:00"
+ },
+ {
+ "name": "react/promise",
+ "version": "v3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/promise.git",
+ "reference": "8a164643313c71354582dc850b42b33fa12a4b63"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63",
+ "reference": "8a164643313c71354582dc850b42b33fa12a4b63",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "1.10.39 || 1.4.10",
+ "phpunit/phpunit": "^9.6 || ^7.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com",
+ "homepage": "https://sorgalla.com/"
+ },
+ {
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering",
+ "homepage": "https://clue.engineering/"
+ },
+ {
+ "name": "Cees-Jan Kiewiet",
+ "email": "reactphp@ceesjankiewiet.nl",
+ "homepage": "https://wyrihaximus.net/"
+ },
+ {
+ "name": "Chris Boden",
+ "email": "cboden@gmail.com",
+ "homepage": "https://cboden.dev/"
+ }
+ ],
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "keywords": [
+ "promise",
+ "promises"
+ ],
+ "support": {
+ "issues": "https://github.com/reactphp/promise/issues",
+ "source": "https://github.com/reactphp/promise/tree/v3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/reactphp",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2024-05-24T10:39:05+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:12:49+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503",
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:58:43+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:59:15+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "5.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e",
+ "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/diff": "^5.0",
+ "sebastian/exporter": "^5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-18T14:56:07+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-21T08:37:17+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "5.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0",
+ "symfony/process": "^6.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:15:17+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "6.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984",
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-23T08:47:14+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "5.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "955288482d97c19a372d3f31006ab3f37da47adf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf",
+ "reference": "955288482d97c19a372d3f31006ab3f37da47adf",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/recursion-context": "^5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:17:12+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "6.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:19:19+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-21T08:38:20+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:08:32+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957",
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:06:18+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "05909fb5bc7df4c52992396d0116aed689f93712"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712",
+ "reference": "05909fb5bc7df4c52992396d0116aed689f93712",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:05:40+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "source": "https://github.com/sebastianbergmann/type/tree/4.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:10:45+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "source": "https://github.com/sebastianbergmann/version/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-07T11:34:05+00:00"
+ },
+ {
+ "name": "seld/jsonlint",
+ "version": "1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/jsonlint.git",
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2",
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
+ },
+ "bin": [
+ "bin/jsonlint"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Seld\\JsonLint\\": "src/Seld/JsonLint/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "JSON Linter",
+ "keywords": [
+ "json",
+ "linter",
+ "parser",
+ "validator"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/jsonlint/issues",
+ "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-11T14:55:45+00:00"
+ },
+ {
+ "name": "seld/phar-utils",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/phar-utils.git",
+ "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
+ "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Seld\\PharUtils\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be"
+ }
+ ],
+ "description": "PHAR file format utilities, for when PHP phars you up",
+ "keywords": [
+ "phar"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/phar-utils/issues",
+ "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1"
+ },
+ "time": "2022-08-31T10:31:18+00:00"
+ },
+ {
+ "name": "seld/signal-handler",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/signal-handler.git",
+ "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98",
+ "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1",
+ "phpstan/phpstan-deprecation-rules": "^1.0",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-strict-rules": "^1.3",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23",
+ "psr/log": "^1 || ^2 || ^3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Seld\\Signal\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development",
+ "keywords": [
+ "posix",
+ "sigint",
+ "signal",
+ "sigterm",
+ "unix"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/signal-handler/issues",
+ "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2"
+ },
+ "time": "2023-09-03T09:24:00+00:00"
+ },
+ {
+ "name": "slevomat/coding-standard",
+ "version": "8.15.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/slevomat/coding-standard.git",
+ "reference": "7d1d957421618a3803b593ec31ace470177d7817"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817",
+ "reference": "7d1d957421618a3803b593ec31ace470177d7817",
+ "shasum": ""
+ },
+ "require": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpdoc-parser": "^1.23.1",
+ "squizlabs/php_codesniffer": "^3.9.0"
+ },
+ "require-dev": {
+ "phing/phing": "2.17.4",
+ "php-parallel-lint/php-parallel-lint": "1.3.2",
+ "phpstan/phpstan": "1.10.60",
+ "phpstan/phpstan-deprecation-rules": "1.1.4",
+ "phpstan/phpstan-phpunit": "1.3.16",
+ "phpstan/phpstan-strict-rules": "1.5.2",
+ "phpunit/phpunit": "8.5.21|9.6.8|10.5.11"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "8.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "SlevomatCodingStandard\\": "SlevomatCodingStandard/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
+ "keywords": [
+ "dev",
+ "phpcs"
+ ],
+ "support": {
+ "issues": "https://github.com/slevomat/coding-standard/issues",
+ "source": "https://github.com/slevomat/coding-standard/tree/8.15.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/kukulich",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-03-09T15:20:58+00:00"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "3.11.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10",
+ "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ },
+ "bin": [
+ "bin/phpcbf",
+ "bin/phpcs"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "keywords": [
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-01-23T17:04:15+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v7.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "87a71856f2f56e4100373e92529eed3171695cfb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb",
+ "reference": "87a71856f2f56e4100373e92529eed3171695cfb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/finder/tree/v7.2.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-12-30T19:00:17+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php73",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
+ "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php81",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php81.git",
+ "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
+ "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php81\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v7.2.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
+ "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v7.2.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-05T08:33:46+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:36:25+00:00"
+ },
+ {
+ "name": "twig/markdown-extra",
+ "version": "v3.20.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/markdown-extra.git",
+ "reference": "f4616e1dd375209dacf6026f846e6b537d036ce4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/markdown-extra/zipball/f4616e1dd375209dacf6026f846e6b537d036ce4",
+ "reference": "f4616e1dd375209dacf6026f846e6b537d036ce4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "twig/twig": "^3.13|^4.0"
+ },
+ "require-dev": {
+ "erusev/parsedown": "dev-master as 1.x-dev",
+ "league/commonmark": "^1.0|^2.0",
+ "league/html-to-markdown": "^4.8|^5.0",
+ "michelf/php-markdown": "^1.8|^2.0",
+ "symfony/phpunit-bridge": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Twig\\Extra\\Markdown\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ }
+ ],
+ "description": "A Twig extension for Markdown",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "html",
+ "markdown",
+ "twig"
+ ],
+ "support": {
+ "source": "https://github.com/twigphp/markdown-extra/tree/v3.20.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-31T20:45:36+00:00"
+ },
+ {
+ "name": "twig/twig",
+ "version": "v3.20.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/Twig.git",
+ "reference": "3468920399451a384bef53cf7996965f7cd40183"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183",
+ "reference": "3468920399451a384bef53cf7996965f7cd40183",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.0",
+ "psr/container": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Resources/core.php",
+ "src/Resources/debug.php",
+ "src/Resources/escaper.php",
+ "src/Resources/string_loader.php"
+ ],
+ "psr-4": {
+ "Twig\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Twig Team",
+ "role": "Contributors"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com",
+ "role": "Project Founder"
+ }
+ ],
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "templating"
+ ],
+ "support": {
+ "issues": "https://github.com/twigphp/Twig/issues",
+ "source": "https://github.com/twigphp/Twig/tree/v3.20.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-13T08:34:43+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {},
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=8.1"
+ },
+ "platform-dev": {},
+ "plugin-api-version": "2.6.0"
+}
diff --git a/idrocap_wa/config/.env.example b/idrocap_wa/config/.env.example
new file mode 100644
index 0000000..e90937b
--- /dev/null
+++ b/idrocap_wa/config/.env.example
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+# Used as a default to seed config/.env which
+# enables you to use environment variables to configure
+# the aspects of your application that vary by
+# environment.
+#
+# Having this file in production is considered a **SECURITY RISK** and also decreases
+# the bootstrap performance of your application.
+#
+# To use this file, first copy it into `config/.env`. Also ensure the related
+# code block for loading this file is uncommented in `config/bootstrap.php`
+#
+# In development .env files are parsed by PHP
+# and set into the environment. This provides a simpler
+# development workflow over standard environment variables.
+export APP_NAME="__APP_NAME__"
+export DEBUG="true"
+export APP_ENCODING="UTF-8"
+export APP_DEFAULT_LOCALE="en_US"
+export APP_DEFAULT_TIMEZONE="UTC"
+export SECURITY_SALT="__SALT__"
+
+# Uncomment these to define cache configuration via environment variables.
+#export CACHE_DURATION="+2 minutes"
+#export CACHE_DEFAULT_URL="file:///path/to/tmp/cache/?prefix=${APP_NAME}_default_&duration=${CACHE_DURATION}"
+#export CACHE_CAKECORE_URL="file:///path/to/tmp/cache/persistent?prefix=${APP_NAME}_cake_core_&serialize=true&duration=${CACHE_DURATION}"
+#export CACHE_CAKEMODEL_URL="file:///path/to/tmp/cache/models?prefix=${APP_NAME}_cake_model_&serialize=true&duration=${CACHE_DURATION}"
+
+# Uncomment these to define email transport configuration via environment variables.
+#export EMAIL_TRANSPORT_DEFAULT_URL=""
+
+# Uncomment these to define database configuration via environment variables.
+#export DATABASE_URL="mysql://my_app:secret@localhost/${APP_NAME}?encoding=utf8&timezone=UTC&cacheMetadata=true"eIdentifiers=false&persistent=false"
+#export DATABASE_TEST_URL="mysql://my_app:secret@localhost/test_${APP_NAME}?encoding=utf8&timezone=UTC&cacheMetadata=true"eIdentifiers=false&persistent=false"
+
+# Uncomment these to define logging configuration via environment variables.
+#export LOG_DEBUG_URL="file:///path/to/logs/?levels[]=notice&levels[]=info&levels[]=debug&file=debug"
+#export LOG_ERROR_URL="file:///path/to/logs/?levels[]=warning&levels[]=error&levels[]=critical&levels[]=alert&levels[]=emergency&file=error"
diff --git a/idrocap_wa/config/app.php b/idrocap_wa/config/app.php
new file mode 100644
index 0000000..f8f6a0b
--- /dev/null
+++ b/idrocap_wa/config/app.php
@@ -0,0 +1,436 @@
+ filter_var(env('DEBUG', false), FILTER_VALIDATE_BOOLEAN),
+
+ /*
+ * Configure basic information about the application.
+ *
+ * - namespace - The namespace to find app classes under.
+ * - defaultLocale - The default locale for translation, formatting currencies and numbers, date and time.
+ * - encoding - The encoding used for HTML + database connections.
+ * - base - The base directory the app resides in. If false this
+ * will be auto detected.
+ * - dir - Name of app directory.
+ * - webroot - The webroot directory.
+ * - wwwRoot - The file path to webroot.
+ * - baseUrl - To configure CakePHP to *not* use mod_rewrite and to
+ * use CakePHP pretty URLs, remove these .htaccess
+ * files:
+ * /.htaccess
+ * /webroot/.htaccess
+ * And uncomment the baseUrl key below.
+ * - fullBaseUrl - A base URL to use for absolute links. When set to false (default)
+ * CakePHP generates required value based on `HTTP_HOST` environment variable.
+ * However, you can define it manually to optimize performance or if you
+ * are concerned about people manipulating the `Host` header.
+ * - imageBaseUrl - Web path to the public images directory under webroot.
+ * - cssBaseUrl - Web path to the public css directory under webroot.
+ * - jsBaseUrl - Web path to the public js directory under webroot.
+ * - paths - Configure paths for non class based resources. Supports the
+ * `plugins`, `templates`, `locales` subkeys, which allow the definition of
+ * paths for plugins, view templates and locale files respectively.
+ */
+ 'App' => [
+ 'namespace' => 'App',
+ 'encoding' => env('APP_ENCODING', 'UTF-8'),
+ 'defaultLocale' => env('APP_DEFAULT_LOCALE', 'it'),
+ 'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'UTC'),
+ 'defaultUserTimezone' => 'Europe/Rome',
+ 'base' => false,
+ 'dir' => 'src',
+ 'webroot' => 'webroot',
+ 'wwwRoot' => WWW_ROOT,
+ //'baseUrl' => env('SCRIPT_NAME'),
+ 'fullBaseUrl' => false,
+ 'imageBaseUrl' => 'img/',
+ 'cssBaseUrl' => 'css/',
+ 'jsBaseUrl' => 'js/',
+ 'paths' => [
+ 'plugins' => [ROOT . DS . 'plugins' . DS],
+ 'templates' => [ROOT . DS . 'templates' . DS],
+ 'locales' => [RESOURCES . 'locales' . DS],
+ ],
+ ],
+
+ /*
+ * Security and encryption configuration
+ *
+ * - salt - A random string used in security hashing methods.
+ * The salt value is also used as the encryption key.
+ * You should treat it as extremely sensitive data.
+ */
+ 'Security' => [
+ 'salt' => env('SECURITY_SALT'),
+ ],
+
+ /*
+ * Apply timestamps with the last modified time to static assets (js, css, images).
+ * Will append a querystring parameter containing the time the file was modified.
+ * This is useful for busting browser caches.
+ *
+ * Set to true to apply timestamps when debug is true. Set to 'force' to always
+ * enable timestamping regardless of debug value.
+ */
+ 'Asset' => [
+ //'timestamp' => true,
+ // 'cacheTime' => '+1 year'
+ ],
+
+ /*
+ * Configure the cache adapters.
+ */
+ 'Cache' => [
+ 'default' => [
+ 'className' => RedisEngine::class,
+ 'database' => 1,
+ 'duration' => 3600,
+ 'groups' => [],
+ 'password' => false,
+ 'persistent' => true,
+ 'port' => 6379,
+ 'prefix' => '',
+ 'probability' => 100,
+ 'host' => null,
+ 'server' => 'redis',
+ 'timeout' => 0,
+ 'unix_socket' => false,
+ ],
+
+ /*
+ * Configure the cache used for general framework caching.
+ * Translation cache files are stored with this configuration.
+ * Duration will be set to '+2 minutes' in bootstrap.php when debug = true
+ * If you set 'className' => 'Null' core cache will be disabled.
+ */
+ '_cake_translations_' => [
+ 'className' => FileEngine::class,
+ 'prefix' => 'myapp_cake_core_',
+ 'path' => CACHE . 'persistent' . DS,
+ 'serialize' => true,
+ 'duration' => '+1 years',
+ 'url' => env('CACHE_CAKECORE_URL', null),
+ ],
+
+ /*
+ * Configure the cache for model and datasource caches. This cache
+ * configuration is used to store schema descriptions, and table listings
+ * in connections.
+ * Duration will be set to '+2 minutes' in bootstrap.php when debug = true
+ */
+ '_cake_model_' => [
+ 'className' => FileEngine::class,
+ 'prefix' => 'myapp_cake_model_',
+ 'path' => CACHE . 'models' . DS,
+ 'serialize' => true,
+ 'duration' => '+1 years',
+ 'url' => env('CACHE_CAKEMODEL_URL', null),
+ ],
+ ],
+
+ /*
+ * Configure the Error and Exception handlers used by your application.
+ *
+ * By default errors are displayed using Debugger, when debug is true and logged
+ * by Cake\Log\Log when debug is false.
+ *
+ * In CLI environments exceptions will be printed to stderr with a backtrace.
+ * In web environments an HTML page will be displayed for the exception.
+ * With debug true, framework errors like Missing Controller will be displayed.
+ * When debug is false, framework errors will be coerced into generic HTTP errors.
+ *
+ * Options:
+ *
+ * - `errorLevel` - int - The level of errors you are interested in capturing.
+ * - `trace` - boolean - Whether backtraces should be included in
+ * logged errors/exceptions.
+ * - `log` - boolean - Whether you want exceptions logged.
+ * - `exceptionRenderer` - string - The class responsible for rendering uncaught exceptions.
+ * The chosen class will be used for both CLI and web environments. If you want different
+ * classes used in CLI and web environments you'll need to write that conditional logic as well.
+ * The conventional location for custom renderers is in `src/Error`. Your exception renderer needs to
+ * implement the `render()` method and return either a string or Http\Response.
+ * `errorRenderer` - string - The class responsible for rendering PHP errors. The selected
+ * class will be used for both web and CLI contexts. If you want different classes for each environment
+ * you'll need to write that conditional logic as well. Error renderers need to
+ * to implement the `Cake\Error\ErrorRendererInterface`.
+ * - `skipLog` - array - List of exceptions to skip for logging. Exceptions that
+ * extend one of the listed exceptions will also be skipped for logging.
+ * E.g.:
+ * `'skipLog' => ['Cake\Http\Exception\NotFoundException', 'Cake\Http\Exception\UnauthorizedException']`
+ * - `extraFatalErrorMemory` - int - The number of megabytes to increase the memory limit by
+ * when a fatal error is encountered. This allows
+ * breathing room to complete logging or error handling.
+ * - `ignoredDeprecationPaths` - array - A list of glob compatible file paths that deprecations
+ * should be ignored in. Use this to ignore deprecations for plugins or parts of
+ * your application that still emit deprecations.
+ */
+ 'Error' => [
+ 'errorLevel' => E_ALL,
+ 'skipLog' => [],
+ 'log' => true,
+ 'trace' => true,
+ 'ignoredDeprecationPaths' => [],
+ 'exceptionRenderer' => 'App\Error\AppExceptionRenderer',
+ ],
+
+ /*
+ * Debugger configuration
+ *
+ * Define development error values for Cake\Error\Debugger
+ *
+ * - `editor` Set the editor URL format you want to use.
+ * By default atom, emacs, macvim, phpstorm, sublime, textmate, and vscode are
+ * available. You can add additional editor link formats using
+ * `Debugger::addEditor()` during your application bootstrap.
+ * - `outputMask` A mapping of `key` to `replacement` values that
+ * `Debugger` should replace in dumped data and logs generated by `Debugger`.
+ */
+ 'Debugger' => [
+ 'editor' => 'phpstorm',
+ ],
+
+ /*
+ * Email configuration.
+ *
+ * By defining transports separately from delivery profiles you can easily
+ * re-use transport configuration across multiple profiles.
+ *
+ * You can specify multiple configurations for production, development and
+ * testing.
+ *
+ * Each transport needs a `className`. Valid options are as follows:
+ *
+ * Mail - Send using PHP mail function
+ * Smtp - Send using SMTP
+ * Debug - Do not send the email, just return the result
+ *
+ * You can add custom transports (or override existing transports) by adding the
+ * appropriate file to src/Mailer/Transport. Transports should be named
+ * 'YourTransport.php', where 'Your' is the name of the transport.
+ */
+ 'EmailTransport' => [
+ 'default' => [
+ 'className' => MailTransport::class,
+ /*
+ * The keys host, port, timeout, username, password, client and tls
+ * are used in SMTP transports
+ */
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'timeout' => 30,
+ /*
+ * It is recommended to set these options through your environment or app_local.php
+ */
+ //'username' => null,
+ //'password' => null,
+ 'client' => null,
+ 'tls' => false,
+ 'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
+ ],
+ ],
+
+ /*
+ * Email delivery profiles
+ *
+ * Delivery profiles allow you to predefine various properties about email
+ * messages from your application and give the settings a name. This saves
+ * duplication across your application and makes maintenance and development
+ * easier. Each profile accepts a number of keys. See `Cake\Mailer\Email`
+ * for more information.
+ */
+ 'Email' => [
+ 'default' => [
+ 'transport' => 'default',
+ 'from' => 'you@localhost',
+ /*
+ * Will by default be set to config value of App.encoding, if that exists otherwise to UTF-8.
+ */
+ //'charset' => 'utf-8',
+ //'headerCharset' => 'utf-8',
+ ],
+ ],
+
+ /*
+ * Connection information used by the ORM to connect
+ * to your application's datastores.
+ *
+ * ### Notes
+ * - Drivers include Mysql Postgres Sqlite Sqlserver
+ * See vendor\cakephp\cakephp\src\Database\Driver for complete list
+ * - Do not use periods in database name - it may lead to error.
+ * See https://github.com/cakephp/cakephp/issues/6471 for details.
+ * - 'encoding' is recommended to be set to full UTF-8 4-Byte support.
+ * E.g set it to 'utf8mb4' in MariaDB and MySQL and 'utf8' for any
+ * other RDBMS.
+ */
+ 'Datasources' => [
+ /*
+ * These configurations should contain permanent settings used
+ * by all environments.
+ *
+ * The values in app_local.php will override any values set here
+ * and should be used for local and per-environment configurations.
+ *
+ * Environment variable based configurations can be loaded here or
+ * in app_local.php depending on the applications needs.
+ */
+ 'default' => [
+ 'className' => Connection::class,
+ 'driver' => Mysql::class,
+ 'persistent' => false,
+ 'timezone' => 'UTC',
+
+ /*
+ * For MariaDB/MySQL the internal default changed from utf8 to utf8mb4, aka full utf-8 support, in CakePHP 3.6
+ */
+ //'encoding' => 'utf8mb4',
+
+ /*
+ * If your MySQL server is configured with `skip-character-set-client-handshake`
+ * then you MUST use the `flags` config to set your charset encoding.
+ * For e.g. `'flags' => [\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4']`
+ */
+ 'flags' => [],
+ 'cacheMetadata' => true,
+ 'log' => false,
+
+ /*
+ * Set identifier quoting to true if you are using reserved words or
+ * special characters in your table or column names. Enabling this
+ * setting will result in queries built using the Query Builder having
+ * identifiers quoted when creating SQL. It should be noted that this
+ * decreases performance because each query needs to be traversed and
+ * manipulated before being executed.
+ */
+ 'quoteIdentifiers' => true,
+
+ /*
+ * During development, if using MySQL < 5.6, uncommenting the
+ * following line could boost the speed at which schema metadata is
+ * fetched from the database. It can also be set directly with the
+ * mysql configuration directive 'innodb_stats_on_metadata = 0'
+ * which is the recommended value in production environments
+ */
+ //'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
+ ],
+
+ 'geo' => [
+ 'className' => Connection::class,
+ 'driver' => Mysql::class,
+ 'persistent' => false,
+ 'timezone' => 'UTC',
+ 'encoding' => 'utf8',
+ 'flags' => [],
+ 'cacheMetadata' => true,
+ 'log' => false,
+ 'quoteIdentifiers' => false,
+ ],
+
+ /*
+ * The test connection is used during the test suite.
+ */
+ 'test' => [
+ 'className' => Connection::class,
+ 'driver' => Mysql::class,
+ 'persistent' => false,
+ 'timezone' => 'UTC',
+ //'encoding' => 'utf8mb4',
+ 'flags' => [],
+ 'cacheMetadata' => true,
+ 'quoteIdentifiers' => false,
+ 'log' => false,
+ //'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
+ ],
+ ],
+
+ /*
+ * Configures logging options
+ */
+ 'Log' => [
+ 'debug' => [
+ 'className' => FileLog::class,
+ 'path' => LOGS,
+ 'file' => 'debug',
+ 'url' => env('LOG_DEBUG_URL', null),
+ 'scopes' => null,
+ 'levels' => ['notice', 'info', 'debug'],
+ ],
+ 'error' => [
+ 'className' => FileLog::class,
+ 'path' => LOGS,
+ 'file' => 'error',
+ 'url' => env('LOG_ERROR_URL', null),
+ 'scopes' => null,
+ 'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
+ ],
+ // To enable this dedicated query log, you need set your datasource's log flag to true
+ 'queries' => [
+ 'className' => FileLog::class,
+ 'path' => LOGS,
+ 'file' => 'queries',
+ 'url' => env('LOG_QUERIES_URL', null),
+ 'scopes' => ['cake.database.queries'],
+ ],
+ ],
+
+ /*
+ * Session configuration.
+ *
+ * Contains an array of settings to use for session configuration. The
+ * `defaults` key is used to define a default preset to use for sessions, any
+ * settings declared here will override the settings of the default config.
+ *
+ * ## Options
+ *
+ * - `cookie` - The name of the cookie to use. Defaults to value set for `session.name` php.ini config.
+ * Avoid using `.` in cookie names, as PHP will drop sessions from cookies with `.` in the name.
+ * - `cookiePath` - The url path for which session cookie is set. Maps to the
+ * `session.cookie_path` php.ini config. Defaults to base path of app.
+ * - `timeout` - The time in minutes the session should be valid for.
+ * Pass 0 to disable checking timeout.
+ * Please note that php.ini's session.gc_maxlifetime must be equal to or greater
+ * than the largest Session['timeout'] in all served websites for it to have the
+ * desired effect.
+ * - `defaults` - The default configuration set to use as a basis for your session.
+ * There are four built-in options: php, cake, cache, database.
+ * - `handler` - Can be used to enable a custom session handler. Expects an
+ * array with at least the `engine` key, being the name of the Session engine
+ * class to use for managing the session. CakePHP bundles the `CacheSession`
+ * and `DatabaseSession` engines.
+ * - `ini` - An associative array of additional 'session.*` ini values to set.
+ *
+ * The built-in `defaults` options are:
+ *
+ * - 'php' - Uses settings defined in your php.ini.
+ * - 'cake' - Saves session files in CakePHP's /tmp directory.
+ * - 'database' - Uses CakePHP's database sessions.
+ * - 'cache' - Use the Cache class to save sessions.
+ *
+ * To define a custom session handler, save it at src/Http/Session/.php.
+ * Make sure the class implements PHP's `SessionHandlerInterface` and set
+ * Session.handler to
+ *
+ * To use database sessions, load the SQL file located at config/schema/sessions.sql
+ */
+ 'Session' => [
+ 'cookie' => 'JIXEL',
+ 'defaults' => 'cache',
+ ],
+];
diff --git a/idrocap_wa/config/app_local.example.php b/idrocap_wa/config/app_local.example.php
new file mode 100644
index 0000000..8bdb855
--- /dev/null
+++ b/idrocap_wa/config/app_local.example.php
@@ -0,0 +1,94 @@
+ filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),
+
+ /*
+ * Security and encryption configuration
+ *
+ * - salt - A random string used in security hashing methods.
+ * The salt value is also used as the encryption key.
+ * You should treat it as extremely sensitive data.
+ */
+ 'Security' => [
+ 'salt' => env('SECURITY_SALT', '__SALT__'),
+ ],
+
+ /*
+ * Connection information used by the ORM to connect
+ * to your application's datastores.
+ *
+ * See app.php for more configuration options.
+ */
+ 'Datasources' => [
+ 'default' => [
+ 'host' => 'localhost',
+ /*
+ * CakePHP will use the default DB port based on the driver selected
+ * MySQL on MAMP uses port 8889, MAMP users will want to uncomment
+ * the following line and set the port accordingly
+ */
+ //'port' => 'non_standard_port_number',
+
+ 'username' => 'my_app',
+ 'password' => 'secret',
+
+ 'database' => 'my_app',
+ /*
+ * If not using the default 'public' schema with the PostgreSQL driver
+ * set it here.
+ */
+ //'schema' => 'myapp',
+
+ /*
+ * You can use a DSN string to set the entire configuration
+ */
+ 'url' => env('DATABASE_URL', null),
+ ],
+
+ /*
+ * The test connection is used during the test suite.
+ */
+ 'test' => [
+ 'host' => 'localhost',
+ //'port' => 'non_standard_port_number',
+ 'username' => 'my_app',
+ 'password' => 'secret',
+ 'database' => 'test_myapp',
+ //'schema' => 'myapp',
+ 'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tmp/tests.sqlite'),
+ ],
+ ],
+
+ /*
+ * Email configuration.
+ *
+ * Host and credential configuration in case you are using SmtpTransport
+ *
+ * See app.php for more configuration options.
+ */
+ 'EmailTransport' => [
+ 'default' => [
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'username' => null,
+ 'password' => null,
+ 'client' => null,
+ 'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
+ ],
+ ],
+];
diff --git a/idrocap_wa/config/app_local.php b/idrocap_wa/config/app_local.php
new file mode 100644
index 0000000..eb0c81e
--- /dev/null
+++ b/idrocap_wa/config/app_local.php
@@ -0,0 +1,94 @@
+ filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),
+
+ /*
+ * Security and encryption configuration
+ *
+ * - salt - A random string used in security hashing methods.
+ * The salt value is also used as the encryption key.
+ * You should treat it as extremely sensitive data.
+ */
+ 'Security' => [
+ 'salt' => env('SECURITY_SALT', '1d8f10d21d25f4efea479140b503d0c32a7aac909d93d0a48bb9e153d49a0449'),
+ ],
+
+ /*
+ * Connection information used by the ORM to connect
+ * to your application's datastores.
+ *
+ * See app.php for more configuration options.
+ */
+ 'Datasources' => [
+ 'default' => [
+ 'host' => 'localhost',
+ /*
+ * CakePHP will use the default DB port based on the driver selected
+ * MySQL on MAMP uses port 8889, MAMP users will want to uncomment
+ * the following line and set the port accordingly
+ */
+ //'port' => 'non_standard_port_number',
+
+ 'username' => 'my_app',
+ 'password' => 'secret',
+
+ 'database' => 'my_app',
+ /*
+ * If not using the default 'public' schema with the PostgreSQL driver
+ * set it here.
+ */
+ //'schema' => 'myapp',
+
+ /*
+ * You can use a DSN string to set the entire configuration
+ */
+ 'url' => env('DATABASE_URL', null),
+ ],
+
+ /*
+ * The test connection is used during the test suite.
+ */
+ 'test' => [
+ 'host' => 'localhost',
+ //'port' => 'non_standard_port_number',
+ 'username' => 'my_app',
+ 'password' => 'secret',
+ 'database' => 'test_myapp',
+ //'schema' => 'myapp',
+ 'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tmp/tests.sqlite'),
+ ],
+ ],
+
+ /*
+ * Email configuration.
+ *
+ * Host and credential configuration in case you are using SmtpTransport
+ *
+ * See app.php for more configuration options.
+ */
+ 'EmailTransport' => [
+ 'default' => [
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'username' => null,
+ 'password' => null,
+ 'client' => null,
+ 'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
+ ],
+ ],
+];
diff --git a/idrocap_wa/config/bootstrap.php b/idrocap_wa/config/bootstrap.php
new file mode 100644
index 0000000..9c0aaaa
--- /dev/null
+++ b/idrocap_wa/config/bootstrap.php
@@ -0,0 +1,231 @@
+parse()
+// ->putenv()
+// ->toEnv()
+// ->toServer();
+// }
+
+/*
+ * Read configuration file and inject configuration into various
+ * CakePHP classes.
+ *
+ * By default there is only one configuration file. It is often a good
+ * idea to create multiple configuration files, and separate the configuration
+ * that changes from configuration that does not. This makes deployment simpler.
+ */
+try {
+ Configure::config('default', new PhpConfig());
+ Configure::load('app', 'default', false);
+} catch (\Exception $e) {
+ exit($e->getMessage() . "\n");
+}
+
+/*
+ * Load an environment local configuration file to provide overrides to your configuration.
+ * Notice: For security reasons app_local.php **should not** be included in your git repo.
+ */
+if (file_exists(CONFIG . 'app_local.php')) {
+ Configure::load('app_local', 'default');
+}
+
+/*
+ * When debug = true the metadata cache should only last
+ * for a short time.
+ */
+if (Configure::read('debug')) {
+ Configure::write('Cache._cake_model_.duration', '+2 minutes');
+ Configure::write('Cache._cake_core_.duration', '+2 minutes');
+ // disable router cache during development
+ Configure::write('Cache._cake_routes_.duration', '+2 seconds');
+}
+
+/*
+ * Set the default server timezone. Using UTC makes time calculations / conversions easier.
+ * Check https://php.net/manual/en/timezones.php for list of valid timezone strings.
+ */
+date_default_timezone_set(Configure::read('App.defaultTimezone'));
+
+/*
+ * Configure the mbstring extension to use the correct encoding.
+ */
+mb_internal_encoding(Configure::read('App.encoding'));
+
+/*
+ * Set the default locale. This controls how dates, number and currency is
+ * formatted and sets the default language to use for translations.
+ */
+ini_set('intl.default_locale', Configure::read('App.defaultLocale'));
+
+/*
+ * Register application error and exception handlers.
+ */
+(new ErrorTrap(Configure::read('Error')))->register();
+(new ExceptionTrap(Configure::read('Error')))->register();
+
+/*
+ * Include the CLI bootstrap overrides.
+ */
+if (PHP_SAPI === 'cli') {
+ require CONFIG . 'bootstrap_cli.php';
+}
+
+/*
+ * Set the full base URL.
+ * This URL is used as the base of all absolute links.
+ */
+$fullBaseUrl = Configure::read('App.fullBaseUrl');
+if (!$fullBaseUrl) {
+ /*
+ * When using proxies or load balancers, SSL/TLS connections might
+ * get terminated before reaching the server. If you trust the proxy,
+ * you can enable `$trustProxy` to rely on the `X-Forwarded-Proto`
+ * header to determine whether to generate URLs using `https`.
+ *
+ * See also https://book.cakephp.org/4/en/controllers/request-response.html#trusting-proxy-headers
+ */
+ $trustProxy = false;
+
+ $s = null;
+ if (env('HTTPS') || ($trustProxy && env('HTTP_X_FORWARDED_PROTO') === 'https')) {
+ $s = 's';
+ }
+
+ $httpHost = env('HTTP_HOST');
+ if (isset($httpHost)) {
+ $fullBaseUrl = 'http' . $s . '://' . $httpHost;
+ }
+ unset($httpHost, $s);
+}
+if ($fullBaseUrl) {
+ Router::fullBaseUrl($fullBaseUrl);
+}
+unset($fullBaseUrl);
+
+Cache::setConfig(Configure::consume('Cache'));
+ConnectionManager::setConfig(Configure::consume('Datasources'));
+TransportFactory::setConfig(Configure::consume('EmailTransport'));
+Mailer::setConfig(Configure::consume('Email'));
+Log::setConfig(Configure::consume('Log'));
+Security::setSalt(Configure::consume('Security.salt'));
+
+/*
+ * Setup detectors for mobile and tablet.
+ * If you don't use these checks you can safely remove this code
+ * and the mobiledetect package from composer.json.
+ */
+ServerRequest::addDetector('mobile', function ($request) {
+ $detector = new \Detection\MobileDetect();
+
+ return $detector->isMobile();
+});
+ServerRequest::addDetector('tablet', function ($request) {
+ $detector = new \Detection\MobileDetect();
+
+ return $detector->isTablet();
+});
+
+/*
+ * You can enable default locale format parsing by adding calls
+ * to `useLocaleParser()`. This enables the automatic conversion of
+ * locale specific date formats. For details see
+ * @link https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html#parsing-localized-datetime-data
+ */
+// \Cake\Database\TypeFactory::build('time')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('date')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('datetime')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('timestamp')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('datetimefractional')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('timestampfractional')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('datetimetimezone')
+// ->useLocaleParser();
+// \Cake\Database\TypeFactory::build('timestamptimezone')
+// ->useLocaleParser();
+
+/*
+ * Custom Inflector rules, can be set to correctly pluralize or singularize
+ * table, model, controller names or whatever other string is passed to the
+ * inflection functions.
+ */
+//Inflector::rules('plural', ['/^(inflect)or$/i' => '\1ables']);
+//Inflector::rules('irregular', ['red' => 'redlings']);
+//Inflector::rules('uninflected', ['dontinflectme']);
+
+// set a custom date and time format
+// see https://book.cakephp.org/4/en/core-libraries/time.html#setting-the-default-locale-and-format-string
+// and https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax
+//\Cake\I18n\FrozenDate::setToStringFormat('dd.MM.yyyy');
+//\Cake\I18n\FrozenTime::setToStringFormat('dd.MM.yyyy HH:mm');
diff --git a/idrocap_wa/config/bootstrap_cli.php b/idrocap_wa/config/bootstrap_cli.php
new file mode 100644
index 0000000..fc0dc30
--- /dev/null
+++ b/idrocap_wa/config/bootstrap_cli.php
@@ -0,0 +1,35 @@
+ [
+ 'app-name' => '' . Configure::read('Theme.title') . ' ',
+ 'app-logo' => Configure::read('Theme.logo'),
+
+ 'small-text' => false,
+ 'dark-mode' => false,
+ 'layout-boxed' => false,
+
+ 'header' => [
+ 'fixed' => false,
+ 'border' => true,
+ 'style' => Header::STYLE_DARK,
+ 'dropdown-legacy' => false,
+ ],
+
+ 'sidebar' => [
+ 'fixed' => true,
+ 'collapsed' => false,
+ 'mini' => true,
+ 'mini-md' => false,
+ 'mini-xs' => false,
+ 'style' => Sidebar::STYLE_DARK_PRIMARY,
+
+ 'flat-style' => false,
+ 'legacy-style' => false,
+ 'compact' => false,
+ 'child-indent' => true,
+ 'child-hide-collapse' => false,
+ 'disabled-auto-expand' => false,
+ ],
+
+ 'footer' => [
+ 'fixed' => false,
+ ],
+ ],
+];
\ No newline at end of file
diff --git a/idrocap_wa/config/keys/private.key b/idrocap_wa/config/keys/private.key
new file mode 100644
index 0000000..7a309aa
--- /dev/null
+++ b/idrocap_wa/config/keys/private.key
@@ -0,0 +1,52 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEA0YVnol1T7RaJIiMDiivC1bgDyqn2b31j+t8NQXcLm7dOq8az
+Wgsn3ySGj1Was/Mlye5uCegnj9LPOvK6b6wG4NcNKEouAdjwoZ8PFsTZU2q/lGzr
+Ze4Kc/E19oVgdKRhTgDuCKq7sShC7Un+2lY0CCt2GSA133Mqoztih5Y+zvlqyKaM
+xF6eNy62L1IqNUWEMFIgkVq4Jy2XMii7qrYdE9cJbleZ1MDlTO7a0v3bhLxdC5D6
+2HPcalV3qYKiCWX/EhCz4b8JWfoW8tfV8GoEX+6JV+AohOXC9wdopCV89SJu1x+S
+p4yWkBtm1nSMifaPfXqyz9tiGFL8ziJpEW59lTgbd1KZMCcoGIHR8gq7PowDVkAQ
+IdU628DS3FPgBgPRV7r9oPuytjPzojmuu64aClgWylE6WDn2daBHUHtlY0NLA7VN
+jIMMnvnlM0OBGGN4god4LVzFZkgso36i6RJghYUiKaz7DOQEMEGx6bWQlHxnLR0/
+khv/1ERpKNWq/q0vXeoNA7L1jZ64k3U/MyWmaJPdjcoPFGYI2Vwlz//M1TZmyoV7
+YC01YJcsTbA5+ocukOZDlvsEWZKWJoi/I5vYcQfBZGrAY8pl7LFCVlnpUR+UHB3a
+Fp0+Q4OK0OhQuOmbMqz2J/t2MbWXwBsnQkP3XNnoA1t4fbraPeex25NTZVMCAwEA
+AQKCAgEAjnRkzQkleeq7nIEv8+7jDsqJkW7UBmO76aNkcOFO/DW7AKId6ZfyKQ69
+ipEKmVU1mUFKgePdmjUb/xlv12OgXZj58i3VcB4fJdRuvu1iUgwfa/xOZMRfSQt0
+xENVHJlzK0UIks36xW35azrHU44O3IsoRdcXqfC0yb0jtcpatADzMK/Ev/MRIbXZ
+2vzDg+rbALumNw32bXTa+xik2GHwDUBEwkg/aF8qyI8SKyi861fi721IkIjeEVJB
+BPiz0S4PKio/E7r+0bVvivdjF44NoWge66eWBR3u3GSmKgzvFACwWgW2gcLdz+dB
+mYgu0dLZJtiY4ShpXt510nWk+Fwmd2YHSt0U/rnoiOSEXRqh2UPZL9zgK0F81E8v
+Ay1Yij59P0tkjIz3VtYluMGV6nXoQunJyIFsUN3r3h2p6ZxeitN+CEmUN/zOvmrN
+Ziqy4Hnta03eC3ZZ3i3NIHuth63hVrh5qFEKT5Ggqvw6Swfzg1mL9biZ+4A1xICP
+8850+yBaX6n3BgRwLmFd9xjtA7GNJ1vrcOn6+uw7OOaUl+WUlnX8uqDCPE/mhMd4
+SM/O4kL/G4BFb45q4LeYkiuFk5UHatWdcOlttQkvrgSCH4PpfJDiilKn/tVU34HY
+OM7/N+j9wMpZj7dqPMra+WbzKA4I0d+rnKZsUVHbCAZZzEf0w/kCggEBAPRQKV8W
+w1Z+JlZeRtoxSSCSEgHDpun13ZiXBi17ErYhN5LTCMJ8XUmeeexVCcRMOqjvClgz
+2hrHaC66nW2pfBu2euVHqecD0likKEINsucbTa2PNZeP0sV8px1k5NASRlNilqGy
+vrWT425E7yrss2RBOcE6ro6M9QYZSLZjiYNqzk6w4j6McyFertq7/Yz9JCaAq72e
+ptCrvzoAtCFra3nwTgxlu1QVB8I/Kjg94lpTLQcS7mehDep+qYSlnFzJ5CnGF7t4
+K5WZ4VEo1u4dpbewTVDfc3W+ODTQgmYByU6mUwl4Kf4V6ovKJ9say1z0ZdbXcHRJ
+ZG8+Hdld47TwHe8CggEBANuLLtsoCvUyLs9X6+6kToSTN3FVRnkfoJLbXe9+smw/
+5QAvvh2lwlwc6xXajEEsNK8z9mVRSCrXoiqRTjTo2ioe0oxx9Gnou+/d2MB9WJm3
+hQAwMGjwifg6AD9bZre+NiEl92WmlJs3fm4zFrEMpCBCOJ7JIe7GxsdKwR/guvQt
+9k/NCQj2fOnCzCoFYtebPPDXukcn2Ad2XOkvLWzLmG4HRGuLPeqgjvxppBdtU3Xm
+NJklIndw1g+xcY8/7bbNyo8Nd/PV/ymv/sflrQyXjVs4mwwAgY9usFntO+qT4nEd
+wfPgedDlpsNDprSdjDo5xNA79yaVFUuzJCIDFXO9Ut0CggEAaA5QYKCoWAlouLZ0
+xO/i7o1oP/od+F3woNIKHorhwFLLgayCeZtQfE+ULFVX0JSLE3KkXEbRaUBvHh/7
+dz6NjpwdIdRxB+S3zWs1flSpUwdtATQSplfqdJSP9NQJJJnz/AXslDg2Q84WOtv/
+Za/lBBlHyQX+XNaqcYuJTa19X0y5TAjIg818J8VVAfK5njgfEosRGrUc5ZmQ29p6
+3hULdKcmBt+5dqlyYYhXqhapdsEgV3f3tImDDNIfz1BeFaMjm6s0ZnNbVN9yeQfE
+6ywTbfYYKA7T9V0sQUphj6LJI8dxbIISmJarDBjw+sAhx5iMW4Hs8opjzYGOYws7
+NdBjXwKCAQBc0Bh8+g633gFAEtFhUAEJtxsHRJ/IcQB3VVn+97cCYHi1fXmIGx1x
+x5/y2zPUEZYsQ3F1H8m8ovChwlAnuhERIXqteTd01rktDMKnjdY5FgaaL8UneBk7
+4XldT4y7PSSxGtXeGXBVtj4y5FJBgzCXmqdJKYq44TwD4KyIh39B33R0BCA/s8TX
+Jk0drq08rRo0T18m2cdQUE+zHQi9J81HJrdcJ7+DQ2FvgFGovcU84Jd37uUFTaSR
+ediiUMp0L8fkdjMx2FRJEWhKpeRkoGVYHTQe/M/JDWhsfAiKgP6IB6aJLWsSTyQT
+BLSjQr+XlfiId/FiVEBugktSPa+CAJXZAoIBAQDj32TA+MI5gWtWlP4u9KsyrDGD
+NJyutrAGziQSibgj5CW++fVm6TcXZ3rezxFZ/QDr8MlEJhpGoi3Ca+U0JyIcrn3z
+fgwKGJd7kVFD8jhqm85j8rMk9sqEgg88cE6yt4tC+LAwLLeyhVqea5q5vF5dV9gN
+1LtP6E30MQxWRBWhcp7FyZEzS6eYIjQwVCaVD2tDXg3hQQ/gxyPantsEdgoqCfgu
+MjBJiaw5fO+qBROzema0LDXs7m5HAZRur22c9a45d0+SmCAmudsxoKrnV6w7gdd+
+1Jp1KFef7gx9iSBm3E3rcCBBOfPfRKbvBD5bhNXxT/a/iK8wPQY4uKiwgKt+
+-----END RSA PRIVATE KEY-----
+
diff --git a/idrocap_wa/config/keys/public.key b/idrocap_wa/config/keys/public.key
new file mode 100644
index 0000000..fc7f1a9
--- /dev/null
+++ b/idrocap_wa/config/keys/public.key
@@ -0,0 +1,15 @@
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0YVnol1T7RaJIiMDiivC
+1bgDyqn2b31j+t8NQXcLm7dOq8azWgsn3ySGj1Was/Mlye5uCegnj9LPOvK6b6wG
+4NcNKEouAdjwoZ8PFsTZU2q/lGzrZe4Kc/E19oVgdKRhTgDuCKq7sShC7Un+2lY0
+CCt2GSA133Mqoztih5Y+zvlqyKaMxF6eNy62L1IqNUWEMFIgkVq4Jy2XMii7qrYd
+E9cJbleZ1MDlTO7a0v3bhLxdC5D62HPcalV3qYKiCWX/EhCz4b8JWfoW8tfV8GoE
+X+6JV+AohOXC9wdopCV89SJu1x+Sp4yWkBtm1nSMifaPfXqyz9tiGFL8ziJpEW59
+lTgbd1KZMCcoGIHR8gq7PowDVkAQIdU628DS3FPgBgPRV7r9oPuytjPzojmuu64a
+ClgWylE6WDn2daBHUHtlY0NLA7VNjIMMnvnlM0OBGGN4god4LVzFZkgso36i6RJg
+hYUiKaz7DOQEMEGx6bWQlHxnLR0/khv/1ERpKNWq/q0vXeoNA7L1jZ64k3U/MyWm
+aJPdjcoPFGYI2Vwlz//M1TZmyoV7YC01YJcsTbA5+ocukOZDlvsEWZKWJoi/I5vY
+cQfBZGrAY8pl7LFCVlnpUR+UHB3aFp0+Q4OK0OhQuOmbMqz2J/t2MbWXwBsnQkP3
+XNnoA1t4fbraPeex25NTZVMCAwEAAQ==
+-----END PUBLIC KEY-----
+
diff --git a/idrocap_wa/config/paths.php b/idrocap_wa/config/paths.php
new file mode 100644
index 0000000..fcd260d
--- /dev/null
+++ b/idrocap_wa/config/paths.php
@@ -0,0 +1,94 @@
+ [
+ 'onlyDebug' => true,
+ ],
+ 'Bake' => [
+ 'onlyCli' => true,
+ 'optional' => true,
+ ],
+ 'Migrations' => [
+ 'onlyCli' => true,
+ ],
+ 'CakeLte' => [],
+];
diff --git a/idrocap_wa/config/routes.php b/idrocap_wa/config/routes.php
new file mode 100644
index 0000000..a7f36a7
--- /dev/null
+++ b/idrocap_wa/config/routes.php
@@ -0,0 +1,357 @@
+setRouteClass(InflectedRoute::class);
+
+ $routes->prefix('Api', function (RouteBuilder $routes) {
+ $routes->setExtensions(['json', 'csv']);
+
+ $routes->resources('Attachments', [
+ 'id' => '.*',
+ ]);
+
+ $routes->resources('Notifications', [
+ 'map' => [
+ '' => [
+ 'action' => 'index',
+ 'method' => ['GET'],
+ ],
+ 'index' => [
+ 'action' => 'index',
+ 'method' => ['GET'],
+ ],
+ 'count' => [
+ 'action' => 'count',
+ 'method' => ['GET'],
+ ],
+ 'edit/{id}' => [
+ 'action' => 'edit',
+ 'method' => ['POST'],
+ ],
+ 'check' => [
+ 'action' => 'check',
+ 'method' => ['GET'],
+ ],
+ ],
+ ]);
+
+ $routes->resources('Organisations', [
+ 'connectOptions' => [
+ 'photo' => '.*',
+ 'pass' => ['id', 'photo'],
+ ],
+ 'map' => [
+ 'get_photo/{photo}' => [
+ 'action' => 'getPhoto',
+ 'method' => ['GET'],
+ ],
+ ],
+ ]);
+
+ $routes->resources('OrganisationTypes', ['inflect' => 'underscore']);
+
+ $routes->resources('Users', [
+ 'connectOptions' => [
+ 'photo' => '.*',
+ 'pass' => ['id', 'photo'],
+ ],
+ 'map' => [
+ 'login' => [
+ 'action' => 'login',
+ 'method' => ['POST', 'GET'],
+ ],
+ 'get_photo/{photo}' => [
+ 'action' => 'getPhoto',
+ 'method' => ['GET'],
+ ],
+ ],
+ ]);
+
+ $routes->resources('Subscriptions', [
+ 'map' => [
+ 'subscribe' => [
+ 'action' => 'subscribe',
+ 'method' => ['POST'],
+ ],
+ 'unsubscribe' => [
+ 'action' => 'unsubscribe',
+ 'method' => ['DELETE'],
+ ],
+ ],
+ ]);
+
+ $routes->resources('WaterDrawingPaperworks', [
+ 'inflect' => 'underscore',
+ 'map' => [
+ '' => [
+ 'action' => 'index',
+ 'method' => ['GET'],
+ ],
+ 'index' => [
+ 'action' => 'index',
+ 'method' => ['GET'],
+ ],
+ 'view/{id}' => [
+ 'action' => 'view',
+ 'method' => ['GET'],
+ ],
+ ],
+ ]);
+
+ $routes->resources('WaterDrawingDerivations', [
+ 'inflect' => 'underscore',
+ 'map' => [
+ 'update_data' => [
+ 'action' => 'update_data',
+ 'method' => ['POST'],
+ ],
+ 'update_location' => [
+ 'action' => 'update_location',
+ 'method' => ['POST'],
+ ],
+ 'view/{id}' => [
+ 'action' => 'view',
+ 'method' => ['GET'],
+ ],
+ ],
+ ]);
+
+ $routes->resources('WaterDrawingMeasurements', [
+ 'inflect' => 'underscore',
+ 'map' => [
+ 'add' => [
+ 'action' => 'add',
+ 'method' => ['POST'],
+ ],
+ 'last_index/{id}' => [
+ 'action' => 'last_index',
+ 'method' => ['GET'],
+ ],
+ ],
+ ]);
+ });
+
+ $routes->scope('/', function (RouteBuilder $builder) {
+ $builder->setExtensions(['json', 'csv']);
+
+ $builder->connect('/', ['controller' => 'Dashboard', 'action' => 'index']);
+
+ $builder->connect('/attachments/view/{id}', ['controller' => 'Attachments', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/attachments/markAsRelevant/{id}', ['controller' => 'Attachments', 'action' => 'markAsRelevant'])->setPass(['id']);
+ $builder->connect('/attachments/markAsDeleted/{id}', ['controller' => 'Attachments', 'action' => 'markAsDeleted'])->setPass(['id']);
+
+ $builder->connect('/capabilities', ['controller' => 'Capabilities', 'action' => 'index']);
+ $builder->connect('/capabilities/index', ['controller' => 'Capabilities', 'action' => 'index']);
+ $builder->connect('/capabilities/hide/{id}', ['controller' => 'Capabilities', 'action' => 'hide'])->setPass(['id']);
+ $builder->connect('/capabilities/show/{id}', ['controller' => 'Capabilities', 'action' => 'show'])->setPass(['id']);
+ $builder->connect('/capabilities/delete/{id}', ['controller' => 'Capabilities', 'action' => 'delete'])->setPass(['id']);
+ $builder->connect('/capabilities/restore/{id}', ['controller' => 'Capabilities', 'action' => 'restore'])->setPass(['id']);
+
+ $builder->connect('/controllable_objects/getAttachments/{id}', ['controller' => 'ControllableObjects', 'action' => 'getAttachments'])->setPass(['id']);
+
+ $builder->connect('/deliveries/{id}', ['controller' => 'Deliveries', 'action' => 'index'])->setPass(['id']);
+ $builder->connect('/deliveries/index/{id}', ['controller' => 'Deliveries', 'action' => 'index'])->setPass(['id']);
+ $builder->connect('/deliveries/delete/{id}', ['controller' => 'Deliveries', 'action' => 'delete'])->setPass(['id']);
+
+ $builder->connect('/emails/add/{id}', ['controller' => 'Emails', 'action' => 'add'])->setPass(['id']);
+ $builder->connect('/emails/edit/{id}', ['controller' => 'Emails', 'action' => 'edit'])->setPass(['id']);
+
+ $builder->connect('/faxes/add/{id}', ['controller' => 'Faxes', 'action' => 'add'])->setPass(['id']);
+ $builder->connect('/faxes/edit/{id}', ['controller' => 'Faxes', 'action' => 'edit'])->setPass(['id']);
+
+ $builder->connect('/filters/getFilterInput/{id}', ['controller' => 'Filters', 'action' => 'getFilterInput'])->setPass(['id']);
+
+ $builder->connect('/groups', ['controller' => 'Groups', 'action' => 'index']);
+ $builder->connect('/groups/index', ['controller' => 'Groups', 'action' => 'index']);
+ $builder->connect('/groups/add', ['controller' => 'Groups', 'action' => 'add']);
+ $builder->connect('/groups/view/{id}', ['controller' => 'Groups', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/groups/edit/{id}', ['controller' => 'Groups', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/groups/delete/{id}', ['controller' => 'Groups', 'action' => 'delete'])->setPass(['id']);
+ $builder->connect('/groups/handleCapabilities/{id}', ['controller' => 'Groups', 'action' => 'handleCapabilities'])->setPass(['id']);
+
+ $builder->connect('/maps', ['controller' => 'Maps', 'action' => 'index']);
+ $builder->connect('/maps/index', ['controller' => 'Maps', 'action' => 'index']);
+ $builder->connect('/maps/getWfs', ['controller' => 'Maps', 'action' => 'getWfs']);
+ $builder->connect('/maps/geocode', ['controller' => 'Maps', 'action' => 'geocode']);
+
+ $builder->connect('/mobile_phones/add/{id}', ['controller' => 'MobilePhones', 'action' => 'add'])->setPass(['id']);
+ $builder->connect('/mobile_phones/edit/{id}', ['controller' => 'MobilePhones', 'action' => 'edit'])->setPass(['id']);
+
+ $builder->connect('/notifications', ['controller' => 'Notifications', 'action' => 'index']);
+ $builder->connect('/notifications/index', ['controller' => 'Notifications', 'action' => 'index']);
+ $builder->connect('/notifications/readAll', ['controller' => 'Notifications', 'action' => 'readAll']);
+ $builder->connect('/notifications/testAll', ['controller' => 'Notifications', 'action' => 'testAll']);
+ $builder->connect('/notifications/view/{id}', ['controller' => 'Notifications', 'action' => 'view'])->setPass(['id']);
+
+ $builder->connect('/organisations', ['controller' => 'Organisations', 'action' => 'index']);
+ $builder->connect('/organisations/index', ['controller' => 'Organisations', 'action' => 'index']);
+ $builder->connect('/organisations/add', ['controller' => 'Organisations', 'action' => 'add']);
+ $builder->connect('/organisations/view/{id}', ['controller' => 'Organisations', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/organisations/edit/{id}', ['controller' => 'Organisations', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/organisations/delete/{id}', ['controller' => 'Organisations', 'action' => 'delete'])->setPass(['id']);
+
+ $builder->connect('/phones/add/{id}', ['controller' => 'Phones', 'action' => 'add'])->setPass(['id']);
+ $builder->connect('/phones/edit/{id}', ['controller' => 'Phones', 'action' => 'edit'])->setPass(['id']);
+
+ $builder->connect('/telegram_chats/add/{id}', ['controller' => 'TelegramChats', 'action' => 'add'])->setPass(['id']);
+ $builder->connect('/telegram_chats/edit/{id}', ['controller' => 'TelegramChats', 'action' => 'edit'])->setPass(['id']);
+
+ $builder->connect('/users', ['controller' => 'Users', 'action' => 'index']);
+ $builder->connect('/users/login_oidc', ['controller' => 'Users', 'action' => 'login_oidc']);
+ $builder->connect('/users/login_oidc_authenticated', ['controller' => 'Users', 'action' => 'login_oidc_authenticated']);
+ $builder->connect('/users/index', ['controller' => 'Users', 'action' => 'index']);
+ $builder->connect('/users/add', ['controller' => 'Users', 'action' => 'add']);
+ $builder->connect('/users/view/{id}', ['controller' => 'Users', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/users/edit/{id}', ['controller' => 'Users', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/users/delete/{id}', ['controller' => 'Users', 'action' => 'delete'])->setPass(['id']);
+ $builder->connect('/users/login', ['controller' => 'Users', 'action' => 'login']);
+ $builder->connect('/users/logout', ['controller' => 'Users', 'action' => 'logout']);
+ $builder->connect('/users/passwordRecovery', ['controller' => 'Users', 'action' => 'passwordRecovery']);
+ $builder->connect('/users/chooseNewPassword/{id}', ['controller' => 'Users', 'action' => 'chooseNewPassword'])->setPass(['id']);
+ $builder->connect('/users/oneTimePassword/{otp}', ['controller' => 'Users', 'action' => 'oneTimePassword'])->setPass(['otp']);
+ $builder->connect('/users/getPhoto/{id}', ['controller' => 'Users', 'action' => 'getPhoto'])->setPass(['id']);
+ $builder->connect('/users/deleteUserPhoto/{id}', ['controller' => 'Users', 'action' => 'deleteUserPhoto'])->setPass(['id']);
+ $builder->connect('/users/add-citizen', ['controller' => 'Users', 'action' => 'add_citizen']);
+ $builder->connect('/users/verify-citizen/{token}', ['controller' => 'Users', 'action' => 'verify_citizen'])->setPass(['token']);
+
+ $builder->connect('/water_drawing_paperworks', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index']);
+ $builder->connect('/water_drawing_paperworks/index', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index']);
+ $builder->connect('/water_drawing_paperworks/index_snapshots/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_snapshots'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_paperworks/index_snapshots_all', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_snapshots_all']);
+ $builder->connect('/water_drawing_paperworks/validate_index', ['controller' => 'WaterDrawingPaperworks', 'action' => 'validate_index']);
+ $builder->connect('/water_drawing_paperworks/add_scan', ['controller' => 'WaterDrawingPaperworks', 'action' => 'add_scan']);
+ $builder->connect('/water_drawing_paperworks/add', ['controller' => 'WaterDrawingPaperworks', 'action' => 'add']);
+ $builder->connect('/water_drawing_paperworks/view_scan/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'view_scan'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/view/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/view_scan_snapshot/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'view_scan_snapshot'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/view_snapshot/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'view_snapshot'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/edit_scan/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'edit_scan'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/edit/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/delete/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'delete'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/validate_scan/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'validate_scan'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/validate/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'validate'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/send_to_drar/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'send_to_drar'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/send_to_gc/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'send_to_gc'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/submit_antimafia_request/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'submit_antimafia_request'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/antimafia_request_to_anac/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'antimafia_request_to_anac'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/request_self_certification/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'request_self_certification'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/applicants_water_drawing_paperworks_item_block/{id}/{status_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'applicants_water_drawing_paperworks_item_block'])->setPass(['id', 'status_id']);
+ $builder->connect('/water_drawing_paperworks/applicants_water_drawing_paperworks_item_block/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'applicants_water_drawing_paperworks_item_block'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/intended_uses_water_drawing_paperworks_item_block/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'intended_uses_water_drawing_paperworks_item_block'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/upload_attachment/{id}/{tag_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'upload_attachment'])->setPass(['id', 'tag_id']);
+ $builder->connect('/water_drawing_paperworks/upload_attachment_scan/{id}/{tag_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'upload_attachment_scan'])->setPass(['id', 'tag_id']);
+ $builder->connect('/water_drawing_paperworks/upload_antimafia_attachment/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'upload_antimafia_attachment'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/assign/{id}/{organisation_type_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'assign'])->setPass(['id', 'organisation_type_id']);
+ $builder->connect('/water_drawing_paperworks/citizen_submission_index', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index']);
+ $builder->connect('/water_drawing_paperworks/citizen_documentation_index/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_documentation_index'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/citizen_documentation_requested/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_documentation_requested'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/citizen_upload_attachment/{id}/{tag_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_upload_attachment'])->setPass(['id', 'tag_id']);
+ $builder->connect('/water_drawing_paperworks/citizen_submit_paperwork/{applicant_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submit_paperwork'])->setPass(['applicant_id']);
+ $builder->connect('/water_drawing_paperworks/citizen_request_paperwork', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_request_paperwork']);
+ $builder->connect('/water_drawing_paperworks/citizen_send_to_validation/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_send_to_validation'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperworks/delete_attachment/{id}/{attachment_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'delete_attachment'])->setPass(['id', 'attachment_id']);
+ $builder->connect('/water_drawing_paperworks/send_to_validation/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'send_to_validation'])->setPass(['id']);
+
+ $builder->connect('/applicants/search_applicants', ['controller' => 'Applicants', 'action' => 'search_applicants']);
+ $builder->connect('/applicants/get_applicant/{id}', ['controller' => 'Applicants', 'action' => 'get_applicant'])->setPass(['id']);
+ $builder->connect('/applicants/edit/{id}', ['controller' => 'Applicants', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/applicants/edit/{id}/{water_id}', ['controller' => 'Applicants', 'action' => 'edit'])->setPass(['id','water_id']);
+ $builder->connect('/applicants/view/{id}/', ['controller' => 'Applicants', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/applicants/citizen_add/', ['controller' => 'Applicants', 'action' => 'citizen_add']);
+ $builder->connect('/applicants/citizen_edit/{id}', ['controller' => 'Applicants', 'action' => 'citizen_edit'])->setPass(['id']);
+ $builder->connect('/applicants/citizen_view', ['controller' => 'Applicants', 'action' => 'citizen_view']);
+
+ $builder->connect('/water_drawing_measurements/add/{water_drawing_meter_id}', ['controller' => 'WaterDrawingMeasurements', 'action' => 'add'])->setPass(['water_drawing_meter_id']);
+ $builder->connect('/water_drawing_measurements/index/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingMeasurements', 'action' => 'index'])->setPass(['water_drawing_paperwork_id']);
+
+ $builder->connect('/water_drawing_meters/add/{water_drawing_derivation_id}', ['controller' => 'WaterDrawingMeters', 'action' => 'add'])->setPass(['water_drawing_derivation_id']);
+ $builder->connect('/water_drawing_meters/edit/{water_drawing_meter_id}', ['controller' => 'WaterDrawingMeters', 'action' => 'edit'])->setPass(['water_drawing_meter_id']);
+ $builder->connect('/water_drawing_meters/view/{water_drawing_meter_id}', ['controller' => 'WaterDrawingMeters', 'action' => 'view'])->setPass(['water_drawing_meter_id']);
+ $builder->connect('/water_drawing_meters/dismiss/{water_drawing_meter_id}', ['controller' => 'WaterDrawingMeters', 'action' => 'dismiss'])->setPass(['water_drawing_meter_id']);
+
+ $builder->connect('/water_drawing_payments/index_all', ['controller' => 'WaterDrawingPayments', 'action' => 'index_all']);
+ $builder->connect('/water_drawing_payments/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingPayments', 'action' => 'index'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_payments/index/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingPayments', 'action' => 'index'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_payments/add/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingPayments', 'action' => 'add'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_payments/edit/{id}', ['controller' => 'WaterDrawingPayments', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/water_drawing_payments/view/{id}', ['controller' => 'WaterDrawingPayments', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/water_drawing_payments/delete/{id}', ['controller' => 'WaterDrawingPayments', 'action' => 'delete'])->setPass(['id']);
+
+ $builder->connect('/water_drawing_derivations/add/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingDerivations', 'action' => 'add'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_derivations/view/{water_drawing_derivation_id}', ['controller' => 'WaterDrawingDerivations', 'action' => 'view'])->setPass(['water_drawing_derivation_id']);
+ $builder->connect('/water_drawing_derivations/edit/{water_drawing_derivation_id}', ['controller' => 'WaterDrawingDerivations', 'action' => 'edit'])->setPass(['water_drawing_derivation_id']);
+ $builder->connect('/water_drawing_derivations/delete/{water_drawing_derivation_id}', ['controller' => 'WaterDrawingDerivations', 'action' => 'delete'])->setPass(['water_drawing_derivation_id']);
+
+ $builder->connect('/water_drawing_return_points/add/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingReturnPoints', 'action' => 'add'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_return_points/view/{id}', ['controller' => 'WaterDrawingReturnPoints', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/water_drawing_return_points/edit/{id}', ['controller' => 'WaterDrawingReturnPoints', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/water_drawing_return_points/delete/{id}', ['controller' => 'WaterDrawingReturnPoints', 'action' => 'delete'])->setPass(['id']);
+
+ $builder->connect('/water_drawing_articles/', ['controller' => 'WaterDrawingArticles', 'action' => 'index']);
+ $builder->connect('/water_drawing_articles/add', ['controller' => 'WaterDrawingArticles', 'action' => 'add']);
+ $builder->connect('/water_drawing_articles/edit/{id}', ['controller' => 'WaterDrawingArticles', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/water_drawing_articles/view/{id}', ['controller' => 'WaterDrawingArticles', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/water_drawing_articles/delete/{id}', ['controller' => 'WaterDrawingArticles', 'action' => 'delete'])->setPass(['id']);
+ $builder->connect('/water_drawing_articles/change_status/{id}', ['controller' => 'WaterDrawingArticles', 'action' => 'change_status'])->setPass(['id']);
+
+ $builder->connect('/water_drawing_fees/index/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingFees', 'action' => 'index'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_fees/add/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingFees', 'action' => 'add'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_fees/view/{id}', ['controller' => 'WaterDrawingFees', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/water_drawing_fees/edit/{id}', ['controller' => 'WaterDrawingFees', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/water_drawing_fees/delete/{id}', ['controller' => 'WaterDrawingFees', 'action' => 'delete'])->setPass(['id']);
+
+ $builder->connect('/water_drawing_paperwork_pecs/index/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'index'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_paperwork_pecs/add/{water_drawing_paperwork_id}', ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'add'])->setPass(['water_drawing_paperwork_id']);
+ $builder->connect('/water_drawing_paperwork_pecs/edit/{id}', ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'edit'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperwork_pecs/view/{id}', ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/water_drawing_paperwork_pecs/delete/{id}', ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'delete'])->setPass(['id']);
+
+ $builder->connect('/ai_services/autocomplete', ['controller' => 'AiServices', 'action' => 'autocomplete']);
+ $builder->connect('/pecs/add/{id}', ['controller' => 'Pecs', 'action' => 'add'])->setPass(['id']);
+ $builder->connect('/pecs/edit/{id}', ['controller' => 'Pecs', 'action' => 'edit'])->setPass(['id']);
+
+ $builder->connect('/privacy/edit/', ['controller' => 'Privacy', 'action' => 'edit']);
+ $builder->connect('/privacy/view', ['controller' => 'Privacy', 'action' => 'view']);
+ $builder->connect('/privacy/view_public', ['controller' => 'Privacy', 'action' => 'view_public']);
+ $builder->connect('/privacy/accept_privacy', ['controller' => 'Privacy', 'action' => 'accept_privacy']);
+
+ $builder->connect('/districts/search_districts', ['controller' => 'Districts', 'action' => 'search_districts']);
+ $builder->connect('/water_drawing_paperworks/citizen_upload_payment_receipt/{id}/{tag_id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_upload_payment_receipt'])->setPass(['id', 'tag_id']);
+ $builder->connect('/water_drawing_paperworks/index_csv', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_csv']);
+ $builder->connect('/water_drawing_paperworks/index_snapshots_all_csv', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_snapshots_all_csv']);
+ $builder->connect('/water_drawing_paperworks/index_snapshots_csv/{id}', ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_snapshots_csv'])->setPass(['id']);
+
+ $builder->connect('/tags', ['controller' => 'Tags', 'action' => 'index']);
+ $builder->connect('/tags/index', ['controller' => 'Tags', 'action' => 'index']);
+ $builder->connect('/tags/add', ['controller' => 'Tags', 'action' => 'add']);
+ $builder->connect('/tags/view', ['controller' => 'Tags', 'action' => 'view']);
+ $builder->connect('/tags/view/{id}', ['controller' => 'Tags', 'action' => 'view'])->setPass(['id']);
+ $builder->connect('/tags/edit', ['controller' => 'Tags', 'action' => 'edit']);
+ $builder->connect('/tags/edit/{id}', ['controller' => 'Tags', 'action' => 'edit'])->setPass(['id']);
+
+ });
+};
diff --git a/idrocap_wa/config/schema/i18n.sql b/idrocap_wa/config/schema/i18n.sql
new file mode 100644
index 0000000..e59d1e6
--- /dev/null
+++ b/idrocap_wa/config/schema/i18n.sql
@@ -0,0 +1,18 @@
+# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+#
+# Licensed under The MIT License
+# For full copyright and license information, please see the LICENSE.txt
+# Redistributions of files must retain the above copyright notice.
+# MIT License (https://opensource.org/licenses/mit-license.php)
+
+CREATE TABLE i18n (
+ id int NOT NULL auto_increment,
+ locale varchar(6) NOT NULL,
+ model varchar(255) NOT NULL,
+ foreign_key int(10) NOT NULL,
+ field varchar(255) NOT NULL,
+ content text,
+ PRIMARY KEY (id),
+ UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
+ INDEX I18N_FIELD(model, foreign_key, field)
+);
diff --git a/idrocap_wa/config/schema/sessions.sql b/idrocap_wa/config/schema/sessions.sql
new file mode 100644
index 0000000..1aa0a0f
--- /dev/null
+++ b/idrocap_wa/config/schema/sessions.sql
@@ -0,0 +1,15 @@
+# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+#
+# Licensed under The MIT License
+# For full copyright and license information, please see the LICENSE.txt
+# Redistributions of files must retain the above copyright notice.
+# MIT License (https://opensource.org/licenses/mit-license.php)
+
+CREATE TABLE `sessions` (
+ `id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
+ `created` datetime DEFAULT CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
+ `modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
+ `data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob
+ `expires` int(10) unsigned DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/idrocap_wa/dockerfiles/cake b/idrocap_wa/dockerfiles/cake
new file mode 100755
index 0000000..bffbd99
--- /dev/null
+++ b/idrocap_wa/dockerfiles/cake
@@ -0,0 +1,152 @@
+#!/usr/bin/env sh
+
+if [ -f /run/secrets/sentry_dsn ]; then
+ export SENTRY_DSN=$(cat /run/secrets/sentry_dsn)
+else
+ echo "Secret file 'sentry_dsn' not found!" >&2
+fi
+if [ -f /run/secrets/oidc_client_id ]; then
+ export OIDC_CLIENT_ID=$(cat /run/secrets/oidc_client_id)
+else
+ echo "Secret file 'oidc_client_id' not found!" >&2
+fi
+if [ -f /run/secrets/rabbitmq_username ]; then
+ export RABBITMQ_USERNAME=$(cat /run/secrets/rabbitmq_username)
+else
+ echo "Secret file 'rabbitmq_username' not found!" >&2
+fi
+if [ -f /run/secrets/rabbitmq_password ]; then
+ export RABBITMQ_PASSWORD=$(cat /run/secrets/rabbitmq_password)
+else
+ echo "Secret file 'rabbitmq_password' not found!" >&2
+fi
+if [ -f /run/secrets/geoserver_username ]; then
+ export GEOSERVER_USERNAME=$(cat /run/secrets/geoserver_username)
+else
+ echo "Secret file 'geoserver_username' not found!" >&2
+fi
+if [ -f /run/secrets/geoserver_password ]; then
+ export GEOSERVER_PASSWORD=$(cat /run/secrets/geoserver_password)
+else
+ echo "Secret file 'geoserver_password' not found!" >&2
+fi
+if [ -f /run/secrets/minio_access_key ]; then
+ export MINIO_ACCESS_KEY=$(cat /run/secrets/minio_access_key)
+else
+ echo "Secret file 'minio_access_key' not found!" >&2
+fi
+if [ -f /run/secrets/minio_secret_key ]; then
+ export MINIO_SECRET_KEY=$(cat /run/secrets/minio_secret_key)
+else
+ echo "Secret file 'minio_secret_key' not found!" >&2
+fi
+if [ -f /run/secrets/telegram_bot_token ]; then
+ export TELEGRAM_BOT_TOKEN=$(cat /run/secrets/telegram_bot_token)
+else
+ echo "Secret file 'telegram_bot_token' not found!" >&2
+fi
+if [ -f /run/secrets/security_jwuc ]; then
+ export SECURITY_JWUC=$(cat /run/secrets/security_jwuc)
+else
+ echo "Secret file 'security_jwuc' not found!" >&2
+fi
+if [ -f /run/secrets/security_jwac ]; then
+ export SECURITY_JWAC=$(cat /run/secrets/security_jwac)
+else
+ echo "Secret file 'security_jwac' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_jixel_username ]; then
+ export MYSQL_JIXEL_USERNAME=$(cat /run/secrets/mysql_jixel_username)
+else
+ echo "Secret file 'mysql_jixel_username' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_jixel_password ]; then
+ export MYSQL_JIXEL_PASSWORD=$(cat /run/secrets/mysql_jixel_password)
+else
+ echo "Secret file 'mysql_jixel_password' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_geo_jixel_username ]; then
+ export MYSQL_GEO_JIXEL_USERNAME=$(cat /run/secrets/mysql_geo_jixel_username)
+else
+ echo "Secret file 'mysql_geo_jixel_username' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_geo_jixel_password ]; then
+ export MYSQL_GEO_JIXEL_PASSWORD=$(cat /run/secrets/mysql_geo_jixel_password)
+else
+ echo "Secret file 'mysql_geo_jixel_password' not found!" >&2
+fi
+
+################################################################################
+#
+# Cake is a shell script for invoking CakePHP shell commands
+#
+# CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+#
+# Licensed under The MIT License
+# For full copyright and license information, please see the LICENSE.txt
+# Redistributions of files must retain the above copyright notice.
+#
+# @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+# @link https://cakephp.org CakePHP(tm) Project
+# @since 1.2.0
+# @license https://opensource.org/licenses/mit-license.php MIT License
+#
+################################################################################
+
+# Canonicalize by following every symlink of the given name recursively
+canonicalize() {
+ NAME="$1"
+ if [ -f "$NAME" ]
+ then
+ DIR=$(dirname -- "$NAME")
+ NAME=$(cd -P "$DIR" > /dev/null && pwd -P)/$(basename -- "$NAME")
+ fi
+ while [ -h "$NAME" ]; do
+ DIR=$(dirname -- "$NAME")
+ SYM=$(readlink "$NAME")
+ NAME=$(cd "$DIR" > /dev/null && cd "$(dirname -- "$SYM")" > /dev/null && pwd)/$(basename -- "$SYM")
+ done
+ echo "$NAME"
+}
+
+# Find a CLI version of PHP
+findCliPhp() {
+ for TESTEXEC in php php-cli /usr/local/bin/php
+ do
+ SAPI=$(echo "= PHP_SAPI ?>" | $TESTEXEC 2>/dev/null)
+ if [ "$SAPI" = "cli" ]
+ then
+ echo $TESTEXEC
+ return
+ fi
+ done
+ echo "Failed to find a CLI version of PHP; falling back to system standard php executable" >&2
+ echo "php";
+}
+
+# If current path is a symlink, resolve to real path
+realname="$0"
+if [ -L "$realname" ]
+then
+ realname=$(readlink -f "$0")
+fi
+
+CONSOLE=$(dirname -- "$(canonicalize "$realname")")
+APP=$(dirname "$CONSOLE")
+
+# If your CLI PHP is somewhere that this doesn't find, you can define a PHP environment
+# variable with the correct path in it.
+if [ -z "$PHP" ]
+then
+ PHP=$(findCliPhp)
+fi
+
+if [ "$(basename "$realname")" != 'cake' ]
+then
+ exec "$PHP" "$CONSOLE"/cake.php "$(basename "$realname")" "$@"
+else
+ exec "$PHP" "$CONSOLE"/cake.php "$@"
+fi
+
+exit
diff --git a/idrocap_wa/dockerfiles/run b/idrocap_wa/dockerfiles/run
new file mode 100755
index 0000000..b5e4d8a
--- /dev/null
+++ b/idrocap_wa/dockerfiles/run
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+httpd_user=${httpd_user:-apache}
+httpd_uid=${httpd_uid:-48}
+httpd_group=${httpd_group:-apache}
+
+useradd -u $httpd_uid -s /sbin/nologin $httpd_user
+
+export httpd_user
+export httpd_group
+
+if [ -f /run/secrets/sentry_dsn ]; then
+ export SENTRY_DSN=$(cat /run/secrets/sentry_dsn)
+else
+ echo "Secret file 'sentry_dsn' not found!" >&2
+fi
+if [ -f /run/secrets/oidc_client_id ]; then
+ export OIDC_CLIENT_ID=$(cat /run/secrets/oidc_client_id)
+else
+ echo "Secret file 'oidc_client_id' not found!" >&2
+fi
+if [ -f /run/secrets/rabbitmq_username ]; then
+ export RABBITMQ_USERNAME=$(cat /run/secrets/rabbitmq_username)
+else
+ echo "Secret file 'rabbitmq_username' not found!" >&2
+fi
+if [ -f /run/secrets/rabbitmq_password ]; then
+ export RABBITMQ_PASSWORD=$(cat /run/secrets/rabbitmq_password)
+else
+ echo "Secret file 'rabbitmq_password' not found!" >&2
+fi
+if [ -f /run/secrets/geoserver_username ]; then
+ export GEOSERVER_USERNAME=$(cat /run/secrets/geoserver_username)
+else
+ echo "Secret file 'geoserver_username' not found!" >&2
+fi
+if [ -f /run/secrets/geoserver_password ]; then
+ export GEOSERVER_PASSWORD=$(cat /run/secrets/geoserver_password)
+else
+ echo "Secret file 'geoserver_password' not found!" >&2
+fi
+if [ -f /run/secrets/minio_access_key ]; then
+ export MINIO_ACCESS_KEY=$(cat /run/secrets/minio_access_key)
+else
+ echo "Secret file 'minio_access_key' not found!" >&2
+fi
+if [ -f /run/secrets/minio_secret_key ]; then
+ export MINIO_SECRET_KEY=$(cat /run/secrets/minio_secret_key)
+else
+ echo "Secret file 'minio_secret_key' not found!" >&2
+fi
+if [ -f /run/secrets/telegram_bot_token ]; then
+ export TELEGRAM_BOT_TOKEN=$(cat /run/secrets/telegram_bot_token)
+else
+ echo "Secret file 'telegram_bot_token' not found!" >&2
+fi
+if [ -f /run/secrets/security_jwuc ]; then
+ export SECURITY_JWUC=$(cat /run/secrets/security_jwuc)
+else
+ echo "Secret file 'security_jwuc' not found!" >&2
+fi
+if [ -f /run/secrets/security_jwac ]; then
+ export SECURITY_JWAC=$(cat /run/secrets/security_jwac)
+else
+ echo "Secret file 'security_jwac' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_jixel_username ]; then
+ export MYSQL_JIXEL_USERNAME=$(cat /run/secrets/mysql_jixel_username)
+else
+ echo "Secret file 'mysql_jixel_username' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_jixel_password ]; then
+ export MYSQL_JIXEL_PASSWORD=$(cat /run/secrets/mysql_jixel_password)
+else
+ echo "Secret file 'mysql_jixel_password' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_geo_jixel_username ]; then
+ export MYSQL_GEO_JIXEL_USERNAME=$(cat /run/secrets/mysql_geo_jixel_username)
+else
+ echo "Secret file 'mysql_geo_jixel_username' not found!" >&2
+fi
+if [ -f /run/secrets/mysql_geo_jixel_password ]; then
+ export MYSQL_GEO_JIXEL_PASSWORD=$(cat /run/secrets/mysql_geo_jixel_password)
+else
+ echo "Secret file 'mysql_geo_jixel_password' not found!" >&2
+fi
+
+chmod -R o+w /var/www/jixel/tmp/
+chmod -R o+w /var/www/jixel/logs/
+
+/usr/sbin/php-fpm
+chown -R $httpd_user:$httpd_group /run/php-fpm
+/usr/sbin/httpd -DFOREGROUND
diff --git a/idrocap_wa/dockerfiles/www.conf b/idrocap_wa/dockerfiles/www.conf
new file mode 100644
index 0000000..ddc8904
--- /dev/null
+++ b/idrocap_wa/dockerfiles/www.conf
@@ -0,0 +1,453 @@
+; Start a new pool named 'www'.
+; the variable $pool can be used in any directive and will be replaced by the
+; pool name ('www' here)
+[www]
+
+; Per pool prefix
+; It only applies on the following directives:
+; - 'access.log'
+; - 'slowlog'
+; - 'listen' (unixsocket)
+; - 'chroot'
+; - 'chdir'
+; - 'php_values'
+; - 'php_admin_values'
+; When not set, the global prefix (or @php_fpm_prefix@) applies instead.
+; Note: This directive can also be relative to the global prefix.
+; Default Value: none
+;prefix = /path/to/pools/$pool
+
+; Unix user/group of processes
+; Note: The user is mandatory. If the group is not set, the default user's group
+; will be used.
+; RPM: apache user chosen to provide access to the same directories as httpd
+user = apache
+; RPM: Keep a group allowed to write in log dir.
+group = apache
+
+; The address on which to accept FastCGI requests.
+; Valid syntaxes are:
+; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
+; a specific port;
+; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
+; a specific port;
+; 'port' - to listen on a TCP socket to all addresses
+; (IPv6 and IPv4-mapped) on a specific port;
+; '/path/to/unix/socket' - to listen on a unix socket.
+; Note: This value is mandatory.
+listen = /run/php-fpm/www.sock
+
+; Set listen(2) backlog.
+; Default Value: 511
+;listen.backlog = 511
+
+; Set permissions for unix socket, if one is used. In Linux, read/write
+; permissions must be set in order to allow connections from a web server.
+; Default Values: user and group are set as the running user
+; mode is set to 0660
+;listen.owner = nobody
+;listen.group = nobody
+;listen.mode = 0660
+
+; When POSIX Access Control Lists are supported you can set them using
+; these options, value is a comma separated list of user/group names.
+; When set, listen.owner and listen.group are ignored
+listen.acl_users = apache,nginx
+;listen.acl_groups =
+
+; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
+; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
+; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
+; must be separated by a comma. If this value is left blank, connections will be
+; accepted from any ip address.
+; Default Value: any
+listen.allowed_clients = 127.0.0.1
+
+; Specify the nice(2) priority to apply to the pool processes (only if set)
+; The value can vary from -19 (highest priority) to 20 (lower priority)
+; Note: - It will only work if the FPM master process is launched as root
+; - The pool processes will inherit the master process priority
+; unless it specified otherwise
+; Default Value: no set
+; process.priority = -19
+
+; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user
+; or group is differrent than the master process user. It allows to create process
+; core dump and ptrace the process for the pool user.
+; Default Value: no
+; process.dumpable = yes
+
+; Choose how the process manager will control the number of child processes.
+; Possible Values:
+; static - a fixed number (pm.max_children) of child processes;
+; dynamic - the number of child processes are set dynamically based on the
+; following directives. With this process management, there will be
+; always at least 1 children.
+; pm.max_children - the maximum number of children that can
+; be alive at the same time.
+; pm.start_servers - the number of children created on startup.
+; pm.min_spare_servers - the minimum number of children in 'idle'
+; state (waiting to process). If the number
+; of 'idle' processes is less than this
+; number then some children will be created.
+; pm.max_spare_servers - the maximum number of children in 'idle'
+; state (waiting to process). If the number
+; of 'idle' processes is greater than this
+; number then some children will be killed.
+; ondemand - no children are created at startup. Children will be forked when
+; new requests will connect. The following parameter are used:
+; pm.max_children - the maximum number of children that
+; can be alive at the same time.
+; pm.process_idle_timeout - The number of seconds after which
+; an idle process will be killed.
+; Note: This value is mandatory.
+pm = dynamic
+
+; The number of child processes to be created when pm is set to 'static' and the
+; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
+; This value sets the limit on the number of simultaneous requests that will be
+; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
+; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
+; CGI. The below defaults are based on a server without much resources. Don't
+; forget to tweak pm.* to fit your needs.
+; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
+; Note: This value is mandatory.
+pm.max_children = 50
+
+; The number of child processes created on startup.
+; Note: Used only when pm is set to 'dynamic'
+; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
+pm.start_servers = 5
+
+; The desired minimum number of idle server processes.
+; Note: Used only when pm is set to 'dynamic'
+; Note: Mandatory when pm is set to 'dynamic'
+pm.min_spare_servers = 5
+
+; The desired maximum number of idle server processes.
+; Note: Used only when pm is set to 'dynamic'
+; Note: Mandatory when pm is set to 'dynamic'
+pm.max_spare_servers = 35
+
+; The number of seconds after which an idle process will be killed.
+; Note: Used only when pm is set to 'ondemand'
+; Default Value: 10s
+;pm.process_idle_timeout = 10s;
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries. For
+; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default Value: 0
+;pm.max_requests = 500
+
+; The URI to view the FPM status page. If this value is not set, no URI will be
+; recognized as a status page. It shows the following informations:
+; pool - the name of the pool;
+; process manager - static, dynamic or ondemand;
+; start time - the date and time FPM has started;
+; start since - number of seconds since FPM has started;
+; accepted conn - the number of request accepted by the pool;
+; listen queue - the number of request in the queue of pending
+; connections (see backlog in listen(2));
+; max listen queue - the maximum number of requests in the queue
+; of pending connections since FPM has started;
+; listen queue len - the size of the socket queue of pending connections;
+; idle processes - the number of idle processes;
+; active processes - the number of active processes;
+; total processes - the number of idle + active processes;
+; max active processes - the maximum number of active processes since FPM
+; has started;
+; max children reached - number of times, the process limit has been reached,
+; when pm tries to start more children (works only for
+; pm 'dynamic' and 'ondemand');
+; Value are updated in real time.
+; Example output:
+; pool: www
+; process manager: static
+; start time: 01/Jul/2011:17:53:49 +0200
+; start since: 62636
+; accepted conn: 190460
+; listen queue: 0
+; max listen queue: 1
+; listen queue len: 42
+; idle processes: 4
+; active processes: 11
+; total processes: 15
+; max active processes: 12
+; max children reached: 0
+;
+; By default the status page output is formatted as text/plain. Passing either
+; 'html', 'xml' or 'json' in the query string will return the corresponding
+; output syntax. Example:
+; http://www.foo.bar/status
+; http://www.foo.bar/status?json
+; http://www.foo.bar/status?html
+; http://www.foo.bar/status?xml
+;
+; By default the status page only outputs short status. Passing 'full' in the
+; query string will also return status for each pool process.
+; Example:
+; http://www.foo.bar/status?full
+; http://www.foo.bar/status?json&full
+; http://www.foo.bar/status?html&full
+; http://www.foo.bar/status?xml&full
+; The Full status returns for each process:
+; pid - the PID of the process;
+; state - the state of the process (Idle, Running, ...);
+; start time - the date and time the process has started;
+; start since - the number of seconds since the process has started;
+; requests - the number of requests the process has served;
+; request duration - the duration in µs of the requests;
+; request method - the request method (GET, POST, ...);
+; request URI - the request URI with the query string;
+; content length - the content length of the request (only with POST);
+; user - the user (PHP_AUTH_USER) (or '-' if not set);
+; script - the main script called (or '-' if not set);
+; last request cpu - the %cpu the last request consumed
+; it's always 0 if the process is not in Idle state
+; because CPU calculation is done when the request
+; processing has terminated;
+; last request memory - the max amount of memory the last request consumed
+; it's always 0 if the process is not in Idle state
+; because memory calculation is done when the request
+; processing has terminated;
+; If the process is in Idle state, then informations are related to the
+; last request the process has served. Otherwise informations are related to
+; the current request being served.
+; Example output:
+; ************************
+; pid: 31330
+; state: Running
+; start time: 01/Jul/2011:17:53:49 +0200
+; start since: 63087
+; requests: 12808
+; request duration: 1250261
+; request method: GET
+; request URI: /test_mem.php?N=10000
+; content length: 0
+; user: -
+; script: /home/fat/web/docs/php/test_mem.php
+; last request cpu: 0.00
+; last request memory: 0
+;
+; Note: There is a real-time FPM status monitoring sample web page available
+; It's available in: @EXPANDED_DATADIR@/fpm/status.html
+;
+; Note: The value must start with a leading slash (/). The value can be
+; anything, but it may not be a good idea to use the .php extension or it
+; may conflict with a real PHP file.
+; Default Value: not set
+;pm.status_path = /status
+
+; The ping URI to call the monitoring page of FPM. If this value is not set, no
+; URI will be recognized as a ping page. This could be used to test from outside
+; that FPM is alive and responding, or to
+; - create a graph of FPM availability (rrd or such);
+; - remove a server from a group if it is not responding (load balancing);
+; - trigger alerts for the operating team (24/7).
+; Note: The value must start with a leading slash (/). The value can be
+; anything, but it may not be a good idea to use the .php extension or it
+; may conflict with a real PHP file.
+; Default Value: not set
+;ping.path = /ping
+
+; This directive may be used to customize the response of a ping request. The
+; response is formatted as text/plain with a 200 response code.
+; Default Value: pong
+;ping.response = pong
+
+; The access log file
+; Default: not set
+;access.log = log/$pool.access.log
+
+; The access log format.
+; The following syntax is allowed
+; %%: the '%' character
+; %C: %CPU used by the request
+; it can accept the following format:
+; - %{user}C for user CPU only
+; - %{system}C for system CPU only
+; - %{total}C for user + system CPU (default)
+; %d: time taken to serve the request
+; it can accept the following format:
+; - %{seconds}d (default)
+; - %{miliseconds}d
+; - %{mili}d
+; - %{microseconds}d
+; - %{micro}d
+; %e: an environment variable (same as $_ENV or $_SERVER)
+; it must be associated with embraces to specify the name of the env
+; variable. Some exemples:
+; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
+; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
+; %f: script filename
+; %l: content-length of the request (for POST request only)
+; %m: request method
+; %M: peak of memory allocated by PHP
+; it can accept the following format:
+; - %{bytes}M (default)
+; - %{kilobytes}M
+; - %{kilo}M
+; - %{megabytes}M
+; - %{mega}M
+; %n: pool name
+; %o: output header
+; it must be associated with embraces to specify the name of the header:
+; - %{Content-Type}o
+; - %{X-Powered-By}o
+; - %{Transfert-Encoding}o
+; - ....
+; %p: PID of the child that serviced the request
+; %P: PID of the parent of the child that serviced the request
+; %q: the query string
+; %Q: the '?' character if query string exists
+; %r: the request URI (without the query string, see %q and %Q)
+; %R: remote IP address
+; %s: status (response code)
+; %t: server time the request was received
+; it can accept a strftime(3) format:
+; %d/%b/%Y:%H:%M:%S %z (default)
+; The strftime(3) format must be encapsuled in a %{}t tag
+; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
+; %T: time the log has been written (the request has finished)
+; it can accept a strftime(3) format:
+; %d/%b/%Y:%H:%M:%S %z (default)
+; The strftime(3) format must be encapsuled in a %{}t tag
+; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
+; %u: remote user
+;
+; Default: "%R - %u %t \"%m %r\" %s"
+;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
+
+; The log file for slow requests
+; Default Value: not set
+; Note: slowlog is mandatory if request_slowlog_timeout is set
+slowlog = /var/log/php-fpm/www-slow.log
+
+; The timeout for serving a single request after which a PHP backtrace will be
+; dumped to the 'slowlog' file. A value of '0s' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_slowlog_timeout = 0
+
+; Depth of slow log stack trace.
+; Default Value: 20
+;request_slowlog_trace_depth = 20
+
+; The timeout for serving a single request after which the worker process will
+; be killed. This option should be used when the 'max_execution_time' ini option
+; does not stop script execution for some reason. A value of '0' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_terminate_timeout = 0
+
+; Set open file descriptor rlimit.
+; Default Value: system defined value
+;rlimit_files = 1024
+
+; Set max core size rlimit.
+; Possible Values: 'unlimited' or an integer greater or equal to 0
+; Default Value: system defined value
+;rlimit_core = 0
+
+; Chroot to this directory at the start. This value must be defined as an
+; absolute path. When this value is not set, chroot is not used.
+; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
+; of its subdirectories. If the pool prefix is not set, the global prefix
+; will be used instead.
+; Note: chrooting is a great security feature and should be used whenever
+; possible. However, all PHP paths will be relative to the chroot
+; (error_log, sessions.save_path, ...).
+; Default Value: not set
+;chroot =
+
+; Chdir to this directory at the start.
+; Note: relative path can be used.
+; Default Value: current directory or / when chroot
+;chdir = /var/www
+
+; Redirect worker stdout and stderr into main error log. If not set, stdout and
+; stderr will be redirected to /dev/null according to FastCGI specs.
+; Note: on highloaded environement, this can cause some delay in the page
+; process time (several ms).
+; Default Value: no
+;catch_workers_output = yes
+
+; Clear environment in FPM workers
+; Prevents arbitrary environment variables from reaching FPM worker processes
+; by clearing the environment in workers before env vars specified in this
+; pool configuration are added.
+; Setting to "no" will make all environment variables available to PHP code
+; via getenv(), $_ENV and $_SERVER.
+; Default Value: yes
+; clear_env = no
+
+; Limits the extensions of the main script FPM will allow to parse. This can
+; prevent configuration mistakes on the web server side. You should only limit
+; FPM to .php extensions to prevent malicious users to use other extensions to
+; execute php code.
+; Note: set an empty value to allow all extensions.
+; Default Value: .php
+;security.limit_extensions = .php .php3 .php4 .php5 .php7
+
+; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
+; the current environment.
+; Default Value: clean env
+;env[HOSTNAME] = $HOSTNAME
+;env[PATH] = /usr/local/bin:/usr/bin:/bin
+;env[TMP] = /tmp
+;env[TMPDIR] = /tmp
+;env[TEMP] = /tmp
+env[SENTRY_DSN] = "${SENTRY_DSN}"
+env[OIDC_CLIENT_ID] = "${OIDC_CLIENT_ID}"
+env[RABBITMQ_USERNAME] = "${RABBITMQ_USERNAME}"
+env[RABBITMQ_PASSWORD] = "${RABBITMQ_PASSWORD}"
+env[GEOSERVER_USERNAME] = "${GEOSERVER_USERNAME}"
+env[GEOSERVER_PASSWORD] = "${GEOSERVER_PASSWORD}"
+env[MINIO_ACCESS_KEY] = "${MINIO_ACCESS_KEY}"
+env[MINIO_SECRET_KEY] = "${MINIO_SECRET_KEY}"
+env[TELEGRAM_BOT_TOKEN] = "${TELEGRAM_BOT_TOKEN}"
+env[SECURITY_JWUC] = "${SECURITY_JWUC}"
+env[SECURITY_JWAC] = "${SECURITY_JWAC}"
+env[MYSQL_JIXEL_USERNAME] = "${MYSQL_JIXEL_USERNAME}"
+env[MYSQL_JIXEL_PASSWORD] = "${MYSQL_JIXEL_PASSWORD}"
+env[MYSQL_GEO_JIXEL_USERNAME] = "${MYSQL_GEO_JIXEL_USERNAME}"
+env[MYSQL_GEO_JIXEL_PASSWORD] = "${MYSQL_GEO_JIXEL_PASSWORD}"
+
+; Additional php.ini defines, specific to this pool of workers. These settings
+; overwrite the values previously defined in the php.ini. The directives are the
+; same as the PHP SAPI:
+; php_value/php_flag - you can set classic ini defines which can
+; be overwritten from PHP call 'ini_set'.
+; php_admin_value/php_admin_flag - these directives won't be overwritten by
+; PHP call 'ini_set'
+; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
+
+; Defining 'extension' will load the corresponding shared extension from
+; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
+; overwrite previously defined php.ini values, but will append the new value
+; instead.
+
+; Note: path INI options can be relative and will be expanded with the prefix
+; (pool, global or @prefix@)
+
+; Default Value: nothing is defined by default except the values in php.ini and
+; specified at startup with the -d argument
+;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
+;php_flag[display_errors] = off
+php_admin_value[error_log] = /var/log/php-fpm/www-error.log
+php_admin_flag[log_errors] = on
+;php_admin_value[memory_limit] = 128M
+
+; Set the following data paths to directories owned by the FPM process user.
+;
+; Do not change the ownership of existing system directories, if the process
+; user does not have write permission, create dedicated directories for this
+; purpose.
+;
+; See warning about choosing the location of these directories on your system
+; at http://php.net/session.save-path
+php_value[session.save_handler] = files
+php_value[session.save_path] = /var/lib/php/session
+php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache
+;php_value[opcache.file_cache] = /var/lib/php/opcache
\ No newline at end of file
diff --git a/idrocap_wa/index.php b/idrocap_wa/index.php
new file mode 100644
index 0000000..4591769
--- /dev/null
+++ b/idrocap_wa/index.php
@@ -0,0 +1,16 @@
+ " + self.execution_command + ':\n{}'.format(completed_process.stderr.decode('utf-8')))
+ if completed_process.stdout:
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " -> " + self.execution_command + ':\n{}'.format(completed_process.stdout.decode('utf-8')))
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " -> " + self.execution_command + ' - RETURN CODE: {}'.format(completed_process.returncode))
+ completed_process.check_returncode()
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " -> " + self.execution_command + ': Shell command successfully executed!')
+ self.result = True
+ except FileNotFoundError as error:
+ self.logger.exception(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " -> " + self.execution_command + ' - A FileNotFoundError error has occured during shell command execution:', stack_info=False, exc_info=False)
+ self.logger.exception(error, stack_info=False, exc_info=False)
+ return False
+ except subprocess.CalledProcessError as error:
+ self.logger.exception(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " -> " + self.execution_command + ' - A CalledProcessError has occured during processing:', stack_info=False, exc_info=False)
+ self.logger.exception(error, stack_info=False, exc_info=False)
+ self.result = False
+
+ def __data_processing(self, channel, mr):
+ self.logger.info(mr)
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + ' - Starting processing thread:')
+ self.result = None
+ thread = threading.Thread(target=self.__execute_command, args=(mr,))
+ thread.start()
+
+ while thread.is_alive():
+ self.connection.process_data_events()
+
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - Result received:")
+ self.logger.info(self.result)
+ if (self.result is not True):
+ self.__send_error(json.dumps(mr))
+ return self.result
+
+ def __send_ack_nack(self, ack, channel, method):
+ channel.basic_ack(delivery_tag=method.delivery_tag)
+ if ack is True:
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - Ack performed")
+ else:
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - Ack performed BUT ERRORS OCCURRED!")
+
+ def __data_handler(self, channel, method, properties, body):
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + ' - New message received:')
+ error = False
+
+ try:
+ mr = json.loads(body.decode())
+ error = not self.__data_processing(channel, mr)
+ except json.JSONDecodeError as error:
+ self.logger.exception(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - Malformed message", stack_info=False, exc_info=False)
+ self.logger.exception(error, stack_info=False, exc_info=False)
+ self.logger.exception(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - This message will be removed from the queue", stack_info=False, exc_info=False)
+ self.__send_ack_nack(False, channel, method)
+ time.sleep(60)
+ return
+
+ if self.result is True and error is False:
+ self.__send_ack_nack(True, channel, method)
+ else:
+ self.logger.error(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - An error has occured during processing")
+ if self.discarding_mode is True:
+ self.logger.error(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - Discarding mode enabled.")
+ self.__send_ack_nack(True, channel, method)
+ else:
+ self.__send_ack_nack(False, channel, method)
+
+ time.sleep(5)
+
+ self.logger.info(self.rabbitmq_vhost + "/" + self.rabbitmq_queue + " - Data handling complete. Waiting for new messages")
+
+ def __send_error(self, message):
+ self.channel.basic_publish(exchange='', routing_key=self.rabbitmq_queue+'_errors', body=message)
+
+if __name__ == '__main__':
+ formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
+ handler = logging.handlers.TimedRotatingFileHandler("{}{}".format(os.environ['logging_file_path'], os.environ['logging_name']), when=os.environ['logging_file_rotate_when'], interval=int(os.environ['logging_file_rotate_interval']), backupCount=int(os.environ['logging_file_backup_count']))
+ handler.setFormatter(formatter)
+ logger = logging.getLogger(os.environ['logging_name'])
+ logger.addHandler(handler)
+ logger.setLevel(logging.DEBUG)
+
+ app = JixelGeneralPurposeRabbitConsumer(
+ os.environ['RABBITMQ_USERNAME'],
+ os.environ['RABBITMQ_PASSWORD'],
+ os.environ['rabbitmq_host'],
+ os.environ['rabbitmq_vhost'],
+ os.environ['rabbitmq_port'],
+ os.environ['rabbitmq_queue'],
+ os.environ['rabbitmq_heartbeat'],
+ os.environ['execution_path'],
+ os.environ['execution_command'],
+ logger,
+ os.environ['discarding_mode']
+ )
+ app.consume()
diff --git a/idrocap_wa/jixel-background-task-handler/jgprc.sh b/idrocap_wa/jixel-background-task-handler/jgprc.sh
new file mode 100755
index 0000000..63e583b
--- /dev/null
+++ b/idrocap_wa/jixel-background-task-handler/jgprc.sh
@@ -0,0 +1,26 @@
+export rabbitmq_username='jixel'
+export rabbitmq_password='jixel'
+export rabbitmq_host='rabbitmq'
+export rabbitmq_vhost='gp'
+export rabbitmq_queue='gp'
+export rabbitmq_port='5672'
+export execution_path='/var/www/jixel/bin/'
+export execution_command='gp'
+export rabbitmq_heartbeat=60
+export discarding_mode='False'
+
+# Log file rotation policy:
+# Current 'when' events supported:
+# 'S' - Seconds
+# 'M' - Minutes
+# 'H' - Hours
+# 'D' - Days
+# 'midnight' - roll over at midnight
+# 'W{0-6}' - roll over on a certain day; W0 - Monday, W1 - Tuesday, etc
+export logging_file_rotate_when='H'
+export logging_file_rotate_interval=24
+export logging_name='JixelGeneralPurposeRabbitConsumer'
+export logging_file_path='/general_purpose_rabbit_consumer/logs/'
+export logging_file_backup_count=30
+
+python3 ./jgprc.py
diff --git a/idrocap_wa/jixel-background-task-handler/jixel-background-task-handler.sh b/idrocap_wa/jixel-background-task-handler/jixel-background-task-handler.sh
new file mode 100755
index 0000000..031bfff
--- /dev/null
+++ b/idrocap_wa/jixel-background-task-handler/jixel-background-task-handler.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+if [ -f /run/secrets/rabbitmq_username ]; then
+ export RABBITMQ_USERNAME=$(cat /run/secrets/rabbitmq_username)
+else
+ echo "Secret file 'rabbitmq_username' not found!" >&2
+fi
+if [ -f /run/secrets/rabbitmq_password ]; then
+ export RABBITMQ_PASSWORD=$(cat /run/secrets/rabbitmq_password)
+else
+ echo "Secret file 'rabbitmq_password' not found!" >&2
+fi
+/usr/bin/python3 /usr/local/ies-solutions/jixel-background-task-handler/jbth.py
diff --git a/idrocap_wa/jixel-background-task-handler/jixel-cron.log b/idrocap_wa/jixel-background-task-handler/jixel-cron.log
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/jixel-background-task-handler/jixel-cron.sh b/idrocap_wa/jixel-background-task-handler/jixel-cron.sh
new file mode 100755
index 0000000..d99d9d3
--- /dev/null
+++ b/idrocap_wa/jixel-background-task-handler/jixel-cron.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+crond
+crontab /usr/local/ies-solutions/jixel-cron/jixel-cron.txt
+tail -f /usr/local/ies-solutions/jixel-cron/jixel-cron.txt
+
diff --git a/idrocap_wa/jixel-background-task-handler/jixel-cron.txt b/idrocap_wa/jixel-background-task-handler/jixel-cron.txt
new file mode 100644
index 0000000..3dcf589
--- /dev/null
+++ b/idrocap_wa/jixel-background-task-handler/jixel-cron.txt
@@ -0,0 +1,6 @@
+# always put 3 rows: service called, date and the actual service called output:
+* * * * * echo "/var/www/jixel/bin/cake" >> /usr/local/ies-solutions/jixel-cron/jixel-cron.log
+* * * * * date >> /usr/local/ies-solutions/jixel-cron/jixel-cron.log
+* * * * * /var/www/jixel/bin/cake >> /usr/local/ies-solutions/jixel-cron/jixel-cron.log
+0 0 * * 0 rm -f /usr/local/ies-solutions/jixel-cron/jixel-cron.log
+# keep this line empty!
\ No newline at end of file
diff --git a/idrocap_wa/jixel-background-task-handler/jixel-general-purpose-rabbit-consumer.sh b/idrocap_wa/jixel-background-task-handler/jixel-general-purpose-rabbit-consumer.sh
new file mode 100755
index 0000000..ce79ed6
--- /dev/null
+++ b/idrocap_wa/jixel-background-task-handler/jixel-general-purpose-rabbit-consumer.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+if [ -f /run/secrets/rabbitmq_username ]; then
+ export RABBITMQ_USERNAME=$(cat /run/secrets/rabbitmq_username)
+else
+ echo "Secret file 'rabbitmq_username' not found!" >&2
+fi
+if [ -f /run/secrets/rabbitmq_password ]; then
+ export RABBITMQ_PASSWORD=$(cat /run/secrets/rabbitmq_password)
+else
+ echo "Secret file 'rabbitmq_password' not found!" >&2
+fi
+/usr/bin/python3 /usr/local/ies-solutions/jixel-general-purpose-rabbit-consumer/jgprc.py
diff --git a/idrocap_wa/phpcs.xml b/idrocap_wa/phpcs.xml
new file mode 100644
index 0000000..cb4c2dc
--- /dev/null
+++ b/idrocap_wa/phpcs.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ */src/Controller/*
+
+
+ src/
+ tests/
+
diff --git a/idrocap_wa/phpstan.neon b/idrocap_wa/phpstan.neon
new file mode 100644
index 0000000..c131dec
--- /dev/null
+++ b/idrocap_wa/phpstan.neon
@@ -0,0 +1,6 @@
+parameters:
+ level: 8
+ treatPhpDocTypesAsCertain: false
+ checkGenericClassInNonGenericObjectType: false
+ paths:
+ - src/
diff --git a/idrocap_wa/phpunit.xml.dist b/idrocap_wa/phpunit.xml.dist
new file mode 100644
index 0000000..4dfd186
--- /dev/null
+++ b/idrocap_wa/phpunit.xml.dist
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+ tests/TestCase/
+
+
+
+
+
+
+
+
+
+
+
+
+ src/
+ plugins/*/src/
+
+
+ src/Console/Installer.php
+
+
+
diff --git a/idrocap_wa/plugins/.gitkeep b/idrocap_wa/plugins/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/psalm.xml b/idrocap_wa/psalm.xml
new file mode 100644
index 0000000..4e9226b
--- /dev/null
+++ b/idrocap_wa/psalm.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/resources/.gitkeep b/idrocap_wa/resources/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/resources/locales/cake.pot b/idrocap_wa/resources/locales/cake.pot
new file mode 100644
index 0000000..6f1c7d7
--- /dev/null
+++ b/idrocap_wa/resources/locales/cake.pot
@@ -0,0 +1,279 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: CakePHP 4.4.5\n"
+"POT-Creation-Date: 2023-02-28 09:27+0000\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: ./templates/Error/error400.php:39
+#: ./templates/Error/error500.php:43
+msgid "Error"
+msgstr ""
+
+#: ./templates/Error/error400.php:40
+msgid "The requested address {0} was not found on this server."
+msgstr ""
+
+#: ./templates/Error/error500.php:41
+#: ./vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php:361
+msgid "An Internal Error Has Occurred."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Controller/Component/AuthComponent.php:462
+msgid "You are not authorized to access that location."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php:359
+msgid "Not Found"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:390
+msgid "Missing or incorrect CSRF cookie type."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:394
+msgid "Missing or invalid CSRF cookie."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:417
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php:265
+msgid "CSRF token from either the request body or request headers did not match or is missing."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php:247
+msgid "Missing or incorrect CSRF session key"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Http/Response.php:1489
+msgid "The requested file contains `..` and will not be read."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Http/Response.php:1497
+msgid "The requested file was not found"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:116
+msgid "{0,number,#,###.##} KB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:118
+msgid "{0,number,#,###.##} MB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:120
+msgid "{0,number,#,###.##} GB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:122
+msgid "{0,number,#,###.##} TB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:114
+msgid "{0,number,integer} Byte"
+msgid_plural "{0,number,integer} Bytes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:86
+msgid "{0} from now"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:86
+msgid "{0} ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:89
+msgid "{0} after"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:89
+msgid "{0} before"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:120
+msgid "just now"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:157
+msgid "about a second ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:158
+msgid "about a minute ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:159
+msgid "about an hour ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:160
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:370
+msgid "about a day ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:161
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:371
+msgid "about a week ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:162
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:372
+msgid "about a month ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:163
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:373
+msgid "about a year ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:174
+msgid "in about a second"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:175
+msgid "in about a minute"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:176
+msgid "in about an hour"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:177
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:384
+msgid "in about a day"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:178
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:385
+msgid "in about a week"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:179
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:386
+msgid "in about a month"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:180
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:387
+msgid "in about a year"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:342
+msgid "today"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:409
+msgid "%s ago"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:410
+msgid "on %s"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:53
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:132
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:354
+msgid "{0} year"
+msgid_plural "{0} years"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:57
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:135
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:357
+msgid "{0} month"
+msgid_plural "{0} months"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:63
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:138
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:360
+msgid "{0} week"
+msgid_plural "{0} weeks"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:65
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:141
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:363
+msgid "{0} day"
+msgid_plural "{0} days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:70
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:144
+msgid "{0} hour"
+msgid_plural "{0} hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:74
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:147
+msgid "{0} minute"
+msgid_plural "{0} minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:78
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:150
+msgid "{0} second"
+msgid_plural "{0} seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:63
+msgid "This value is already in use"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:110
+msgid "This value does not exist"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:232
+msgid "Cannot modify row: a constraint for the `{0}` association fails."
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:270
+msgid "The count does not match {0}{1}"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Utility/Text.php:923
+msgid "and"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:2539
+msgid "This field is required"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:2559
+#: ./vendor/cakephp/cakephp/src/View/Form/ArrayContext.php:249
+msgid "This field cannot be left empty"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:2711
+msgid "The provided value is invalid"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/View/Helper/FormHelper.php:979
+msgid "Edit {0}"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/View/Helper/FormHelper.php:981
+msgid "New {0}"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/View/Helper/FormHelper.php:1917
+msgid "Submit"
+msgstr ""
+
diff --git a/idrocap_wa/resources/locales/default.pot b/idrocap_wa/resources/locales/default.pot
new file mode 100644
index 0000000..4c05ce9
--- /dev/null
+++ b/idrocap_wa/resources/locales/default.pot
@@ -0,0 +1,1709 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"POT-Creation-Date: 2023-03-03 14:35+0000\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: ./src/Controller/Api/AttachmentsController.php:36
+#: ./src/Controller/AttachmentsController.php:38
+#: ./src/Controller/AttachmentsController.php:68
+msgid "Allegato non trovato"
+msgstr ""
+
+#: ./src/Controller/Api/AttachmentsController.php:37
+#: ./src/Controller/AttachmentsController.php:39
+#: ./src/Controller/AttachmentsController.php:69
+msgid "Non hai i permessi necessari per visionare l'allegato"
+msgstr ""
+
+#: ./src/Controller/Api/OrganisationsController.php:104
+msgid "Organizzazione non trovata!"
+msgstr ""
+
+#: ./src/Controller/Api/UsersController.php:160
+msgid "Utente non trovato!"
+msgstr ""
+
+#: ./src/Controller/AppController.php:95
+msgid "SYSADMIN"
+msgstr ""
+
+#: ./src/Controller/AppController.php:99
+#: ./templates/Capabilities/index.php:13
+#: ./templates/Groups/handle_capabilities.php:23
+#: ./templates/Groups/view.php:42
+msgid "Gestione competenze"
+msgstr ""
+
+#: ./src/Controller/AppController.php:104
+msgid "Test notifiche"
+msgstr ""
+
+#: ./src/Controller/AppController.php:107
+msgid "Procedendo verranno inviate notifiche a tutti gli utenti e le organizzaioni che possiedono uno o più recapiti abilitati alle notifiche! Sei sicuro che vuoi continuare ?"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:24
+#: ./src/Controller/CapabilitiesController.php:54
+#: ./src/Controller/CapabilitiesController.php:97
+#: ./src/Controller/CapabilitiesController.php:135
+#: ./src/Controller/CapabilitiesController.php:177
+#: ./src/Controller/GroupsController.php:31
+#: ./src/Controller/GroupsController.php:54
+#: ./src/Controller/GroupsController.php:92
+#: ./src/Controller/GroupsController.php:112
+#: ./src/Controller/GroupsController.php:136
+#: ./src/Controller/GroupsController.php:160
+#: ./src/Controller/GroupsController.php:183
+#: ./src/Controller/OrganisationsController.php:32
+#: ./src/Controller/OrganisationsController.php:60
+#: ./src/Controller/OrganisationsController.php:109
+#: ./src/Controller/OrganisationsController.php:131
+#: ./src/Controller/OrganisationsController.php:155
+#: ./src/Controller/OrganisationsController.php:181
+#: ./src/Controller/UsersController.php:38
+#: ./src/Controller/UsersController.php:70
+#: ./src/Controller/UsersController.php:113
+#: ./src/Controller/UsersController.php:119
+#: ./src/Controller/UsersController.php:136
+#: ./src/Controller/UsersController.php:177
+#: ./src/Controller/UsersController.php:211
+#: ./src/Controller/UsersController.php:216
+msgid "Non hai i permessi necessari"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:79
+msgid "Competenza \"{0}\" nascosta con successo!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:82
+msgid "Errore durante il tentativo di nascondere la Competenza \"{0}\"!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:117
+msgid "Competenza \"{0}\" resa visibile con successo!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:120
+msgid "Errore durante il tentativo di rendere visibile la Competenza \"{0}\"!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:159
+msgid "Competenza \"{0}\" cancellata con successo!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:162
+msgid "Errore durante la cancellazione della Competenza \"{0}\"!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:197
+msgid "Competenza \"{0}\" ripristinata con successo!"
+msgstr ""
+
+#: ./src/Controller/CapabilitiesController.php:200
+msgid "Errore durante il ripristino della Competenza \"{0}\"!"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:27
+#: ./src/Controller/DeliveriesController.php:125
+#: ./src/Controller/EmailsController.php:25
+#: ./src/Controller/EmailsController.php:64
+#: ./src/Controller/FaxesController.php:25
+#: ./src/Controller/FaxesController.php:64
+#: ./src/Controller/MobilePhonesController.php:26
+#: ./src/Controller/MobilePhonesController.php:65
+#: ./src/Controller/PhonesController.php:25
+#: ./src/Controller/PhonesController.php:64
+#: ./src/Controller/TelegramChatsController.php:25
+#: ./src/Controller/TelegramChatsController.php:63
+msgid "Gestione recapiti non prevista per questa tipologia di oggetto"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:29
+#: ./src/Controller/DeliveriesController.php:127
+#: ./src/Controller/EmailsController.php:26
+#: ./src/Controller/EmailsController.php:65
+#: ./src/Controller/FaxesController.php:26
+#: ./src/Controller/FaxesController.php:65
+#: ./src/Controller/MobilePhonesController.php:27
+#: ./src/Controller/MobilePhonesController.php:66
+#: ./src/Controller/PhonesController.php:26
+#: ./src/Controller/PhonesController.php:65
+#: ./src/Controller/TelegramChatsController.php:26
+#: ./src/Controller/TelegramChatsController.php:64
+msgid "questa organizzazione"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:29
+#: ./src/Controller/DeliveriesController.php:127
+#: ./src/Controller/EmailsController.php:26
+#: ./src/Controller/EmailsController.php:65
+#: ./src/Controller/FaxesController.php:26
+#: ./src/Controller/FaxesController.php:65
+#: ./src/Controller/MobilePhonesController.php:27
+#: ./src/Controller/MobilePhonesController.php:66
+#: ./src/Controller/PhonesController.php:26
+#: ./src/Controller/PhonesController.php:65
+#: ./src/Controller/TelegramChatsController.php:26
+#: ./src/Controller/TelegramChatsController.php:64
+msgid "questo utente"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:30
+msgid "Non hai i permessi per visualizzare i recapiti per {0}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:128
+msgid "Non hai i permessi per eliminare i recapiti di questo tipo per {0}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:134
+#: ./src/Model/Entity/Actor.php:87
+msgid "Cellulare ({0}): {1}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:137
+#: ./src/Model/Entity/Actor.php:97
+msgid "Fax ({0}): {1}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:140
+#: ./src/Model/Entity/Actor.php:107
+msgid "Email ({0}): {1}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:143
+#: ./src/Model/Entity/Actor.php:117
+msgid "Telefono ({0}): {1}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:146
+#: ./src/Model/Entity/Actor.php:127
+msgid "Telegram Chat ID: {0}"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:154
+msgid "Il recapito \"{0}\" è stato cancellato con successo"
+msgstr ""
+
+#: ./src/Controller/DeliveriesController.php:156
+msgid "Errore durante la cancellazione del recapito {0}. Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/EmailsController.php:27
+#: ./src/Controller/FaxesController.php:27
+#: ./src/Controller/MobilePhonesController.php:28
+#: ./src/Controller/PhonesController.php:27
+#: ./src/Controller/TelegramChatsController.php:27
+msgid "Non hai i permessi per aggiungere i recapiti di questo tipo per {0}"
+msgstr ""
+
+#: ./src/Controller/EmailsController.php:39
+msgid "L'Email è stata aggiunta con successo."
+msgstr ""
+
+#: ./src/Controller/EmailsController.php:43
+msgid "Errore durante l'aggiunta dell'Email: {0}"
+msgstr ""
+
+#: ./src/Controller/EmailsController.php:66
+#: ./src/Controller/FaxesController.php:66
+#: ./src/Controller/MobilePhonesController.php:67
+#: ./src/Controller/PhonesController.php:66
+#: ./src/Controller/TelegramChatsController.php:65
+msgid "Non hai i permessi per modificare i recapiti di questo tipo per {0}"
+msgstr ""
+
+#: ./src/Controller/EmailsController.php:71
+msgid "L'Email è stata modificata con successo."
+msgstr ""
+
+#: ./src/Controller/EmailsController.php:75
+msgid "Errore durante la modifica dell'Email. Riprovare di nuovo"
+msgstr ""
+
+#: ./src/Controller/FaxesController.php:39
+msgid "Il Fax è stato aggiunto con successo."
+msgstr ""
+
+#: ./src/Controller/FaxesController.php:43
+msgid "Errore durante l'aggiunta del Fax: {0}"
+msgstr ""
+
+#: ./src/Controller/FaxesController.php:71
+msgid "Il Fax è stato modificato con successo."
+msgstr ""
+
+#: ./src/Controller/FaxesController.php:75
+msgid "Errore durante la modifica del Fax. Riprovare di nuovo"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:57
+#: ./src/Controller/OrganisationsController.php:63
+#: ./templates/Capabilities/index.php:41
+#: ./templates/Deliveries/index.php:49
+#: ./templates/Deliveries/index.php:91
+#: ./templates/Deliveries/index.php:133
+#: ./templates/Deliveries/index.php:175
+#: ./templates/Emails/add.php:48
+#: ./templates/Emails/edit.php:48
+#: ./templates/Faxes/add.php:48
+#: ./templates/Faxes/edit.php:48
+#: ./templates/Groups/add.php:38
+#: ./templates/Groups/edit.php:43
+#: ./templates/Groups/index.php:31
+#: ./templates/Groups/view.php:35
+#: ./templates/MobilePhones/add.php:48
+#: ./templates/MobilePhones/edit.php:48
+#: ./templates/Organisations/index.php:29
+#: ./templates/Phones/add.php:48
+#: ./templates/Phones/edit.php:48
+msgid "Descrizione"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:58
+#: ./templates/Groups/add.php:39
+#: ./templates/Groups/edit.php:44
+#: ./templates/Groups/index.php:32
+#: ./templates/Groups/view.php:37
+msgid "Profilo Default"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:59
+#: ./templates/Groups/add.php:40
+#: ./templates/Groups/edit.php:45
+#: ./templates/Groups/index.php:33
+#: ./templates/Groups/view.php:39
+msgid "Profilo Amministratore"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:64
+#: ./src/Controller/GroupsController.php:67
+#: ./templates/Deliveries/index.php:60
+#: ./templates/Deliveries/index.php:102
+#: ./templates/Deliveries/index.php:144
+#: ./templates/Deliveries/index.php:224
+#: ./templates/Groups/index.php:41
+#: ./templates/Groups/index.php:42
+#: ./templates/Groups/view.php:38
+#: ./templates/Groups/view.php:40
+msgid "SI"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:64
+#: ./src/Controller/GroupsController.php:67
+#: ./templates/Deliveries/index.php:60
+#: ./templates/Deliveries/index.php:102
+#: ./templates/Deliveries/index.php:144
+#: ./templates/Deliveries/index.php:224
+#: ./templates/Groups/index.php:41
+#: ./templates/Groups/index.php:42
+#: ./templates/Groups/view.php:38
+#: ./templates/Groups/view.php:40
+msgid "NO"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:118
+msgid "Profilo Utente creato con successo."
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:122
+msgid "Errore durante la creazione del Profilo Utente: {0}"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:142
+#: ./src/Controller/GroupsController.php:206
+msgid "Profilo Utente \"{0}\" modificato con successo."
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:146
+#: ./src/Controller/GroupsController.php:209
+msgid "Errore durante la modifica del Profilo Utente \"{0}\". Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:166
+msgid "Il Profilo Utente \"{0}\" è stato cancellato con successo"
+msgstr ""
+
+#: ./src/Controller/GroupsController.php:168
+msgid "Errore durante la cancellazione del Profilo Utente \"{0}\". Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/MapsController.php:131
+msgid "Punto alle coordinate (EPSG:4326) Latitudine: {0}, Longitudine: {1}"
+msgstr ""
+
+#: ./src/Controller/MobilePhonesController.php:40
+msgid "Il Cellulare è stato aggiunto con successo."
+msgstr ""
+
+#: ./src/Controller/MobilePhonesController.php:44
+msgid "Errore durante l'aggiunta del Cellulare: {0}"
+msgstr ""
+
+#: ./src/Controller/MobilePhonesController.php:72
+msgid "Il Cellulare è stato modificato con successo."
+msgstr ""
+
+#: ./src/Controller/MobilePhonesController.php:76
+msgid "Errore durante la modifica del Cellulare. Riprovare di nuovo"
+msgstr ""
+
+#: ./src/Controller/NotificationsController.php:51
+msgid "Errore durante la cancellazione della notifica: "
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:64
+#: ./templates/Organisations/add.php:38
+#: ./templates/Organisations/edit.php:42
+#: ./templates/Organisations/index.php:30
+#: ./templates/Organisations/view.php:37
+msgid "Acronimo"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:65
+#: ./templates/Organisations/index.php:31
+msgid "Tipologia"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:66
+#: ./templates/Maps/index.php:131
+#: ./templates/Organisations/add.php:140
+#: ./templates/Organisations/add.php:159
+#: ./templates/Organisations/edit.php:63
+#: ./templates/Organisations/index.php:32
+#: ./templates/Organisations/view.php:52
+#: ./templates/Users/add.php:46
+#: ./templates/Users/edit.php:51
+#: ./templates/Users/view.php:55
+msgid "Indirizzo"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:67
+#: ./templates/Maps/index.php:120
+#: ./templates/Organisations/add.php:129
+#: ./templates/Organisations/add.php:161
+#: ./templates/Organisations/edit.php:65
+#: ./templates/Organisations/index.php:34
+#: ./templates/Organisations/view.php:54
+msgid "Comune"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:68
+#: ./templates/Organisations/add.php:160
+#: ./templates/Organisations/edit.php:64
+#: ./templates/Organisations/index.php:33
+#: ./templates/Organisations/view.php:53
+#: ./templates/Users/add.php:48
+#: ./templates/Users/edit.php:53
+#: ./templates/Users/view.php:59
+msgid "CAP"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:69
+#: ./templates/Maps/index.php:109
+#: ./templates/Organisations/add.php:118
+#: ./templates/Organisations/add.php:162
+#: ./templates/Organisations/edit.php:66
+#: ./templates/Organisations/index.php:35
+#: ./templates/Organisations/view.php:55
+msgid "Provincia"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:70
+#: ./src/Controller/UsersController.php:76
+#: ./templates/Organisations/index.php:36
+#: ./templates/Organisations/view.php:56
+#: ./templates/Users/index.php:32
+msgid "Recapiti"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:137
+msgid "Organizzazione creata con successo."
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:141
+msgid "Errore durante la creazione dell'organizzazione: {0}"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:163
+msgid "Organizzazione \"{0}\" modificata con successo."
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:167
+msgid "Errore durante la modifica dell'organizzazione \"{0}\". Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:188
+msgid "Impossibile eliminare l'organizzazione \"{0}\". Ci sono {1} utenti collegati ad essa."
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:193
+msgid "L'organizzazione \"{0}\" è stata cancellata con successo"
+msgstr ""
+
+#: ./src/Controller/OrganisationsController.php:195
+msgid "Errore durante la cancellazione dell'organizzazione \"{0}\". Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/PhonesController.php:39
+msgid "Il Telefono è stato aggiunto con successo."
+msgstr ""
+
+#: ./src/Controller/PhonesController.php:43
+msgid "Errore durante l'aggiunta del Telefono: {0}"
+msgstr ""
+
+#: ./src/Controller/PhonesController.php:71
+msgid "Il Telefono è stato modificato con successo."
+msgstr ""
+
+#: ./src/Controller/PhonesController.php:75
+msgid "Errore durante la modifica del Telefono. Riprovare di nuovo"
+msgstr ""
+
+#: ./src/Controller/TelegramChatsController.php:39
+msgid "La Chat Telegram è stata aggiunta con successo."
+msgstr ""
+
+#: ./src/Controller/TelegramChatsController.php:43
+msgid "Errore durante l'aggiunta della Chat Telegram: {0}"
+msgstr ""
+
+#: ./src/Controller/TelegramChatsController.php:70
+msgid "La Chat Telegram è stata modificata con successo."
+msgstr ""
+
+#: ./src/Controller/TelegramChatsController.php:74
+msgid "Errore durante la modifica della Chat Telegram. Riprovare di nuovo"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:73
+#: ./templates/Users/add.php:41
+#: ./templates/Users/edit.php:46
+#: ./templates/Users/index.php:29
+#: ./templates/Users/view.php:45
+msgid "Cognome"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:74
+#: ./templates/ControllableObjects/get_attachments.php:59
+#: ./templates/Organisations/add.php:37
+#: ./templates/Organisations/edit.php:41
+#: ./templates/Organisations/view.php:36
+#: ./templates/Users/add.php:40
+#: ./templates/Users/edit.php:45
+#: ./templates/Users/index.php:30
+#: ./templates/Users/view.php:43
+msgid "Nome"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:75
+#: ./templates/Users/index.php:31
+msgid "Username"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:77
+#: ./templates/Users/add.php:52
+#: ./templates/Users/edit.php:57
+#: ./templates/Users/index.php:33
+#: ./templates/Users/view.php:65
+msgid "Profili"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:78
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+#: ./templates/Users/add.php:50
+#: ./templates/Users/edit.php:55
+#: ./templates/Users/index.php:34
+#: ./templates/Users/view.php:63
+msgid "Organizzazione"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:156
+msgid "Utente creato con successo."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:160
+msgid "Errore durante la creazione dell'utente: {0}"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:190
+msgid "Utente \"{0}\" modificato con successo."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:194
+msgid "Errore durante la modifica dell'utente \"{0}\". Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:219
+msgid "L'utente \"{0}\" è stato cancellato con successo"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:221
+msgid "Errore durante la cancellazione dell'utente \"{0}\". Riprovare di nuovo."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:244
+msgid "Ho dimenticato la mia password"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:256
+msgid "Logout eseguito con successo."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:294
+msgid "Inserire un indirizzo email valido!"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:306
+msgid "A breve riceverai un'email all'indirizzo \"{0}\" con le istruzioni per eseguire il reset della password per il tuo account con username \"{1}\"."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:311
+msgid "L'indirizzo email inserito non risulta presente"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:316
+#: ./src/Controller/UsersController.php:364
+msgid "Ritorna al login"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:332
+msgid "Impossibile completare la procedura di recupero password."
+msgstr ""
+
+#: ./src/Controller/UsersController.php:355
+msgid "Impossibile cambiare la password"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:359
+msgid "La nuova password non è valida e/o le 2 password non coincidono"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:397
+msgid "Errore durante l'eliminazione della foto utente!"
+msgstr ""
+
+#: ./src/Controller/UsersController.php:399
+msgid "Foto utente eliminata con successo"
+msgstr ""
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:41
+msgid "Test Test Test"
+msgstr ""
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:43
+msgid "Hai ricevuto questo messaggio di test perchè sei registrato/a sulla piattaforma {0} ed hai almeno un recapito abilitato alla ricezione delle notifiche"
+msgstr ""
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:46
+msgid "Recupero password {0}"
+msgstr ""
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:50
+msgid "Hai ricevuto questo messaggio perchè sei registrato/a sulla piattaforma {0} ed è stata richiesta la procedura di recupero credenziali per il tuo account. Se non hai richiesto tale procedura ti preghiamo di ignorare questo messaggio. Per accedere a {0} utilizza il seguente username: \" {1} \" . Clicca sul seguente link per impostare una nuova password "
+msgstr ""
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:53
+msgid "{0} mancante"
+msgstr ""
+
+#: ./src/Model/Behavior/AttachmentsBehavior.php:132
+msgid "L'allegato è obbligatorio!"
+msgstr ""
+
+#: ./src/Model/Entity/ControllableObject.php:241
+msgid "Le coordinate inserite per georeferenziare uno o più allegati non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell'area di competenza della piattaforma."
+msgstr ""
+
+#: ./src/Model/Table/EmailsTable.php:107
+msgid "Indirizzo email già presente a sistema!"
+msgstr ""
+
+#: ./src/Model/Table/FaxesTable.php:103
+msgid "Fax già presente a sistema!"
+msgstr ""
+
+#: ./src/Model/Table/MobilePhonesTable.php:107
+msgid "Cellulare già presente a sistema!"
+msgstr ""
+
+#: ./src/Model/Table/OrganisationsTable.php:169
+msgid "Le geometrie inserite per georeferenziare l'organizzazione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell'area di competenza della piattaforma."
+msgstr ""
+
+#: ./src/Model/Table/PhonesTable.php:99
+msgid "Telefono già presente a sistema!"
+msgstr ""
+
+#: ./src/Model/Table/PushNotificationsTable.php:97
+msgid "Non puoi associare nuovamente questo token allo stesso utente"
+msgstr ""
+
+#: ./src/Model/Table/UsersTable.php:106
+msgid "La password deve contenere almeno {0} caratteri"
+msgstr ""
+
+#: ./src/Model/Table/UsersTable.php:111
+msgid "La password deve contenere almeno {0} carattere/i maiuscolo/i"
+msgstr ""
+
+#: ./src/Model/Table/UsersTable.php:117
+msgid "La password deve contenere almeno {0} numero/i"
+msgstr ""
+
+#: ./src/Model/Table/UsersTable.php:131
+msgid "La password deve contenere almeno {1} carattere/i speciale/i tra \"{0}\""
+msgstr ""
+
+#: ./src/Model/Table/UsersTable.php:256
+msgid "Errore durante il salvataggio della foto utente. Assicurarsi che sia nel formato corretto (jpeg 160x160)"
+msgstr ""
+
+#: ./src/View/Cell/MapCell.php:182
+msgid "Geometrie disegnate"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:9
+#: ./templates/Deliveries/index.php:9
+#: ./templates/Emails/add.php:9
+#: ./templates/Emails/edit.php:9
+#: ./templates/Faxes/add.php:9
+#: ./templates/Faxes/edit.php:9
+#: ./templates/Groups/add.php:9
+#: ./templates/Groups/edit.php:9
+#: ./templates/Groups/handle_capabilities.php:9
+#: ./templates/Groups/index.php:9
+#: ./templates/Groups/view.php:9
+#: ./templates/Maps/index.php:9
+#: ./templates/MobilePhones/add.php:9
+#: ./templates/MobilePhones/edit.php:9
+#: ./templates/Organisations/add.php:9
+#: ./templates/Organisations/edit.php:9
+#: ./templates/Organisations/index.php:9
+#: ./templates/Organisations/view.php:9
+#: ./templates/Phones/add.php:9
+#: ./templates/Phones/edit.php:9
+#: ./templates/TelegramChats/add.php:9
+#: ./templates/TelegramChats/edit.php:9
+#: ./templates/Users/add.php:9
+#: ./templates/Users/edit.php:9
+#: ./templates/Users/index.php:9
+#: ./templates/Users/view.php:9
+msgid "Configurazioni"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:24
+msgid "Lista delle competenze"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:29
+msgid "Cerca per descrizione competenza o codice o nome del gruppo di competenze"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:29
+msgid "Cerca"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:42
+msgid "Codice"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:43
+msgid "Priorità"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:44
+msgid "Gruppo"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:45
+#: ./templates/ControllableObjects/get_attachments.php:66
+#: ./templates/Deliveries/index.php:52
+#: ./templates/Deliveries/index.php:94
+#: ./templates/Deliveries/index.php:136
+#: ./templates/Deliveries/index.php:177
+#: ./templates/Deliveries/index.php:217
+#: ./templates/Groups/index.php:34
+#: ./templates/Organisations/index.php:37
+#: ./templates/Users/index.php:35
+msgid "Azioni"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:57
+#: ./templates/Groups/handle_capabilities.php:57
+#: ./templates/Groups/handle_capabilities.php:58
+#: ./templates/Groups/handle_capabilities.php:59
+msgid "Competenza non visibile e non configurabile dai non SYSADMIN"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:58
+msgid "Competenza eliminata dal sistema"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:67
+msgid "Nascondi"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:67
+msgid "Mostra"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:68
+msgid "Ripristina"
+msgstr ""
+
+#: ./templates/Capabilities/index.php:68
+#: ./templates/Deliveries/index.php:63
+#: ./templates/Deliveries/index.php:105
+#: ./templates/Deliveries/index.php:147
+#: ./templates/Deliveries/index.php:187
+#: ./templates/Deliveries/index.php:227
+#: ./templates/Groups/index.php:46
+#: ./templates/Groups/view.php:44
+#: ./templates/Organisations/index.php:54
+#: ./templates/Organisations/view.php:71
+#: ./templates/Users/index.php:50
+#: ./templates/Users/view.php:72
+msgid "Cancella"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:45
+msgid "Allegati presenti: {0}"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:45
+msgid "Nessun Allegato presente"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:60
+msgid "Georeferenziazione"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:62
+msgid "Dimensione"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:63
+msgid "Tipo"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:64
+msgid "Caricato il"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:65
+#: ./templates/cell/Filters/display.php:57
+msgid "Da"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:80
+msgid "File pubblico"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:83
+msgid "File privato"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:106
+msgid "Visualizza"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:110
+msgid "Segna da eliminare"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:112
+msgid "Segna come non rilevante"
+msgstr ""
+
+#: ./templates/ControllableObjects/get_attachments.php:112
+msgid "Segna come rilevante"
+msgstr ""
+
+#: ./templates/Dashboard/index.php:16
+msgid "Jixel Dashboard"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Lista {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Organizzazioni"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Utenti"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+msgid "Dettaglio {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+msgid "Utente"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:23
+#: ./templates/Emails/add.php:23
+#: ./templates/Emails/edit.php:23
+#: ./templates/Faxes/add.php:23
+#: ./templates/Faxes/edit.php:23
+#: ./templates/MobilePhones/add.php:23
+#: ./templates/MobilePhones/edit.php:23
+#: ./templates/Organisations/view.php:69
+#: ./templates/Phones/add.php:23
+#: ./templates/Phones/edit.php:23
+#: ./templates/TelegramChats/add.php:23
+#: ./templates/TelegramChats/edit.php:23
+#: ./templates/Users/view.php:70
+msgid "Gestione recapiti"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:31
+msgid "Recapiti associati a {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Deliveries/index.php:41
+msgid "Cellulare: {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:50
+#: ./templates/MobilePhones/add.php:47
+#: ./templates/MobilePhones/edit.php:47
+msgid "Cellulare"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:51
+#: ./templates/Deliveries/index.php:93
+#: ./templates/Deliveries/index.php:135
+#: ./templates/Deliveries/index.php:216
+#: ./templates/Emails/add.php:49
+#: ./templates/Emails/edit.php:49
+#: ./templates/Faxes/add.php:49
+#: ./templates/Faxes/edit.php:49
+#: ./templates/MobilePhones/add.php:49
+#: ./templates/MobilePhones/edit.php:49
+#: ./templates/TelegramChats/add.php:48
+#: ./templates/TelegramChats/edit.php:48
+msgid "Ricevi notifiche a questo recapito"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:62
+#: ./templates/Deliveries/index.php:104
+#: ./templates/Deliveries/index.php:146
+#: ./templates/Deliveries/index.php:186
+#: ./templates/Deliveries/index.php:226
+#: ./templates/Groups/index.php:45
+#: ./templates/Groups/view.php:43
+#: ./templates/Organisations/index.php:53
+#: ./templates/Organisations/view.php:70
+#: ./templates/Users/index.php:49
+#: ./templates/Users/view.php:71
+msgid "Modifica"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:63
+msgid "Sei sicuro che vuoi cancellare il Cellulare \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:73
+#: ./templates/MobilePhones/add.php:28
+msgid "Aggiungi Cellulare"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:84
+msgid "Fax: {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:92
+#: ./templates/Faxes/add.php:47
+#: ./templates/Faxes/edit.php:47
+msgid "Fax"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:105
+msgid "Sei sicuro che vuoi cancellare il Fax \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:115
+#: ./templates/Faxes/add.php:28
+msgid "Aggiungi Fax"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:126
+msgid "Email: {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:134
+#: ./templates/Emails/add.php:47
+#: ./templates/Emails/edit.php:47
+msgid "Email"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:147
+msgid "Sei sicuro che vuoi cancellare l'Email \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:157
+#: ./templates/Emails/add.php:28
+msgid "Aggiungi Email"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:168
+msgid "Telefono: {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:176
+#: ./templates/Phones/add.php:47
+#: ./templates/Phones/edit.php:47
+msgid "Telefono"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:187
+msgid "Sei sicuro che vuoi cancellare il Telefono \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:197
+#: ./templates/Phones/add.php:28
+msgid "Aggiungi Telefono"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:208
+msgid "Chat Telegram: {0}"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:215
+msgid "ID"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:227
+msgid "Sei sicuro che vuoi cancellare la Chat Telegram con ID \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Deliveries/index.php:237
+#: ./templates/TelegramChats/add.php:28
+msgid "Aggiungi Chat Telegram"
+msgstr ""
+
+#: ./templates/Emails/add.php:40
+msgid "Aggiungi Email per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Emails/add.php:54
+#: ./templates/Emails/edit.php:54
+#: ./templates/Faxes/add.php:54
+#: ./templates/Faxes/edit.php:54
+#: ./templates/Groups/add.php:45
+#: ./templates/Groups/edit.php:50
+#: ./templates/Groups/handle_capabilities.php:71
+#: ./templates/MobilePhones/add.php:54
+#: ./templates/MobilePhones/edit.php:54
+#: ./templates/Organisations/add.php:172
+#: ./templates/Organisations/edit.php:86
+#: ./templates/Phones/add.php:53
+#: ./templates/Phones/edit.php:53
+#: ./templates/TelegramChats/add.php:53
+#: ./templates/TelegramChats/edit.php:53
+#: ./templates/Users/add.php:57
+#: ./templates/Users/choose_new_password.php:8
+#: ./templates/Users/edit.php:62
+msgid "Salva"
+msgstr ""
+
+#: ./templates/Emails/edit.php:28
+msgid "Modifica Email"
+msgstr ""
+
+#: ./templates/Emails/edit.php:40
+msgid "Modifica Email per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Faxes/add.php:40
+msgid "Aggiungi Fax per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Faxes/edit.php:28
+msgid "Modifica Fax"
+msgstr ""
+
+#: ./templates/Faxes/edit.php:40
+msgid "Modifica Fax per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Groups/add.php:13
+#: ./templates/Groups/edit.php:13
+#: ./templates/Groups/handle_capabilities.php:13
+#: ./templates/Groups/index.php:13
+#: ./templates/Groups/index.php:24
+#: ./templates/Groups/view.php:13
+msgid "Lista dei Profili Utente"
+msgstr ""
+
+#: ./templates/Groups/add.php:18
+#: ./templates/Groups/add.php:31
+msgid "Nuovo Profilo Utente"
+msgstr ""
+
+#: ./templates/Groups/edit.php:18
+#: ./templates/Groups/handle_capabilities.php:18
+#: ./templates/Groups/view.php:18
+msgid "Dettaglio Profilo Utente"
+msgstr ""
+
+#: ./templates/Groups/edit.php:23
+#: ./templates/Groups/edit.php:36
+msgid "Modifica Profilo Utente"
+msgstr ""
+
+#: ./templates/Groups/handle_capabilities.php:35
+msgid "Competenze associate al Profilo Utente \"{0}\""
+msgstr ""
+
+#: ./templates/Groups/handle_capabilities.php:45
+msgid "Gruppo di competenze non visibile e non configurabile dai non SYSADMIN"
+msgstr ""
+
+#: ./templates/Groups/handle_capabilities.php:52
+msgid "Gruppo di competenze \"{0}\""
+msgstr ""
+
+#: ./templates/Groups/index.php:44
+#: ./templates/Organisations/index.php:52
+#: ./templates/Users/index.php:48
+#: ./templates/plugin/AdminLTE/element/nav-top.php:118
+msgid "Dettaglio"
+msgstr ""
+
+#: ./templates/Groups/index.php:46
+#: ./templates/Groups/view.php:44
+msgid "Sei sicuro che vuoi cancellare il profilo \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Groups/view.php:30
+msgid "Informazioni Profilo Utente"
+msgstr ""
+
+#: ./templates/Maps/index.php:25
+msgid "Mappa"
+msgstr ""
+
+#: ./templates/Maps/index.php:30
+msgid "Campo esistente appartenente al form ospite"
+msgstr ""
+
+#: ./templates/Maps/index.php:37
+msgid "Posizione Evento"
+msgstr ""
+
+#: ./templates/Maps/index.php:54
+msgid "Collezione di geometrie"
+msgstr ""
+
+#: ./templates/Maps/index.php:65
+#: ./templates/Organisations/add.php:74
+msgid "Longitudine"
+msgstr ""
+
+#: ./templates/Maps/index.php:76
+#: ./templates/Organisations/add.php:85
+msgid "Latitudine"
+msgstr ""
+
+#: ./templates/Maps/index.php:87
+#: ./templates/Organisations/add.php:96
+#: ./templates/Organisations/add.php:158
+#: ./templates/Organisations/edit.php:62
+#: ./templates/Organisations/view.php:51
+msgid "Coordinate (Longitudine Latitudine)"
+msgstr ""
+
+#: ./templates/Maps/index.php:98
+#: ./templates/Organisations/add.php:107
+msgid "Cap"
+msgstr ""
+
+#: ./templates/Maps/index.php:142
+#: ./templates/Organisations/add.php:151
+msgid "Descrizione luogo"
+msgstr ""
+
+#: ./templates/MobilePhones/add.php:40
+msgid "Aggiungi Cellulare per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/MobilePhones/edit.php:28
+msgid "Modifica Cellulare"
+msgstr ""
+
+#: ./templates/MobilePhones/edit.php:40
+msgid "Modifica Cellulare per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Organisations/add.php:13
+#: ./templates/Organisations/edit.php:13
+#: ./templates/Organisations/index.php:13
+#: ./templates/Organisations/view.php:13
+msgid "Lista Organizzazioni"
+msgstr ""
+
+#: ./templates/Organisations/add.php:18
+#: ./templates/Organisations/add.php:30
+msgid "Nuova Organizzazione"
+msgstr ""
+
+#: ./templates/Organisations/add.php:39
+#: ./templates/Organisations/edit.php:43
+#: ./templates/Organisations/view.php:38
+msgid "Tipo organizzazione"
+msgstr ""
+
+#: ./templates/Organisations/add.php:46
+#: ./templates/Organisations/edit.php:50
+#: ./templates/Organisations/view.php:45
+msgid "Posizione Organizzazione"
+msgstr ""
+
+#: ./templates/Organisations/edit.php:18
+#: ./templates/Organisations/view.php:18
+#: ./templates/Organisations/view.php:29
+msgid "Dettaglio Organizzazione"
+msgstr ""
+
+#: ./templates/Organisations/edit.php:23
+#: ./templates/Organisations/edit.php:34
+msgid "Modifica Organizzazione"
+msgstr ""
+
+#: ./templates/Organisations/index.php:23
+msgid "Lista delle {0} Organizzazioni"
+msgstr ""
+
+#: ./templates/Organisations/index.php:23
+#: ./templates/Users/index.php:23
+msgid "{0} su {1}"
+msgstr ""
+
+#: ./templates/Organisations/index.php:54
+#: ./templates/Organisations/view.php:71
+msgid "Sei sicuro che vuoi cancellare l'organizzazione \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Phones/add.php:40
+msgid "Aggiungi Telefono per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Phones/edit.php:28
+msgid "Modifica Telefono"
+msgstr ""
+
+#: ./templates/Phones/edit.php:40
+msgid "Modifica Telefono per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/TelegramChats/add.php:40
+msgid "Aggiungi Chat Telegram per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/TelegramChats/add.php:47
+#: ./templates/TelegramChats/edit.php:47
+msgid "Chat Telegram ID"
+msgstr ""
+
+#: ./templates/TelegramChats/edit.php:28
+msgid "Modifica Chat Telegram"
+msgstr ""
+
+#: ./templates/TelegramChats/edit.php:40
+msgid "Modifica Chat Telegram per {0} \"{1}\""
+msgstr ""
+
+#: ./templates/Users/add.php:13
+#: ./templates/Users/edit.php:13
+#: ./templates/Users/index.php:13
+#: ./templates/Users/view.php:13
+msgid "Lista Utenti"
+msgstr ""
+
+#: ./templates/Users/add.php:18
+#: ./templates/Users/add.php:31
+msgid "Nuovo Utente"
+msgstr ""
+
+#: ./templates/Users/add.php:38
+#: ./templates/Users/edit.php:43
+#: ./templates/Users/view.php:41
+msgid "Nome utente"
+msgstr ""
+
+#: ./templates/Users/add.php:39
+#: ./templates/Users/edit.php:44
+msgid "Password"
+msgstr ""
+
+#: ./templates/Users/add.php:42
+#: ./templates/Users/edit.php:47
+#: ./templates/Users/view.php:47
+msgid "Codice Fiscale"
+msgstr ""
+
+#: ./templates/Users/add.php:43
+#: ./templates/Users/edit.php:48
+#: ./templates/Users/view.php:49
+msgid "Data di nascita"
+msgstr ""
+
+#: ./templates/Users/add.php:44
+#: ./templates/Users/edit.php:49
+#: ./templates/Users/view.php:51
+msgid "Luogo di nascita"
+msgstr ""
+
+#: ./templates/Users/add.php:45
+#: ./templates/Users/edit.php:50
+#: ./templates/Users/view.php:53
+msgid "Sesso"
+msgstr ""
+
+#: ./templates/Users/add.php:47
+#: ./templates/Users/edit.php:52
+#: ./templates/Users/view.php:57
+msgid "Città"
+msgstr ""
+
+#: ./templates/Users/add.php:49
+#: ./templates/Users/edit.php:54
+#: ./templates/Users/view.php:61
+msgid "Lingua preferita"
+msgstr ""
+
+#: ./templates/Users/add.php:51
+#: ./templates/Users/edit.php:56
+msgid "Foto del profilo (solo jpeg di dimensioni 160x160!)"
+msgstr ""
+
+#: ./templates/Users/choose_new_password.php:4
+msgid "Imposta una nuova password"
+msgstr ""
+
+#: ./templates/Users/choose_new_password.php:5
+msgid "Digita la nuova password"
+msgstr ""
+
+#: ./templates/Users/choose_new_password.php:6
+msgid "Ridigita la nuova password"
+msgstr ""
+
+#: ./templates/Users/edit.php:18
+#: ./templates/Users/view.php:18
+msgid "Dettaglio Utente"
+msgstr ""
+
+#: ./templates/Users/edit.php:23
+#: ./templates/Users/edit.php:36
+msgid "Modifica Utente"
+msgstr ""
+
+#: ./templates/Users/index.php:23
+msgid "Lista dei {0} Utenti"
+msgstr ""
+
+#: ./templates/Users/index.php:50
+#: ./templates/Users/view.php:72
+msgid "Sei sicuro che vuoi cancellare l'utente \"{0}\" ?"
+msgstr ""
+
+#: ./templates/Users/login.php:4
+msgid "Accedi"
+msgstr ""
+
+#: ./templates/Users/login.php:8
+msgid "Login"
+msgstr ""
+
+#: ./templates/Users/password_recovery.php:4
+msgid "Inserisci un indirizzo email associato alla tua utenza"
+msgstr ""
+
+#: ./templates/Users/password_recovery.php:7
+msgid "Richiedi reset password"
+msgstr ""
+
+#: ./templates/Users/view.php:30
+msgid "Informazioni Utente"
+msgstr ""
+
+#: ./templates/Users/view.php:34
+msgid "Elimina foto"
+msgstr ""
+
+#: ./templates/Users/view.php:34
+msgid "Sei sicuro che vuoi eliminare la foto ?"
+msgstr ""
+
+#: ./templates/Users/view.php:62
+msgid "Non specificata"
+msgstr ""
+
+#: ./templates/Users/view.php:67
+msgid "Recapiti:"
+msgstr ""
+
+#: ./templates/cell/FilterInput/display.php:9
+#: ./templates/element/attachments.php:127
+msgid "Rimuovi"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:3
+#: ./templates/cell/Filters/display.php:113
+msgid "Filtri attivi"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:3
+#: ./templates/cell/Filters/display.php:116
+msgid "Filtri disattivati"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:15
+msgid "Aggiungi un filtro"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:34
+#: ./templates/cell/Filters/display.php:55
+msgid "Applica"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:39
+msgid "Reset"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:56
+msgid "Annulla"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:58
+msgid "A"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:59
+msgid "Dal Al"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:60
+#: ./templates/cell/Filters/display.php:87
+msgid "Oggi"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:62
+msgid "Dom"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:63
+msgid "Lun"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:64
+msgid "Mar"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:65
+msgid "Mer"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:66
+msgid "Gio"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:67
+msgid "Ven"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:68
+msgid "Sab"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:71
+msgid "Gennaio"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:72
+msgid "Febbraio"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:73
+msgid "Marzo"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:74
+msgid "Aprile"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:75
+msgid "Maggio"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:76
+msgid "Giugno"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:77
+msgid "Luglio"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:78
+msgid "Agosto"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:79
+msgid "Settembre"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:80
+msgid "Ottobre"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:81
+msgid "Novembre"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:82
+msgid "Dicembre"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:88
+msgid "Ieri"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:89
+msgid "Questa settimana"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:90
+msgid "Questo mese"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:91
+msgid "Lo scorso mese"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:92
+msgid "Ultimi 7 giorni"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:93
+msgid "Ultimi 15 giorni"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:94
+msgid "Ultimi 30 giorni"
+msgstr ""
+
+#: ./templates/cell/Filters/display.php:131
+msgid "Errore durante il recupero del filtro selezionato. Riprovare di nuovo"
+msgstr ""
+
+#: ./templates/element/Map.php:107
+#: ./templates/element/Map.php:118
+#: ./templates/element/Map.php:122
+msgid "OpenStreetMap ONLINE"
+msgstr ""
+
+#: ./templates/element/Map.php:107
+#: ./templates/element/Map.php:127
+#: ./templates/element/Map.php:131
+msgid "OpenStreetMap OFFLINE"
+msgstr ""
+
+#: ./templates/element/Map.php:312
+#: ./templates/element/Map.php:541
+msgid "Indirizzo non trovato o fuori dall'area di competenza"
+msgstr ""
+
+#: ./templates/element/Map.php:530
+msgid "Punto alle coordinate (EPSG:4326) Latitudine:"
+msgstr ""
+
+#: ./templates/element/Map.php:530
+msgid "Longitudine:"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:10
+msgid "Scegli un risultato:"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:30
+msgid "Inserisci un indirizzo o le coordinate (in formato EPSG:4326)"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:31
+msgid "Cerca un indirizzo"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:36
+msgid "Inserisci un punto in mappa"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:41
+msgid "Inserisci un poligono in mappa"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:46
+msgid "Inserisci un cerchio in mappa"
+msgstr ""
+
+#: ./templates/element/MapCore/MapPrimitives.php:51
+msgid "Cancella una geometria"
+msgstr ""
+
+#: ./templates/element/attachmentPreview.php:16
+msgid "Il tuo browser non supporta HTML5 video tag. Prova ad aggiornare il tuo browser."
+msgstr ""
+
+#: ./templates/element/attachmentPreview.php:35
+msgid "Anteprima non disponibile"
+msgstr ""
+
+#: ./templates/element/attachments.php:30
+msgid "di tipo: \"{0}\""
+msgstr ""
+
+#: ./templates/element/attachments.php:39
+msgid "Mostra allegati correlati"
+msgstr ""
+
+#: ./templates/element/attachments.php:48
+msgid "Allega un file "
+msgstr ""
+
+#: ./templates/element/attachments.php:48
+msgid "Allega files "
+msgstr ""
+
+#: ./templates/element/attachments.php:54
+msgid "Allega file pubblico "
+msgstr ""
+
+#: ./templates/element/attachments.php:54
+msgid "Allega un file privato "
+msgstr ""
+
+#: ./templates/element/attachments.php:54
+msgid "Allega files privati "
+msgstr ""
+
+#: ./templates/element/attachments.php:58
+msgid "Allega files..."
+msgstr ""
+
+#: ./templates/element/attachments.php:65
+msgid "Allega files {1} {0}"
+msgstr ""
+
+#: ./templates/element/attachments.php:118
+msgid "latitudine"
+msgstr ""
+
+#: ./templates/element/attachments.php:119
+msgid "longitudine"
+msgstr ""
+
+#: ./templates/layout/error.php:38
+msgid "Back"
+msgstr ""
+
+#: ./templates/plugin/AdminLTE/element/aside-control-sidebar.php:4
+msgid "Notifiche"
+msgstr ""
+
+#: ./templates/plugin/AdminLTE/element/footer.php:6
+msgid "Versione"
+msgstr ""
+
+#: ./templates/plugin/AdminLTE/element/footer.php:9
+msgid "Tutti i diritti riservati"
+msgstr ""
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:67
+msgid "Nuove notifiche: {0}"
+msgstr ""
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:91
+msgid "Segna tutte le notifiche come lette"
+msgstr ""
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:121
+msgid "Esci"
+msgstr ""
+
diff --git a/idrocap_wa/resources/locales/en/default.po b/idrocap_wa/resources/locales/en/default.po
new file mode 100644
index 0000000..bd63efb
--- /dev/null
+++ b/idrocap_wa/resources/locales/en/default.po
@@ -0,0 +1,1709 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"POT-Creation-Date: 2023-03-03 14:35+0000\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: ./src/Controller/Api/AttachmentsController.php:36
+#: ./src/Controller/AttachmentsController.php:38
+#: ./src/Controller/AttachmentsController.php:68
+msgid "Allegato non trovato"
+msgstr "Attachment not found"
+
+#: ./src/Controller/Api/AttachmentsController.php:37
+#: ./src/Controller/AttachmentsController.php:39
+#: ./src/Controller/AttachmentsController.php:69
+msgid "Non hai i permessi necessari per visionare l'allegato"
+msgstr "You do not have permission to view the attachment"
+
+#: ./src/Controller/Api/OrganisationsController.php:104
+msgid "Organizzazione non trovata!"
+msgstr "Organisation not found!"
+
+#: ./src/Controller/Api/UsersController.php:160
+msgid "Utente non trovato!"
+msgstr "User not found!"
+
+#: ./src/Controller/AppController.php:95
+msgid "SYSADMIN"
+msgstr "SYSADMIN"
+
+#: ./src/Controller/AppController.php:99
+#: ./templates/Capabilities/index.php:13
+#: ./templates/Groups/handle_capabilities.php:23
+#: ./templates/Groups/view.php:42
+msgid "Gestione competenze"
+msgstr "Handle capabilities"
+
+#: ./src/Controller/AppController.php:104
+msgid "Test notifiche"
+msgstr "Test notification system"
+
+#: ./src/Controller/AppController.php:107
+msgid "Procedendo verranno inviate notifiche a tutti gli utenti e le organizzaioni che possiedono uno o più recapiti abilitati alle notifiche! Sei sicuro che vuoi continuare ?"
+msgstr "Notifications will be sent to all users and organisations that have at least one notification enabled contact! Are you sure you want to proceed ?"
+
+#: ./src/Controller/CapabilitiesController.php:24
+#: ./src/Controller/CapabilitiesController.php:54
+#: ./src/Controller/CapabilitiesController.php:97
+#: ./src/Controller/CapabilitiesController.php:135
+#: ./src/Controller/CapabilitiesController.php:177
+#: ./src/Controller/GroupsController.php:31
+#: ./src/Controller/GroupsController.php:54
+#: ./src/Controller/GroupsController.php:92
+#: ./src/Controller/GroupsController.php:112
+#: ./src/Controller/GroupsController.php:136
+#: ./src/Controller/GroupsController.php:160
+#: ./src/Controller/GroupsController.php:183
+#: ./src/Controller/OrganisationsController.php:32
+#: ./src/Controller/OrganisationsController.php:60
+#: ./src/Controller/OrganisationsController.php:109
+#: ./src/Controller/OrganisationsController.php:131
+#: ./src/Controller/OrganisationsController.php:155
+#: ./src/Controller/OrganisationsController.php:181
+#: ./src/Controller/UsersController.php:38
+#: ./src/Controller/UsersController.php:70
+#: ./src/Controller/UsersController.php:113
+#: ./src/Controller/UsersController.php:119
+#: ./src/Controller/UsersController.php:136
+#: ./src/Controller/UsersController.php:177
+#: ./src/Controller/UsersController.php:211
+#: ./src/Controller/UsersController.php:216
+msgid "Non hai i permessi necessari"
+msgstr "You do not have needed permissions"
+
+#: ./src/Controller/CapabilitiesController.php:79
+msgid "Competenza \"{0}\" nascosta con successo!"
+msgstr "Capability \"{0}\" successfully hidden!"
+
+#: ./src/Controller/CapabilitiesController.php:82
+msgid "Errore durante il tentativo di nascondere la Competenza \"{0}\"!"
+msgstr "Error trying to hide the capability \"{0}\"!"
+
+#: ./src/Controller/CapabilitiesController.php:117
+msgid "Competenza \"{0}\" resa visibile con successo!"
+msgstr "Capability \"{0}\" successfully set unhidden!"
+
+#: ./src/Controller/CapabilitiesController.php:120
+msgid "Errore durante il tentativo di rendere visibile la Competenza \"{0}\"!"
+msgstr "Error trying to set the capability \"{0}\" unhidden!"
+
+#: ./src/Controller/CapabilitiesController.php:159
+msgid "Competenza \"{0}\" cancellata con successo!"
+msgstr "Capability \"{0}\" successfully deleted!"
+
+#: ./src/Controller/CapabilitiesController.php:162
+msgid "Errore durante la cancellazione della Competenza \"{0}\"!"
+msgstr "Error trying to delete the Capability \"{0}\"!"
+
+#: ./src/Controller/CapabilitiesController.php:197
+msgid "Competenza \"{0}\" ripristinata con successo!"
+msgstr "Capability \"{0}\" successfully restored!"
+
+#: ./src/Controller/CapabilitiesController.php:200
+msgid "Errore durante il ripristino della Competenza \"{0}\"!"
+msgstr "Error trying to restore the capability \"{0}\"!"
+
+#: ./src/Controller/DeliveriesController.php:27
+#: ./src/Controller/DeliveriesController.php:125
+#: ./src/Controller/EmailsController.php:25
+#: ./src/Controller/EmailsController.php:64
+#: ./src/Controller/FaxesController.php:25
+#: ./src/Controller/FaxesController.php:64
+#: ./src/Controller/MobilePhonesController.php:26
+#: ./src/Controller/MobilePhonesController.php:65
+#: ./src/Controller/PhonesController.php:25
+#: ./src/Controller/PhonesController.php:64
+#: ./src/Controller/TelegramChatsController.php:25
+#: ./src/Controller/TelegramChatsController.php:63
+msgid "Gestione recapiti non prevista per questa tipologia di oggetto"
+msgstr "Contacts management is not expected for this type of object"
+
+#: ./src/Controller/DeliveriesController.php:29
+#: ./src/Controller/DeliveriesController.php:127
+#: ./src/Controller/EmailsController.php:26
+#: ./src/Controller/EmailsController.php:65
+#: ./src/Controller/FaxesController.php:26
+#: ./src/Controller/FaxesController.php:65
+#: ./src/Controller/MobilePhonesController.php:27
+#: ./src/Controller/MobilePhonesController.php:66
+#: ./src/Controller/PhonesController.php:26
+#: ./src/Controller/PhonesController.php:65
+#: ./src/Controller/TelegramChatsController.php:26
+#: ./src/Controller/TelegramChatsController.php:64
+msgid "questa organizzazione"
+msgstr "this organisation"
+
+#: ./src/Controller/DeliveriesController.php:29
+#: ./src/Controller/DeliveriesController.php:127
+#: ./src/Controller/EmailsController.php:26
+#: ./src/Controller/EmailsController.php:65
+#: ./src/Controller/FaxesController.php:26
+#: ./src/Controller/FaxesController.php:65
+#: ./src/Controller/MobilePhonesController.php:27
+#: ./src/Controller/MobilePhonesController.php:66
+#: ./src/Controller/PhonesController.php:26
+#: ./src/Controller/PhonesController.php:65
+#: ./src/Controller/TelegramChatsController.php:26
+#: ./src/Controller/TelegramChatsController.php:64
+msgid "questo utente"
+msgstr "this user"
+
+#: ./src/Controller/DeliveriesController.php:30
+msgid "Non hai i permessi per visualizzare i recapiti per {0}"
+msgstr "You do not have permission to view contacts for {0}"
+
+#: ./src/Controller/DeliveriesController.php:128
+msgid "Non hai i permessi per eliminare i recapiti di questo tipo per {0}"
+msgstr "You do not have permission to delete contacts of this type for {0}"
+
+#: ./src/Controller/DeliveriesController.php:134
+#: ./src/Model/Entity/Actor.php:87
+msgid "Cellulare ({0}): {1}"
+msgstr "Mobile Phone ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:137
+#: ./src/Model/Entity/Actor.php:97
+msgid "Fax ({0}): {1}"
+msgstr "Fax ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:140
+#: ./src/Model/Entity/Actor.php:107
+msgid "Email ({0}): {1}"
+msgstr "Email ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:143
+#: ./src/Model/Entity/Actor.php:117
+msgid "Telefono ({0}): {1}"
+msgstr "Phone ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:146
+#: ./src/Model/Entity/Actor.php:127
+msgid "Telegram Chat ID: {0}"
+msgstr "Telegram Chat ID: {0}"
+
+#: ./src/Controller/DeliveriesController.php:154
+msgid "Il recapito \"{0}\" è stato cancellato con successo"
+msgstr "Contact \"{0}\" successfully deleted"
+
+#: ./src/Controller/DeliveriesController.php:156
+msgid "Errore durante la cancellazione del recapito {0}. Riprovare di nuovo."
+msgstr "Error trying to delete contact {0}. Please try again."
+
+#: ./src/Controller/EmailsController.php:27
+#: ./src/Controller/FaxesController.php:27
+#: ./src/Controller/MobilePhonesController.php:28
+#: ./src/Controller/PhonesController.php:27
+#: ./src/Controller/TelegramChatsController.php:27
+msgid "Non hai i permessi per aggiungere i recapiti di questo tipo per {0}"
+msgstr "You do not have permission to add this type of contact for {0}"
+
+#: ./src/Controller/EmailsController.php:39
+msgid "L'Email è stata aggiunta con successo."
+msgstr "Email successfully updated."
+
+#: ./src/Controller/EmailsController.php:43
+msgid "Errore durante l'aggiunta dell'Email: {0}"
+msgstr "Error trying adding Email: {0}"
+
+#: ./src/Controller/EmailsController.php:66
+#: ./src/Controller/FaxesController.php:66
+#: ./src/Controller/MobilePhonesController.php:67
+#: ./src/Controller/PhonesController.php:66
+#: ./src/Controller/TelegramChatsController.php:65
+msgid "Non hai i permessi per modificare i recapiti di questo tipo per {0}"
+msgstr "You do not have permission to edit this type of contact for {0}"
+
+#: ./src/Controller/EmailsController.php:71
+msgid "L'Email è stata modificata con successo."
+msgstr "Email successfully updated."
+
+#: ./src/Controller/EmailsController.php:75
+msgid "Errore durante la modifica dell'Email. Riprovare di nuovo"
+msgstr "Error trying to edit Email contact. Please try again"
+
+#: ./src/Controller/FaxesController.php:39
+msgid "Il Fax è stato aggiunto con successo."
+msgstr "Fax successfully added."
+
+#: ./src/Controller/FaxesController.php:43
+msgid "Errore durante l'aggiunta del Fax: {0}"
+msgstr "Error trying to add Fax: {0}"
+
+#: ./src/Controller/FaxesController.php:71
+msgid "Il Fax è stato modificato con successo."
+msgstr "Fax successfully updated."
+
+#: ./src/Controller/FaxesController.php:75
+msgid "Errore durante la modifica del Fax. Riprovare di nuovo"
+msgstr "Error trying to edit Fax. Please try again"
+
+#: ./src/Controller/GroupsController.php:57
+#: ./src/Controller/OrganisationsController.php:63
+#: ./templates/Capabilities/index.php:41
+#: ./templates/Deliveries/index.php:49
+#: ./templates/Deliveries/index.php:91
+#: ./templates/Deliveries/index.php:133
+#: ./templates/Deliveries/index.php:175
+#: ./templates/Emails/add.php:48
+#: ./templates/Emails/edit.php:48
+#: ./templates/Faxes/add.php:48
+#: ./templates/Faxes/edit.php:48
+#: ./templates/Groups/add.php:38
+#: ./templates/Groups/edit.php:43
+#: ./templates/Groups/index.php:31
+#: ./templates/Groups/view.php:35
+#: ./templates/MobilePhones/add.php:48
+#: ./templates/MobilePhones/edit.php:48
+#: ./templates/Organisations/index.php:29
+#: ./templates/Phones/add.php:48
+#: ./templates/Phones/edit.php:48
+msgid "Descrizione"
+msgstr "Description"
+
+#: ./src/Controller/GroupsController.php:58
+#: ./templates/Groups/add.php:39
+#: ./templates/Groups/edit.php:44
+#: ./templates/Groups/index.php:32
+#: ./templates/Groups/view.php:37
+msgid "Profilo Default"
+msgstr "Default Profile"
+
+#: ./src/Controller/GroupsController.php:59
+#: ./templates/Groups/add.php:40
+#: ./templates/Groups/edit.php:45
+#: ./templates/Groups/index.php:33
+#: ./templates/Groups/view.php:39
+msgid "Profilo Amministratore"
+msgstr "Admin Profile"
+
+#: ./src/Controller/GroupsController.php:64
+#: ./src/Controller/GroupsController.php:67
+#: ./templates/Deliveries/index.php:60
+#: ./templates/Deliveries/index.php:102
+#: ./templates/Deliveries/index.php:144
+#: ./templates/Deliveries/index.php:224
+#: ./templates/Groups/index.php:41
+#: ./templates/Groups/index.php:42
+#: ./templates/Groups/view.php:38
+#: ./templates/Groups/view.php:40
+msgid "SI"
+msgstr "YES"
+
+#: ./src/Controller/GroupsController.php:64
+#: ./src/Controller/GroupsController.php:67
+#: ./templates/Deliveries/index.php:60
+#: ./templates/Deliveries/index.php:102
+#: ./templates/Deliveries/index.php:144
+#: ./templates/Deliveries/index.php:224
+#: ./templates/Groups/index.php:41
+#: ./templates/Groups/index.php:42
+#: ./templates/Groups/view.php:38
+#: ./templates/Groups/view.php:40
+msgid "NO"
+msgstr "NO"
+
+#: ./src/Controller/GroupsController.php:118
+msgid "Profilo Utente creato con successo."
+msgstr "User Profile successfully created."
+
+#: ./src/Controller/GroupsController.php:122
+msgid "Errore durante la creazione del Profilo Utente: {0}"
+msgstr "Error trying to create User Profile: {0}"
+
+#: ./src/Controller/GroupsController.php:142
+#: ./src/Controller/GroupsController.php:206
+msgid "Profilo Utente \"{0}\" modificato con successo."
+msgstr "User Profile \"{0}\" successfully updated."
+
+#: ./src/Controller/GroupsController.php:146
+#: ./src/Controller/GroupsController.php:209
+msgid "Errore durante la modifica del Profilo Utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to edit the \"{0}\" User Profile. Please try again."
+
+#: ./src/Controller/GroupsController.php:166
+msgid "Il Profilo Utente \"{0}\" è stato cancellato con successo"
+msgstr "\"{0}\" User Profile successfully deleted"
+
+#: ./src/Controller/GroupsController.php:168
+msgid "Errore durante la cancellazione del Profilo Utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to delete the \"{0}\" User Profile. Please try again."
+
+#: ./src/Controller/MapsController.php:131
+msgid "Punto alle coordinate (EPSG:4326) Latitudine: {0}, Longitudine: {1}"
+msgstr "Point at coordinates (EPSG:4326) Latitude: {0}, Longitude: {1}"
+
+#: ./src/Controller/MobilePhonesController.php:40
+msgid "Il Cellulare è stato aggiunto con successo."
+msgstr "Mobile Phone contact successfully created."
+
+#: ./src/Controller/MobilePhonesController.php:44
+msgid "Errore durante l'aggiunta del Cellulare: {0}"
+msgstr "Error trying to create Mobile Phone: {0}"
+
+#: ./src/Controller/MobilePhonesController.php:72
+msgid "Il Cellulare è stato modificato con successo."
+msgstr "Mobile Phone successfully updated."
+
+#: ./src/Controller/MobilePhonesController.php:76
+msgid "Errore durante la modifica del Cellulare. Riprovare di nuovo"
+msgstr "Error trying to edit Mobile Phone. Please try again"
+
+#: ./src/Controller/NotificationsController.php:51
+msgid "Errore durante la cancellazione della notifica: "
+msgstr "Error trying to delete the notification: "
+
+#: ./src/Controller/OrganisationsController.php:64
+#: ./templates/Organisations/add.php:38
+#: ./templates/Organisations/edit.php:42
+#: ./templates/Organisations/index.php:30
+#: ./templates/Organisations/view.php:37
+msgid "Acronimo"
+msgstr "Acronym"
+
+#: ./src/Controller/OrganisationsController.php:65
+#: ./templates/Organisations/index.php:31
+msgid "Tipologia"
+msgstr "Typology"
+
+#: ./src/Controller/OrganisationsController.php:66
+#: ./templates/Maps/index.php:131
+#: ./templates/Organisations/add.php:140
+#: ./templates/Organisations/add.php:159
+#: ./templates/Organisations/edit.php:63
+#: ./templates/Organisations/index.php:32
+#: ./templates/Organisations/view.php:52
+#: ./templates/Users/add.php:46
+#: ./templates/Users/edit.php:51
+#: ./templates/Users/view.php:55
+msgid "Indirizzo"
+msgstr "Address"
+
+#: ./src/Controller/OrganisationsController.php:67
+#: ./templates/Maps/index.php:120
+#: ./templates/Organisations/add.php:129
+#: ./templates/Organisations/add.php:161
+#: ./templates/Organisations/edit.php:65
+#: ./templates/Organisations/index.php:34
+#: ./templates/Organisations/view.php:54
+msgid "Comune"
+msgstr "District"
+
+#: ./src/Controller/OrganisationsController.php:68
+#: ./templates/Organisations/add.php:160
+#: ./templates/Organisations/edit.php:64
+#: ./templates/Organisations/index.php:33
+#: ./templates/Organisations/view.php:53
+#: ./templates/Users/add.php:48
+#: ./templates/Users/edit.php:53
+#: ./templates/Users/view.php:59
+msgid "CAP"
+msgstr "ZIP code"
+
+#: ./src/Controller/OrganisationsController.php:69
+#: ./templates/Maps/index.php:109
+#: ./templates/Organisations/add.php:118
+#: ./templates/Organisations/add.php:162
+#: ./templates/Organisations/edit.php:66
+#: ./templates/Organisations/index.php:35
+#: ./templates/Organisations/view.php:55
+msgid "Provincia"
+msgstr "Province"
+
+#: ./src/Controller/OrganisationsController.php:70
+#: ./src/Controller/UsersController.php:76
+#: ./templates/Organisations/index.php:36
+#: ./templates/Organisations/view.php:56
+#: ./templates/Users/index.php:32
+msgid "Recapiti"
+msgstr "Contacts"
+
+#: ./src/Controller/OrganisationsController.php:137
+msgid "Organizzazione creata con successo."
+msgstr "Organisation successfully created."
+
+#: ./src/Controller/OrganisationsController.php:141
+msgid "Errore durante la creazione dell'organizzazione: {0}"
+msgstr "Error trying to create the organisation: {0}"
+
+#: ./src/Controller/OrganisationsController.php:163
+msgid "Organizzazione \"{0}\" modificata con successo."
+msgstr "Organisation \"{0}\" successfully updated."
+
+#: ./src/Controller/OrganisationsController.php:167
+msgid "Errore durante la modifica dell'organizzazione \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to edit the organisation \"{0}\". Please try again."
+
+#: ./src/Controller/OrganisationsController.php:188
+msgid "Impossibile eliminare l'organizzazione \"{0}\". Ci sono {1} utenti collegati ad essa."
+msgstr "Unable to delete the organisation \"{0}\". There are {1} belonging users."
+
+#: ./src/Controller/OrganisationsController.php:193
+msgid "L'organizzazione \"{0}\" è stata cancellata con successo"
+msgstr "Organisation \"{0}\" successfully deleted"
+
+#: ./src/Controller/OrganisationsController.php:195
+msgid "Errore durante la cancellazione dell'organizzazione \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to delete the organisation \"{0}\". Please try again."
+
+#: ./src/Controller/PhonesController.php:39
+msgid "Il Telefono è stato aggiunto con successo."
+msgstr "Phone successfully created."
+
+#: ./src/Controller/PhonesController.php:43
+msgid "Errore durante l'aggiunta del Telefono: {0}"
+msgstr "Error trying to create Phone: {0}"
+
+#: ./src/Controller/PhonesController.php:71
+msgid "Il Telefono è stato modificato con successo."
+msgstr "Phone successfully updated."
+
+#: ./src/Controller/PhonesController.php:75
+msgid "Errore durante la modifica del Telefono. Riprovare di nuovo"
+msgstr "Error trying to edit Phone. Please try again"
+
+#: ./src/Controller/TelegramChatsController.php:39
+msgid "La Chat Telegram è stata aggiunta con successo."
+msgstr "Telegram Chat successfully created."
+
+#: ./src/Controller/TelegramChatsController.php:43
+msgid "Errore durante l'aggiunta della Chat Telegram: {0}"
+msgstr "Error trying to create Telegram Chat: {0}"
+
+#: ./src/Controller/TelegramChatsController.php:70
+msgid "La Chat Telegram è stata modificata con successo."
+msgstr "Telegram Chat successfully created."
+
+#: ./src/Controller/TelegramChatsController.php:74
+msgid "Errore durante la modifica della Chat Telegram. Riprovare di nuovo"
+msgstr "Error trying to edit Telegram Chat. Please try again"
+
+#: ./src/Controller/UsersController.php:73
+#: ./templates/Users/add.php:41
+#: ./templates/Users/edit.php:46
+#: ./templates/Users/index.php:29
+#: ./templates/Users/view.php:45
+msgid "Cognome"
+msgstr "Surname"
+
+#: ./src/Controller/UsersController.php:74
+#: ./templates/ControllableObjects/get_attachments.php:59
+#: ./templates/Organisations/add.php:37
+#: ./templates/Organisations/edit.php:41
+#: ./templates/Organisations/view.php:36
+#: ./templates/Users/add.php:40
+#: ./templates/Users/edit.php:45
+#: ./templates/Users/index.php:30
+#: ./templates/Users/view.php:43
+msgid "Nome"
+msgstr "Name"
+
+#: ./src/Controller/UsersController.php:75
+#: ./templates/Users/index.php:31
+msgid "Username"
+msgstr "Username"
+
+#: ./src/Controller/UsersController.php:77
+#: ./templates/Users/add.php:52
+#: ./templates/Users/edit.php:57
+#: ./templates/Users/index.php:33
+#: ./templates/Users/view.php:65
+msgid "Profili"
+msgstr "Profiles"
+
+#: ./src/Controller/UsersController.php:78
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+#: ./templates/Users/add.php:50
+#: ./templates/Users/edit.php:55
+#: ./templates/Users/index.php:34
+#: ./templates/Users/view.php:63
+msgid "Organizzazione"
+msgstr "Organisation"
+
+#: ./src/Controller/UsersController.php:156
+msgid "Utente creato con successo."
+msgstr "User successfully created."
+
+#: ./src/Controller/UsersController.php:160
+msgid "Errore durante la creazione dell'utente: {0}"
+msgstr "Error trying to create user: {0}"
+
+#: ./src/Controller/UsersController.php:190
+msgid "Utente \"{0}\" modificato con successo."
+msgstr "User \"{0}\" successfully updated."
+
+#: ./src/Controller/UsersController.php:194
+msgid "Errore durante la modifica dell'utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to edit user \"{0}\". Please try again."
+
+#: ./src/Controller/UsersController.php:219
+msgid "L'utente \"{0}\" è stato cancellato con successo"
+msgstr "User \"{0}\" successfully deleted"
+
+#: ./src/Controller/UsersController.php:221
+msgid "Errore durante la cancellazione dell'utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to delete user \"{0}\". Please try again."
+
+#: ./src/Controller/UsersController.php:244
+msgid "Ho dimenticato la mia password"
+msgstr "I forgot my password"
+
+#: ./src/Controller/UsersController.php:256
+msgid "Logout eseguito con successo."
+msgstr "Successfully logged out."
+
+#: ./src/Controller/UsersController.php:294
+msgid "Inserire un indirizzo email valido!"
+msgstr "Insert a valid email address!"
+
+#: ./src/Controller/UsersController.php:306
+msgid "A breve riceverai un'email all'indirizzo \"{0}\" con le istruzioni per eseguire il reset della password per il tuo account con username \"{1}\"."
+msgstr "You will receive shortly an email at \"{0}\" with the instructions to reset the password for your account with username \"{1}\"."
+
+#: ./src/Controller/UsersController.php:311
+msgid "L'indirizzo email inserito non risulta presente"
+msgstr "The email address you inserted is not valid or does not exists"
+
+#: ./src/Controller/UsersController.php:316
+#: ./src/Controller/UsersController.php:364
+msgid "Ritorna al login"
+msgstr "Back to login"
+
+#: ./src/Controller/UsersController.php:332
+msgid "Impossibile completare la procedura di recupero password."
+msgstr "Unable to complete reset password procedure. Please try again."
+
+#: ./src/Controller/UsersController.php:355
+msgid "Impossibile cambiare la password"
+msgstr "Unable to change the password"
+
+#: ./src/Controller/UsersController.php:359
+msgid "La nuova password non è valida e/o le 2 password non coincidono"
+msgstr "Either the new password is invalid or the two passwords don't match"
+
+#: ./src/Controller/UsersController.php:397
+msgid "Errore durante l'eliminazione della foto utente!"
+msgstr "Error trying to delete the user photo!"
+
+#: ./src/Controller/UsersController.php:399
+msgid "Foto utente eliminata con successo"
+msgstr "User photo successfully deleted"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:41
+msgid "Test Test Test"
+msgstr "Test Test Test"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:43
+msgid "Hai ricevuto questo messaggio di test perchè sei registrato/a sulla piattaforma {0} ed hai almeno un recapito abilitato alla ricezione delle notifiche"
+msgstr "You're receiving this message because you are a registered user to {0} platform and you have at least one notification enabled contact"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:46
+msgid "Recupero password {0}"
+msgstr "{0} password reset"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:50
+msgid "Hai ricevuto questo messaggio perchè sei registrato/a sulla piattaforma {0} ed è stata richiesta la procedura di recupero credenziali per il tuo account. Se non hai richiesto tale procedura ti preghiamo di ignorare questo messaggio. Per accedere a {0} utilizza il seguente username: \" {1} \" . Clicca sul seguente link per impostare una nuova password "
+msgstr "You're receiving this message because you are a registered user to {0} platform and you requested a password reset for your account. Plese disregard this message if you didn't request it or if you changed your mind. Please use the following username to gain access to your account: \" {1} \" . Follow this link to reset your password instead "
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:53
+msgid "{0} mancante"
+msgstr "Missing \"{0}\" notification code"
+
+#: ./src/Model/Behavior/AttachmentsBehavior.php:132
+msgid "L'allegato è obbligatorio!"
+msgstr "The attachment is mandatory!"
+
+#: ./src/Model/Entity/ControllableObject.php:241
+msgid "Le coordinate inserite per georeferenziare uno o più allegati non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell'area di competenza della piattaforma."
+msgstr "The given coordinates used to georeferencing one or more attachments are not valid. Please check that they are in the expected format (WGS84) and that they identify a point inside the platform configured bounding box."
+
+#: ./src/Model/Table/EmailsTable.php:107
+msgid "Indirizzo email già presente a sistema!"
+msgstr "Email address already exists!"
+
+#: ./src/Model/Table/FaxesTable.php:103
+msgid "Fax già presente a sistema!"
+msgstr "Fax already exists!"
+
+#: ./src/Model/Table/MobilePhonesTable.php:107
+msgid "Cellulare già presente a sistema!"
+msgstr "Mobile Phone already exists!"
+
+#: ./src/Model/Table/OrganisationsTable.php:169
+msgid "Le geometrie inserite per georeferenziare l'organizzazione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell'area di competenza della piattaforma."
+msgstr "The inserted geometries used to georeferenciate the organisation, are not valid. Please check that they are in the expected format (WGS84) and that they identify a point inside the platform configured bounding box."
+
+#: ./src/Model/Table/PhonesTable.php:99
+msgid "Telefono già presente a sistema!"
+msgstr "Phone already exists!"
+
+#: ./src/Model/Table/PushNotificationsTable.php:97
+msgid "Non puoi associare nuovamente questo token allo stesso utente"
+msgstr "You cannot use this push notification token again with this user"
+
+#: ./src/Model/Table/UsersTable.php:106
+msgid "La password deve contenere almeno {0} caratteri"
+msgstr "The password must contain at least {0} characters"
+
+#: ./src/Model/Table/UsersTable.php:111
+msgid "La password deve contenere almeno {0} carattere/i maiuscolo/i"
+msgstr "The password must contain at least {0} uppercase characters"
+
+#: ./src/Model/Table/UsersTable.php:117
+msgid "La password deve contenere almeno {0} numero/i"
+msgstr "The password must contain at least {0} numbers"
+
+#: ./src/Model/Table/UsersTable.php:131
+msgid "La password deve contenere almeno {1} carattere/i speciale/i tra \"{0}\""
+msgstr "The password must contain at least {1} special characters to be chosen among \"{0}\""
+
+#: ./src/Model/Table/UsersTable.php:256
+msgid "Errore durante il salvataggio della foto utente. Assicurarsi che sia nel formato corretto (jpeg 160x160)"
+msgstr "Error trying to save user photo. Please make sure that the photo you are trying to save is in the correct format and size (jpeg 160x160)"
+
+#: ./src/View/Cell/MapCell.php:182
+msgid "Geometrie disegnate"
+msgstr "Drawn geometries"
+
+#: ./templates/Capabilities/index.php:9
+#: ./templates/Deliveries/index.php:9
+#: ./templates/Emails/add.php:9
+#: ./templates/Emails/edit.php:9
+#: ./templates/Faxes/add.php:9
+#: ./templates/Faxes/edit.php:9
+#: ./templates/Groups/add.php:9
+#: ./templates/Groups/edit.php:9
+#: ./templates/Groups/handle_capabilities.php:9
+#: ./templates/Groups/index.php:9
+#: ./templates/Groups/view.php:9
+#: ./templates/Maps/index.php:9
+#: ./templates/MobilePhones/add.php:9
+#: ./templates/MobilePhones/edit.php:9
+#: ./templates/Organisations/add.php:9
+#: ./templates/Organisations/edit.php:9
+#: ./templates/Organisations/index.php:9
+#: ./templates/Organisations/view.php:9
+#: ./templates/Phones/add.php:9
+#: ./templates/Phones/edit.php:9
+#: ./templates/TelegramChats/add.php:9
+#: ./templates/TelegramChats/edit.php:9
+#: ./templates/Users/add.php:9
+#: ./templates/Users/edit.php:9
+#: ./templates/Users/index.php:9
+#: ./templates/Users/view.php:9
+msgid "Configurazioni"
+msgstr "Configurations"
+
+#: ./templates/Capabilities/index.php:24
+msgid "Lista delle competenze"
+msgstr "Capabilities list"
+
+#: ./templates/Capabilities/index.php:29
+msgid "Cerca per descrizione competenza o codice o nome del gruppo di competenze"
+msgstr "Search by capability description, code or capability group name"
+
+#: ./templates/Capabilities/index.php:29
+msgid "Cerca"
+msgstr "Search"
+
+#: ./templates/Capabilities/index.php:42
+msgid "Codice"
+msgstr "Code"
+
+#: ./templates/Capabilities/index.php:43
+msgid "Priorità"
+msgstr "Priority"
+
+#: ./templates/Capabilities/index.php:44
+msgid "Gruppo"
+msgstr "Group"
+
+#: ./templates/Capabilities/index.php:45
+#: ./templates/ControllableObjects/get_attachments.php:66
+#: ./templates/Deliveries/index.php:52
+#: ./templates/Deliveries/index.php:94
+#: ./templates/Deliveries/index.php:136
+#: ./templates/Deliveries/index.php:177
+#: ./templates/Deliveries/index.php:217
+#: ./templates/Groups/index.php:34
+#: ./templates/Organisations/index.php:37
+#: ./templates/Users/index.php:35
+msgid "Azioni"
+msgstr "Actions"
+
+#: ./templates/Capabilities/index.php:57
+#: ./templates/Groups/handle_capabilities.php:57
+#: ./templates/Groups/handle_capabilities.php:58
+#: ./templates/Groups/handle_capabilities.php:59
+msgid "Competenza non visibile e non configurabile dai non SYSADMIN"
+msgstr "Capability not visible and not configurable by non SYSADMIN users"
+
+#: ./templates/Capabilities/index.php:58
+msgid "Competenza eliminata dal sistema"
+msgstr "Capability successfully deleted"
+
+#: ./templates/Capabilities/index.php:67
+msgid "Nascondi"
+msgstr "Hide"
+
+#: ./templates/Capabilities/index.php:67
+msgid "Mostra"
+msgstr "Show"
+
+#: ./templates/Capabilities/index.php:68
+msgid "Ripristina"
+msgstr "Restore"
+
+#: ./templates/Capabilities/index.php:68
+#: ./templates/Deliveries/index.php:63
+#: ./templates/Deliveries/index.php:105
+#: ./templates/Deliveries/index.php:147
+#: ./templates/Deliveries/index.php:187
+#: ./templates/Deliveries/index.php:227
+#: ./templates/Groups/index.php:46
+#: ./templates/Groups/view.php:44
+#: ./templates/Organisations/index.php:54
+#: ./templates/Organisations/view.php:71
+#: ./templates/Users/index.php:50
+#: ./templates/Users/view.php:72
+msgid "Cancella"
+msgstr "Delete"
+
+#: ./templates/ControllableObjects/get_attachments.php:45
+msgid "Allegati presenti: {0}"
+msgstr "Attachments: {0}"
+
+#: ./templates/ControllableObjects/get_attachments.php:45
+msgid "Nessun Allegato presente"
+msgstr "No Attachments"
+
+#: ./templates/ControllableObjects/get_attachments.php:60
+msgid "Georeferenziazione"
+msgstr "Georeferencing"
+
+#: ./templates/ControllableObjects/get_attachments.php:62
+msgid "Dimensione"
+msgstr "Size"
+
+#: ./templates/ControllableObjects/get_attachments.php:63
+msgid "Tipo"
+msgstr "Type"
+
+#: ./templates/ControllableObjects/get_attachments.php:64
+msgid "Caricato il"
+msgstr "Uploaded"
+
+#: ./templates/ControllableObjects/get_attachments.php:65
+#: ./templates/cell/Filters/display.php:57
+msgid "Da"
+msgstr "From"
+
+#: ./templates/ControllableObjects/get_attachments.php:80
+msgid "File pubblico"
+msgstr "Public file"
+
+#: ./templates/ControllableObjects/get_attachments.php:83
+msgid "File privato"
+msgstr "Private file"
+
+#: ./templates/ControllableObjects/get_attachments.php:106
+msgid "Visualizza"
+msgstr "View"
+
+#: ./templates/ControllableObjects/get_attachments.php:110
+msgid "Segna da eliminare"
+msgstr "Mark as to be deleted"
+
+#: ./templates/ControllableObjects/get_attachments.php:112
+msgid "Segna come non rilevante"
+msgstr "Mark as not relevant"
+
+#: ./templates/ControllableObjects/get_attachments.php:112
+msgid "Segna come rilevante"
+msgstr "Mark as relevant"
+
+#: ./templates/Dashboard/index.php:16
+msgid "Jixel Dashboard"
+msgstr "Jixel Dashboard"
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Lista {0}"
+msgstr "List {0}"
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Organizzazioni"
+msgstr "Organisations"
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Utenti"
+msgstr "Users"
+
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+msgid "Dettaglio {0}"
+msgstr "{0} Details"
+
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+msgid "Utente"
+msgstr "User"
+
+#: ./templates/Deliveries/index.php:23
+#: ./templates/Emails/add.php:23
+#: ./templates/Emails/edit.php:23
+#: ./templates/Faxes/add.php:23
+#: ./templates/Faxes/edit.php:23
+#: ./templates/MobilePhones/add.php:23
+#: ./templates/MobilePhones/edit.php:23
+#: ./templates/Organisations/view.php:69
+#: ./templates/Phones/add.php:23
+#: ./templates/Phones/edit.php:23
+#: ./templates/TelegramChats/add.php:23
+#: ./templates/TelegramChats/edit.php:23
+#: ./templates/Users/view.php:70
+msgid "Gestione recapiti"
+msgstr "Contacts management"
+
+#: ./templates/Deliveries/index.php:31
+msgid "Recapiti associati a {0} \"{1}\""
+msgstr "Associated contacts to {0} \"{1}\""
+
+#: ./templates/Deliveries/index.php:41
+msgid "Cellulare: {0}"
+msgstr "Mobile Phone {0}"
+
+#: ./templates/Deliveries/index.php:50
+#: ./templates/MobilePhones/add.php:47
+#: ./templates/MobilePhones/edit.php:47
+msgid "Cellulare"
+msgstr "Mobile Phone"
+
+#: ./templates/Deliveries/index.php:51
+#: ./templates/Deliveries/index.php:93
+#: ./templates/Deliveries/index.php:135
+#: ./templates/Deliveries/index.php:216
+#: ./templates/Emails/add.php:49
+#: ./templates/Emails/edit.php:49
+#: ./templates/Faxes/add.php:49
+#: ./templates/Faxes/edit.php:49
+#: ./templates/MobilePhones/add.php:49
+#: ./templates/MobilePhones/edit.php:49
+#: ./templates/TelegramChats/add.php:48
+#: ./templates/TelegramChats/edit.php:48
+msgid "Ricevi notifiche a questo recapito"
+msgstr "Receive notifications at this contact"
+
+#: ./templates/Deliveries/index.php:62
+#: ./templates/Deliveries/index.php:104
+#: ./templates/Deliveries/index.php:146
+#: ./templates/Deliveries/index.php:186
+#: ./templates/Deliveries/index.php:226
+#: ./templates/Groups/index.php:45
+#: ./templates/Groups/view.php:43
+#: ./templates/Organisations/index.php:53
+#: ./templates/Organisations/view.php:70
+#: ./templates/Users/index.php:49
+#: ./templates/Users/view.php:71
+msgid "Modifica"
+msgstr "Edit"
+
+#: ./templates/Deliveries/index.php:63
+msgid "Sei sicuro che vuoi cancellare il Cellulare \"{0}\" ?"
+msgstr "Are you sure you want to delete the Mobile Phone \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:73
+#: ./templates/MobilePhones/add.php:28
+msgid "Aggiungi Cellulare"
+msgstr "Add Mobile Phone"
+
+#: ./templates/Deliveries/index.php:84
+msgid "Fax: {0}"
+msgstr "Fax: {0}"
+
+#: ./templates/Deliveries/index.php:92
+#: ./templates/Faxes/add.php:47
+#: ./templates/Faxes/edit.php:47
+msgid "Fax"
+msgstr "Fax"
+
+#: ./templates/Deliveries/index.php:105
+msgid "Sei sicuro che vuoi cancellare il Fax \"{0}\" ?"
+msgstr "Are you sure you want to delete the Fax \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:115
+#: ./templates/Faxes/add.php:28
+msgid "Aggiungi Fax"
+msgstr "Add Fax"
+
+#: ./templates/Deliveries/index.php:126
+msgid "Email: {0}"
+msgstr "Email: {0}"
+
+#: ./templates/Deliveries/index.php:134
+#: ./templates/Emails/add.php:47
+#: ./templates/Emails/edit.php:47
+msgid "Email"
+msgstr "Email"
+
+#: ./templates/Deliveries/index.php:147
+msgid "Sei sicuro che vuoi cancellare l'Email \"{0}\" ?"
+msgstr "Are you sure you want to delete the Email \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:157
+#: ./templates/Emails/add.php:28
+msgid "Aggiungi Email"
+msgstr "Add Email"
+
+#: ./templates/Deliveries/index.php:168
+msgid "Telefono: {0}"
+msgstr "Phone {0}"
+
+#: ./templates/Deliveries/index.php:176
+#: ./templates/Phones/add.php:47
+#: ./templates/Phones/edit.php:47
+msgid "Telefono"
+msgstr "Phone"
+
+#: ./templates/Deliveries/index.php:187
+msgid "Sei sicuro che vuoi cancellare il Telefono \"{0}\" ?"
+msgstr "Are you sure you want to delete the Phone \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:197
+#: ./templates/Phones/add.php:28
+msgid "Aggiungi Telefono"
+msgstr "Add Phone"
+
+#: ./templates/Deliveries/index.php:208
+msgid "Chat Telegram: {0}"
+msgstr "Telegram Chat: {0}"
+
+#: ./templates/Deliveries/index.php:215
+msgid "ID"
+msgstr "ID"
+
+#: ./templates/Deliveries/index.php:227
+msgid "Sei sicuro che vuoi cancellare la Chat Telegram con ID \"{0}\" ?"
+msgstr "Are you sure you want to delete the Telegram Chat with ID \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:237
+#: ./templates/TelegramChats/add.php:28
+msgid "Aggiungi Chat Telegram"
+msgstr "Add Telegram Chat"
+
+#: ./templates/Emails/add.php:40
+msgid "Aggiungi Email per {0} \"{1}\""
+msgstr "Add Email for {0} \"{1}\""
+
+#: ./templates/Emails/add.php:54
+#: ./templates/Emails/edit.php:54
+#: ./templates/Faxes/add.php:54
+#: ./templates/Faxes/edit.php:54
+#: ./templates/Groups/add.php:45
+#: ./templates/Groups/edit.php:50
+#: ./templates/Groups/handle_capabilities.php:71
+#: ./templates/MobilePhones/add.php:54
+#: ./templates/MobilePhones/edit.php:54
+#: ./templates/Organisations/add.php:172
+#: ./templates/Organisations/edit.php:86
+#: ./templates/Phones/add.php:53
+#: ./templates/Phones/edit.php:53
+#: ./templates/TelegramChats/add.php:53
+#: ./templates/TelegramChats/edit.php:53
+#: ./templates/Users/add.php:57
+#: ./templates/Users/choose_new_password.php:8
+#: ./templates/Users/edit.php:62
+msgid "Salva"
+msgstr "Save"
+
+#: ./templates/Emails/edit.php:28
+msgid "Modifica Email"
+msgstr "Edit Email"
+
+#: ./templates/Emails/edit.php:40
+msgid "Modifica Email per {0} \"{1}\""
+msgstr "Edit Email for {0} \"{1}\""
+
+#: ./templates/Faxes/add.php:40
+msgid "Aggiungi Fax per {0} \"{1}\""
+msgstr "Add Fax for {0} \"{1}\""
+
+#: ./templates/Faxes/edit.php:28
+msgid "Modifica Fax"
+msgstr "Edit Fax"
+
+#: ./templates/Faxes/edit.php:40
+msgid "Modifica Fax per {0} \"{1}\""
+msgstr "Edit Fax for {0} \"{1}\""
+
+#: ./templates/Groups/add.php:13
+#: ./templates/Groups/edit.php:13
+#: ./templates/Groups/handle_capabilities.php:13
+#: ./templates/Groups/index.php:13
+#: ./templates/Groups/index.php:24
+#: ./templates/Groups/view.php:13
+msgid "Lista dei Profili Utente"
+msgstr "User Profiles List"
+
+#: ./templates/Groups/add.php:18
+#: ./templates/Groups/add.php:31
+msgid "Nuovo Profilo Utente"
+msgstr "New User Profile"
+
+#: ./templates/Groups/edit.php:18
+#: ./templates/Groups/handle_capabilities.php:18
+#: ./templates/Groups/view.php:18
+msgid "Dettaglio Profilo Utente"
+msgstr "User Profile Details"
+
+#: ./templates/Groups/edit.php:23
+#: ./templates/Groups/edit.php:36
+msgid "Modifica Profilo Utente"
+msgstr "Edit User Profile"
+
+#: ./templates/Groups/handle_capabilities.php:35
+msgid "Competenze associate al Profilo Utente \"{0}\""
+msgstr "User Profile \"{0}\" associated capabilities"
+
+#: ./templates/Groups/handle_capabilities.php:45
+msgid "Gruppo di competenze non visibile e non configurabile dai non SYSADMIN"
+msgstr "Capability Groups not visible and not configurable by non SYSADMIN users"
+
+#: ./templates/Groups/handle_capabilities.php:52
+msgid "Gruppo di competenze \"{0}\""
+msgstr "Capability Group \"{0}\""
+
+#: ./templates/Groups/index.php:44
+#: ./templates/Organisations/index.php:52
+#: ./templates/Users/index.php:48
+#: ./templates/plugin/AdminLTE/element/nav-top.php:118
+msgid "Dettaglio"
+msgstr "Details"
+
+#: ./templates/Groups/index.php:46
+#: ./templates/Groups/view.php:44
+msgid "Sei sicuro che vuoi cancellare il profilo \"{0}\" ?"
+msgstr "Are you sure you want to delete the user profile \"{0}\" ?"
+
+#: ./templates/Groups/view.php:30
+msgid "Informazioni Profilo Utente"
+msgstr "User Profile Informations"
+
+#: ./templates/Maps/index.php:25
+msgid "Mappa"
+msgstr "Map"
+
+#: ./templates/Maps/index.php:30
+msgid "Campo esistente appartenente al form ospite"
+msgstr "Existing field that belongs to the hosting form"
+
+#: ./templates/Maps/index.php:37
+msgid "Posizione Evento"
+msgstr "Incident location"
+
+#: ./templates/Maps/index.php:54
+msgid "Collezione di geometrie"
+msgstr "Geometry collection"
+
+#: ./templates/Maps/index.php:65
+#: ./templates/Organisations/add.php:74
+msgid "Longitudine"
+msgstr "Longitude"
+
+#: ./templates/Maps/index.php:76
+#: ./templates/Organisations/add.php:85
+msgid "Latitudine"
+msgstr "Latitude"
+
+#: ./templates/Maps/index.php:87
+#: ./templates/Organisations/add.php:96
+#: ./templates/Organisations/add.php:158
+#: ./templates/Organisations/edit.php:62
+#: ./templates/Organisations/view.php:51
+msgid "Coordinate (Longitudine Latitudine)"
+msgstr "Coordinates (Longitude Latitude)"
+
+#: ./templates/Maps/index.php:98
+#: ./templates/Organisations/add.php:107
+msgid "Cap"
+msgstr "ZIP code"
+
+#: ./templates/Maps/index.php:142
+#: ./templates/Organisations/add.php:151
+msgid "Descrizione luogo"
+msgstr "Location description"
+
+#: ./templates/MobilePhones/add.php:40
+msgid "Aggiungi Cellulare per {0} \"{1}\""
+msgstr "Add Mobile Phone for {0} \"{1}\""
+
+#: ./templates/MobilePhones/edit.php:28
+msgid "Modifica Cellulare"
+msgstr "Edit Mobile Phone"
+
+#: ./templates/MobilePhones/edit.php:40
+msgid "Modifica Cellulare per {0} \"{1}\""
+msgstr "Edit Mobile Phone for {0} \"{1}\""
+
+#: ./templates/Organisations/add.php:13
+#: ./templates/Organisations/edit.php:13
+#: ./templates/Organisations/index.php:13
+#: ./templates/Organisations/view.php:13
+msgid "Lista Organizzazioni"
+msgstr "Organisations List"
+
+#: ./templates/Organisations/add.php:18
+#: ./templates/Organisations/add.php:30
+msgid "Nuova Organizzazione"
+msgstr "New Organisation"
+
+#: ./templates/Organisations/add.php:39
+#: ./templates/Organisations/edit.php:43
+#: ./templates/Organisations/view.php:38
+msgid "Tipo organizzazione"
+msgstr "Organisation type"
+
+#: ./templates/Organisations/add.php:46
+#: ./templates/Organisations/edit.php:50
+#: ./templates/Organisations/view.php:45
+msgid "Posizione Organizzazione"
+msgstr "Organisation Location"
+
+#: ./templates/Organisations/edit.php:18
+#: ./templates/Organisations/view.php:18
+#: ./templates/Organisations/view.php:29
+msgid "Dettaglio Organizzazione"
+msgstr "Organisation Details"
+
+#: ./templates/Organisations/edit.php:23
+#: ./templates/Organisations/edit.php:34
+msgid "Modifica Organizzazione"
+msgstr "Edit Organisation"
+
+#: ./templates/Organisations/index.php:23
+msgid "Lista delle {0} Organizzazioni"
+msgstr "List of {0} Organisations"
+
+#: ./templates/Organisations/index.php:23
+#: ./templates/Users/index.php:23
+msgid "{0} su {1}"
+msgstr "{0} out of {1}"
+
+#: ./templates/Organisations/index.php:54
+#: ./templates/Organisations/view.php:71
+msgid "Sei sicuro che vuoi cancellare l'organizzazione \"{0}\" ?"
+msgstr "Are you sure you want to delete the organisation \"{0}\" ?"
+
+#: ./templates/Phones/add.php:40
+msgid "Aggiungi Telefono per {0} \"{1}\""
+msgstr "Add Phone for {0} \"{1}\""
+
+#: ./templates/Phones/edit.php:28
+msgid "Modifica Telefono"
+msgstr "Edit Phone"
+
+#: ./templates/Phones/edit.php:40
+msgid "Modifica Telefono per {0} \"{1}\""
+msgstr "Edit Phone for {0} \"{1}\""
+
+#: ./templates/TelegramChats/add.php:40
+msgid "Aggiungi Chat Telegram per {0} \"{1}\""
+msgstr "Add Telegram Chat for {0} \"{1}\""
+
+#: ./templates/TelegramChats/add.php:47
+#: ./templates/TelegramChats/edit.php:47
+msgid "Chat Telegram ID"
+msgstr "Telegram Chat ID"
+
+#: ./templates/TelegramChats/edit.php:28
+msgid "Modifica Chat Telegram"
+msgstr "Edit Telegram Chat"
+
+#: ./templates/TelegramChats/edit.php:40
+msgid "Modifica Chat Telegram per {0} \"{1}\""
+msgstr "Edit Telegram Chat for {0} \"{1}\""
+
+#: ./templates/Users/add.php:13
+#: ./templates/Users/edit.php:13
+#: ./templates/Users/index.php:13
+#: ./templates/Users/view.php:13
+msgid "Lista Utenti"
+msgstr "Users List"
+
+#: ./templates/Users/add.php:18
+#: ./templates/Users/add.php:31
+msgid "Nuovo Utente"
+msgstr "New User"
+
+#: ./templates/Users/add.php:38
+#: ./templates/Users/edit.php:43
+#: ./templates/Users/view.php:41
+msgid "Nome utente"
+msgstr "Username"
+
+#: ./templates/Users/add.php:39
+#: ./templates/Users/edit.php:44
+msgid "Password"
+msgstr "Password"
+
+#: ./templates/Users/add.php:42
+#: ./templates/Users/edit.php:47
+#: ./templates/Users/view.php:47
+msgid "Codice Fiscale"
+msgstr "Tax ID code"
+
+#: ./templates/Users/add.php:43
+#: ./templates/Users/edit.php:48
+#: ./templates/Users/view.php:49
+msgid "Data di nascita"
+msgstr "Date of birth"
+
+#: ./templates/Users/add.php:44
+#: ./templates/Users/edit.php:49
+#: ./templates/Users/view.php:51
+msgid "Luogo di nascita"
+msgstr "Birth place"
+
+#: ./templates/Users/add.php:45
+#: ./templates/Users/edit.php:50
+#: ./templates/Users/view.php:53
+msgid "Sesso"
+msgstr "Gender"
+
+#: ./templates/Users/add.php:47
+#: ./templates/Users/edit.php:52
+#: ./templates/Users/view.php:57
+msgid "Città"
+msgstr "City"
+
+#: ./templates/Users/add.php:49
+#: ./templates/Users/edit.php:54
+#: ./templates/Users/view.php:61
+msgid "Lingua preferita"
+msgstr "Favourite language"
+
+#: ./templates/Users/add.php:51
+#: ./templates/Users/edit.php:56
+msgid "Foto del profilo (solo jpeg di dimensioni 160x160!)"
+msgstr "Photo (160x160 sized jpeg only!)"
+
+#: ./templates/Users/choose_new_password.php:4
+msgid "Imposta una nuova password"
+msgstr "Set a new password"
+
+#: ./templates/Users/choose_new_password.php:5
+msgid "Digita la nuova password"
+msgstr "Enter the new password"
+
+#: ./templates/Users/choose_new_password.php:6
+msgid "Ridigita la nuova password"
+msgstr "Retype the previous entered password"
+
+#: ./templates/Users/edit.php:18
+#: ./templates/Users/view.php:18
+msgid "Dettaglio Utente"
+msgstr "User Details"
+
+#: ./templates/Users/edit.php:23
+#: ./templates/Users/edit.php:36
+msgid "Modifica Utente"
+msgstr "Edit User"
+
+#: ./templates/Users/index.php:23
+msgid "Lista dei {0} Utenti"
+msgstr "List of {0} Users"
+
+#: ./templates/Users/index.php:50
+#: ./templates/Users/view.php:72
+msgid "Sei sicuro che vuoi cancellare l'utente \"{0}\" ?"
+msgstr "Are you sure you wanto to delete the user \"{0}\" ?"
+
+#: ./templates/Users/login.php:4
+msgid "Accedi"
+msgstr "Gain access"
+
+#: ./templates/Users/login.php:8
+msgid "Login"
+msgstr "Login"
+
+#: ./templates/Users/password_recovery.php:4
+msgid "Inserisci un indirizzo email associato alla tua utenza"
+msgstr "Insert an email that is currently associated with your account"
+
+#: ./templates/Users/password_recovery.php:7
+msgid "Richiedi reset password"
+msgstr "Request password reset"
+
+#: ./templates/Users/view.php:30
+msgid "Informazioni Utente"
+msgstr "User Informations"
+
+#: ./templates/Users/view.php:34
+msgid "Elimina foto"
+msgstr "Delete photo"
+
+#: ./templates/Users/view.php:34
+msgid "Sei sicuro che vuoi eliminare la foto ?"
+msgstr "Are you sure you want to delete the photo ?"
+
+#: ./templates/Users/view.php:62
+msgid "Non specificata"
+msgstr "Not specified"
+
+#: ./templates/Users/view.php:67
+msgid "Recapiti:"
+msgstr "Contacts"
+
+#: ./templates/cell/FilterInput/display.php:9
+#: ./templates/element/attachments.php:127
+msgid "Rimuovi"
+msgstr "Remove"
+
+#: ./templates/cell/Filters/display.php:3
+#: ./templates/cell/Filters/display.php:113
+msgid "Filtri attivi"
+msgstr "Filters applied"
+
+#: ./templates/cell/Filters/display.php:3
+#: ./templates/cell/Filters/display.php:116
+msgid "Filtri disattivati"
+msgstr "No Filters applied"
+
+#: ./templates/cell/Filters/display.php:15
+msgid "Aggiungi un filtro"
+msgstr "Add a filter"
+
+#: ./templates/cell/Filters/display.php:34
+#: ./templates/cell/Filters/display.php:55
+msgid "Applica"
+msgstr "Apply"
+
+#: ./templates/cell/Filters/display.php:39
+msgid "Reset"
+msgstr "Reset"
+
+#: ./templates/cell/Filters/display.php:56
+msgid "Annulla"
+msgstr "Cancel"
+
+#: ./templates/cell/Filters/display.php:58
+msgid "A"
+msgstr "TO"
+
+#: ./templates/cell/Filters/display.php:59
+msgid "Dal Al"
+msgstr "From To"
+
+#: ./templates/cell/Filters/display.php:60
+#: ./templates/cell/Filters/display.php:87
+msgid "Oggi"
+msgstr "Today"
+
+#: ./templates/cell/Filters/display.php:62
+msgid "Dom"
+msgstr "Sun"
+
+#: ./templates/cell/Filters/display.php:63
+msgid "Lun"
+msgstr "Mon"
+
+#: ./templates/cell/Filters/display.php:64
+msgid "Mar"
+msgstr "Tue"
+
+#: ./templates/cell/Filters/display.php:65
+msgid "Mer"
+msgstr "Wed"
+
+#: ./templates/cell/Filters/display.php:66
+msgid "Gio"
+msgstr "Thu"
+
+#: ./templates/cell/Filters/display.php:67
+msgid "Ven"
+msgstr "Fri"
+
+#: ./templates/cell/Filters/display.php:68
+msgid "Sab"
+msgstr "Sat"
+
+#: ./templates/cell/Filters/display.php:71
+msgid "Gennaio"
+msgstr "January"
+
+#: ./templates/cell/Filters/display.php:72
+msgid "Febbraio"
+msgstr "February"
+
+#: ./templates/cell/Filters/display.php:73
+msgid "Marzo"
+msgstr "March"
+
+#: ./templates/cell/Filters/display.php:74
+msgid "Aprile"
+msgstr "April"
+
+#: ./templates/cell/Filters/display.php:75
+msgid "Maggio"
+msgstr "May"
+
+#: ./templates/cell/Filters/display.php:76
+msgid "Giugno"
+msgstr "June"
+
+#: ./templates/cell/Filters/display.php:77
+msgid "Luglio"
+msgstr "July"
+
+#: ./templates/cell/Filters/display.php:78
+msgid "Agosto"
+msgstr "August"
+
+#: ./templates/cell/Filters/display.php:79
+msgid "Settembre"
+msgstr "September"
+
+#: ./templates/cell/Filters/display.php:80
+msgid "Ottobre"
+msgstr "October"
+
+#: ./templates/cell/Filters/display.php:81
+msgid "Novembre"
+msgstr "November"
+
+#: ./templates/cell/Filters/display.php:82
+msgid "Dicembre"
+msgstr "December"
+
+#: ./templates/cell/Filters/display.php:88
+msgid "Ieri"
+msgstr "Yesterday"
+
+#: ./templates/cell/Filters/display.php:89
+msgid "Questa settimana"
+msgstr "This week"
+
+#: ./templates/cell/Filters/display.php:90
+msgid "Questo mese"
+msgstr "This month"
+
+#: ./templates/cell/Filters/display.php:91
+msgid "Lo scorso mese"
+msgstr "Last month"
+
+#: ./templates/cell/Filters/display.php:92
+msgid "Ultimi 7 giorni"
+msgstr "Last 7 days"
+
+#: ./templates/cell/Filters/display.php:93
+msgid "Ultimi 15 giorni"
+msgstr "Last 15 days"
+
+#: ./templates/cell/Filters/display.php:94
+msgid "Ultimi 30 giorni"
+msgstr "Last 30 days"
+
+#: ./templates/cell/Filters/display.php:131
+msgid "Errore durante il recupero del filtro selezionato. Riprovare di nuovo"
+msgstr "Error trying to retrieve the selected filter. Pleas try again"
+
+#: ./templates/element/Map.php:107
+#: ./templates/element/Map.php:118
+#: ./templates/element/Map.php:122
+msgid "OpenStreetMap ONLINE"
+msgstr "OpenStreetMap ONLINE"
+
+#: ./templates/element/Map.php:107
+#: ./templates/element/Map.php:127
+#: ./templates/element/Map.php:131
+msgid "OpenStreetMap OFFLINE"
+msgstr "OpenStreetMap OFFLINE"
+
+#: ./templates/element/Map.php:312
+#: ./templates/element/Map.php:541
+msgid "Indirizzo non trovato o fuori dall'area di competenza"
+msgstr "Address not found or out of the platform configured bounding box"
+
+#: ./templates/element/Map.php:530
+msgid "Punto alle coordinate (EPSG:4326) Latitudine:"
+msgstr "Point of coordinates (EPSG:4326) Latitude:"
+
+#: ./templates/element/Map.php:530
+msgid "Longitudine:"
+msgstr "Longitude:"
+
+#: ./templates/element/MapCore/MapPrimitives.php:10
+msgid "Scegli un risultato:"
+msgstr "Pick a result"
+
+#: ./templates/element/MapCore/MapPrimitives.php:30
+msgid "Inserisci un indirizzo o le coordinate (in formato EPSG:4326)"
+msgstr "Insert an address or coordinates (EPSG:4326)"
+
+#: ./templates/element/MapCore/MapPrimitives.php:31
+msgid "Cerca un indirizzo"
+msgstr "Look up for an address"
+
+#: ./templates/element/MapCore/MapPrimitives.php:36
+msgid "Inserisci un punto in mappa"
+msgstr "Insert a point on map"
+
+#: ./templates/element/MapCore/MapPrimitives.php:41
+msgid "Inserisci un poligono in mappa"
+msgstr "Draw a polygon on map"
+
+#: ./templates/element/MapCore/MapPrimitives.php:46
+msgid "Inserisci un cerchio in mappa"
+msgstr "Draw a circle on map"
+
+#: ./templates/element/MapCore/MapPrimitives.php:51
+msgid "Cancella una geometria"
+msgstr "Delete a geometry"
+
+#: ./templates/element/attachmentPreview.php:16
+msgid "Il tuo browser non supporta HTML5 video tag. Prova ad aggiornare il tuo browser."
+msgstr "Your browser doesn't seem to support HTML5 video tag. Please try and update your browser to a more recent version."
+
+#: ./templates/element/attachmentPreview.php:35
+msgid "Anteprima non disponibile"
+msgstr "Preview not available"
+
+#: ./templates/element/attachments.php:30
+msgid "di tipo: \"{0}\""
+msgstr "of type \"{0}\""
+
+#: ./templates/element/attachments.php:39
+msgid "Mostra allegati correlati"
+msgstr "Show also linked attachments"
+
+#: ./templates/element/attachments.php:48
+msgid "Allega un file "
+msgstr "Attach a file"
+
+#: ./templates/element/attachments.php:48
+msgid "Allega files "
+msgstr "Attach files"
+
+#: ./templates/element/attachments.php:54
+msgid "Allega file pubblico "
+msgstr "Attach public file"
+
+#: ./templates/element/attachments.php:54
+msgid "Allega un file privato "
+msgstr "Attach a private file"
+
+#: ./templates/element/attachments.php:54
+msgid "Allega files privati "
+msgstr "Attach private files "
+
+#: ./templates/element/attachments.php:58
+msgid "Allega files..."
+msgstr "Attach files..."
+
+#: ./templates/element/attachments.php:65
+msgid "Allega files {1} {0}"
+msgstr "Attach files {1} {0}"
+
+#: ./templates/element/attachments.php:118
+msgid "latitudine"
+msgstr "latitude"
+
+#: ./templates/element/attachments.php:119
+msgid "longitudine"
+msgstr "longitude"
+
+#: ./templates/layout/error.php:38
+msgid "Back"
+msgstr "Back"
+
+#: ./templates/plugin/AdminLTE/element/aside-control-sidebar.php:4
+msgid "Notifiche"
+msgstr "Notifications"
+
+#: ./templates/plugin/AdminLTE/element/footer.php:6
+msgid "Versione"
+msgstr "Version"
+
+#: ./templates/plugin/AdminLTE/element/footer.php:9
+msgid "Tutti i diritti riservati"
+msgstr "All rights reserved"
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:67
+msgid "Nuove notifiche: {0}"
+msgstr "New notifications: {0}"
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:91
+msgid "Segna tutte le notifiche come lette"
+msgstr "Mark all new notifications as read"
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:121
+msgid "Esci"
+msgstr "Logout"
+
diff --git a/idrocap_wa/resources/locales/en/previous_default.po b/idrocap_wa/resources/locales/en/previous_default.po
new file mode 100644
index 0000000..bd63efb
--- /dev/null
+++ b/idrocap_wa/resources/locales/en/previous_default.po
@@ -0,0 +1,1709 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"POT-Creation-Date: 2023-03-03 14:35+0000\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: ./src/Controller/Api/AttachmentsController.php:36
+#: ./src/Controller/AttachmentsController.php:38
+#: ./src/Controller/AttachmentsController.php:68
+msgid "Allegato non trovato"
+msgstr "Attachment not found"
+
+#: ./src/Controller/Api/AttachmentsController.php:37
+#: ./src/Controller/AttachmentsController.php:39
+#: ./src/Controller/AttachmentsController.php:69
+msgid "Non hai i permessi necessari per visionare l'allegato"
+msgstr "You do not have permission to view the attachment"
+
+#: ./src/Controller/Api/OrganisationsController.php:104
+msgid "Organizzazione non trovata!"
+msgstr "Organisation not found!"
+
+#: ./src/Controller/Api/UsersController.php:160
+msgid "Utente non trovato!"
+msgstr "User not found!"
+
+#: ./src/Controller/AppController.php:95
+msgid "SYSADMIN"
+msgstr "SYSADMIN"
+
+#: ./src/Controller/AppController.php:99
+#: ./templates/Capabilities/index.php:13
+#: ./templates/Groups/handle_capabilities.php:23
+#: ./templates/Groups/view.php:42
+msgid "Gestione competenze"
+msgstr "Handle capabilities"
+
+#: ./src/Controller/AppController.php:104
+msgid "Test notifiche"
+msgstr "Test notification system"
+
+#: ./src/Controller/AppController.php:107
+msgid "Procedendo verranno inviate notifiche a tutti gli utenti e le organizzaioni che possiedono uno o più recapiti abilitati alle notifiche! Sei sicuro che vuoi continuare ?"
+msgstr "Notifications will be sent to all users and organisations that have at least one notification enabled contact! Are you sure you want to proceed ?"
+
+#: ./src/Controller/CapabilitiesController.php:24
+#: ./src/Controller/CapabilitiesController.php:54
+#: ./src/Controller/CapabilitiesController.php:97
+#: ./src/Controller/CapabilitiesController.php:135
+#: ./src/Controller/CapabilitiesController.php:177
+#: ./src/Controller/GroupsController.php:31
+#: ./src/Controller/GroupsController.php:54
+#: ./src/Controller/GroupsController.php:92
+#: ./src/Controller/GroupsController.php:112
+#: ./src/Controller/GroupsController.php:136
+#: ./src/Controller/GroupsController.php:160
+#: ./src/Controller/GroupsController.php:183
+#: ./src/Controller/OrganisationsController.php:32
+#: ./src/Controller/OrganisationsController.php:60
+#: ./src/Controller/OrganisationsController.php:109
+#: ./src/Controller/OrganisationsController.php:131
+#: ./src/Controller/OrganisationsController.php:155
+#: ./src/Controller/OrganisationsController.php:181
+#: ./src/Controller/UsersController.php:38
+#: ./src/Controller/UsersController.php:70
+#: ./src/Controller/UsersController.php:113
+#: ./src/Controller/UsersController.php:119
+#: ./src/Controller/UsersController.php:136
+#: ./src/Controller/UsersController.php:177
+#: ./src/Controller/UsersController.php:211
+#: ./src/Controller/UsersController.php:216
+msgid "Non hai i permessi necessari"
+msgstr "You do not have needed permissions"
+
+#: ./src/Controller/CapabilitiesController.php:79
+msgid "Competenza \"{0}\" nascosta con successo!"
+msgstr "Capability \"{0}\" successfully hidden!"
+
+#: ./src/Controller/CapabilitiesController.php:82
+msgid "Errore durante il tentativo di nascondere la Competenza \"{0}\"!"
+msgstr "Error trying to hide the capability \"{0}\"!"
+
+#: ./src/Controller/CapabilitiesController.php:117
+msgid "Competenza \"{0}\" resa visibile con successo!"
+msgstr "Capability \"{0}\" successfully set unhidden!"
+
+#: ./src/Controller/CapabilitiesController.php:120
+msgid "Errore durante il tentativo di rendere visibile la Competenza \"{0}\"!"
+msgstr "Error trying to set the capability \"{0}\" unhidden!"
+
+#: ./src/Controller/CapabilitiesController.php:159
+msgid "Competenza \"{0}\" cancellata con successo!"
+msgstr "Capability \"{0}\" successfully deleted!"
+
+#: ./src/Controller/CapabilitiesController.php:162
+msgid "Errore durante la cancellazione della Competenza \"{0}\"!"
+msgstr "Error trying to delete the Capability \"{0}\"!"
+
+#: ./src/Controller/CapabilitiesController.php:197
+msgid "Competenza \"{0}\" ripristinata con successo!"
+msgstr "Capability \"{0}\" successfully restored!"
+
+#: ./src/Controller/CapabilitiesController.php:200
+msgid "Errore durante il ripristino della Competenza \"{0}\"!"
+msgstr "Error trying to restore the capability \"{0}\"!"
+
+#: ./src/Controller/DeliveriesController.php:27
+#: ./src/Controller/DeliveriesController.php:125
+#: ./src/Controller/EmailsController.php:25
+#: ./src/Controller/EmailsController.php:64
+#: ./src/Controller/FaxesController.php:25
+#: ./src/Controller/FaxesController.php:64
+#: ./src/Controller/MobilePhonesController.php:26
+#: ./src/Controller/MobilePhonesController.php:65
+#: ./src/Controller/PhonesController.php:25
+#: ./src/Controller/PhonesController.php:64
+#: ./src/Controller/TelegramChatsController.php:25
+#: ./src/Controller/TelegramChatsController.php:63
+msgid "Gestione recapiti non prevista per questa tipologia di oggetto"
+msgstr "Contacts management is not expected for this type of object"
+
+#: ./src/Controller/DeliveriesController.php:29
+#: ./src/Controller/DeliveriesController.php:127
+#: ./src/Controller/EmailsController.php:26
+#: ./src/Controller/EmailsController.php:65
+#: ./src/Controller/FaxesController.php:26
+#: ./src/Controller/FaxesController.php:65
+#: ./src/Controller/MobilePhonesController.php:27
+#: ./src/Controller/MobilePhonesController.php:66
+#: ./src/Controller/PhonesController.php:26
+#: ./src/Controller/PhonesController.php:65
+#: ./src/Controller/TelegramChatsController.php:26
+#: ./src/Controller/TelegramChatsController.php:64
+msgid "questa organizzazione"
+msgstr "this organisation"
+
+#: ./src/Controller/DeliveriesController.php:29
+#: ./src/Controller/DeliveriesController.php:127
+#: ./src/Controller/EmailsController.php:26
+#: ./src/Controller/EmailsController.php:65
+#: ./src/Controller/FaxesController.php:26
+#: ./src/Controller/FaxesController.php:65
+#: ./src/Controller/MobilePhonesController.php:27
+#: ./src/Controller/MobilePhonesController.php:66
+#: ./src/Controller/PhonesController.php:26
+#: ./src/Controller/PhonesController.php:65
+#: ./src/Controller/TelegramChatsController.php:26
+#: ./src/Controller/TelegramChatsController.php:64
+msgid "questo utente"
+msgstr "this user"
+
+#: ./src/Controller/DeliveriesController.php:30
+msgid "Non hai i permessi per visualizzare i recapiti per {0}"
+msgstr "You do not have permission to view contacts for {0}"
+
+#: ./src/Controller/DeliveriesController.php:128
+msgid "Non hai i permessi per eliminare i recapiti di questo tipo per {0}"
+msgstr "You do not have permission to delete contacts of this type for {0}"
+
+#: ./src/Controller/DeliveriesController.php:134
+#: ./src/Model/Entity/Actor.php:87
+msgid "Cellulare ({0}): {1}"
+msgstr "Mobile Phone ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:137
+#: ./src/Model/Entity/Actor.php:97
+msgid "Fax ({0}): {1}"
+msgstr "Fax ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:140
+#: ./src/Model/Entity/Actor.php:107
+msgid "Email ({0}): {1}"
+msgstr "Email ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:143
+#: ./src/Model/Entity/Actor.php:117
+msgid "Telefono ({0}): {1}"
+msgstr "Phone ({0}): {1}"
+
+#: ./src/Controller/DeliveriesController.php:146
+#: ./src/Model/Entity/Actor.php:127
+msgid "Telegram Chat ID: {0}"
+msgstr "Telegram Chat ID: {0}"
+
+#: ./src/Controller/DeliveriesController.php:154
+msgid "Il recapito \"{0}\" è stato cancellato con successo"
+msgstr "Contact \"{0}\" successfully deleted"
+
+#: ./src/Controller/DeliveriesController.php:156
+msgid "Errore durante la cancellazione del recapito {0}. Riprovare di nuovo."
+msgstr "Error trying to delete contact {0}. Please try again."
+
+#: ./src/Controller/EmailsController.php:27
+#: ./src/Controller/FaxesController.php:27
+#: ./src/Controller/MobilePhonesController.php:28
+#: ./src/Controller/PhonesController.php:27
+#: ./src/Controller/TelegramChatsController.php:27
+msgid "Non hai i permessi per aggiungere i recapiti di questo tipo per {0}"
+msgstr "You do not have permission to add this type of contact for {0}"
+
+#: ./src/Controller/EmailsController.php:39
+msgid "L'Email è stata aggiunta con successo."
+msgstr "Email successfully updated."
+
+#: ./src/Controller/EmailsController.php:43
+msgid "Errore durante l'aggiunta dell'Email: {0}"
+msgstr "Error trying adding Email: {0}"
+
+#: ./src/Controller/EmailsController.php:66
+#: ./src/Controller/FaxesController.php:66
+#: ./src/Controller/MobilePhonesController.php:67
+#: ./src/Controller/PhonesController.php:66
+#: ./src/Controller/TelegramChatsController.php:65
+msgid "Non hai i permessi per modificare i recapiti di questo tipo per {0}"
+msgstr "You do not have permission to edit this type of contact for {0}"
+
+#: ./src/Controller/EmailsController.php:71
+msgid "L'Email è stata modificata con successo."
+msgstr "Email successfully updated."
+
+#: ./src/Controller/EmailsController.php:75
+msgid "Errore durante la modifica dell'Email. Riprovare di nuovo"
+msgstr "Error trying to edit Email contact. Please try again"
+
+#: ./src/Controller/FaxesController.php:39
+msgid "Il Fax è stato aggiunto con successo."
+msgstr "Fax successfully added."
+
+#: ./src/Controller/FaxesController.php:43
+msgid "Errore durante l'aggiunta del Fax: {0}"
+msgstr "Error trying to add Fax: {0}"
+
+#: ./src/Controller/FaxesController.php:71
+msgid "Il Fax è stato modificato con successo."
+msgstr "Fax successfully updated."
+
+#: ./src/Controller/FaxesController.php:75
+msgid "Errore durante la modifica del Fax. Riprovare di nuovo"
+msgstr "Error trying to edit Fax. Please try again"
+
+#: ./src/Controller/GroupsController.php:57
+#: ./src/Controller/OrganisationsController.php:63
+#: ./templates/Capabilities/index.php:41
+#: ./templates/Deliveries/index.php:49
+#: ./templates/Deliveries/index.php:91
+#: ./templates/Deliveries/index.php:133
+#: ./templates/Deliveries/index.php:175
+#: ./templates/Emails/add.php:48
+#: ./templates/Emails/edit.php:48
+#: ./templates/Faxes/add.php:48
+#: ./templates/Faxes/edit.php:48
+#: ./templates/Groups/add.php:38
+#: ./templates/Groups/edit.php:43
+#: ./templates/Groups/index.php:31
+#: ./templates/Groups/view.php:35
+#: ./templates/MobilePhones/add.php:48
+#: ./templates/MobilePhones/edit.php:48
+#: ./templates/Organisations/index.php:29
+#: ./templates/Phones/add.php:48
+#: ./templates/Phones/edit.php:48
+msgid "Descrizione"
+msgstr "Description"
+
+#: ./src/Controller/GroupsController.php:58
+#: ./templates/Groups/add.php:39
+#: ./templates/Groups/edit.php:44
+#: ./templates/Groups/index.php:32
+#: ./templates/Groups/view.php:37
+msgid "Profilo Default"
+msgstr "Default Profile"
+
+#: ./src/Controller/GroupsController.php:59
+#: ./templates/Groups/add.php:40
+#: ./templates/Groups/edit.php:45
+#: ./templates/Groups/index.php:33
+#: ./templates/Groups/view.php:39
+msgid "Profilo Amministratore"
+msgstr "Admin Profile"
+
+#: ./src/Controller/GroupsController.php:64
+#: ./src/Controller/GroupsController.php:67
+#: ./templates/Deliveries/index.php:60
+#: ./templates/Deliveries/index.php:102
+#: ./templates/Deliveries/index.php:144
+#: ./templates/Deliveries/index.php:224
+#: ./templates/Groups/index.php:41
+#: ./templates/Groups/index.php:42
+#: ./templates/Groups/view.php:38
+#: ./templates/Groups/view.php:40
+msgid "SI"
+msgstr "YES"
+
+#: ./src/Controller/GroupsController.php:64
+#: ./src/Controller/GroupsController.php:67
+#: ./templates/Deliveries/index.php:60
+#: ./templates/Deliveries/index.php:102
+#: ./templates/Deliveries/index.php:144
+#: ./templates/Deliveries/index.php:224
+#: ./templates/Groups/index.php:41
+#: ./templates/Groups/index.php:42
+#: ./templates/Groups/view.php:38
+#: ./templates/Groups/view.php:40
+msgid "NO"
+msgstr "NO"
+
+#: ./src/Controller/GroupsController.php:118
+msgid "Profilo Utente creato con successo."
+msgstr "User Profile successfully created."
+
+#: ./src/Controller/GroupsController.php:122
+msgid "Errore durante la creazione del Profilo Utente: {0}"
+msgstr "Error trying to create User Profile: {0}"
+
+#: ./src/Controller/GroupsController.php:142
+#: ./src/Controller/GroupsController.php:206
+msgid "Profilo Utente \"{0}\" modificato con successo."
+msgstr "User Profile \"{0}\" successfully updated."
+
+#: ./src/Controller/GroupsController.php:146
+#: ./src/Controller/GroupsController.php:209
+msgid "Errore durante la modifica del Profilo Utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to edit the \"{0}\" User Profile. Please try again."
+
+#: ./src/Controller/GroupsController.php:166
+msgid "Il Profilo Utente \"{0}\" è stato cancellato con successo"
+msgstr "\"{0}\" User Profile successfully deleted"
+
+#: ./src/Controller/GroupsController.php:168
+msgid "Errore durante la cancellazione del Profilo Utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to delete the \"{0}\" User Profile. Please try again."
+
+#: ./src/Controller/MapsController.php:131
+msgid "Punto alle coordinate (EPSG:4326) Latitudine: {0}, Longitudine: {1}"
+msgstr "Point at coordinates (EPSG:4326) Latitude: {0}, Longitude: {1}"
+
+#: ./src/Controller/MobilePhonesController.php:40
+msgid "Il Cellulare è stato aggiunto con successo."
+msgstr "Mobile Phone contact successfully created."
+
+#: ./src/Controller/MobilePhonesController.php:44
+msgid "Errore durante l'aggiunta del Cellulare: {0}"
+msgstr "Error trying to create Mobile Phone: {0}"
+
+#: ./src/Controller/MobilePhonesController.php:72
+msgid "Il Cellulare è stato modificato con successo."
+msgstr "Mobile Phone successfully updated."
+
+#: ./src/Controller/MobilePhonesController.php:76
+msgid "Errore durante la modifica del Cellulare. Riprovare di nuovo"
+msgstr "Error trying to edit Mobile Phone. Please try again"
+
+#: ./src/Controller/NotificationsController.php:51
+msgid "Errore durante la cancellazione della notifica: "
+msgstr "Error trying to delete the notification: "
+
+#: ./src/Controller/OrganisationsController.php:64
+#: ./templates/Organisations/add.php:38
+#: ./templates/Organisations/edit.php:42
+#: ./templates/Organisations/index.php:30
+#: ./templates/Organisations/view.php:37
+msgid "Acronimo"
+msgstr "Acronym"
+
+#: ./src/Controller/OrganisationsController.php:65
+#: ./templates/Organisations/index.php:31
+msgid "Tipologia"
+msgstr "Typology"
+
+#: ./src/Controller/OrganisationsController.php:66
+#: ./templates/Maps/index.php:131
+#: ./templates/Organisations/add.php:140
+#: ./templates/Organisations/add.php:159
+#: ./templates/Organisations/edit.php:63
+#: ./templates/Organisations/index.php:32
+#: ./templates/Organisations/view.php:52
+#: ./templates/Users/add.php:46
+#: ./templates/Users/edit.php:51
+#: ./templates/Users/view.php:55
+msgid "Indirizzo"
+msgstr "Address"
+
+#: ./src/Controller/OrganisationsController.php:67
+#: ./templates/Maps/index.php:120
+#: ./templates/Organisations/add.php:129
+#: ./templates/Organisations/add.php:161
+#: ./templates/Organisations/edit.php:65
+#: ./templates/Organisations/index.php:34
+#: ./templates/Organisations/view.php:54
+msgid "Comune"
+msgstr "District"
+
+#: ./src/Controller/OrganisationsController.php:68
+#: ./templates/Organisations/add.php:160
+#: ./templates/Organisations/edit.php:64
+#: ./templates/Organisations/index.php:33
+#: ./templates/Organisations/view.php:53
+#: ./templates/Users/add.php:48
+#: ./templates/Users/edit.php:53
+#: ./templates/Users/view.php:59
+msgid "CAP"
+msgstr "ZIP code"
+
+#: ./src/Controller/OrganisationsController.php:69
+#: ./templates/Maps/index.php:109
+#: ./templates/Organisations/add.php:118
+#: ./templates/Organisations/add.php:162
+#: ./templates/Organisations/edit.php:66
+#: ./templates/Organisations/index.php:35
+#: ./templates/Organisations/view.php:55
+msgid "Provincia"
+msgstr "Province"
+
+#: ./src/Controller/OrganisationsController.php:70
+#: ./src/Controller/UsersController.php:76
+#: ./templates/Organisations/index.php:36
+#: ./templates/Organisations/view.php:56
+#: ./templates/Users/index.php:32
+msgid "Recapiti"
+msgstr "Contacts"
+
+#: ./src/Controller/OrganisationsController.php:137
+msgid "Organizzazione creata con successo."
+msgstr "Organisation successfully created."
+
+#: ./src/Controller/OrganisationsController.php:141
+msgid "Errore durante la creazione dell'organizzazione: {0}"
+msgstr "Error trying to create the organisation: {0}"
+
+#: ./src/Controller/OrganisationsController.php:163
+msgid "Organizzazione \"{0}\" modificata con successo."
+msgstr "Organisation \"{0}\" successfully updated."
+
+#: ./src/Controller/OrganisationsController.php:167
+msgid "Errore durante la modifica dell'organizzazione \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to edit the organisation \"{0}\". Please try again."
+
+#: ./src/Controller/OrganisationsController.php:188
+msgid "Impossibile eliminare l'organizzazione \"{0}\". Ci sono {1} utenti collegati ad essa."
+msgstr "Unable to delete the organisation \"{0}\". There are {1} belonging users."
+
+#: ./src/Controller/OrganisationsController.php:193
+msgid "L'organizzazione \"{0}\" è stata cancellata con successo"
+msgstr "Organisation \"{0}\" successfully deleted"
+
+#: ./src/Controller/OrganisationsController.php:195
+msgid "Errore durante la cancellazione dell'organizzazione \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to delete the organisation \"{0}\". Please try again."
+
+#: ./src/Controller/PhonesController.php:39
+msgid "Il Telefono è stato aggiunto con successo."
+msgstr "Phone successfully created."
+
+#: ./src/Controller/PhonesController.php:43
+msgid "Errore durante l'aggiunta del Telefono: {0}"
+msgstr "Error trying to create Phone: {0}"
+
+#: ./src/Controller/PhonesController.php:71
+msgid "Il Telefono è stato modificato con successo."
+msgstr "Phone successfully updated."
+
+#: ./src/Controller/PhonesController.php:75
+msgid "Errore durante la modifica del Telefono. Riprovare di nuovo"
+msgstr "Error trying to edit Phone. Please try again"
+
+#: ./src/Controller/TelegramChatsController.php:39
+msgid "La Chat Telegram è stata aggiunta con successo."
+msgstr "Telegram Chat successfully created."
+
+#: ./src/Controller/TelegramChatsController.php:43
+msgid "Errore durante l'aggiunta della Chat Telegram: {0}"
+msgstr "Error trying to create Telegram Chat: {0}"
+
+#: ./src/Controller/TelegramChatsController.php:70
+msgid "La Chat Telegram è stata modificata con successo."
+msgstr "Telegram Chat successfully created."
+
+#: ./src/Controller/TelegramChatsController.php:74
+msgid "Errore durante la modifica della Chat Telegram. Riprovare di nuovo"
+msgstr "Error trying to edit Telegram Chat. Please try again"
+
+#: ./src/Controller/UsersController.php:73
+#: ./templates/Users/add.php:41
+#: ./templates/Users/edit.php:46
+#: ./templates/Users/index.php:29
+#: ./templates/Users/view.php:45
+msgid "Cognome"
+msgstr "Surname"
+
+#: ./src/Controller/UsersController.php:74
+#: ./templates/ControllableObjects/get_attachments.php:59
+#: ./templates/Organisations/add.php:37
+#: ./templates/Organisations/edit.php:41
+#: ./templates/Organisations/view.php:36
+#: ./templates/Users/add.php:40
+#: ./templates/Users/edit.php:45
+#: ./templates/Users/index.php:30
+#: ./templates/Users/view.php:43
+msgid "Nome"
+msgstr "Name"
+
+#: ./src/Controller/UsersController.php:75
+#: ./templates/Users/index.php:31
+msgid "Username"
+msgstr "Username"
+
+#: ./src/Controller/UsersController.php:77
+#: ./templates/Users/add.php:52
+#: ./templates/Users/edit.php:57
+#: ./templates/Users/index.php:33
+#: ./templates/Users/view.php:65
+msgid "Profili"
+msgstr "Profiles"
+
+#: ./src/Controller/UsersController.php:78
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+#: ./templates/Users/add.php:50
+#: ./templates/Users/edit.php:55
+#: ./templates/Users/index.php:34
+#: ./templates/Users/view.php:63
+msgid "Organizzazione"
+msgstr "Organisation"
+
+#: ./src/Controller/UsersController.php:156
+msgid "Utente creato con successo."
+msgstr "User successfully created."
+
+#: ./src/Controller/UsersController.php:160
+msgid "Errore durante la creazione dell'utente: {0}"
+msgstr "Error trying to create user: {0}"
+
+#: ./src/Controller/UsersController.php:190
+msgid "Utente \"{0}\" modificato con successo."
+msgstr "User \"{0}\" successfully updated."
+
+#: ./src/Controller/UsersController.php:194
+msgid "Errore durante la modifica dell'utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to edit user \"{0}\". Please try again."
+
+#: ./src/Controller/UsersController.php:219
+msgid "L'utente \"{0}\" è stato cancellato con successo"
+msgstr "User \"{0}\" successfully deleted"
+
+#: ./src/Controller/UsersController.php:221
+msgid "Errore durante la cancellazione dell'utente \"{0}\". Riprovare di nuovo."
+msgstr "Error trying to delete user \"{0}\". Please try again."
+
+#: ./src/Controller/UsersController.php:244
+msgid "Ho dimenticato la mia password"
+msgstr "I forgot my password"
+
+#: ./src/Controller/UsersController.php:256
+msgid "Logout eseguito con successo."
+msgstr "Successfully logged out."
+
+#: ./src/Controller/UsersController.php:294
+msgid "Inserire un indirizzo email valido!"
+msgstr "Insert a valid email address!"
+
+#: ./src/Controller/UsersController.php:306
+msgid "A breve riceverai un'email all'indirizzo \"{0}\" con le istruzioni per eseguire il reset della password per il tuo account con username \"{1}\"."
+msgstr "You will receive shortly an email at \"{0}\" with the instructions to reset the password for your account with username \"{1}\"."
+
+#: ./src/Controller/UsersController.php:311
+msgid "L'indirizzo email inserito non risulta presente"
+msgstr "The email address you inserted is not valid or does not exists"
+
+#: ./src/Controller/UsersController.php:316
+#: ./src/Controller/UsersController.php:364
+msgid "Ritorna al login"
+msgstr "Back to login"
+
+#: ./src/Controller/UsersController.php:332
+msgid "Impossibile completare la procedura di recupero password."
+msgstr "Unable to complete reset password procedure. Please try again."
+
+#: ./src/Controller/UsersController.php:355
+msgid "Impossibile cambiare la password"
+msgstr "Unable to change the password"
+
+#: ./src/Controller/UsersController.php:359
+msgid "La nuova password non è valida e/o le 2 password non coincidono"
+msgstr "Either the new password is invalid or the two passwords don't match"
+
+#: ./src/Controller/UsersController.php:397
+msgid "Errore durante l'eliminazione della foto utente!"
+msgstr "Error trying to delete the user photo!"
+
+#: ./src/Controller/UsersController.php:399
+msgid "Foto utente eliminata con successo"
+msgstr "User photo successfully deleted"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:41
+msgid "Test Test Test"
+msgstr "Test Test Test"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:43
+msgid "Hai ricevuto questo messaggio di test perchè sei registrato/a sulla piattaforma {0} ed hai almeno un recapito abilitato alla ricezione delle notifiche"
+msgstr "You're receiving this message because you are a registered user to {0} platform and you have at least one notification enabled contact"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:46
+msgid "Recupero password {0}"
+msgstr "{0} password reset"
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:50
+msgid "Hai ricevuto questo messaggio perchè sei registrato/a sulla piattaforma {0} ed è stata richiesta la procedura di recupero credenziali per il tuo account. Se non hai richiesto tale procedura ti preghiamo di ignorare questo messaggio. Per accedere a {0} utilizza il seguente username: \" {1} \" . Clicca sul seguente link per impostare una nuova password "
+msgstr "You're receiving this message because you are a registered user to {0} platform and you requested a password reset for your account. Plese disregard this message if you didn't request it or if you changed your mind. Please use the following username to gain access to your account: \" {1} \" . Follow this link to reset your password instead "
+
+#: ./src/Ies/NotificationsHandler/NotificationGenerator.php:53
+msgid "{0} mancante"
+msgstr "Missing \"{0}\" notification code"
+
+#: ./src/Model/Behavior/AttachmentsBehavior.php:132
+msgid "L'allegato è obbligatorio!"
+msgstr "The attachment is mandatory!"
+
+#: ./src/Model/Entity/ControllableObject.php:241
+msgid "Le coordinate inserite per georeferenziare uno o più allegati non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell'area di competenza della piattaforma."
+msgstr "The given coordinates used to georeferencing one or more attachments are not valid. Please check that they are in the expected format (WGS84) and that they identify a point inside the platform configured bounding box."
+
+#: ./src/Model/Table/EmailsTable.php:107
+msgid "Indirizzo email già presente a sistema!"
+msgstr "Email address already exists!"
+
+#: ./src/Model/Table/FaxesTable.php:103
+msgid "Fax già presente a sistema!"
+msgstr "Fax already exists!"
+
+#: ./src/Model/Table/MobilePhonesTable.php:107
+msgid "Cellulare già presente a sistema!"
+msgstr "Mobile Phone already exists!"
+
+#: ./src/Model/Table/OrganisationsTable.php:169
+msgid "Le geometrie inserite per georeferenziare l'organizzazione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell'area di competenza della piattaforma."
+msgstr "The inserted geometries used to georeferenciate the organisation, are not valid. Please check that they are in the expected format (WGS84) and that they identify a point inside the platform configured bounding box."
+
+#: ./src/Model/Table/PhonesTable.php:99
+msgid "Telefono già presente a sistema!"
+msgstr "Phone already exists!"
+
+#: ./src/Model/Table/PushNotificationsTable.php:97
+msgid "Non puoi associare nuovamente questo token allo stesso utente"
+msgstr "You cannot use this push notification token again with this user"
+
+#: ./src/Model/Table/UsersTable.php:106
+msgid "La password deve contenere almeno {0} caratteri"
+msgstr "The password must contain at least {0} characters"
+
+#: ./src/Model/Table/UsersTable.php:111
+msgid "La password deve contenere almeno {0} carattere/i maiuscolo/i"
+msgstr "The password must contain at least {0} uppercase characters"
+
+#: ./src/Model/Table/UsersTable.php:117
+msgid "La password deve contenere almeno {0} numero/i"
+msgstr "The password must contain at least {0} numbers"
+
+#: ./src/Model/Table/UsersTable.php:131
+msgid "La password deve contenere almeno {1} carattere/i speciale/i tra \"{0}\""
+msgstr "The password must contain at least {1} special characters to be chosen among \"{0}\""
+
+#: ./src/Model/Table/UsersTable.php:256
+msgid "Errore durante il salvataggio della foto utente. Assicurarsi che sia nel formato corretto (jpeg 160x160)"
+msgstr "Error trying to save user photo. Please make sure that the photo you are trying to save is in the correct format and size (jpeg 160x160)"
+
+#: ./src/View/Cell/MapCell.php:182
+msgid "Geometrie disegnate"
+msgstr "Drawn geometries"
+
+#: ./templates/Capabilities/index.php:9
+#: ./templates/Deliveries/index.php:9
+#: ./templates/Emails/add.php:9
+#: ./templates/Emails/edit.php:9
+#: ./templates/Faxes/add.php:9
+#: ./templates/Faxes/edit.php:9
+#: ./templates/Groups/add.php:9
+#: ./templates/Groups/edit.php:9
+#: ./templates/Groups/handle_capabilities.php:9
+#: ./templates/Groups/index.php:9
+#: ./templates/Groups/view.php:9
+#: ./templates/Maps/index.php:9
+#: ./templates/MobilePhones/add.php:9
+#: ./templates/MobilePhones/edit.php:9
+#: ./templates/Organisations/add.php:9
+#: ./templates/Organisations/edit.php:9
+#: ./templates/Organisations/index.php:9
+#: ./templates/Organisations/view.php:9
+#: ./templates/Phones/add.php:9
+#: ./templates/Phones/edit.php:9
+#: ./templates/TelegramChats/add.php:9
+#: ./templates/TelegramChats/edit.php:9
+#: ./templates/Users/add.php:9
+#: ./templates/Users/edit.php:9
+#: ./templates/Users/index.php:9
+#: ./templates/Users/view.php:9
+msgid "Configurazioni"
+msgstr "Configurations"
+
+#: ./templates/Capabilities/index.php:24
+msgid "Lista delle competenze"
+msgstr "Capabilities list"
+
+#: ./templates/Capabilities/index.php:29
+msgid "Cerca per descrizione competenza o codice o nome del gruppo di competenze"
+msgstr "Search by capability description, code or capability group name"
+
+#: ./templates/Capabilities/index.php:29
+msgid "Cerca"
+msgstr "Search"
+
+#: ./templates/Capabilities/index.php:42
+msgid "Codice"
+msgstr "Code"
+
+#: ./templates/Capabilities/index.php:43
+msgid "Priorità"
+msgstr "Priority"
+
+#: ./templates/Capabilities/index.php:44
+msgid "Gruppo"
+msgstr "Group"
+
+#: ./templates/Capabilities/index.php:45
+#: ./templates/ControllableObjects/get_attachments.php:66
+#: ./templates/Deliveries/index.php:52
+#: ./templates/Deliveries/index.php:94
+#: ./templates/Deliveries/index.php:136
+#: ./templates/Deliveries/index.php:177
+#: ./templates/Deliveries/index.php:217
+#: ./templates/Groups/index.php:34
+#: ./templates/Organisations/index.php:37
+#: ./templates/Users/index.php:35
+msgid "Azioni"
+msgstr "Actions"
+
+#: ./templates/Capabilities/index.php:57
+#: ./templates/Groups/handle_capabilities.php:57
+#: ./templates/Groups/handle_capabilities.php:58
+#: ./templates/Groups/handle_capabilities.php:59
+msgid "Competenza non visibile e non configurabile dai non SYSADMIN"
+msgstr "Capability not visible and not configurable by non SYSADMIN users"
+
+#: ./templates/Capabilities/index.php:58
+msgid "Competenza eliminata dal sistema"
+msgstr "Capability successfully deleted"
+
+#: ./templates/Capabilities/index.php:67
+msgid "Nascondi"
+msgstr "Hide"
+
+#: ./templates/Capabilities/index.php:67
+msgid "Mostra"
+msgstr "Show"
+
+#: ./templates/Capabilities/index.php:68
+msgid "Ripristina"
+msgstr "Restore"
+
+#: ./templates/Capabilities/index.php:68
+#: ./templates/Deliveries/index.php:63
+#: ./templates/Deliveries/index.php:105
+#: ./templates/Deliveries/index.php:147
+#: ./templates/Deliveries/index.php:187
+#: ./templates/Deliveries/index.php:227
+#: ./templates/Groups/index.php:46
+#: ./templates/Groups/view.php:44
+#: ./templates/Organisations/index.php:54
+#: ./templates/Organisations/view.php:71
+#: ./templates/Users/index.php:50
+#: ./templates/Users/view.php:72
+msgid "Cancella"
+msgstr "Delete"
+
+#: ./templates/ControllableObjects/get_attachments.php:45
+msgid "Allegati presenti: {0}"
+msgstr "Attachments: {0}"
+
+#: ./templates/ControllableObjects/get_attachments.php:45
+msgid "Nessun Allegato presente"
+msgstr "No Attachments"
+
+#: ./templates/ControllableObjects/get_attachments.php:60
+msgid "Georeferenziazione"
+msgstr "Georeferencing"
+
+#: ./templates/ControllableObjects/get_attachments.php:62
+msgid "Dimensione"
+msgstr "Size"
+
+#: ./templates/ControllableObjects/get_attachments.php:63
+msgid "Tipo"
+msgstr "Type"
+
+#: ./templates/ControllableObjects/get_attachments.php:64
+msgid "Caricato il"
+msgstr "Uploaded"
+
+#: ./templates/ControllableObjects/get_attachments.php:65
+#: ./templates/cell/Filters/display.php:57
+msgid "Da"
+msgstr "From"
+
+#: ./templates/ControllableObjects/get_attachments.php:80
+msgid "File pubblico"
+msgstr "Public file"
+
+#: ./templates/ControllableObjects/get_attachments.php:83
+msgid "File privato"
+msgstr "Private file"
+
+#: ./templates/ControllableObjects/get_attachments.php:106
+msgid "Visualizza"
+msgstr "View"
+
+#: ./templates/ControllableObjects/get_attachments.php:110
+msgid "Segna da eliminare"
+msgstr "Mark as to be deleted"
+
+#: ./templates/ControllableObjects/get_attachments.php:112
+msgid "Segna come non rilevante"
+msgstr "Mark as not relevant"
+
+#: ./templates/ControllableObjects/get_attachments.php:112
+msgid "Segna come rilevante"
+msgstr "Mark as relevant"
+
+#: ./templates/Dashboard/index.php:16
+msgid "Jixel Dashboard"
+msgstr "Jixel Dashboard"
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Lista {0}"
+msgstr "List {0}"
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Organizzazioni"
+msgstr "Organisations"
+
+#: ./templates/Deliveries/index.php:13
+#: ./templates/Emails/add.php:13
+#: ./templates/Emails/edit.php:13
+#: ./templates/Faxes/add.php:13
+#: ./templates/Faxes/edit.php:13
+#: ./templates/MobilePhones/add.php:13
+#: ./templates/MobilePhones/edit.php:13
+#: ./templates/Phones/add.php:13
+#: ./templates/Phones/edit.php:13
+#: ./templates/TelegramChats/add.php:13
+#: ./templates/TelegramChats/edit.php:13
+msgid "Utenti"
+msgstr "Users"
+
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+msgid "Dettaglio {0}"
+msgstr "{0} Details"
+
+#: ./templates/Deliveries/index.php:18
+#: ./templates/Emails/add.php:18
+#: ./templates/Emails/edit.php:18
+#: ./templates/Faxes/add.php:18
+#: ./templates/Faxes/edit.php:18
+#: ./templates/MobilePhones/add.php:18
+#: ./templates/MobilePhones/edit.php:18
+#: ./templates/Phones/add.php:18
+#: ./templates/Phones/edit.php:18
+#: ./templates/TelegramChats/add.php:18
+#: ./templates/TelegramChats/edit.php:18
+msgid "Utente"
+msgstr "User"
+
+#: ./templates/Deliveries/index.php:23
+#: ./templates/Emails/add.php:23
+#: ./templates/Emails/edit.php:23
+#: ./templates/Faxes/add.php:23
+#: ./templates/Faxes/edit.php:23
+#: ./templates/MobilePhones/add.php:23
+#: ./templates/MobilePhones/edit.php:23
+#: ./templates/Organisations/view.php:69
+#: ./templates/Phones/add.php:23
+#: ./templates/Phones/edit.php:23
+#: ./templates/TelegramChats/add.php:23
+#: ./templates/TelegramChats/edit.php:23
+#: ./templates/Users/view.php:70
+msgid "Gestione recapiti"
+msgstr "Contacts management"
+
+#: ./templates/Deliveries/index.php:31
+msgid "Recapiti associati a {0} \"{1}\""
+msgstr "Associated contacts to {0} \"{1}\""
+
+#: ./templates/Deliveries/index.php:41
+msgid "Cellulare: {0}"
+msgstr "Mobile Phone {0}"
+
+#: ./templates/Deliveries/index.php:50
+#: ./templates/MobilePhones/add.php:47
+#: ./templates/MobilePhones/edit.php:47
+msgid "Cellulare"
+msgstr "Mobile Phone"
+
+#: ./templates/Deliveries/index.php:51
+#: ./templates/Deliveries/index.php:93
+#: ./templates/Deliveries/index.php:135
+#: ./templates/Deliveries/index.php:216
+#: ./templates/Emails/add.php:49
+#: ./templates/Emails/edit.php:49
+#: ./templates/Faxes/add.php:49
+#: ./templates/Faxes/edit.php:49
+#: ./templates/MobilePhones/add.php:49
+#: ./templates/MobilePhones/edit.php:49
+#: ./templates/TelegramChats/add.php:48
+#: ./templates/TelegramChats/edit.php:48
+msgid "Ricevi notifiche a questo recapito"
+msgstr "Receive notifications at this contact"
+
+#: ./templates/Deliveries/index.php:62
+#: ./templates/Deliveries/index.php:104
+#: ./templates/Deliveries/index.php:146
+#: ./templates/Deliveries/index.php:186
+#: ./templates/Deliveries/index.php:226
+#: ./templates/Groups/index.php:45
+#: ./templates/Groups/view.php:43
+#: ./templates/Organisations/index.php:53
+#: ./templates/Organisations/view.php:70
+#: ./templates/Users/index.php:49
+#: ./templates/Users/view.php:71
+msgid "Modifica"
+msgstr "Edit"
+
+#: ./templates/Deliveries/index.php:63
+msgid "Sei sicuro che vuoi cancellare il Cellulare \"{0}\" ?"
+msgstr "Are you sure you want to delete the Mobile Phone \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:73
+#: ./templates/MobilePhones/add.php:28
+msgid "Aggiungi Cellulare"
+msgstr "Add Mobile Phone"
+
+#: ./templates/Deliveries/index.php:84
+msgid "Fax: {0}"
+msgstr "Fax: {0}"
+
+#: ./templates/Deliveries/index.php:92
+#: ./templates/Faxes/add.php:47
+#: ./templates/Faxes/edit.php:47
+msgid "Fax"
+msgstr "Fax"
+
+#: ./templates/Deliveries/index.php:105
+msgid "Sei sicuro che vuoi cancellare il Fax \"{0}\" ?"
+msgstr "Are you sure you want to delete the Fax \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:115
+#: ./templates/Faxes/add.php:28
+msgid "Aggiungi Fax"
+msgstr "Add Fax"
+
+#: ./templates/Deliveries/index.php:126
+msgid "Email: {0}"
+msgstr "Email: {0}"
+
+#: ./templates/Deliveries/index.php:134
+#: ./templates/Emails/add.php:47
+#: ./templates/Emails/edit.php:47
+msgid "Email"
+msgstr "Email"
+
+#: ./templates/Deliveries/index.php:147
+msgid "Sei sicuro che vuoi cancellare l'Email \"{0}\" ?"
+msgstr "Are you sure you want to delete the Email \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:157
+#: ./templates/Emails/add.php:28
+msgid "Aggiungi Email"
+msgstr "Add Email"
+
+#: ./templates/Deliveries/index.php:168
+msgid "Telefono: {0}"
+msgstr "Phone {0}"
+
+#: ./templates/Deliveries/index.php:176
+#: ./templates/Phones/add.php:47
+#: ./templates/Phones/edit.php:47
+msgid "Telefono"
+msgstr "Phone"
+
+#: ./templates/Deliveries/index.php:187
+msgid "Sei sicuro che vuoi cancellare il Telefono \"{0}\" ?"
+msgstr "Are you sure you want to delete the Phone \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:197
+#: ./templates/Phones/add.php:28
+msgid "Aggiungi Telefono"
+msgstr "Add Phone"
+
+#: ./templates/Deliveries/index.php:208
+msgid "Chat Telegram: {0}"
+msgstr "Telegram Chat: {0}"
+
+#: ./templates/Deliveries/index.php:215
+msgid "ID"
+msgstr "ID"
+
+#: ./templates/Deliveries/index.php:227
+msgid "Sei sicuro che vuoi cancellare la Chat Telegram con ID \"{0}\" ?"
+msgstr "Are you sure you want to delete the Telegram Chat with ID \"{0}\" ?"
+
+#: ./templates/Deliveries/index.php:237
+#: ./templates/TelegramChats/add.php:28
+msgid "Aggiungi Chat Telegram"
+msgstr "Add Telegram Chat"
+
+#: ./templates/Emails/add.php:40
+msgid "Aggiungi Email per {0} \"{1}\""
+msgstr "Add Email for {0} \"{1}\""
+
+#: ./templates/Emails/add.php:54
+#: ./templates/Emails/edit.php:54
+#: ./templates/Faxes/add.php:54
+#: ./templates/Faxes/edit.php:54
+#: ./templates/Groups/add.php:45
+#: ./templates/Groups/edit.php:50
+#: ./templates/Groups/handle_capabilities.php:71
+#: ./templates/MobilePhones/add.php:54
+#: ./templates/MobilePhones/edit.php:54
+#: ./templates/Organisations/add.php:172
+#: ./templates/Organisations/edit.php:86
+#: ./templates/Phones/add.php:53
+#: ./templates/Phones/edit.php:53
+#: ./templates/TelegramChats/add.php:53
+#: ./templates/TelegramChats/edit.php:53
+#: ./templates/Users/add.php:57
+#: ./templates/Users/choose_new_password.php:8
+#: ./templates/Users/edit.php:62
+msgid "Salva"
+msgstr "Save"
+
+#: ./templates/Emails/edit.php:28
+msgid "Modifica Email"
+msgstr "Edit Email"
+
+#: ./templates/Emails/edit.php:40
+msgid "Modifica Email per {0} \"{1}\""
+msgstr "Edit Email for {0} \"{1}\""
+
+#: ./templates/Faxes/add.php:40
+msgid "Aggiungi Fax per {0} \"{1}\""
+msgstr "Add Fax for {0} \"{1}\""
+
+#: ./templates/Faxes/edit.php:28
+msgid "Modifica Fax"
+msgstr "Edit Fax"
+
+#: ./templates/Faxes/edit.php:40
+msgid "Modifica Fax per {0} \"{1}\""
+msgstr "Edit Fax for {0} \"{1}\""
+
+#: ./templates/Groups/add.php:13
+#: ./templates/Groups/edit.php:13
+#: ./templates/Groups/handle_capabilities.php:13
+#: ./templates/Groups/index.php:13
+#: ./templates/Groups/index.php:24
+#: ./templates/Groups/view.php:13
+msgid "Lista dei Profili Utente"
+msgstr "User Profiles List"
+
+#: ./templates/Groups/add.php:18
+#: ./templates/Groups/add.php:31
+msgid "Nuovo Profilo Utente"
+msgstr "New User Profile"
+
+#: ./templates/Groups/edit.php:18
+#: ./templates/Groups/handle_capabilities.php:18
+#: ./templates/Groups/view.php:18
+msgid "Dettaglio Profilo Utente"
+msgstr "User Profile Details"
+
+#: ./templates/Groups/edit.php:23
+#: ./templates/Groups/edit.php:36
+msgid "Modifica Profilo Utente"
+msgstr "Edit User Profile"
+
+#: ./templates/Groups/handle_capabilities.php:35
+msgid "Competenze associate al Profilo Utente \"{0}\""
+msgstr "User Profile \"{0}\" associated capabilities"
+
+#: ./templates/Groups/handle_capabilities.php:45
+msgid "Gruppo di competenze non visibile e non configurabile dai non SYSADMIN"
+msgstr "Capability Groups not visible and not configurable by non SYSADMIN users"
+
+#: ./templates/Groups/handle_capabilities.php:52
+msgid "Gruppo di competenze \"{0}\""
+msgstr "Capability Group \"{0}\""
+
+#: ./templates/Groups/index.php:44
+#: ./templates/Organisations/index.php:52
+#: ./templates/Users/index.php:48
+#: ./templates/plugin/AdminLTE/element/nav-top.php:118
+msgid "Dettaglio"
+msgstr "Details"
+
+#: ./templates/Groups/index.php:46
+#: ./templates/Groups/view.php:44
+msgid "Sei sicuro che vuoi cancellare il profilo \"{0}\" ?"
+msgstr "Are you sure you want to delete the user profile \"{0}\" ?"
+
+#: ./templates/Groups/view.php:30
+msgid "Informazioni Profilo Utente"
+msgstr "User Profile Informations"
+
+#: ./templates/Maps/index.php:25
+msgid "Mappa"
+msgstr "Map"
+
+#: ./templates/Maps/index.php:30
+msgid "Campo esistente appartenente al form ospite"
+msgstr "Existing field that belongs to the hosting form"
+
+#: ./templates/Maps/index.php:37
+msgid "Posizione Evento"
+msgstr "Incident location"
+
+#: ./templates/Maps/index.php:54
+msgid "Collezione di geometrie"
+msgstr "Geometry collection"
+
+#: ./templates/Maps/index.php:65
+#: ./templates/Organisations/add.php:74
+msgid "Longitudine"
+msgstr "Longitude"
+
+#: ./templates/Maps/index.php:76
+#: ./templates/Organisations/add.php:85
+msgid "Latitudine"
+msgstr "Latitude"
+
+#: ./templates/Maps/index.php:87
+#: ./templates/Organisations/add.php:96
+#: ./templates/Organisations/add.php:158
+#: ./templates/Organisations/edit.php:62
+#: ./templates/Organisations/view.php:51
+msgid "Coordinate (Longitudine Latitudine)"
+msgstr "Coordinates (Longitude Latitude)"
+
+#: ./templates/Maps/index.php:98
+#: ./templates/Organisations/add.php:107
+msgid "Cap"
+msgstr "ZIP code"
+
+#: ./templates/Maps/index.php:142
+#: ./templates/Organisations/add.php:151
+msgid "Descrizione luogo"
+msgstr "Location description"
+
+#: ./templates/MobilePhones/add.php:40
+msgid "Aggiungi Cellulare per {0} \"{1}\""
+msgstr "Add Mobile Phone for {0} \"{1}\""
+
+#: ./templates/MobilePhones/edit.php:28
+msgid "Modifica Cellulare"
+msgstr "Edit Mobile Phone"
+
+#: ./templates/MobilePhones/edit.php:40
+msgid "Modifica Cellulare per {0} \"{1}\""
+msgstr "Edit Mobile Phone for {0} \"{1}\""
+
+#: ./templates/Organisations/add.php:13
+#: ./templates/Organisations/edit.php:13
+#: ./templates/Organisations/index.php:13
+#: ./templates/Organisations/view.php:13
+msgid "Lista Organizzazioni"
+msgstr "Organisations List"
+
+#: ./templates/Organisations/add.php:18
+#: ./templates/Organisations/add.php:30
+msgid "Nuova Organizzazione"
+msgstr "New Organisation"
+
+#: ./templates/Organisations/add.php:39
+#: ./templates/Organisations/edit.php:43
+#: ./templates/Organisations/view.php:38
+msgid "Tipo organizzazione"
+msgstr "Organisation type"
+
+#: ./templates/Organisations/add.php:46
+#: ./templates/Organisations/edit.php:50
+#: ./templates/Organisations/view.php:45
+msgid "Posizione Organizzazione"
+msgstr "Organisation Location"
+
+#: ./templates/Organisations/edit.php:18
+#: ./templates/Organisations/view.php:18
+#: ./templates/Organisations/view.php:29
+msgid "Dettaglio Organizzazione"
+msgstr "Organisation Details"
+
+#: ./templates/Organisations/edit.php:23
+#: ./templates/Organisations/edit.php:34
+msgid "Modifica Organizzazione"
+msgstr "Edit Organisation"
+
+#: ./templates/Organisations/index.php:23
+msgid "Lista delle {0} Organizzazioni"
+msgstr "List of {0} Organisations"
+
+#: ./templates/Organisations/index.php:23
+#: ./templates/Users/index.php:23
+msgid "{0} su {1}"
+msgstr "{0} out of {1}"
+
+#: ./templates/Organisations/index.php:54
+#: ./templates/Organisations/view.php:71
+msgid "Sei sicuro che vuoi cancellare l'organizzazione \"{0}\" ?"
+msgstr "Are you sure you want to delete the organisation \"{0}\" ?"
+
+#: ./templates/Phones/add.php:40
+msgid "Aggiungi Telefono per {0} \"{1}\""
+msgstr "Add Phone for {0} \"{1}\""
+
+#: ./templates/Phones/edit.php:28
+msgid "Modifica Telefono"
+msgstr "Edit Phone"
+
+#: ./templates/Phones/edit.php:40
+msgid "Modifica Telefono per {0} \"{1}\""
+msgstr "Edit Phone for {0} \"{1}\""
+
+#: ./templates/TelegramChats/add.php:40
+msgid "Aggiungi Chat Telegram per {0} \"{1}\""
+msgstr "Add Telegram Chat for {0} \"{1}\""
+
+#: ./templates/TelegramChats/add.php:47
+#: ./templates/TelegramChats/edit.php:47
+msgid "Chat Telegram ID"
+msgstr "Telegram Chat ID"
+
+#: ./templates/TelegramChats/edit.php:28
+msgid "Modifica Chat Telegram"
+msgstr "Edit Telegram Chat"
+
+#: ./templates/TelegramChats/edit.php:40
+msgid "Modifica Chat Telegram per {0} \"{1}\""
+msgstr "Edit Telegram Chat for {0} \"{1}\""
+
+#: ./templates/Users/add.php:13
+#: ./templates/Users/edit.php:13
+#: ./templates/Users/index.php:13
+#: ./templates/Users/view.php:13
+msgid "Lista Utenti"
+msgstr "Users List"
+
+#: ./templates/Users/add.php:18
+#: ./templates/Users/add.php:31
+msgid "Nuovo Utente"
+msgstr "New User"
+
+#: ./templates/Users/add.php:38
+#: ./templates/Users/edit.php:43
+#: ./templates/Users/view.php:41
+msgid "Nome utente"
+msgstr "Username"
+
+#: ./templates/Users/add.php:39
+#: ./templates/Users/edit.php:44
+msgid "Password"
+msgstr "Password"
+
+#: ./templates/Users/add.php:42
+#: ./templates/Users/edit.php:47
+#: ./templates/Users/view.php:47
+msgid "Codice Fiscale"
+msgstr "Tax ID code"
+
+#: ./templates/Users/add.php:43
+#: ./templates/Users/edit.php:48
+#: ./templates/Users/view.php:49
+msgid "Data di nascita"
+msgstr "Date of birth"
+
+#: ./templates/Users/add.php:44
+#: ./templates/Users/edit.php:49
+#: ./templates/Users/view.php:51
+msgid "Luogo di nascita"
+msgstr "Birth place"
+
+#: ./templates/Users/add.php:45
+#: ./templates/Users/edit.php:50
+#: ./templates/Users/view.php:53
+msgid "Sesso"
+msgstr "Gender"
+
+#: ./templates/Users/add.php:47
+#: ./templates/Users/edit.php:52
+#: ./templates/Users/view.php:57
+msgid "Città"
+msgstr "City"
+
+#: ./templates/Users/add.php:49
+#: ./templates/Users/edit.php:54
+#: ./templates/Users/view.php:61
+msgid "Lingua preferita"
+msgstr "Favourite language"
+
+#: ./templates/Users/add.php:51
+#: ./templates/Users/edit.php:56
+msgid "Foto del profilo (solo jpeg di dimensioni 160x160!)"
+msgstr "Photo (160x160 sized jpeg only!)"
+
+#: ./templates/Users/choose_new_password.php:4
+msgid "Imposta una nuova password"
+msgstr "Set a new password"
+
+#: ./templates/Users/choose_new_password.php:5
+msgid "Digita la nuova password"
+msgstr "Enter the new password"
+
+#: ./templates/Users/choose_new_password.php:6
+msgid "Ridigita la nuova password"
+msgstr "Retype the previous entered password"
+
+#: ./templates/Users/edit.php:18
+#: ./templates/Users/view.php:18
+msgid "Dettaglio Utente"
+msgstr "User Details"
+
+#: ./templates/Users/edit.php:23
+#: ./templates/Users/edit.php:36
+msgid "Modifica Utente"
+msgstr "Edit User"
+
+#: ./templates/Users/index.php:23
+msgid "Lista dei {0} Utenti"
+msgstr "List of {0} Users"
+
+#: ./templates/Users/index.php:50
+#: ./templates/Users/view.php:72
+msgid "Sei sicuro che vuoi cancellare l'utente \"{0}\" ?"
+msgstr "Are you sure you wanto to delete the user \"{0}\" ?"
+
+#: ./templates/Users/login.php:4
+msgid "Accedi"
+msgstr "Gain access"
+
+#: ./templates/Users/login.php:8
+msgid "Login"
+msgstr "Login"
+
+#: ./templates/Users/password_recovery.php:4
+msgid "Inserisci un indirizzo email associato alla tua utenza"
+msgstr "Insert an email that is currently associated with your account"
+
+#: ./templates/Users/password_recovery.php:7
+msgid "Richiedi reset password"
+msgstr "Request password reset"
+
+#: ./templates/Users/view.php:30
+msgid "Informazioni Utente"
+msgstr "User Informations"
+
+#: ./templates/Users/view.php:34
+msgid "Elimina foto"
+msgstr "Delete photo"
+
+#: ./templates/Users/view.php:34
+msgid "Sei sicuro che vuoi eliminare la foto ?"
+msgstr "Are you sure you want to delete the photo ?"
+
+#: ./templates/Users/view.php:62
+msgid "Non specificata"
+msgstr "Not specified"
+
+#: ./templates/Users/view.php:67
+msgid "Recapiti:"
+msgstr "Contacts"
+
+#: ./templates/cell/FilterInput/display.php:9
+#: ./templates/element/attachments.php:127
+msgid "Rimuovi"
+msgstr "Remove"
+
+#: ./templates/cell/Filters/display.php:3
+#: ./templates/cell/Filters/display.php:113
+msgid "Filtri attivi"
+msgstr "Filters applied"
+
+#: ./templates/cell/Filters/display.php:3
+#: ./templates/cell/Filters/display.php:116
+msgid "Filtri disattivati"
+msgstr "No Filters applied"
+
+#: ./templates/cell/Filters/display.php:15
+msgid "Aggiungi un filtro"
+msgstr "Add a filter"
+
+#: ./templates/cell/Filters/display.php:34
+#: ./templates/cell/Filters/display.php:55
+msgid "Applica"
+msgstr "Apply"
+
+#: ./templates/cell/Filters/display.php:39
+msgid "Reset"
+msgstr "Reset"
+
+#: ./templates/cell/Filters/display.php:56
+msgid "Annulla"
+msgstr "Cancel"
+
+#: ./templates/cell/Filters/display.php:58
+msgid "A"
+msgstr "TO"
+
+#: ./templates/cell/Filters/display.php:59
+msgid "Dal Al"
+msgstr "From To"
+
+#: ./templates/cell/Filters/display.php:60
+#: ./templates/cell/Filters/display.php:87
+msgid "Oggi"
+msgstr "Today"
+
+#: ./templates/cell/Filters/display.php:62
+msgid "Dom"
+msgstr "Sun"
+
+#: ./templates/cell/Filters/display.php:63
+msgid "Lun"
+msgstr "Mon"
+
+#: ./templates/cell/Filters/display.php:64
+msgid "Mar"
+msgstr "Tue"
+
+#: ./templates/cell/Filters/display.php:65
+msgid "Mer"
+msgstr "Wed"
+
+#: ./templates/cell/Filters/display.php:66
+msgid "Gio"
+msgstr "Thu"
+
+#: ./templates/cell/Filters/display.php:67
+msgid "Ven"
+msgstr "Fri"
+
+#: ./templates/cell/Filters/display.php:68
+msgid "Sab"
+msgstr "Sat"
+
+#: ./templates/cell/Filters/display.php:71
+msgid "Gennaio"
+msgstr "January"
+
+#: ./templates/cell/Filters/display.php:72
+msgid "Febbraio"
+msgstr "February"
+
+#: ./templates/cell/Filters/display.php:73
+msgid "Marzo"
+msgstr "March"
+
+#: ./templates/cell/Filters/display.php:74
+msgid "Aprile"
+msgstr "April"
+
+#: ./templates/cell/Filters/display.php:75
+msgid "Maggio"
+msgstr "May"
+
+#: ./templates/cell/Filters/display.php:76
+msgid "Giugno"
+msgstr "June"
+
+#: ./templates/cell/Filters/display.php:77
+msgid "Luglio"
+msgstr "July"
+
+#: ./templates/cell/Filters/display.php:78
+msgid "Agosto"
+msgstr "August"
+
+#: ./templates/cell/Filters/display.php:79
+msgid "Settembre"
+msgstr "September"
+
+#: ./templates/cell/Filters/display.php:80
+msgid "Ottobre"
+msgstr "October"
+
+#: ./templates/cell/Filters/display.php:81
+msgid "Novembre"
+msgstr "November"
+
+#: ./templates/cell/Filters/display.php:82
+msgid "Dicembre"
+msgstr "December"
+
+#: ./templates/cell/Filters/display.php:88
+msgid "Ieri"
+msgstr "Yesterday"
+
+#: ./templates/cell/Filters/display.php:89
+msgid "Questa settimana"
+msgstr "This week"
+
+#: ./templates/cell/Filters/display.php:90
+msgid "Questo mese"
+msgstr "This month"
+
+#: ./templates/cell/Filters/display.php:91
+msgid "Lo scorso mese"
+msgstr "Last month"
+
+#: ./templates/cell/Filters/display.php:92
+msgid "Ultimi 7 giorni"
+msgstr "Last 7 days"
+
+#: ./templates/cell/Filters/display.php:93
+msgid "Ultimi 15 giorni"
+msgstr "Last 15 days"
+
+#: ./templates/cell/Filters/display.php:94
+msgid "Ultimi 30 giorni"
+msgstr "Last 30 days"
+
+#: ./templates/cell/Filters/display.php:131
+msgid "Errore durante il recupero del filtro selezionato. Riprovare di nuovo"
+msgstr "Error trying to retrieve the selected filter. Pleas try again"
+
+#: ./templates/element/Map.php:107
+#: ./templates/element/Map.php:118
+#: ./templates/element/Map.php:122
+msgid "OpenStreetMap ONLINE"
+msgstr "OpenStreetMap ONLINE"
+
+#: ./templates/element/Map.php:107
+#: ./templates/element/Map.php:127
+#: ./templates/element/Map.php:131
+msgid "OpenStreetMap OFFLINE"
+msgstr "OpenStreetMap OFFLINE"
+
+#: ./templates/element/Map.php:312
+#: ./templates/element/Map.php:541
+msgid "Indirizzo non trovato o fuori dall'area di competenza"
+msgstr "Address not found or out of the platform configured bounding box"
+
+#: ./templates/element/Map.php:530
+msgid "Punto alle coordinate (EPSG:4326) Latitudine:"
+msgstr "Point of coordinates (EPSG:4326) Latitude:"
+
+#: ./templates/element/Map.php:530
+msgid "Longitudine:"
+msgstr "Longitude:"
+
+#: ./templates/element/MapCore/MapPrimitives.php:10
+msgid "Scegli un risultato:"
+msgstr "Pick a result"
+
+#: ./templates/element/MapCore/MapPrimitives.php:30
+msgid "Inserisci un indirizzo o le coordinate (in formato EPSG:4326)"
+msgstr "Insert an address or coordinates (EPSG:4326)"
+
+#: ./templates/element/MapCore/MapPrimitives.php:31
+msgid "Cerca un indirizzo"
+msgstr "Look up for an address"
+
+#: ./templates/element/MapCore/MapPrimitives.php:36
+msgid "Inserisci un punto in mappa"
+msgstr "Insert a point on map"
+
+#: ./templates/element/MapCore/MapPrimitives.php:41
+msgid "Inserisci un poligono in mappa"
+msgstr "Draw a polygon on map"
+
+#: ./templates/element/MapCore/MapPrimitives.php:46
+msgid "Inserisci un cerchio in mappa"
+msgstr "Draw a circle on map"
+
+#: ./templates/element/MapCore/MapPrimitives.php:51
+msgid "Cancella una geometria"
+msgstr "Delete a geometry"
+
+#: ./templates/element/attachmentPreview.php:16
+msgid "Il tuo browser non supporta HTML5 video tag. Prova ad aggiornare il tuo browser."
+msgstr "Your browser doesn't seem to support HTML5 video tag. Please try and update your browser to a more recent version."
+
+#: ./templates/element/attachmentPreview.php:35
+msgid "Anteprima non disponibile"
+msgstr "Preview not available"
+
+#: ./templates/element/attachments.php:30
+msgid "di tipo: \"{0}\""
+msgstr "of type \"{0}\""
+
+#: ./templates/element/attachments.php:39
+msgid "Mostra allegati correlati"
+msgstr "Show also linked attachments"
+
+#: ./templates/element/attachments.php:48
+msgid "Allega un file "
+msgstr "Attach a file"
+
+#: ./templates/element/attachments.php:48
+msgid "Allega files "
+msgstr "Attach files"
+
+#: ./templates/element/attachments.php:54
+msgid "Allega file pubblico "
+msgstr "Attach public file"
+
+#: ./templates/element/attachments.php:54
+msgid "Allega un file privato "
+msgstr "Attach a private file"
+
+#: ./templates/element/attachments.php:54
+msgid "Allega files privati "
+msgstr "Attach private files "
+
+#: ./templates/element/attachments.php:58
+msgid "Allega files..."
+msgstr "Attach files..."
+
+#: ./templates/element/attachments.php:65
+msgid "Allega files {1} {0}"
+msgstr "Attach files {1} {0}"
+
+#: ./templates/element/attachments.php:118
+msgid "latitudine"
+msgstr "latitude"
+
+#: ./templates/element/attachments.php:119
+msgid "longitudine"
+msgstr "longitude"
+
+#: ./templates/layout/error.php:38
+msgid "Back"
+msgstr "Back"
+
+#: ./templates/plugin/AdminLTE/element/aside-control-sidebar.php:4
+msgid "Notifiche"
+msgstr "Notifications"
+
+#: ./templates/plugin/AdminLTE/element/footer.php:6
+msgid "Versione"
+msgstr "Version"
+
+#: ./templates/plugin/AdminLTE/element/footer.php:9
+msgid "Tutti i diritti riservati"
+msgstr "All rights reserved"
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:67
+msgid "Nuove notifiche: {0}"
+msgstr "New notifications: {0}"
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:91
+msgid "Segna tutte le notifiche come lette"
+msgstr "Mark all new notifications as read"
+
+#: ./templates/plugin/AdminLTE/element/nav-top.php:121
+msgid "Esci"
+msgstr "Logout"
+
diff --git a/idrocap_wa/resources/locales/it/cake.po b/idrocap_wa/resources/locales/it/cake.po
new file mode 100644
index 0000000..799b01c
--- /dev/null
+++ b/idrocap_wa/resources/locales/it/cake.po
@@ -0,0 +1,279 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: CakePHP 4.4.5\n"
+"POT-Creation-Date: 2023-02-28 09:27+0000\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: ./templates/Error/error400.php:39
+#: ./templates/Error/error500.php:43
+msgid "Error"
+msgstr "Errore"
+
+#: ./templates/Error/error400.php:40
+msgid "The requested address {0} was not found on this server."
+msgstr "L'indirizzo richiesto {0} non è stato trovato su questo server."
+
+#: ./templates/Error/error500.php:41
+#: ./vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php:361
+msgid "An Internal Error Has Occurred."
+msgstr "Errore interno."
+
+#: ./vendor/cakephp/cakephp/src/Controller/Component/AuthComponent.php:462
+msgid "You are not authorized to access that location."
+msgstr "Non sei autorizzato ad accedere a quella risorsa."
+
+#: ./vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php:359
+msgid "Not Found"
+msgstr "Non Trovato"
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:390
+msgid "Missing or incorrect CSRF cookie type."
+msgstr "tipo di CSRF cookie mancante o incorretto."
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:394
+msgid "Missing or invalid CSRF cookie."
+msgstr "CSRF cookie mancante o incorretto."
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:417
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php:265
+msgid "CSRF token from either the request body or request headers did not match or is missing."
+msgstr "Il CSRF token è mancante o quello presente nel body non corrisponde."
+
+#: ./vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php:247
+msgid "Missing or incorrect CSRF session key"
+msgstr "Chiave di sessione CSRF incorretta o mancante"
+
+#: ./vendor/cakephp/cakephp/src/Http/Response.php:1489
+msgid "The requested file contains `..` and will not be read."
+msgstr "Il file richiesto contiene `..` e quindi non verrà letto."
+
+#: ./vendor/cakephp/cakephp/src/Http/Response.php:1497
+msgid "The requested file was not found"
+msgstr "Il file richiesto non è stato trovato"
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:116
+msgid "{0,number,#,###.##} KB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:118
+msgid "{0,number,#,###.##} MB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:120
+msgid "{0,number,#,###.##} GB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:122
+msgid "{0,number,#,###.##} TB"
+msgstr ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/Number.php:114
+msgid "{0,number,integer} Byte"
+msgid_plural "{0,number,integer} Bytes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:86
+msgid "{0} from now"
+msgstr "{0} da adesso"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:86
+msgid "{0} ago"
+msgstr "{0} fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:89
+msgid "{0} after"
+msgstr "{0} dopo"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:89
+msgid "{0} before"
+msgstr "{0} prima"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:120
+msgid "just now"
+msgstr "in questo momento"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:157
+msgid "about a second ago"
+msgstr "circa un secondo fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:158
+msgid "about a minute ago"
+msgstr "circa un minuto fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:159
+msgid "about an hour ago"
+msgstr "circa un'ora fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:160
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:370
+msgid "about a day ago"
+msgstr "circa un giorno fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:161
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:371
+msgid "about a week ago"
+msgstr "circa una settimana fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:162
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:372
+msgid "about a month ago"
+msgstr "circa un mese fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:163
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:373
+msgid "about a year ago"
+msgstr "circa un anno fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:174
+msgid "in about a second"
+msgstr "fra circa un secondo"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:175
+msgid "in about a minute"
+msgstr "fra circa un minuto"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:176
+msgid "in about an hour"
+msgstr "fra circa un'ora"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:177
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:384
+msgid "in about a day"
+msgstr "fra circa un giorno"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:178
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:385
+msgid "in about a week"
+msgstr "tra circa una settimana"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:179
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:386
+msgid "in about a month"
+msgstr "tra circa un mese"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:180
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:387
+msgid "in about a year"
+msgstr "tra circa un anno"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:342
+msgid "today"
+msgstr "oggi"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:409
+msgid "%s ago"
+msgstr "%s fa"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:410
+msgid "on %s"
+msgstr "%s"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:53
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:132
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:354
+msgid "{0} year"
+msgid_plural "{0} years"
+msgstr[0] "{0} anno"
+msgstr[1] "{0} anni"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:57
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:135
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:357
+msgid "{0} month"
+msgid_plural "{0} months"
+msgstr[0] "{0} mese"
+msgstr[1] "{0} mesi"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:63
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:138
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:360
+msgid "{0} week"
+msgid_plural "{0} weeks"
+msgstr[0] "{0} settimana"
+msgstr[1] "{0} settimane"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:65
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:141
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:363
+msgid "{0} day"
+msgid_plural "{0} days"
+msgstr[0] "{0} giorno"
+msgstr[1] "{0} giorni"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:70
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:144
+msgid "{0} hour"
+msgid_plural "{0} hours"
+msgstr[0] "{0} ora"
+msgstr[1] "{0} ore"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:74
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:147
+msgid "{0} minute"
+msgid_plural "{0} minutes"
+msgstr[0] "{0} minuto"
+msgstr[1] "{0} minuti"
+
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:78
+#: ./vendor/cakephp/cakephp/src/I18n/RelativeTimeFormatter.php:150
+msgid "{0} second"
+msgid_plural "{0} seconds"
+msgstr[0] "{0} secondo"
+msgstr[1] "{0} secondi"
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:63
+msgid "This value is already in use"
+msgstr "Questo valore è già in uso"
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:110
+msgid "This value does not exist"
+msgstr "Questo valore non esiste"
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:232
+msgid "Cannot modify row: a constraint for the `{0}` association fails."
+msgstr "Impossibile modificare: il vincolo per l'associazione `{0}` fallisce."
+
+#: ./vendor/cakephp/cakephp/src/ORM/RulesChecker.php:270
+msgid "The count does not match {0}{1}"
+msgstr "Il conteggio non corrisponde {0}{1}"
+
+#: ./vendor/cakephp/cakephp/src/Utility/Text.php:923
+msgid "and"
+msgstr "e"
+
+#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:2539
+msgid "This field is required"
+msgstr "Questo campo è richiesto"
+
+#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:2559
+#: ./vendor/cakephp/cakephp/src/View/Form/ArrayContext.php:249
+msgid "This field cannot be left empty"
+msgstr "Questo campo non può essere lasciato vuoto"
+
+#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:2711
+msgid "The provided value is invalid"
+msgstr "Il valore fornito non è valido"
+
+#: ./vendor/cakephp/cakephp/src/View/Helper/FormHelper.php:979
+msgid "Edit {0}"
+msgstr "Modifica {0}"
+
+#: ./vendor/cakephp/cakephp/src/View/Helper/FormHelper.php:981
+msgid "New {0}"
+msgstr "Nuovo {0}"
+
+#: ./vendor/cakephp/cakephp/src/View/Helper/FormHelper.php:1917
+msgid "Submit"
+msgstr "Salva"
+
diff --git a/idrocap_wa/src/Application.php b/idrocap_wa/src/Application.php
new file mode 100644
index 0000000..6cdeb82
--- /dev/null
+++ b/idrocap_wa/src/Application.php
@@ -0,0 +1,268 @@
+addPlugin('Authentication');
+
+ if (PHP_SAPI === 'cli') {
+ $this->bootstrapCli();
+ } else {
+ FactoryLocator::add(
+ 'Table',
+ (new TableLocator())->allowFallbackClass(false)
+ );
+ }
+
+ /*
+ * Only try to load DebugKit in development mode
+ * Debug Kit should not be installed on a production system
+ */
+ if (Configure::read('debug')) {
+ Configure::write('DebugKit.safeTld', ['it']);
+ }
+
+ // Load more plugins here
+ $this->addPlugin('Muffin/Trash');
+ $this->addPlugin('CsvView');
+ $this->addPlugin('CakeSentry');
+ }
+
+
+ /**
+ * Returns a service provider instance.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request Request
+ * @return \Authentication\AuthenticationServiceInterface
+ */
+ public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
+ {
+ $service = new AuthenticationService();
+
+ $fields = [
+ AbstractIdentifier::CREDENTIAL_USERNAME => 'username',
+ AbstractIdentifier::CREDENTIAL_PASSWORD => 'password'
+ ];
+
+ if (strpos($request->getPath(), '/api/') !== 0) {
+ // NORMAL REQUESTS
+
+ // se si tratta della request "/notifications/index" non eseguire il redirect e restituisci 401!
+ if ($request->getPath() !== '/notifications/index') {
+ // Define where users should be redirected to when they are not authenticated
+ $service->setConfig([
+ 'unauthenticatedRedirect' => Router::url([
+ 'prefix' => false,
+ 'plugin' => null,
+ 'controller' => 'Users',
+ 'action' => 'login',
+ ]),
+ 'queryParam' => 'redirect',
+ ]);
+ }
+
+ // Load the authenticators. Session should be first.
+ $service->loadAuthenticator('Authentication.Session');
+
+ $service->loadAuthenticator('Authentication.Cookie', [
+ 'fields' => $fields,
+ 'loginUrl' => Router::url([
+ 'prefix' => false,
+ 'plugin' => null,
+ 'controller' => 'Users',
+ 'action' => 'login',
+ ]),
+ ]);
+
+ $service->loadAuthenticator('Authentication.Form', [
+ 'fields' => $fields,
+ 'loginUrl' => Router::url([
+ 'prefix' => false,
+ 'plugin' => null,
+ 'controller' => 'Users',
+ 'action' => 'login',
+ ]),
+ ]);
+
+ // Load identifiers
+ $service->loadIdentifier('JixelPassword', [
+ 'fields' => $fields,
+ ]);
+ } else {
+ // API REQUESTS
+
+ if (strpos($request->getPath(), '/api/users/login') === 0) {
+ // API REQUEST LOGIN
+
+ // Load the authenticators.
+ $service->loadAuthenticator('Authentication.Form', [
+ 'fields' => $fields,
+ 'loginUrl' => Router::url([
+ 'prefix' => 'Api',
+ 'plugin' => null,
+ 'controller' => 'Users',
+ 'action' => 'login',
+ ]),
+ ]);
+
+ // Load identifiers
+ $service->loadIdentifier('Authentication.Password', compact('fields'));
+ } else {
+ // Load identifiers
+ $service->loadIdentifier('Authentication.JwtSubject', [
+ 'tokenField' => 'username',
+ ]);
+
+ // Load the authenticators
+ $service->loadAuthenticator('Authentication.Jwt', [
+ 'secretKey' => file_get_contents(Configure::read('App.jwt.keys.public')),
+ 'algorithm' => Configure::read('App.jwt.algorithm'),
+ 'returnPayload' => false
+ ]);
+ }
+ }
+ return $service;
+ }
+
+ /**
+ * Setup the middleware queue your application will use.
+ *
+ * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
+ * @return \Cake\Http\MiddlewareQueue The updated middleware queue.
+ */
+ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
+ {
+ $middlewareQueue
+ ->add(new LocaleSelectorMiddleware(['it', 'en']))
+
+ // Catch any exceptions in the lower layers,
+ // and make an error page/response
+ ->add(new ErrorHandlerMiddleware(Configure::read('Error')))
+
+ // Handle plugin/theme assets like CakePHP normally does.
+ ->add(new AssetMiddleware([
+ 'cacheTime' => Configure::read('Asset.cacheTime'),
+ ]))
+
+ // Add routing middleware.
+ // If you have a large number of routes connected, turning on routes
+ // caching in production could improve performance. For that when
+ // creating the middleware instance specify the cache config name by
+ // using it's second constructor argument:
+ // `new RoutingMiddleware($this, '_cake_routes_')`
+ ->add(new RoutingMiddleware($this))
+
+ // Parse various types of encoded request bodies so that they are
+ // available as array through $request->getData()
+ // https://book.cakephp.org/4/en/controllers/middleware.html#body-parser-middleware
+ ->add(new BodyParserMiddleware());
+
+ // Cross Site Request Forgery (CSRF) Protection Middleware
+ // https://book.cakephp.org/4/en/security/csrf.html#cross-site-request-forgery-csrf-middleware
+ $csrf = new CsrfProtectionMiddleware();
+
+ // Token check will be skipped when callback returns `true`.
+ $csrf->skipCheckCallback(function ($request) {
+ // Skip token check for API URLs.
+ if ($request->getParam('prefix') === 'Api') {
+ return true;
+ }
+ // Skip token check for ajax calls.
+ if ($request->is('ajax')) {
+ return true;
+ }
+ });
+
+ // Ensure routing middleware is added to the queue before CSRF protection middleware.
+ $middlewareQueue->add($csrf)
+ // encryption/decryption management of listed cookies:
+ ->add(new EncryptedCookieMiddleware(['CookieAuth'], Configure::read('Security.CookieEncryptionKey')))
+
+ // Add the AuthenticationMiddleware. It should be
+ // after routing and body parser.
+ ->add(new AuthenticationMiddleware($this))
+ ->add(new UserTimezoneDatetimeRequestDataMiddleware());
+
+ return $middlewareQueue;
+ }
+
+ /**
+ * Register application container services.
+ *
+ * @param \Cake\Core\ContainerInterface $container The Container to update.
+ * @return void
+ * @link https://book.cakephp.org/4/en/development/dependency-injection.html#dependency-injection
+ */
+ public function services(ContainerInterface $container): void
+ {
+ }
+
+ /**
+ * Bootstrapping for CLI application.
+ *
+ * That is when running commands.
+ *
+ * @return void
+ */
+ protected function bootstrapCli(): void
+ {
+ $this->addOptionalPlugin('Cake/Repl');
+
+ // Load more plugins here
+ }
+}
diff --git a/idrocap_wa/src/Command/AddCadastralCodeToUsesCommand.php b/idrocap_wa/src/Command/AddCadastralCodeToUsesCommand.php
new file mode 100644
index 0000000..3893135
--- /dev/null
+++ b/idrocap_wa/src/Command/AddCadastralCodeToUsesCommand.php
@@ -0,0 +1,95 @@
+addArgument('chunk_size', [
+ 'help' => 'the amount of records to process in chunk (at least 10 which is the default value)',
+ 'required' => false,
+ ]);
+ return $parser;
+ }
+
+ /*
+ * Implement this method with your command's logic.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return null|void|int The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io)
+ {
+ $chunkSize = (int)($args->getArgument('chunk_size') ?? 10);
+ if ($chunkSize < 10) $io->abort("Please specify a chunk size of at least 10!");
+ $page = 1;
+ $total = 0;
+ $io->info("AddCadastralCodeToUsesCommand started!");
+ $io->info("Chunk size is: $chunkSize");
+
+ do {
+ $intendedUses = $this->fetchTable('WaterDrawingIntendedUses')->find()
+ ->where([
+ // recuperiamo solo le entries di tipo uso IRRIGUO che non hanno il codice BELFIORE:
+ "WaterDrawingIntendedUses.water_drawing_intended_use_type_id" => 1,
+ "WaterDrawingIntendedUses.cadastral_code IS NULL",
+
+ // devono però avere foglio e particella validi:
+ "WaterDrawingIntendedUses.cadastral_sheet IS NOT NULL",
+ "WaterDrawingIntendedUses.cadastral_parcel IS NOT NULL",
+ "WaterDrawingIntendedUses.cadastral_sheet <> ''",
+ "WaterDrawingIntendedUses.cadastral_parcel <> ''",
+ ])
+ ->limit($chunkSize)
+ ->page($page)
+ ->all();
+
+ foreach($intendedUses as $intendedUse){
+ $io->info("Processing WaterDrawingIntendedUse with ID: $intendedUse->id");
+ // recuperiamo il codice BELFIORE dal primo delle derivazioni connesse alla pratica (se ve ne sono....):
+ $derivation = $this->fetchTable('WaterDrawingDerivations')->find()->where([
+ 'WaterDrawingDerivations.water_drawing_paperwork_id' => $intendedUse->water_drawing_paperwork_id
+ ])->first();
+ if (!isset($derivation->cadastral_code)) {
+ $io->warning('WARNING: related water_drawing_paperwork has no suitable water_drawing_derivations to get cadastral_code from -> SKIPPED!');
+ continue;
+ }
+ $intendedUse->cadastral_code = $derivation->cadastral_code;
+ $intendedUse->vegetation_match_status = CadastralUtils::isParcelWithinVegetationArea(strtolower($intendedUse->cadastral_code), $intendedUse->cadastral_sheet, $intendedUse->cadastral_parcel) ? 1 : -1;
+
+ if(!$this->fetchTable('WaterDrawingIntendedUses')->save($intendedUse, ['skipResetIsMismatch' => true])){
+ $io->warning('WARNING: Error during save!');
+ $io->warning(json_encode($intendedUse->getErrors()));
+ }
+ }
+
+ $count = $intendedUses->count();
+ $total += $count;
+ if ($count) $io->success("processed $count items for page $page");
+ $page++;
+ } while ($count === $chunkSize);
+
+ $io->success("total processed $total items!");
+ return static::CODE_SUCCESS;
+ }
+}
+?>
diff --git a/idrocap_wa/src/Command/AddDerivationCoordinatesCommand.php b/idrocap_wa/src/Command/AddDerivationCoordinatesCommand.php
new file mode 100644
index 0000000..5695e31
--- /dev/null
+++ b/idrocap_wa/src/Command/AddDerivationCoordinatesCommand.php
@@ -0,0 +1,44 @@
+fetchTable('WaterDrawingDerivations')->find()->where([
+ 'WaterDrawingDerivations.latitude' => '',
+ 'WaterDrawingDerivations.longitude' => '',
+ 'WaterDrawingDerivations.cadastral_code IS NOT NULL',
+ 'WaterDrawingDerivations.cadastral_sheet IS NOT NULL',
+ 'WaterDrawingDerivations.cadastral_parcel IS NOT NULL',
+ ])->toArray();
+ foreach($derivations as $derivation){
+ $coordinates = CadastralUtils::getParcelCentroidCoordinates(strtolower($derivation->cadastral_code), (string) $derivation->cadastral_sheet, (string) $derivation->cadastral_parcel);
+ if(isset($coordinates)){
+ $derivation = $this->fetchTable('WaterDrawingDerivations')->patchEntity($derivation, [
+ 'latitude' => $coordinates->latitude,
+ 'longitude' => $coordinates->longitude,
+ 'feature_collection' => '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":['. $coordinates->longitude .','. $coordinates->latitude .']},"properties":null}]}'
+ ]);
+ if(!$this->fetchTable('WaterDrawingDerivations')->save($derivation)){
+ $io->out(__('Errore durante il salvataggio.'));
+ $io->out(json_encode($derivation->getErrors()));
+ }
+ }
+ }
+ return static::CODE_SUCCESS;
+ }
+}
+?>
diff --git a/idrocap_wa/src/Command/CheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand.php b/idrocap_wa/src/Command/CheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand.php
new file mode 100644
index 0000000..44a04b0
--- /dev/null
+++ b/idrocap_wa/src/Command/CheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand.php
@@ -0,0 +1,57 @@
+info("\n\nCheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand: START!!!");
+
+ // prima recupero, per ogni pratica, le water_drawing_antimafia_certification_requests con ID massimo
+ // questo mi assicura di prendere in considerazione l'ultima richiesta fatta:
+ $latest_water_drawing_antimafia_certification_request_ids = $this->fetchTable('WaterDrawingAntimafiaCertificationRequests')
+ ->find()
+ ->select(['max_id' => 'MAX(WaterDrawingAntimafiaCertificationRequests.id)'])
+ ->group('water_drawing_paperwork_id');
+
+ // quindi recuoero le pratiche per cui risulti l'ultima richiesta AM scaduta (termine dei 30gg)
+ // che sia in "stato richiesta" in modo da poter notificare i relativi utenti DRAR:
+ $to_be_notified_water_drawing_paperworks = $this->fetchTable('WaterDrawingPaperworks')
+ ->find()
+ ->matching('WaterDrawingAntimafiaCertificationRequests')
+ ->where([
+ 'WaterDrawingAntimafiaCertificationRequests.id IN' => $latest_water_drawing_antimafia_certification_request_ids,
+ 'WaterDrawingAntimafiaCertificationRequests.water_drawing_antimafia_certification_request_status_id' => 2,
+ 'WaterDrawingAntimafiaCertificationRequests.created <= NOW() - INTERVAL 30 DAY'
+ ])
+ ->toArray();
+
+ foreach($to_be_notified_water_drawing_paperworks as $waterDrawingPaperwork) {
+ // DISPATCH NOTIFICHE:
+ $io->info("\nCheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand: richiesta AM scaduta per pratica con ID: " . $waterDrawingPaperwork->id);
+ if (isset($waterDrawingPaperwork->drar_user_id)) {
+ $io->success("CheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand: Invio notifica a utente DRAR con ID: " . $waterDrawingPaperwork->drar_user_id);
+ // invio notifica a utente DRAR che aveva richiesto la certificazione antimafia perchè la richiesta è scaduta:
+ NotificationsHandler::dispatch($waterDrawingPaperwork->controllable_object_id, 'send_to_drar_user_antimafia_request_expired', ['drar_user_id' => $waterDrawingPaperwork->drar_user_id, 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ } else {
+ $io->error("CheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand: LA PRATICA NON HA UTENTI DRAR ASSEGNATI !!!!!");
+ }
+ }
+
+ $io->info("\n\nCheckExpiredWaterDrawingAntimafiaCertificateRequestsCommand: END!!!");
+ return static::CODE_SUCCESS;
+ }
+}
+?>
diff --git a/idrocap_wa/src/Command/CopyTranslationsCommand.php b/idrocap_wa/src/Command/CopyTranslationsCommand.php
new file mode 100644
index 0000000..8363d6e
--- /dev/null
+++ b/idrocap_wa/src/Command/CopyTranslationsCommand.php
@@ -0,0 +1,144 @@
+addArgument('template_filename', [
+ 'help' => '.POT Template file (with full or relative path)',
+ 'required' => true,
+ ])
+ ->addArgument('input_filename', [
+ 'help' => '.PO Input file (with full or relative path)',
+ 'required' => true,
+ ])
+ ->addArgument('output_filename', [
+ 'help' => 'Output PO file (with full or relative path)',
+ 'required' => true,
+ ]);
+ return $parser;
+ }
+
+ /**
+ * Implement this method with your command's logic.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return null|void|int The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io)
+ {
+ $template_filename = $args->getArgument('template_filename');
+ $input_filename = $args->getArgument('input_filename');
+ $output_filename = $args->getArgument('output_filename');
+
+ $io->info("\n\ntemplate file path: $template_filename, input file path: $input_filename, output file path: $output_filename\n\n");
+
+ if (!file_exists($template_filename)) $io->abort("\n\n\nError: File \"$template_filename\" doesn't exists!");
+ if (!file_exists($input_filename)) $io->abort("\n\n\nError: File \"$input_filename\" doesn't exists!");
+
+ // lettura pot e retrieving identifiers:
+ $template_filename_handle = fopen($template_filename, "r");
+ if ($template_filename_handle) {
+ $pot_row_count = 0;
+ $io->info("\n\n\nFetching translation identifiers from template file \"$template_filename\":\n");
+ while (($buffer = fgets($template_filename_handle, 4096)) !== false) {
+ if (substr($buffer, 0, 5) !== "msgid") continue;
+ $text = explode("\"\n", explode("msgid \"", $buffer)[1])[0];
+ if ($text === "") continue;
+ ++$pot_row_count;
+ $io->info("msgid at row $pot_row_count: $text");
+ $this->pot_identifiers[$text] = "";
+ }
+ if (!feof($template_filename_handle)) {
+ $io->abort("\n\n\nError: unexpected fgets() fail");
+ }
+ fclose($template_filename_handle);
+ $io->success("\n\nNumber of identifiers successfully fetched from template file \"$template_filename\": $pot_row_count\n\n");
+ } else {
+ $io->abort("\n\n\nError: Unable to Open File \"$template_filename\"!");
+ }
+
+ // lettura input file e retrieving translations (x gli identifiers che matchano):
+ $input_filename_handle = fopen($input_filename, "r");
+ if ($input_filename_handle) {
+ $count = 0;
+ $last_identifier = null;
+ $io->info("\n\n\nRetrieving translations from input file \"$input_filename\":\n");
+ while (($buffer = fgets($input_filename_handle, 4096)) !== false) {
+ if (substr($buffer, 0, 6) === "msgid ") {
+ $last_identifier = explode("\"\n", explode("msgid \"", $buffer)[1])[0];
+ if ($last_identifier === "" || !isset($this->pot_identifiers[$last_identifier])) $last_identifier = null;
+ }
+ if (substr($buffer, 0, 6) === "msgstr" && isset($last_identifier)) {
+ $this->pot_identifiers[$last_identifier] = explode("\"\n", explode("msgstr \"", $buffer)[1])[0];
+ if (!empty($this->pot_identifiers[$last_identifier])) ++$count;
+ $io->info("Retrieved translations so far: $count - Parsing: \"$last_identifier\" = \"" . $this->pot_identifiers[$last_identifier] . "\"");
+ }
+ }
+ if (!feof($input_filename_handle)) {
+ $io->abort("\n\n\nError: unexpected fgets() fail");
+ }
+ fclose($input_filename_handle);
+ $io->success("\n\nSuccessfully retrieved $count translations from input po file \"$input_filename\"!\n\n");
+ } else {
+ $io->abort("\n\n\nError: Unable to Open File \"$input_filename\"!");
+ }
+
+ // creazione file .PO di output partendo da struttura del .POT fornito e arricchito con le traduzioni recuperate dal file di input
+ $template_filename_handle = fopen($template_filename, "r");
+ $output_filename_handle = fopen($output_filename, 'w');
+
+ if ($template_filename_handle) {
+ $count = 0;
+ $last_identifier = null;
+ $io->info("\n\n\nCreating new translation file \"$output_filename\":\n");
+ while (($buffer = fgets($template_filename_handle, 4096)) !== false) {
+ if (substr($buffer, 0, 5) === "msgid") {
+ $last_identifier = explode("\"\n", explode("msgid \"", $buffer)[1])[0];
+ if ($last_identifier !== "" && !empty($this->pot_identifiers[$last_identifier])) {
+ ++$count;
+ } else {
+ $last_identifier = null;
+ }
+ }
+ if (substr($buffer, 0, 6) === "msgstr" && isset($last_identifier)) {
+ $io->info("Adding translation number: $count for identifier: \"$last_identifier\"" . " with translation: \"" . $this->pot_identifiers[$last_identifier] . "\"");
+ $buffer = "msgstr \"" . $this->pot_identifiers[$last_identifier] . "\"\n";
+ }
+ fwrite($output_filename_handle, $buffer);
+ }
+ if (!feof($template_filename_handle)) {
+ $io->abort("\n\n\nError: unexpected fgets() fail");
+ }
+ fclose($template_filename_handle);
+ fclose($output_filename_handle);
+ $io->success("\n\nSuccessfully created po file \"$output_filename\" with $count added translations!\n\n");
+ } else {
+ $io->abort("\n\n\nError: Unable to Open File \"$template_filename\"!");
+ }
+ }
+}
diff --git a/idrocap_wa/src/Command/IntendedUseVegetationCheckCommand.php b/idrocap_wa/src/Command/IntendedUseVegetationCheckCommand.php
new file mode 100644
index 0000000..6b26b14
--- /dev/null
+++ b/idrocap_wa/src/Command/IntendedUseVegetationCheckCommand.php
@@ -0,0 +1,107 @@
+addArgument('data', [
+ 'help' => 'the serialized data to process',
+ 'required' => true,
+ ]);
+ return $parser;
+ }
+
+ /*
+ * Implement this method with your command's logic.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return null|void|int The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io)
+ {
+ $io->info("IntendedUseVegetationCheckCommand - JOB STARTED!");
+ $data = $args->getArgument('data');
+ $io->info("IntendedUseVegetationCheckCommand - received data: {$data}");
+
+ $deserialized_data = json_decode($data, true);
+
+ if (empty($deserialized_data['water_drawing_paperwork_id'])) {
+ $io->abort("IntendedUseVegetationCheckCommand - water_drawing_paperwork_id is missing!");
+ }
+
+ $water_drawing_paperwork = $this->fetchTable('WaterDrawingPaperworks')->find()->where(['WaterDrawingPaperworks.id' => $deserialized_data['water_drawing_paperwork_id']])->first();
+ if (!$water_drawing_paperwork) {
+ $io->abort("IntendedUseVegetationCheckCommand - water_drawing_paperwork with ID: {$deserialized_data['water_drawing_paperwork_id']} not found!");
+ }
+
+ $water_drawing_intended_uses = $this->fetchTable('WaterDrawingIntendedUses')->find()->where(['WaterDrawingIntendedUses.water_drawing_paperwork_id' => $water_drawing_paperwork->id])->all();
+
+ $intended_use_linked = count($water_drawing_intended_uses);
+ $intended_use_processed = 0;
+
+ foreach ($water_drawing_intended_uses as $water_drawing_intended_use) {
+ $io->info("IntendedUseVegetationCheckCommand - checking linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id}, cadastral_code: {$water_drawing_intended_use->cadastral_code}, cadastral_sheet: {$water_drawing_intended_use->cadastral_sheet}, cadastral_parcel: {$water_drawing_intended_use->cadastral_parcel}, water_drawing_intended_use_type_id: {$water_drawing_intended_use->water_drawing_intended_use_type_id}...");
+ if ($water_drawing_intended_use->water_drawing_intended_use_type_id != 1) {
+ $io->comment("IntendedUseVegetationCheckCommand - linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id} has water_drawing_intended_use_type_id: {$water_drawing_intended_use->water_drawing_intended_use_type_id} (must be 1), SKIPPED!");
+ continue;
+ }
+ if (empty($water_drawing_intended_use->cadastral_code)) {
+ $io->comment("IntendedUseVegetationCheckCommand - linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id} has NO valid cadastral_code, SKIPPED!");
+ continue;
+ }
+ if (empty($water_drawing_intended_use->cadastral_sheet)) {
+ $io->comment("IntendedUseVegetationCheckCommand - linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id} has NO valid cadastral_sheet, SKIPPED!");
+ continue;
+ }
+ if (empty($water_drawing_intended_use->cadastral_parcel)) {
+ $io->comment("IntendedUseVegetationCheckCommand - linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id} has NO valid cadastral_parcel, SKIPPED!");
+ continue;
+ }
+ $water_drawing_intended_use->vegetation_match_status = CadastralUtils::isParcelWithinVegetationArea(strtolower($water_drawing_intended_use->cadastral_code), $water_drawing_intended_use->cadastral_sheet, $water_drawing_intended_use->cadastral_parcel) ? 1 : -1;
+ if ($water_drawing_intended_use->vegetation_match_status == -1) {
+ $io->comment("IntendedUseVegetationCheckCommand - linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id} has NO MATCHING INTENDED USE!!!");
+ } else {
+ $io->success("IntendedUseVegetationCheckCommand - linked water_drawing_intended_use with ID: {$water_drawing_intended_use->id} has PERFECT MATCHING INTENDED USE!");
+ }
+ if (!$this->fetchTable('WaterDrawingIntendedUses')->save($water_drawing_intended_use, ['skipResetIsMismatch' => true])) {
+ $io->error("IntendedUseVegetationCheckCommand - error saving processed water_drawing_intended_use with ID: {$water_drawing_intended_use->id}");
+ } else {
+ $intended_use_processed++;
+ }
+ }
+
+ $io->success("IntendedUseVegetationCheckCommand - checked {$intended_use_linked} linked intended uses and successfully processed {$intended_use_processed} of them!");
+
+ if (!empty($deserialized_data['notification_user_id'])) {
+ $user_to_be_notified_id = $deserialized_data['notification_user_id'];
+ $io->info("IntendedUseVegetationCheckCommand - sending notification to user with ID: {$user_to_be_notified_id}");
+ NotificationsHandler::dispatch($water_drawing_paperwork->controllable_object_id, 'send_to_last_edit_user_intended_use_check_completed', ['last_edit_user_id' => $user_to_be_notified_id, 'link' => '/water_drawing_paperworks/view' . ($water_drawing_paperwork->scanned ? '_scan' : '') .'/' . $water_drawing_paperwork->id, 'water_drawing_paperwork_id' => $water_drawing_paperwork->id]);
+ } else {
+ $io->comment("IntendedUseVegetationCheckCommand - notification_user_id is missing, skipping notification!");
+ }
+
+ $io->info("IntendedUseVegetationCheckCommand - JOB ENDED!");
+ return static::CODE_SUCCESS;
+ }
+}
+?>
diff --git a/idrocap_wa/src/Command/NormalizeApplicantProvinceCommand.php b/idrocap_wa/src/Command/NormalizeApplicantProvinceCommand.php
new file mode 100644
index 0000000..d793798
--- /dev/null
+++ b/idrocap_wa/src/Command/NormalizeApplicantProvinceCommand.php
@@ -0,0 +1,65 @@
+fetchTable('Applicants')->find()->where(['Applicants.province IN' => ['Palermo', 'Catania', 'Caltanissetta', 'Enna', 'Ragusa', 'Agrigento', 'Messina', 'Siracusa', 'Trapani']])->toArray();
+ foreach($applicants as $applicant){
+ switch(strtolower($applicant->province)){
+ case 'catania':
+ $province = 'CT';
+ break;
+ case 'palermo':
+ $province = 'PA';
+ break;
+ case 'caltanissetta':
+ $province = 'CL';
+ break;
+ case 'enna':
+ $province = 'EN';
+ break;
+ case 'ragusa':
+ $province = 'RG';
+ break;
+ case 'siracusa':
+ $province = 'SR';
+ break;
+ case 'trapani':
+ $province = 'TP';
+ break;
+ case 'messina':
+ $province = 'ME';
+ break;
+ case 'agrigento':
+ $province = 'AG';
+ break;
+ }
+ if(!isset($province)) continue;
+ $applicant = $this->fetchTable('Applicants')->patchEntity($applicant, [
+ 'province' => $province
+ ]);
+ if(!$this->fetchTable('Applicants')->save($applicant, [
+ 'checkRules' => false
+ ])){
+ $io->out(__('Errore durante il salvataggio'));
+ $io->out(json_encode($applicant->getErrors(), JSON_PRETTY_PRINT));
+ }
+ $province = null;
+ }
+ return static::CODE_SUCCESS;
+ }
+}
+?>
diff --git a/idrocap_wa/src/Command/NotificationsHandlerCommand.php b/idrocap_wa/src/Command/NotificationsHandlerCommand.php
new file mode 100644
index 0000000..b185036
--- /dev/null
+++ b/idrocap_wa/src/Command/NotificationsHandlerCommand.php
@@ -0,0 +1,65 @@
+addArgument('data', [
+ 'help' => 'the serialized data to process',
+ 'required' => true,
+ ]);
+
+ return $parser;
+ }
+
+ /**
+ * Implement this method with your command's logic.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return null|void|int The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io): int
+ {
+ $data = $args->getArgument('data');
+ $io->info("NotificationsHandlerCommand - received data: {$data}");
+
+ $deserialized_data = json_decode($data, true);
+
+ if (empty($deserialized_data['background_task_id'])) {
+ $io->abort("NotificationsHandlerCommand - background_task_id is missing!");
+ }
+
+ $background_task = $this->fetchTable('BackgroundTasks')->find()->where(['BackgroundTasks.id' => $deserialized_data['background_task_id']])->first();
+ if (!$background_task) {
+ $io->abort("NotificationsHandlerCommand - background_task not found!");
+ }
+
+ $request = json_decode($background_task->data, true);
+ NotificationsHandler::executeDispatch($request['co_id'], $request['notification_code'], $request['options'], $request['group'], $request['user_logged']);
+
+ $io->success("NotificationsHandlerCommand - successfully processed!");
+ return static::CODE_SUCCESS;
+ }
+}
diff --git a/idrocap_wa/src/Command/UnpackWaterDrawingPaperworkSnapshotsCommand.php b/idrocap_wa/src/Command/UnpackWaterDrawingPaperworkSnapshotsCommand.php
new file mode 100644
index 0000000..9fa732f
--- /dev/null
+++ b/idrocap_wa/src/Command/UnpackWaterDrawingPaperworkSnapshotsCommand.php
@@ -0,0 +1,98 @@
+setDescription('Unpacks water_drawing_paperworks from Snapshots and store them to unpacked_water_drawing_paperwork_snapshots table with the last unpacking version number available');
+
+ $parser
+ ->addOptions([
+ 'limit' => [
+ 'short' => 'l',
+ 'help' => 'Number of rows to process',
+ 'boolean' => false,
+ 'required' => true,
+ ],
+ ]);
+
+ return $parser;
+ }
+
+ /**
+ * Implement this method with your command's logic.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return null|void|int The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io)
+ {
+ $limit = $args->getOption('limit');
+ if ($limit < 1) $io->abort("You must specify an Int number greater than ZERO!");
+ $io->info("trying processing $limit items...");
+ $lastWaterDrawingPaperworkUnpackingVersion = SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion();
+ $io->info("lastWaterDrawingPaperworkUnpackingVersion: $lastWaterDrawingPaperworkUnpackingVersion");
+
+ $processed = 0;
+ $unpackable_water_drawing_paperwork_snapshots = $this->fetchTable('Snapshots')->find()->where(['Snapshots.controllable_object_type_id' => 9, 'OR' => ['Snapshots.unpacked_with_version is NULL', 'Snapshots.unpacked_with_version <>' => $lastWaterDrawingPaperworkUnpackingVersion]])->limit((int)$limit)->toArray();
+
+ $io->info("found " . count($unpackable_water_drawing_paperwork_snapshots) . " unpackable items.");
+
+ if (count($unpackable_water_drawing_paperwork_snapshots) > 0) ConnectionManager::get('default')->begin();
+
+ $this->fetchTable('WaterDrawingPaperworks')->removeBehavior('Trash');
+
+ foreach ($unpackable_water_drawing_paperwork_snapshots as $unpackable_water_drawing_paperwork_snapshot) {
+ $io->info("\nUnpackedWaterDrawingPaperworkSnapshot entity:");
+ $unpackedWaterDrawingPaperworkSnapshot = SnapshotsHandler::getUnpackedWaterDrawingPaperworkSnapshot($unpackable_water_drawing_paperwork_snapshot->id);
+ if (!$unpackedWaterDrawingPaperworkSnapshot) {
+ ConnectionManager::get('default')->rollback();
+ $io->abort("\nError retrieving unpackedWaterDrawingPaperworkSnapshot!");
+ }
+ $io->info(json_encode($unpackedWaterDrawingPaperworkSnapshot));
+ $io->info("\nSaving unpacked water_drawing_paperwork snapshot to unpackedWaterDrawingPaperworkSnapshots table...");
+ if (!$this->fetchTable('UnpackedWaterDrawingPaperworkSnapshots')->save($unpackedWaterDrawingPaperworkSnapshot)) {
+ ConnectionManager::get('default')->rollback();
+ $io->abort("\nError saving unpackedWaterDrawingPaperworkSnapshot: " . json_encode($unpackedWaterDrawingPaperworkSnapshot->getErrors()));
+ }
+ $io->info("\nMarking and saving snapshot with ID " . $unpackable_water_drawing_paperwork_snapshot->id . " as unpacked with version: " . $lastWaterDrawingPaperworkUnpackingVersion);
+ $unpackable_water_drawing_paperwork_snapshot->unpacked_with_version = $lastWaterDrawingPaperworkUnpackingVersion;
+ if (!$this->fetchTable('Snapshots')->save($unpackable_water_drawing_paperwork_snapshot)) {
+ ConnectionManager::get('default')->rollback();
+ $io->abort("\nError saving snapshot: " . json_encode($unpackable_water_drawing_paperwork_snapshot->getErrors()));
+ }
+ $processed++;
+ $io->success("\nSUCCESSFULLY PROCESSED: $processed !\n");
+ }
+
+ $this->fetchTable('WaterDrawingPaperworks')->addBehavior('Muffin/Trash.Trash');
+
+ $io->success("\nJOB IS DONE. REQUESTED: $limit, UNPACKABLE: " . count($unpackable_water_drawing_paperwork_snapshots) . " SUCCESSFULLY PROCESSED: $processed");
+
+ if (count($unpackable_water_drawing_paperwork_snapshots) > 0) ConnectionManager::get('default')->commit();
+
+ return static::CODE_SUCCESS;
+ }
+}
diff --git a/idrocap_wa/src/Console/Installer.php b/idrocap_wa/src/Console/Installer.php
new file mode 100644
index 0000000..6f55798
--- /dev/null
+++ b/idrocap_wa/src/Console/Installer.php
@@ -0,0 +1,250 @@
+getIO();
+
+ $rootDir = dirname(__DIR__, 2);
+
+ static::createAppLocalConfig($rootDir, $io);
+ static::createWritableDirectories($rootDir, $io);
+
+ static::setFolderPermissions($rootDir, $io);
+ static::setSecuritySalt($rootDir, $io);
+
+ if (class_exists(CodeceptionInstaller::class)) {
+ CodeceptionInstaller::customizeCodeceptionBinary($event);
+ }
+ }
+
+ /**
+ * Create config/app_local.php file if it does not exist.
+ *
+ * @param string $dir The application's root directory.
+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
+ * @return void
+ */
+ public static function createAppLocalConfig(string $dir, IOInterface $io): void
+ {
+ $appLocalConfig = $dir . '/config/app_local.php';
+ $appLocalConfigTemplate = $dir . '/config/app_local.example.php';
+ if (!file_exists($appLocalConfig)) {
+ copy($appLocalConfigTemplate, $appLocalConfig);
+ $io->write('Created `config/app_local.php` file');
+ }
+ }
+
+ /**
+ * Create the `logs` and `tmp` directories.
+ *
+ * @param string $dir The application's root directory.
+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
+ * @return void
+ */
+ public static function createWritableDirectories(string $dir, IOInterface $io): void
+ {
+ foreach (static::WRITABLE_DIRS as $path) {
+ $path = $dir . '/' . $path;
+ if (!file_exists($path)) {
+ mkdir($path);
+ $io->write('Created `' . $path . '` directory');
+ }
+ }
+ }
+
+ /**
+ * Set globally writable permissions on the "tmp" and "logs" directory.
+ *
+ * This is not the most secure default, but it gets people up and running quickly.
+ *
+ * @param string $dir The application's root directory.
+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
+ * @return void
+ */
+ public static function setFolderPermissions(string $dir, IOInterface $io): void
+ {
+ // ask if the permissions should be changed
+ if ($io->isInteractive()) {
+ $validator = function (string $arg): string {
+ if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
+ return $arg;
+ }
+ throw new Exception('This is not a valid answer. Please choose Y or n.');
+ };
+ $setFolderPermissions = $io->askAndValidate(
+ 'Set Folder Permissions ? (Default to Y) [Y,n ]? ',
+ $validator,
+ 10,
+ 'Y'
+ );
+
+ if (in_array($setFolderPermissions, ['n', 'N'])) {
+ return;
+ }
+ }
+
+ // Change the permissions on a path and output the results.
+ $changePerms = function (string $path) use ($io): void {
+ $currentPerms = fileperms($path) & 0777;
+ $worldWritable = $currentPerms | 0007;
+ if ($worldWritable == $currentPerms) {
+ return;
+ }
+
+ $res = chmod($path, $worldWritable);
+ if ($res) {
+ $io->write('Permissions set on ' . $path);
+ } else {
+ $io->write('Failed to set permissions on ' . $path);
+ }
+ };
+
+ $walker = function (string $dir) use (&$walker, $changePerms): void {
+ /** @phpstan-ignore-next-line */
+ $files = array_diff(scandir($dir), ['.', '..']);
+ foreach ($files as $file) {
+ $path = $dir . '/' . $file;
+
+ if (!is_dir($path)) {
+ continue;
+ }
+
+ $changePerms($path);
+ $walker($path);
+ }
+ };
+
+ $walker($dir . '/tmp');
+ $changePerms($dir . '/tmp');
+ $changePerms($dir . '/logs');
+ }
+
+ /**
+ * Set the security.salt value in the application's config file.
+ *
+ * @param string $dir The application's root directory.
+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
+ * @return void
+ */
+ public static function setSecuritySalt(string $dir, IOInterface $io): void
+ {
+ $newKey = hash('sha256', Security::randomBytes(64));
+ static::setSecuritySaltInFile($dir, $io, $newKey, 'app_local.php');
+ }
+
+ /**
+ * Set the security.salt value in a given file
+ *
+ * @param string $dir The application's root directory.
+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
+ * @param string $newKey key to set in the file
+ * @param string $file A path to a file relative to the application's root
+ * @return void
+ */
+ public static function setSecuritySaltInFile(string $dir, IOInterface $io, string $newKey, string $file): void
+ {
+ $config = $dir . '/config/' . $file;
+ $content = file_get_contents($config);
+
+ /** @phpstan-ignore-next-line */
+ $content = str_replace('__SALT__', $newKey, $content, $count);
+
+ if ($count == 0) {
+ $io->write('No Security.salt placeholder to replace.');
+
+ return;
+ }
+
+ $result = file_put_contents($config, $content);
+ if ($result) {
+ $io->write('Updated Security.salt value in config/' . $file);
+
+ return;
+ }
+ $io->write('Unable to update Security.salt value.');
+ }
+
+ /**
+ * Set the APP_NAME value in a given file
+ *
+ * @param string $dir The application's root directory.
+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
+ * @param string $appName app name to set in the file
+ * @param string $file A path to a file relative to the application's root
+ * @return void
+ */
+ public static function setAppNameInFile(string $dir, IOInterface $io, string $appName, string $file): void
+ {
+ $config = $dir . '/config/' . $file;
+ $content = file_get_contents($config);
+ /** @phpstan-ignore-next-line */
+ $content = str_replace('__APP_NAME__', $appName, $content, $count);
+
+ if ($count == 0) {
+ $io->write('No __APP_NAME__ placeholder to replace.');
+
+ return;
+ }
+
+ $result = file_put_contents($config, $content);
+ if ($result) {
+ $io->write('Updated __APP_NAME__ value in config/' . $file);
+
+ return;
+ }
+ $io->write('Unable to update __APP_NAME__ value.');
+ }
+}
diff --git a/idrocap_wa/src/Controller/AiServicesController.php b/idrocap_wa/src/Controller/AiServicesController.php
new file mode 100644
index 0000000..b2822b2
--- /dev/null
+++ b/idrocap_wa/src/Controller/AiServicesController.php
@@ -0,0 +1,91 @@
+viewBuilder()->setClassName(JsonView::class);
+ $this->client = new Client([
+ 'timeout' => 120
+ ]);
+ }
+
+ public function autocomplete(): Response
+ {
+ if (!$this->request->is('post')) {
+ $this->respond(405, "Method not allowed");
+ }
+
+ $isAiServiceEnabled = Configure::read('App.aiServiceEnabled');
+
+ if(!$isAiServiceEnabled) {
+ return $this->respond(403, "AI Service is disabled");
+ }
+
+ $request = $this->request->getData();
+ $type = $request['type'] ?? null;
+ $documentHash = $request['documentHash'] ?? null;
+
+ if (!$type || !$documentHash) {
+ return $this->respond(400, "Missing parameters");
+ }
+
+ $attachment = $this->findAttachment($documentHash);
+
+ if (!$attachment) {
+ return $this->respond(404, "Attachment not found");
+ }
+
+ $file_name = $attachment->file_name;
+ $container_co_id = $attachment->container_controllable_object_id;
+ $path = Configure::read('App.attachmentsPath') . "/" . $container_co_id . "/" . $file_name;
+ $output = \App\WGS\FileStorage\FileStorageFactory::create()->getFile($path);
+
+ if ($output === false) {
+ return $this->respond(404, "File not found or could not be opened");
+ }
+ return $this->callAiServiceAndRespond($request['type'], $request['documentHash'], $output);
+ }
+
+ private function callAiServiceAndRespond(string $type, string $documentHash, string $fileContent): Response
+ {
+ try {
+ $postData = json_encode([
+ 'type' => $type,
+ 'documentHash' => $documentHash,
+ 'fileContent' => base64_encode($fileContent),
+ ]);
+ $apiResponse = $this->client->post(Configure::read('App.aiServiceUrl'),$postData, ['type' => "json"]);
+
+ if ($apiResponse->isOk()) {
+ return $this->respond(200, ['result' => $apiResponse->getJson()]);
+ } else {
+ return $this->respond($apiResponse->getStatusCode(), "API Error: " . $apiResponse->getStatusCode());
+ }
+ } catch (Exception $e) {
+ return $this->respond(500, $e->getMessage());
+ }
+ }
+
+ private function findAttachment(string $documentHash): Attachment
+ {
+ return $this->fetchTable('Attachments')->find()
+ ->contain(['ContainerControllableObjects'])
+ ->where(['file_name' => $documentHash])
+ ->first();
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/AppController.php b/idrocap_wa/src/Controller/Api/AppController.php
new file mode 100644
index 0000000..3f4ea42
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/AppController.php
@@ -0,0 +1,74 @@
+loadComponent('FormProtection');`
+ *
+ * @return void
+ */
+ public function initialize(): void
+ {
+ parent::initialize();
+
+ $this->loadComponent('Authentication.Authentication');
+
+ $this->logged_user = $this->Authentication->getIdentity();
+ $this->nopaginate = $this->request->getQuery('nopaginate') !== null && $this->request->getQuery('nopaginate');
+ }
+
+ /**
+ * respond
+ *
+ * @param Int $code
+ * @param null|Object|Array|String $bodyResponse
+ * @param String $content
+ * @return Response
+ */
+ public function respond(Int $code = 200, null|Object|Array|String $bodyResponse = null, String $content = "application/json") : Response
+ {
+ $bodyResponse = is_object($bodyResponse) || is_array($bodyResponse) ? $bodyResponse : ['result' => $bodyResponse];
+ $response = $this->getResponse();
+ $response = $response->withHeader('Access-Control-Allow-Origin', '*');
+ $response = $response->withHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE, PUT');
+ $response = $response->withHeader('Access-Control-Max-Age', '60');
+ $response = $response->withHeader('Access-Control-Allow-Headers', 'x-requested-with, Content-Type, origin, authorization, accept, client-security-token');
+ return $response->withStringBody(json_encode($bodyResponse))->withStatus($code)->withType($content);
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/AttachmentsController.php b/idrocap_wa/src/Controller/Api/AttachmentsController.php
new file mode 100644
index 0000000..0a20053
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/AttachmentsController.php
@@ -0,0 +1,53 @@
+respond(400, "not implemented");}
+ public function add() {return $this->respond(400, "not implemented");}
+ public function edit($id = null) {return $this->respond(400, "not implemented");}
+ public function delete($id = null) {return $this->respond(400, "not implemented");}
+
+ /**
+ * View method
+ *
+ * @param string|null $hash Attachment hash.
+ * @return \Cake\Http\Response|void
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($hash)
+ {
+ $attachment = $this->fetchTable('Attachments')->find()
+ ->contain(['ContainerControllableObjects'])
+ ->where(['file_name' => $hash])
+ ->first();
+
+ if (!$attachment) return $this->respond(404, __('Allegato non trovato'));
+ if (!$this->logged_user->canHandleAttachmentsForControllableObject($attachment->container_controllable_object)) return $this->respond(403, __('Non hai i permessi necessari per visionare l\'allegato'));
+
+ $mimetype = $attachment->mimetype;
+ $file_name = $attachment->file_name;
+ $original_file_name = $attachment->original_file_name;
+ $container_co_id = $attachment->container_controllable_object_id;
+ $path = Configure::read('App.attachmentsPath') . "/" . $container_co_id . "/" . $file_name;
+ $output = \App\WGS\FileStorage\FileStorageFactory::create()->getFile($path);
+ $this->response = $this->response
+ ->withAddedHeader('Content-Disposition', 'filename="' . $original_file_name . '"')
+ ->withCharset('UTF-8')
+ ->withType($mimetype)
+ ->withStringBody($output);
+
+ return $this->response;
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/ErrorController.php b/idrocap_wa/src/Controller/Api/ErrorController.php
new file mode 100644
index 0000000..501e251
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/ErrorController.php
@@ -0,0 +1,70 @@
+viewBuilder()->setTemplatePath('Error');
+ }
+
+ /**
+ * afterFilter callback.
+ *
+ * @param \Cake\Event\EventInterface $event Event.
+ * @return \Cake\Http\Response|null|void
+ */
+ public function afterFilter(EventInterface $event)
+ {
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/NotificationsController.php b/idrocap_wa/src/Controller/Api/NotificationsController.php
new file mode 100644
index 0000000..b64bc81
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/NotificationsController.php
@@ -0,0 +1,156 @@
+respond(400, "not implemented");}
+ public function delete($id = null) {return $this->respond(400, "not implemented");}
+
+ /**
+ * index
+ *
+ * @return \Cake\Http\Response
+ */
+ public function index()
+ {
+ $notifications = $this->fetchTable('Notifications')->find()
+ ->contain(['NotificationTypes'])
+ ->where(['user_id' => $this->logged_user->id, 'read_by_user IS NULL'])
+ ->order(['created' => 'DESC'])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $notifications) {
+ return $notifications
+ ->map(function ($notification) {
+ if ($notification->already_mapped) return $notification;
+ $notification->already_mapped = true;
+ $notification->setHidden(array_merge($notification->getHidden(), ['already_mapped']));
+ $notification->info = json_decode($notification->info);
+ $webURL = Configure::read('App.weburl');
+ $notification->info->weblink = $webURL . $notification->info->link;
+ $notification->info->link = '/api' . $notification->info->link;
+ return $notification;
+ });
+ });
+
+ /**
+ * Default pagination settings.
+ *
+ * When calling paginate() these settings will be merged with the configuration
+ * you provide.
+ *
+ * - `maxLimit` - The maximum limit users can choose to view. Defaults to 100
+ * - `limit` - The initial number of items per page. Defaults to 20.
+ * - `page` - The starting page, defaults to 1.
+ * - `allowedParameters` - A list of parameters users are allowed to set using request
+ * parameters. Modifying this list will allow users to have more influence
+ * over pagination, be careful with what you permit.
+ * - `sortableFields` - A list of fields which can be used for sorting. By
+ * default all table columns can be used for sorting. You can use this option
+ * to restrict sorting only by particular fields. If you want to allow
+ * sorting on either associated columns or calculated fields then you will
+ * have to explicitly specify them (along with other fields). Using an empty
+ * array will disable sorting alltogether.
+ * - `finder` - The table finder to use. Defaults to `all`.
+ * - `scope` - If specified this scope will be used to get the paging options
+ * from the query params passed to paginate(). Scopes allow namespacing the
+ * paging options and allows paginating multiple models in the same action.
+ * Default `null`.
+ *
+ * protected array $_defaultConfig = [
+ * 'page' => 1,
+ * 'limit' => 20,
+ * 'maxLimit' => 100,
+ * 'allowedParameters' => ['limit', 'sort', 'page', 'direction'],
+ * 'sortableFields' => null,
+ * 'finder' => 'all',
+ * 'scope' => null,
+ * ];
+ */
+
+ try {
+ $paginated_notifications = $this->paginate($notifications, [
+ 'maxLimit' => 100,
+ 'limit' => 100,
+ ]);
+ return $this->respond(200, ['notifications' => $paginated_notifications, 'pagination' => $paginated_notifications->pagingParams()]);
+ } catch (\Cake\Http\Exception\NotFoundException $th) {
+ return $this->respond(404, ['result' => $th->getMessage()]);
+ }
+ }
+
+ /**
+ * count
+ *
+ * @return \Cake\Http\Response
+ */
+ public function count()
+ {
+ $notifications_count = $this->fetchTable('Notifications')->find()
+ ->where(['user_id' => $this->logged_user->id, 'read_by_user IS NULL'])
+ ->count();
+ return $this->respond(200, ['count' => $notifications_count]);
+ }
+
+ /**
+ * add
+ *
+ * @return \Cake\Http\Response
+ */
+ public function add()
+ {
+ if (!$this->logged_user->hasCapability(['notifications.read_all'])) {
+ return $this->respond(403, ['capabilities' => ['notifications.read_all']]);
+ }
+ $userId = $this->logged_user->id;
+ $this->fetchTable('Notifications')->updateAll(['read_by_user' => DateTime::now()], ['read_by_user IS NULL', 'user_id' => $userId]);
+ return $this->respond(201, "all notifications has been marked as read");
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $notification = $this->fetchTable('Notifications')->get($id);
+ $userId = $this->logged_user->id;
+ if($notification->user_id != $userId)
+ {
+ return $this->respond(403, "access unauthorised");
+ }
+ if($notification->read_by_user)
+ {
+ return $this->respond(400, "notification has already been read");
+ }
+ $notification->read_by_user = DateTime::now();
+
+ if(!$this->fetchTable('Notifications')->save($notification))
+ {
+ return $this->respond(400, ['error' => $notification->getErrors()]);
+ }
+ $notification->info = json_decode($notification->info);
+ return $this->respond(201, ['notification' => $notification]);
+ }
+
+ public function check()
+ {
+ $notifications_count = $this->fetchTable('Notifications')->find()
+ ->where(['user_id' => $this->logged_user->id, 'read_by_user IS NULL'])
+ ->count();
+ return $this->respond(200, ['result' => $notifications_count != 0]);
+
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/OrganisationTypesController.php b/idrocap_wa/src/Controller/Api/OrganisationTypesController.php
new file mode 100644
index 0000000..978712d
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/OrganisationTypesController.php
@@ -0,0 +1,31 @@
+respond(400, "not implemented");}
+ public function view($id = null) {return $this->respond(400, "not implemented");}
+ public function edit($id = null) {return $this->respond(400, "not implemented");}
+ public function delete($id = null) {return $this->respond(400, "not implemented");}
+
+ /**
+ * index
+ *
+ * @return \Cake\Http\Response
+ */
+ public function index()
+ {
+ $organisationTypes = $this->fetchTable('OrganisationTypes')->find('list')->order(['OrganisationTypes.description' => 'ASC']);
+ return $this->respond(200, ['organisation_types' => $organisationTypes]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/OrganisationsController.php b/idrocap_wa/src/Controller/Api/OrganisationsController.php
new file mode 100644
index 0000000..00c726c
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/OrganisationsController.php
@@ -0,0 +1,157 @@
+respond(400, "not implemented");}
+ public function edit($id = null) {return $this->respond(400, "not implemented");}
+ public function delete($id = null) {return $this->respond(400, "not implemented");}
+
+ /**
+ * index
+ *
+ * @return \Cake\Http\Response
+ */
+ public function index()
+ {
+ $options = ['type' => $this->request->getQuery('type') ?? null];
+
+ $user_can_index = $this->fetchTable('Organisations')->can_index($this->logged_user, $options);
+
+ if (!$user_can_index)
+ {
+ return $this->respond(403, $options['error']);
+ }
+
+ $organisations = $this->fetchTable('Organisations')
+ ->find($options['finder'], params: $options)
+ ->contain(['Actors', 'OrganisationTypes'])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $organisations) {
+ return $organisations
+ ->map(function ($organisation) {
+ if ($organisation->already_mapped) return $organisation;
+ $organisation->already_mapped = true;
+ $organisation->setHidden(array_merge($organisation->getHidden(), ['already_mapped', 'phone', 'mobile', 'fax', 'email', 'organisation_type_id', 'actor_id', 'incident_creator', 'pec', 'deleted', 'incident_default_tab', 'loggable_object_id', 'controllable_object_interface_id']));
+ $organisation->actor->setHidden(array_merge($organisation->actor->getHidden(), ['actor_type_id', 'interoperability_identifier', 'incident_type_group_id', 'deleted']));
+ return $organisation;
+ });
+ });
+
+ $organisations = $this->fetchTable('Organisations')->applySearchParams($organisations, $this->request->getQueryParams());
+
+ /**
+ * Default pagination settings.
+ *
+ * When calling paginate() these settings will be merged with the configuration
+ * you provide.
+ *
+ * - `maxLimit` - The maximum limit users can choose to view. Defaults to 100
+ * - `limit` - The initial number of items per page. Defaults to 20.
+ * - `page` - The starting page, defaults to 1.
+ * - `allowedParameters` - A list of parameters users are allowed to set using request
+ * parameters. Modifying this list will allow users to have more influence
+ * over pagination, be careful with what you permit.
+ * - `sortableFields` - A list of fields which can be used for sorting. By
+ * default all table columns can be used for sorting. You can use this option
+ * to restrict sorting only by particular fields. If you want to allow
+ * sorting on either associated columns or calculated fields then you will
+ * have to explicitly specify them (along with other fields). Using an empty
+ * array will disable sorting alltogether.
+ * - `finder` - The table finder to use. Defaults to `all`.
+ * - `scope` - If specified this scope will be used to get the paging options
+ * from the query params passed to paginate(). Scopes allow namespacing the
+ * paging options and allows paginating multiple models in the same action.
+ * Default `null`.
+ *
+ * protected array $_defaultConfig = [
+ * 'page' => 1,
+ * 'limit' => 20,
+ * 'maxLimit' => 100,
+ * 'allowedParameters' => ['limit', 'sort', 'page', 'direction'],
+ * 'sortableFields' => null,
+ * 'finder' => 'all',
+ * 'scope' => null,
+ * ];
+ */
+
+ try {
+ $paginated_organisations = $this->paginate($organisations, [
+ 'maxLimit' => 100,
+ 'limit' => 100,
+ 'sortableFields' => ['Actors.description', 'OrganisationTypes.description', 'acronym', 'address', 'district', 'cap', 'province'],
+ 'order' => [
+ 'Actors.description' => 'ASC'
+ ],
+ ]);
+ return $this->respond(200, ['organisations' => $paginated_organisations, 'pagination' => $paginated_organisations->pagingParams()]);
+ } catch (\Cake\Http\Exception\NotFoundException $th) {
+ return $this->respond(404, ['result' => $th->getMessage()]);
+ }
+ }
+
+ /**
+ * view
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function view($id = null)
+ {
+ $options = [];
+
+ $organisation = $this->fetchTable('Organisations')->get($id, contain: ['Actors', 'OrganisationTypes']);
+
+ $organisation->setHidden(array_merge($organisation->getHidden(), ['phone', 'mobile', 'fax', 'email', 'organisation_type_id', 'actor_id', 'incident_creator', 'pec', 'deleted', 'incident_default_tab', 'loggable_object_id', 'controllable_object_interface_id']));
+ $organisation->actor->setHidden(array_merge($organisation->actor->getHidden(), ['actor_type_id', 'interoperability_identifier', 'incident_type_group_id', 'deleted']));
+
+ if (($this->logged_user->organisation_id == $id) && (!$organisation->can_view($this->logged_user, $options))) {
+ return $this->respond(403, $options['error']);
+ }
+
+ $organisation->deliveries = $organisation->actor->getContactsList();
+
+ return $this->respond(200, ['organisation' => $organisation]);
+ }
+
+ /**
+ * getPhoto
+ *
+ * @param String $file_name
+ * @return \Cake\Http\Response
+ */
+ public function getPhoto($file_name)
+ {
+ $options = [];
+
+ $organisation = $this->fetchTable('Organisations')->find()
+ ->where(['Organisations.photo' => $file_name])
+ ->first();
+
+ if (!$organisation) {
+ return $this->respond(404, __('Organizzazione non trovata!'));
+ }
+ if (!$organisation->can_view($this->logged_user, $options)) {
+ return $this->respond(403, $options['error']);
+ }
+
+ $mimetype = "image/jpeg";
+ $path = Configure::read('App.organisationPhotoPath') . "/" . $file_name;
+ $output = \App\WGS\FileStorage\FileStorageFactory::create()->getFile($path);
+ $this->response = $this->response
+ ->withType($mimetype)
+ ->withStringBody($output);
+
+ return $this->response;
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/SubscriptionsController.php b/idrocap_wa/src/Controller/Api/SubscriptionsController.php
new file mode 100644
index 0000000..31c1b5f
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/SubscriptionsController.php
@@ -0,0 +1,67 @@
+respond(400, "not implemented");}
+ public function view($id = null) {return $this->respond(400, "not implemented");}
+ public function edit($id = null) {return $this->respond(400, "not implemented");}
+ public function delete($id = null) {return $this->respond(400, "not implemented");}
+
+ /**
+ * subscribe
+ *
+ * @return \Cake\Http\Response
+ */
+ public function subscribe()
+ {
+ $token = $this->request->getData('token') ?? null;
+ if (empty($token)) {
+ return $this->respond(400, ['error' => 'invalid subscribe token']);
+ }
+ $push_notification = $this->fetchTable('PushNotifications')
+ ->newEntity([
+ 'value' => $token,
+ 'enable_notifications' => true,
+ 'delivery' => [
+ 'actor_id' => $this->logged_user->actor_id,
+ 'delivery_type_id' => 0,
+ ],
+ ]);
+
+ $result = $this->fetchTable('PushNotifications')->save($push_notification);
+ $status_code = is_object($result) && get_class($result) === "App\Model\Entity\PushNotification" ? 201 : 400;
+ $message = $status_code == 201 ? $push_notification : $push_notification->getErrors();
+ return $this->respond($status_code, ['result' => $message]);
+ }
+
+ /**
+ * unsubscribe
+ *
+ * @return \Cake\Http\Response
+ */
+ public function unsubscribe()
+ {
+ $user_push_notification_tokens = $this->fetchTable('Deliveries')
+ ->find()
+ ->where(['Deliveries.actor_id' => $this->logged_user->actor_id, 'Deliveries.delivery_type_id' => 0])
+ ->all();
+
+ foreach ($user_push_notification_tokens as $user_push_notification_token) {
+ if (!$this->fetchTable('Deliveries')->delete($user_push_notification_token)) {
+ return $this->respond(500, ['result' => $user_push_notification_token->getErrors()]);
+ }
+ }
+ return $this->respond(200, ['unsubscribed' => $user_push_notification_tokens->count()]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/UsersController.php b/idrocap_wa/src/Controller/Api/UsersController.php
new file mode 100644
index 0000000..aa9e433
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/UsersController.php
@@ -0,0 +1,230 @@
+Authentication->allowUnauthenticated(['login']);
+ }
+
+ public function add() {return $this->respond(400, "not implemented");}
+ public function edit($id = null) {return $this->respond(400, "not implemented");}
+ public function delete($id = null) {return $this->respond(400, "not implemented");}
+
+ /**
+ * index
+ *
+ * @return \Cake\Http\Response
+ */
+ public function index()
+ {
+ $options = [];
+
+ $user_can_index = $this->fetchTable('Users')->can_index($this->logged_user, $options);
+
+ if (!$user_can_index)
+ {
+ return $this->respond(403, $options['error']);
+ }
+
+ $users = $this->fetchTable('Users')
+ ->find($options['finder'], params: $options)
+ ->contain(['UserActors', 'Organisations' => ['Actors']])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $users) {
+ return $users
+ ->map(function ($user) {
+ if ($user->already_mapped) return $user;
+ $user->already_mapped = true;
+ $user->setHidden(array_merge($user->getHidden(), ['already_mapped', 'organisation_id', 'phone', 'mobile', 'mobile2', 'email', 'notification_hash', 'fax', 'change_password', 'last_login', 'last_registered_request', 'from_mobile', 'last_ip_address', 'language_id', 'privacy', 'conditions', 'password_recovery_token', 'last_change_password', 'password_recovery_counter', 'email2', 'actor_id', 'ambiguity_verified', 'invalid_login_date', 'invalid_login_count', 'deleted', 'loggable_object_id', 'email2_wd']));
+ $user->user_actor->setHidden(array_merge($user->user_actor->getHidden(), ['actor_type_id', 'interoperability_identifier', 'incident_type_group_id', 'deleted']));
+ $user->organisation_description = $user->organisation->actor->description;
+ $user->birthday = $user->birthday?->format('d/m/Y');
+ return $user;
+ });
+ });
+
+ $users = $this->fetchTable('Users')->applySearchParams($users, $this->request->getQueryParams());
+
+ /**
+ * Default pagination settings.
+ *
+ * When calling paginate() these settings will be merged with the configuration
+ * you provide.
+ *
+ * - `maxLimit` - The maximum limit users can choose to view. Defaults to 100
+ * - `limit` - The initial number of items per page. Defaults to 20.
+ * - `page` - The starting page, defaults to 1.
+ * - `allowedParameters` - A list of parameters users are allowed to set using request
+ * parameters. Modifying this list will allow users to have more influence
+ * over pagination, be careful with what you permit.
+ * - `sortableFields` - A list of fields which can be used for sorting. By
+ * default all table columns can be used for sorting. You can use this option
+ * to restrict sorting only by particular fields. If you want to allow
+ * sorting on either associated columns or calculated fields then you will
+ * have to explicitly specify them (along with other fields). Using an empty
+ * array will disable sorting alltogether.
+ * - `finder` - The table finder to use. Defaults to `all`.
+ * - `scope` - If specified this scope will be used to get the paging options
+ * from the query params passed to paginate(). Scopes allow namespacing the
+ * paging options and allows paginating multiple models in the same action.
+ * Default `null`.
+ *
+ * protected array $_defaultConfig = [
+ * 'page' => 1,
+ * 'limit' => 20,
+ * 'maxLimit' => 100,
+ * 'allowedParameters' => ['limit', 'sort', 'page', 'direction'],
+ * 'sortableFields' => null,
+ * 'finder' => 'all',
+ * 'scope' => null,
+ * ];
+ */
+
+ try {
+ $paginated_users = $this->paginate($users, [
+ 'maxLimit' => 100,
+ 'limit' => 100,
+ 'sortableFields' => ['UserActors.description', 'username', 'surname', 'name', 'cap', 'gender'],
+ 'order' => [
+ 'Users.surname' => 'ASC',
+ ],
+ ]);
+ return $this->respond(200, ['users' => $paginated_users, 'pagination' => $paginated_users->pagingParams()]);
+ } catch (\Cake\Http\Exception\NotFoundException $th) {
+ return $this->respond(404, ['result' => $th->getMessage()]);
+ }
+ }
+
+ /**
+ * view
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function view($id)
+ {
+ $options = [];
+
+ $user = $this->fetchTable('Users')->get($id, contain: ['UserActors', 'Organisations' => ['Actors', 'OrganisationTypes']]);
+
+ if ($user->id != $this->logged_user->id && (!$user->can_view($this->logged_user, $options))) {
+ return $this->respond(403, $options['error']);
+ }
+
+ $user->setHidden(array_merge($user->getHidden(), ['fax', 'email', 'mobile2', 'mobile', 'email2', 'phone', 'organisation_id', 'notification_hash', 'change_password', 'last_login', 'last_registered_request', 'from_mobile', 'last_ip_address', 'language_id', 'privacy', 'conditions', 'password_recovery_token', 'last_change_password', 'password_recovery_counter', 'actor_id', 'ambiguity_verified', 'invalid_login_date', 'invalid_login_count', 'deleted', 'loggable_object_id', 'email2_wd']));
+ $user->actor = $user->user_actor;
+ unset($user->user_actor);
+ $user->actor->setHidden(array_merge($user->actor->getHidden(), ['actor_type_id', 'interoperability_identifier', 'incident_type_group_id', 'deleted']));
+ $user->organisation_description = null;
+ if ($user->hasValue('organisation')) {
+ $user->organisation->setHidden(array_merge($user->organisation->getHidden(), ['phone', 'mobile', 'fax', 'email', 'organisation_type_id', 'actor_id', 'incident_creator', 'pec', 'deleted', 'incident_default_tab', 'loggable_object_id', 'controllable_object_interface_id']));
+ $user->organisation_description = $user->organisation->actor->description;
+ unset($user->organisation->actor);
+ }
+
+ $user->deliveries = $user->actor->getContactsList();
+
+ return $this->respond(200, ['user' => $user]);
+ }
+
+
+ /**
+ * login
+ *
+ * @return \Cake\Http\Response
+ */
+ public function login()
+ {
+ $result = $this->Authentication->getResult();
+ // If the user is logged in send them away.
+ if ($result->isValid()) {
+ $receivedData = $this->getRequest()->getData();
+ $client_id = isset($receivedData['client_id']) && $receivedData['client_id'] != "" ? $receivedData['client_id'] : 'auto-' . bin2hex(random_bytes(32));
+ $platform = isset($receivedData['platform']) ? $receivedData['platform'] : 'unknown';
+ $tokenExpirationTime = Configure::read('App.jwt.expiration_time');
+
+ $token = JWT::encode([
+ 'sub' => $this->Authentication->getIdentity()->get('username'),
+ 'user_id' => $this->Authentication->getIdentity()->get('id'),
+ 'exp' => time() + $tokenExpirationTime,
+ 'client_id' => $client_id,
+ 'platform' => $platform,
+ ], file_get_contents(Configure::read('App.jwt.keys.private')), Configure::read('App.jwt.algorithm'));
+
+ $user = $this->fetchTable('Users')->get($this->Authentication->getIdentity()->get('id'));
+ $user->setHidden(['password', 'phone', 'mobile', 'mobile2', 'email', 'mobile_token_date', 'mobile_token', 'notification_hash', 'fax', 'change_password', 'last_login', 'last_registered_request', 'from_mobile', 'last_ip_address', 'position', 'position_date', 'ask_new_password', 'password_expiration', 'password_recovery_token', 'password_recovery_counter', 'email2', 'ambiguity_verified', 'invalid_login_date', 'invalid_login_count', 'deleted', 'loggable_object_id', 'email2_wd', 'make_volunteer', 'full_name', 'capabilities']);
+
+ $user->mobile_menu = $this->fetchTable('MobileComponents')
+ ->find()
+ ->matching('Capabilities')
+ ->where(['Capabilities.id IN' => $user->getCapabilityIds(true)])
+ ->order(['MobileComponents.id' => 'ASC'])
+ ->distinct(['MobileComponents.menu_item'])
+ ->select('MobileComponents.menu_item')
+ ->toArray();
+
+ $user->notifications = $this->fetchTable('Notifications')->find()
+ ->contain(['NotificationTypes'])
+ ->where(['user_id' => $user->id, 'read_by_user IS NULL'])
+ ->order(['created' => 'DESC'])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $notifications) {
+ return $notifications
+ ->map(function ($notification) {
+ $notification->info = json_decode($notification->info);
+ $webURL = Configure::read('App.weburl');
+ $notification->info->weblink = $webURL . $notification->info->link;
+ $notification->info->link = '/api' . $notification->info->link;
+ return $notification;
+ });
+ })->count() != 0;
+ return $this->respond(200, ['token' => $token, 'user' => $user, 'mobile_menu' => $user->mobile_menu]);
+ }
+ if ($this->request->is('post')) {
+ return $this->respond(401, ['error' => 'invalid credentials']);
+ }
+ }
+
+ /**
+ * getPhoto
+ *
+ * @param String $file_name
+ * @return \Cake\Http\Response
+ */
+ public function getPhoto($file_name)
+ {
+ $options = [];
+
+ $user = $this->fetchTable('Users')->find()
+ ->where(['Users.photo' => $file_name])
+ ->first();
+
+ if (!$user) {
+ return $this->respond(404, __('Utente non trovato!'));
+ }
+ if (!$user->can_view($this->logged_user, $options)) {
+ return $this->respond(403, $options['error']);
+ }
+
+ $mimetype = "image/jpeg";
+ $path = Configure::read('App.organisationPhotoPath') . "/" . $file_name;
+ $output = \App\WGS\FileStorage\FileStorageFactory::create()->getFile($path);
+ $this->response = $this->response
+ ->withType($mimetype)
+ ->withStringBody($output);
+
+ return $this->response;
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/WaterDrawingDerivationsController.php b/idrocap_wa/src/Controller/Api/WaterDrawingDerivationsController.php
new file mode 100644
index 0000000..e420203
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/WaterDrawingDerivationsController.php
@@ -0,0 +1,75 @@
+fetchTable('WaterDrawingDerivations')->find()->where(['WaterDrawingDerivations.id' => $id])->first();
+ if(!isset($waterDrawingDerivation)) return $this->respond(500, ['message' => 'Punto di derivazione non trovato.']);
+ return $this->respond(200, ['WaterDrawingDerivation' => $waterDrawingDerivation]);
+ }
+
+ public function update_data(){
+ $data = $this->request->getData();
+ $waterDrawingDerivation = $this->fetchTable('WaterDrawingDerivations')->find()->where(['WaterDrawingDerivations.id' => $data['water_drawing_derivation_id']])->first();
+ if(!isset($waterDrawingDerivation)) return $this->respond(500, ['message' => 'Punto di derivazione non trovato.']);
+ $waterDrawingDerivation = $this->fetchTable('WaterDrawingDerivations')->patchEntity($waterDrawingDerivation, [
+ 'annual_volume' => $data['volume'],
+ 'average_flow_rate' => $data['portata']
+ ]);
+ if($this->fetchTable('WaterDrawingDerivations')->save($waterDrawingDerivation)){
+ SnapshotsHandler::createSnapshot($waterDrawingDerivation->water_drawing_paperwork->controllable_object_id);
+ return $this->respond(200, ['message' => $waterDrawingDerivation]);
+ }else{
+ return $this->respond(500, ['message' => 'KO', 'error' => $waterDrawingDerivation->getErrors()]);
+ }
+ }
+
+ public function update_location(){
+ $data = $this->request->getData();
+ $waterDrawingDerivation = $this->fetchTable('WaterDrawingDerivations')->find()->contain(['WaterDrawingPaperworks'])->where(['WaterDrawingDerivations.id' => $data['water_drawing_derivation_id']])->first();
+ if(!isset($waterDrawingDerivation)) return $this->respond(500, ['message' => 'Punto di derivazione non trovato.']);
+ $feature_collection = '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[' . $data['longitude'] . ',' . $data['latitude'] . ']},"properties":null}]}';
+ if(!GeoValidation::isValidGeometry(json_decode($feature_collection))) return $this->respond(500, ['message' => 'Punto di derivazione non valido.']);
+ $reverse_geocoding = Geocoding::performGeocoding('reverse', ['format' => 'json', 'namedetails' => '1', 'lat' => $data['latitude'], 'lon' => $data['longitude']]);
+ if($reverse_geocoding['status_code']['http_code'] == '200'){
+ $waterDrawingDerivation = $this->fetchTable('WaterDrawingDerivations')->patchEntity($waterDrawingDerivation, [
+ 'latitude' => $data['latitude'],
+ 'longitude' => $data['longitude'],
+ 'feature_collection' => '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[' . $data['longitude'] . ',' . $data['latitude'] . ']},"properties":null}]}',
+ 'location' => isset($reverse_geocoding['contents']['address']['road']) ? $reverse_geocoding['contents']['address']['road'] : '',
+ 'district' => isset($reverse_geocoding['contents']['address']['town']) ? $reverse_geocoding['contents']['address']['town'] : '',
+ 'description' => isset($reverse_geocoding['contents']['display_name']) ? $reverse_geocoding['contents']['display_name'] : ''
+ ]);
+ }else{
+ $waterDrawingDerivation = $this->fetchTable('WaterDrawingDerivations')->patchEntity($waterDrawingDerivation, [
+ 'latitude' => $data['latitude'],
+ 'longitude' => $data['longitude'],
+ 'feature_collection' => '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[' . $data['longitude'] . ',' . $data['latitude'] . ']},"properties":null}]}'
+ ]);
+ }
+ if($this->fetchTable('WaterDrawingDerivations')->save($waterDrawingDerivation)){
+ SnapshotsHandler::createSnapshot($waterDrawingDerivation->water_drawing_paperwork->controllable_object_id);
+ return $this->respond(200, ['message' => 'OK']);
+ }else{
+ return $this->respond(500, ['message' => 'KO', 'error' => $waterDrawingDerivation->getErrors()]);
+ }
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/WaterDrawingMeasurementsController.php b/idrocap_wa/src/Controller/Api/WaterDrawingMeasurementsController.php
new file mode 100644
index 0000000..ac2a04f
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/WaterDrawingMeasurementsController.php
@@ -0,0 +1,47 @@
+request->getData();
+ $WaterDrawingMeasurement = $this->fetchTable('WaterDrawingMeasurements')->newEntity([
+ 'volume' => $data['volume'],
+ 'water_drawing_meter_id' => $data['water_drawing_meter_id'],
+ 'date' => DateTime::now(),
+ 'user_id' => $this->logged_user->id
+ ]);
+ if($this->fetchTable('WaterDrawingMeasurements')->save($WaterDrawingMeasurement)){
+ $waterDrawingMeter = $this->fetchTable('WaterDrawingMeters')->get($data['water_drawing_meter_id'], contain: ['WaterDrawingIntendedUses' => ['WaterDrawingPaperworks']]);
+ SnapshotsHandler::createSnapshot($waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork->controllable_object_id);
+ return $this->respond(200, ['message' => __('Salvato con successo')]);
+ }else{
+ return $this->respond(500, ['message' => __('Errore durante il salvataggio.'), 'error' => $WaterDrawingMeasurement->getErrors()]);
+ }
+ }
+
+ public function last_index($id){
+ $WaterDrawingMeasurements = $this->fetchTable('WaterDrawingMeasurements')->find()->contain(['Users'])->where(['WaterDrawingMeasurements.water_drawing_meter_id' => $id])->order(['WaterDrawingMeasurements.date' => 'DESC', 'WaterDrawingMeasurements.id' => 'DESC'])->limit(5)->formatResults( function ($result){
+ return $result->map( function ($q) {
+ $q->date = $q->date?->format('d/m/Y');
+ return $q;
+ });
+ })->toArray();
+ return $this->respond(200, ['WaterDaringMeasurements' => $WaterDrawingMeasurements]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/Api/WaterDrawingPaperworksController.php b/idrocap_wa/src/Controller/Api/WaterDrawingPaperworksController.php
new file mode 100644
index 0000000..23dcb00
--- /dev/null
+++ b/idrocap_wa/src/Controller/Api/WaterDrawingPaperworksController.php
@@ -0,0 +1,170 @@
+fetchTable('WaterDrawingPaperworks')->can_index($this->logged_user, $options);
+
+ if (!$user_can_index)
+ {
+ return $this->respond(403, $options['error']);
+ }
+
+ $waterDrawingPaperworks = $this->fetchTable('WaterDrawingPaperworks')->find()
+ ->contain(['ControllableObjects', 'WaterDrawingPaperworkStatuses'])->matching('Applicants');
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.view',
+ 'documentation.water_drawing_paperworks.view_own_province'
+ ])) {
+ $waterDrawingPaperworks = $waterDrawingPaperworks->where(['authority_province' => $this->logged_user?->organisation_province]);
+ }
+ $waterDrawingPaperworks = $this->fetchTable('WaterDrawingPaperworks')->applySearchParams($waterDrawingPaperworks, $this->request->getQueryParams());
+
+ $waterDrawingPaperworks = $waterDrawingPaperworks->distinct(['WaterDrawingPaperworks.id'])->formatResults(function ($results){
+ return $results->map(function ($row) {
+ if ($row->already_mapped) return $row;
+ $row->already_mapped = true;
+ $row->setHidden(array_merge($row->getHidden(), ['already_mapped']));
+ $row->release_date = $row->release_date?->format('d/m/Y');
+ $row->expiration_date = $row->expiration_date?->format('d/m/Y');
+ $row->controllable_object->created = $row->controllable_object->created?->format('d/m/Y H:i:s');
+ $row->controllable_object->modified = $row->controllable_object->modified?->format('d/m/Y H:i:s');
+ return $row;
+ });
+ });
+
+ /**
+ * Default pagination settings.
+ *
+ * When calling paginate() these settings will be merged with the configuration
+ * you provide.
+ *
+ * - `maxLimit` - The maximum limit users can choose to view. Defaults to 100
+ * - `limit` - The initial number of items per page. Defaults to 20.
+ * - `page` - The starting page, defaults to 1.
+ * - `allowedParameters` - A list of parameters users are allowed to set using request
+ * parameters. Modifying this list will allow users to have more influence
+ * over pagination, be careful with what you permit.
+ * - `sortableFields` - A list of fields which can be used for sorting. By
+ * default all table columns can be used for sorting. You can use this option
+ * to restrict sorting only by particular fields. If you want to allow
+ * sorting on either associated columns or calculated fields then you will
+ * have to explicitly specify them (along with other fields). Using an empty
+ * array will disable sorting alltogether.
+ * - `finder` - The table finder to use. Defaults to `all`.
+ * - `scope` - If specified this scope will be used to get the paging options
+ * from the query params passed to paginate(). Scopes allow namespacing the
+ * paging options and allows paginating multiple models in the same action.
+ * Default `null`.
+ *
+ * protected array $_defaultConfig = [
+ * 'page' => 1,
+ * 'limit' => 20,
+ * 'maxLimit' => 100,
+ * 'allowedParameters' => ['limit', 'sort', 'page', 'direction'],
+ * 'sortableFields' => null,
+ * 'finder' => 'all',
+ * 'scope' => null,
+ * ];
+ */
+
+ try {
+ $paginated_waterDrawingPaperworks = $this->paginate($waterDrawingPaperworks, [
+ 'maxLimit' => 25,
+ 'sortableFields' => ['id', 'WaterDrawingPaperworkStatuses.description', 'district', 'release_date', 'concession_duration', 'expiration_date', 'ControllableObjects.created', 'ControllableObjects.modified'],
+ ]);
+ return $this->respond(200, ['waterDrawingPaperworks' => $paginated_waterDrawingPaperworks, 'pagination' => $paginated_waterDrawingPaperworks->pagingParams()]);
+ } catch (\Cake\Http\Exception\NotFoundException $th) {
+ return $this->respond(404, ['result' => $th->getMessage()]);
+ }
+ }
+
+ public function view($id){
+ $options = [];
+
+ $user_can_index = $this->fetchTable('WaterDrawingPaperworks')->can_index($this->logged_user, $options);
+
+ if (!$user_can_index)
+ {
+ return $this->respond(403, $options['error']);
+ }
+ $organisation = $this->getTableLocator()->get('Organisations')->find()->where(['Organisations.id' => $this->logged_user->organisation_id])->first();
+ $waterDrawingPaperwork = $this->fetchTable('WaterDrawingPaperworks')->find()
+ ->contain([ 'WaterDrawingArticles', 'WaterDrawingFees', 'GcUsers' => ['Organisations'], 'DrarUsers' => ['Organisations'], 'WaterDrawingReturnPoints', 'WaterDrawingDerivations' => ['WaterDrawingDerivationTypes'], 'WaterDrawingPaperworkStatuses', 'ControllableObjects' => ['Attachments' => ['Tags']], 'Applicants',
+ 'WaterDrawingAntimafiaCertificationRequests' =>
+ function ($q){
+ return $q->contain(['WaterDrawingAntimafiaCertificationRequestStatuses', 'Users'])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created');
+ },
+ ]);
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.view',
+ 'documentation.water_drawing_paperworks.view_own_province'
+ ])) {
+ $waterDrawingPaperwork = $waterDrawingPaperwork->where(['authority_province' => $this->logged_user?->organisation_province]);
+ }
+ $waterDrawingPaperwork = $waterDrawingPaperwork->where(['WaterDrawingPaperworks.id' => $id])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) use ($organisation){
+ return $results->map(function ($row) use ($organisation){
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') && ( $this->logged_user->id == $row->gc_user_id && ($row->water_drawing_paperwork_status_id === -1 || $row->water_drawing_paperwork_status_id === -5 ) || ( $this->logged_user->id == $row->drar_user_id && $row->water_drawing_paperwork_status_id === -4 ));
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete');
+ $row->can_validate = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate') && $row->water_drawing_paperwork_status_id === -3;
+ $row->can_send_to_drar = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') && $row->water_drawing_paperwork_status_id === -1 && $row->check_sdd && $row->gc_user_id == $this->logged_user->id;
+ $row->can_send_to_gc = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') && $row->water_drawing_paperwork_status_id === -4 && $row->check_dec && $row->drar_user_id == $this->logged_user->id;
+ $row->can_assign_to_drar = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.assign') && $row->water_drawing_paperwork_status_id <= -2 && $organisation->organisation_type_id == 6;
+ $row->can_assign_to_gc = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.assign') && isset($row->gc_user->organisation->organisation_type_id) && $organisation->organisation_type_id == $row->gc_user->organisation->organisation_type_id;
+ if($row->water_drawing_paperwork_status_id === -5){
+ $row->can_add_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.add');
+ $row->can_edit_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.edit');
+ $row->can_view_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.view');
+ $row->can_add_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment') ;
+ $row->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_add_meter = $this->logged_user->hasCapability('documentation.water_drawing_meters.add');
+ $row->can_add_measurements = $this->logged_user->hasCapability('documentation.water_drawing_measurements.add');
+ $row->can_view_measurements = true;
+ }
+ if($row->water_drawing_paperwork_status_id == -4){
+ $row->can_add_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.add');
+ $row->can_edit_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.edit');
+ $row->can_view_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.view');
+ $row->can_add_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment') ;
+ $row->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_submit_antimafia_request = ($this->logged_user->id == $row->drar_user_id) && (!isset($row->water_drawing_antimafia_certification_requests[0]));
+ $row->can_antimafia_request_to_anac = ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.antimafia_request')) && (isset($row->water_drawing_antimafia_certification_requests[0]) && ($row->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 1));
+ $row->can_request_self_certification = ($this->logged_user->id == $row->drar_user_id) && (isset($row->water_drawing_antimafia_certification_requests[0]) && (new DateTime($row->water_drawing_antimafia_certification_requests[0]->created))->diffInDays(\Cake\I18n\DateTime::now()) > 30);
+ $row->can_upload_antimafia_attachment = (isset($row->water_drawing_antimafia_certification_requests[0]) && (
+ ( ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.antimafia_request')) && !($row->check_dam)) ||
+ ( ($this->logged_user->id == $row->gc_user_id) && $row->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 3)
+ ));
+ }
+ return $row;
+ });
+ })->first();
+ $waterDrawingPaperwork->water_drawing_meters = $this->getTableLocator()->get('WaterDrawingMeters')->find()->contain(['WaterDrawingIntendedUses', 'WaterDrawingToolTypes', 'WaterDrawingMeasurements' => function ($q){
+ return $q->contain(['Users'])->orderDesc('WaterDrawingMeasurements.date')->limit(5);
+ }])->where(['WaterDrawingIntendedUses.water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'WaterDrawingMeters.removal_date IS NULL'])->formatResults(function ($results){
+ return $results->map(function ($row){
+ $row->installation_date = $row->installation_date?->format('d/m/Y');
+ return $row;
+ });
+ })->toArray();
+ return $this->respond(200, ['result' => $waterDrawingPaperwork]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/AppController.php b/idrocap_wa/src/Controller/AppController.php
new file mode 100644
index 0000000..69ef6df
--- /dev/null
+++ b/idrocap_wa/src/Controller/AppController.php
@@ -0,0 +1,424 @@
+loadComponent('FormProtection');`
+ *
+ * @return void
+ */
+ public function initialize(): void
+ {
+ parent::initialize();
+
+ $this->loadComponent('Authentication.Authentication');
+ $this->loadComponent('Flash');
+
+ // recuperiamo l'entità dello user (se loggato):
+ $this->logged_user = $this->Authentication->getIdentity();
+
+ // settiamo il locale come da preferenze utente (se specificato, altrimenti ci pensa il LocaleSelectorMiddleware):
+ if (!empty($this->logged_user->language_id)) I18n::setLocale($this->fetchTable('Languages')->get($this->logged_user->language_id)->language_code);
+ $this->set('locale', I18n::getLocale());
+
+ /*
+ * Enable the following component for recommended CakePHP form protection settings.
+ * see https://book.cakephp.org/4/en/controllers/components/form-protection.html
+ */
+ //$this->loadComponent('FormProtection');
+ }
+
+ public function beforeRender(EventInterface $event)
+ {
+ if ($this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $this->viewBuilder()->disableAutoLayout();
+ }
+
+ $sys_admin_menu_items = null;
+ $menu_sections = [];
+ $menu_items = [];
+ $logged_user_id = null;
+ $logged_user_description = null;
+ $logged_user_access_type_description = null;
+ $logged_user_timezone = null;
+ $logged_user_organisation_description = null;
+ $logged_user_photo = Configure::read('App.defaultUserPhoto');
+ $user_notifications_count = 0;
+ $user_notifications = [];
+
+ // bisogna recuperare le capabilities utente (se esiste un utente loggato)
+ if ($this->logged_user) {
+ // menu SYSADMIN da mostrare solo ai SYSADMIN:
+ $sys_admin_menu_items = [
+ [
+ 'title' => __('SYSADMIN'),
+ 'icon' => 'lock',
+ 'menu_items' => [
+ [
+ 'title' => __('Gestione competenze'),
+ 'icon' => 'wrench',
+ 'link' => '/capabilities',
+ ],
+ [
+ 'title' => __('Test notifiche'),
+ 'icon' => 'bell',
+ 'link' => '/notifications/testAll',
+ 'confirm' => __('Procedendo verranno inviate notifiche a tutti gli utenti e le organizzaioni che possiedono uno o più recapiti abilitati alle notifiche! Sei sicuro che vuoi continuare ?'),
+ 'method' => 'POST',
+ ],
+ ],
+
+ ],
+ ];
+ if (!$this->logged_user->sys_admin) $sys_admin_menu_items = null;
+
+ $logged_user_id = $this->logged_user->id;
+ $logged_user_description = $this->logged_user->name . ' ' . $this->logged_user->surname;
+ $logged_user_access_type_description = $this->logged_user->sys_admin ? 'sys_admin' : ($this->logged_user->passepartout ? 'passepartout' : '');
+ $logged_user_timezone = $this->logged_user->timezone ?? Configure::read('App.defaultUserTimezone');
+ if (isset($this->logged_user->organisation_id)) {
+ $logged_user_organisation_description = $this->fetchTable('Organisations')->get($this->logged_user->organisation_id, contain: ['Actors'])->actor->description;
+ }
+ if (!empty($this->logged_user->photo)) $logged_user_photo = Configure::read('App.userPhotoSrc') . "/" . $this->logged_user->photo;
+
+ $user_notifications_count = $this->fetchTable('Notifications')->find()->where(['Notifications.user_id' => $this->logged_user->id, 'Notifications.read_by_user IS NULL'])->count();
+
+ $user_notifications = $this->fetchTable('Notifications')
+ ->find()
+ ->contain('NotificationTypes')
+ ->where(['Notifications.user_id' => $this->logged_user->id, 'Notifications.read_by_user IS NULL'])
+ ->order(['Notifications.created' => 'DESC'])
+ ->all()
+ ->reduce(function ($acc, $user_notification) {
+ $notification_info = json_decode($user_notification->info);
+ $body = strlen($notification_info->body) > 200 ? substr($notification_info->body, 0, 197) . '...' : $notification_info->body;
+ $icon = $user_notification->notification_type->icon ?? 'bell';
+ $time_ago = (new DateTime($user_notification->created))->timeAgoInWords();
+ $acc[] = ['id' => $user_notification->id, 'icon' => $icon, 'title' => $notification_info->title, 'body' => $body, 'time_ago' => $time_ago];
+ return $acc;
+ }, []);
+
+ $user_capabilityIds_query = $this->logged_user->getCapabilityIds(true);
+
+ $menu_sections_subquery = $this->fetchTable('MenuSections')
+ ->find()
+ ->select(['MenuSections.id'])
+ ->innerJoinWith('Capabilities')
+ ->where(['Capabilities.id IN' => $user_capabilityIds_query])
+ ->distinct(['MenuSections.id']);
+
+ $menu_sections = $this->fetchTable('MenuSections')
+ ->find()
+ ->where(['MenuSections.id IN' => $menu_sections_subquery])
+ ->order(['MenuSections.id' => 'ASC'])
+ ->toArray();
+
+ if (count($menu_sections) > 0) {
+ // questo blocco controlla se nella request è presente il query param 'menu_section'
+ // se è presente e rappresenta un id di menu_section valido, lo settiamo in sessione utente
+ if ($this->getRequest()->getQuery('menu_section')) {
+ $valid_user_menu_section = $this->fetchTable('MenuSections')->find()
+ ->matching('Capabilities')
+ ->where(['Capabilities.id IN' => $user_capabilityIds_query, 'MenuSections.id' => $this->getRequest()->getQuery('menu_section')])
+ ->first();
+
+ $valid_user_menu_section_id = $valid_user_menu_section ? $valid_user_menu_section->id : $menu_sections[0]->id;
+
+ $this->getRequest()->getSession()->write('menu_section', $valid_user_menu_section_id);
+ }
+ $menu_section_id = $this->getRequest()->getSession()->read('menu_section') ?? $menu_sections[0]->id;
+
+ $menu_items_subquery = $this->fetchTable('MenuItems')
+ ->find()
+ ->select(['MenuItems.id'])
+ ->innerJoinWith('Capabilities')
+ ->where(['Capabilities.id IN' => $user_capabilityIds_query])
+ ->where(['MenuItems.menu_item_id IS NULL'])
+ ->where(['MenuItems.menu_section_id' => $menu_section_id])
+ ->distinct(['MenuItems.id']);
+
+ $menu_items = $this->fetchTable('MenuItems')
+ ->find()
+ ->where(['MenuItems.id IN' => $menu_items_subquery])
+ ->order(['MenuItems.menu_order' => 'ASC'])
+ ->toArray();
+ }
+
+ if( $this->request->getPath() !== '/notifications/index' )
+ {
+ $privacy = $this->fetchTable('Privacy')
+ ->find()->orderBy(['created' => 'DESC'])
+ ->first();
+
+ if(isset($privacy))
+ {
+ $hasAcceptedPrivacy = $this->fetchTable('PrivacyUsers')->find()->where([
+ 'PrivacyUsers.user_id' => $this->logged_user->id,
+ 'PrivacyUsers.privacy_id' => $privacy->id
+ ])->first();
+
+ if(
+ !isset($hasAcceptedPrivacy) &&
+ $this->request->getParam('controller') != 'Privacy' &&
+ $this->request->getParam('action') != 'accept_privacy'
+ ) {
+ return $this->redirect(['controller' => 'Privacy', 'action' => 'accept_privacy']);
+ }
+ }
+ }
+ }
+
+ $this->set('menu_sections', $menu_sections);
+ $this->set('menu_items', $menu_items);
+ $this->set('sys_admin_menu_items', $sys_admin_menu_items);
+ $this->set('logged_user_id', $logged_user_id);
+ $this->set('logged_user_description', $logged_user_description);
+ $this->set('logged_user_access_type_description', $logged_user_access_type_description);
+ $this->set('logged_user_timezone', $logged_user_timezone);
+ $this->set('logged_user_organisation_description', $logged_user_organisation_description);
+ $this->set('logged_user_photo', $logged_user_photo);
+ $this->set('user_notifications_count', $user_notifications_count);
+ $this->set('user_notifications', $user_notifications);
+ }
+
+ /**
+ * gen_random_code
+ *
+ * @param Int $length
+ * @return String
+ */
+ protected function gen_random_code(Int $length): String {
+ $characters = "abcdefghijklmnopqrstuvwxyzABCDERFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ $randomString = "";
+
+ for ($i = 0; $i < $length; $i++) {
+ $randomString .= $characters[mt_rand(0, strlen($characters)-1)];
+ }
+ return $randomString;
+ }
+
+ /**
+ * sendNotifications
+ *
+ * @param Int|Null $co_id
+ * @param String $notification_code
+ * @param Array $options
+ * @return void
+ */
+ protected function sendNotifications(Int|Null $co_id, String $notification_code, Array $options)
+ {
+ NotificationsHandler::dispatch($co_id, $notification_code, $options, null, $this->logged_user->id ?? null);
+ }
+
+ /**
+ * applyFilters
+ *
+ * @param Query $query
+ * @return Query
+ */
+ protected function applyFilters(Query $query): Query
+ {
+ // recuperiamo i parametri per costruire la chiave per memorizzare i filtri in sessione.
+ // i filtri sono "scoped" per utente e per route. Quindi per ogni utente possiamo memorizzare
+ // filtri relativi a più liste.
+ $logged_user_id = $this->logged_user->id;
+ $controller = $this->request->getParam('controller');
+ $action = $this->request->getParam('action');
+ $filter_session_key = "filters-$logged_user_id-$controller-$action";
+
+ // recuperiamo i filtri o dal POST data (significa che sono stati appena applicati)
+ // o dalla sessione (se ci sono):
+ $filters = $this->request->is('post') ? $this->request->getData('filters') : $this->request->getSession()->read($filter_session_key);
+ \Cake\Log\Log::write("debug", 'applyFilters - ' . ($this->request->is('post') ? 'POST received' : 'SESSION retrieved') . ' filters: ' . json_encode($filters));
+
+ // ripuliamo i filtri eliminando prima i valori non validi per ciascun filtro
+ // e successivamente eliminiamo direttamente i fitri che non hanno valori validi (rimasti):
+ $filters = collection($filters ?? [])
+ ->map(function ($filter_values, $filter_id) {
+ return collection($filter_values)
+ ->filter(function ($filter_value) {
+ // il controllo con === "0" serve per evitare che il sanitiser elimini
+ // il valore "0" per filtri di tipo "bool"
+ return !empty($filter_value) || $filter_value === "0";
+ })
+ ->reduce(function ($filter_values, $filter_value) {
+ $filter_values[] = $filter_value;
+ return $filter_values;
+ }, []);
+ })
+ ->filter(function ($filter_values, $filter_id) {
+ return !empty($filter_values);
+ })
+ ->toArray();
+
+ \Cake\Log\Log::write("debug", 'applyFilters - SANITISED filters: ' . json_encode($filters));
+
+ // se non si è riusciti a recuperare filtri
+ // o è stato richesto un reset dei filtri tramite POST
+ // o non ne sono rimasti a seguito della sanitizzazione,
+ // cancelliamo comunque la sessione alla chiave $filter_session_key
+ // ed usciamo senza applicare nulla alla query:
+ if (empty($filters)) {
+ \Cake\Log\Log::write("debug", "applyFilters - DELETING DATA SESSION with key '$filter_session_key'");
+ $this->request->getSession()->delete($filter_session_key);
+ \Cake\Log\Log::write("debug", 'applyFilters - NO filters to appply!');
+ return $query;
+ }
+
+ // se abbiamo filtri validi e li abbiamo appena ricevuti (POST), li salviamo in sessione:
+ if ($this->request->is('post')) {
+ \Cake\Log\Log::write("debug", "applyFilters - WRITING DATA SESSION with key '$filter_session_key': " . json_encode($filters));
+ $this->request->getSession()->write($filter_session_key, $filters);
+ }
+
+ // array delle possibili associations da gestire nella query con ->leftJoinWith().
+ // verrà popolato durante il processo di conversione da filtri a conditions:
+ $associations = [];
+
+ // array delle conditions creato a partire dai filters ricevuti, da gestire nella query con ->where()
+ $conditions = collection($filters)
+ // qui trasformiamo i filtri in conditions in base alla tipologia di filtro ricevuto:
+ ->map(function ($filter_values, $filter_id) use (&$associations) {
+ // recuperiamo le info sul filtro dalla table 'filters' avendo ricevuto l'id del filtro:
+ $filter = $this->fetchTable('Filters')->get((Int)explode("filter_id_", $filter_id)[1]);
+ // creazione della condizione in base al tipo di filtro:
+ switch ($filter->filter_type) {
+ case 'class':
+ case 'bool':
+ $condition = [$filter->search . ' IN' => $filter_values];
+ break;
+ case 'text':
+ $condition = collection($filter_values)
+ ->map(function ($filter_value) use ($filter) {
+ return [$filter->search . ' LIKE' => $filter_value];
+ })
+ ->reduce(function ($conditions, $condition) {
+ $conditions['OR'][] = $condition;
+ return $conditions;
+ }, ['OR' => []]);
+ break;
+ case 'date':
+ $condition = collection($filter_values)
+ ->map(function ($filter_value) use ($filter) {
+ $date_array = explode(" - ", $filter_value);
+ $from_date = $date_array[0];
+ $to_date = $date_array[1];
+ return [$filter->search . ' >=' => $from_date, $filter->search . ' <=' => $to_date];
+ })
+ ->reduce(function ($conditions, $condition) {
+ $conditions['OR'][] = $condition;
+ return $conditions;
+ }, ['OR' => []]);
+ break;
+ default:
+ break;
+ }
+ // se il filtro è stato gestito e richiede una association, la inseriamo in apposito array:
+ if (!empty($condition) && !empty($filter->associations)) $associations[] = $filter->associations;
+
+ // se il filtro non è stato gestito, restituiamo null; altrimenti restituiamo la condition
+ return $condition ?? null;
+ })
+ // qui eliminiamo eventuali conditions null (generate da filtri non (al momento) gestiti:
+ ->filter(function ($condition) {
+ return !empty($condition);
+ })
+ // infine restituiamo l'array_values delle conditions ottenute:
+ ->reduce(function ($conditions, $condition) {
+ $conditions[] = $condition;
+ return $conditions;
+ }, []);
+
+ \Cake\Log\Log::write("debug", 'applyFilters - conditions applied: ' . json_encode($conditions));
+
+ if (count($conditions) > 0) $query = $query->where($conditions);
+
+ \Cake\Log\Log::write("debug", 'applyFilters - associations applied: ' . json_encode($associations));
+
+ foreach ($associations as $association) {
+ $query = $query->leftJoinWith($association);
+ }
+
+ if (count($associations) > 0) {
+ $main_table = $query->getRepository()->getAlias();
+ $query = $query->distinct(["$main_table.id"]);
+ \Cake\Log\Log::write("debug", 'applyFilters - distinct applied: ' . "$main_table.id");
+ }
+
+ return $query;
+ }
+
+ /**
+ * Respond with JSON
+ *
+ * @param int $statusCode HTTP status code
+ * @param null|object|array|string|null $responseBody Content of the response
+ * @param string $contentType Content type of the response, default "application/json"
+ * @return Response
+ */
+ public function respond(int $statusCode = 200, null|object|array|string $responseBody = null, string $contentType = "application/json") : Response
+ {
+ $responseBody = is_object($responseBody) || is_array($responseBody) ? $responseBody : ['result' => $responseBody];
+
+ if ($paging = $this->request->getAttribute('paging')) {
+ $responseBody['pagination'] = $paging;
+ }
+
+ try {
+ $encodedBody = json_encode($responseBody, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+ } catch (Exception $e) {
+ return $this->getResponse()
+ ->withStatus(500)
+ ->withStringBody(json_encode(['error' => 'Failed to encode JSON response']))
+ ->withType('application/json');
+ }
+
+ $response = $this->getResponse()
+ ->withStatus($statusCode)
+ ->withType($contentType)
+ ->withStringBody($encodedBody);
+
+ return $response;
+ }
+}
diff --git a/idrocap_wa/src/Controller/ApplicantsController.php b/idrocap_wa/src/Controller/ApplicantsController.php
new file mode 100644
index 0000000..cf643ae
--- /dev/null
+++ b/idrocap_wa/src/Controller/ApplicantsController.php
@@ -0,0 +1,112 @@
+viewBuilder()->setClassName('Json');
+
+ $search = $this->request->getQueryParams('term');
+ $applicants = $this->Applicants->find()->where([
+ 'Applicants.tax_code LIKE "%' . $search['term'] . '%" OR Applicants.name LIKE "%' . $search['term'] . '%" OR Applicants.surname LIKE "%' . $search['term'] . '%"'
+ ])->formatResults(function ($results){
+ return $results->map(function ($row) {
+ return ['id' => $row->id, 'text' => $row->tax_code . ' - ' . $row->name . ' ' . $row->surname];
+ });
+ })->toArray();
+ $this->set(compact('applicants'));
+ $this->viewBuilder()->setOption('serialize', ['applicants'])->setOption('jsonOptions', JSON_FORCE_OBJECT);
+ }
+
+ public function get_applicant($id){
+ $applicant = $this->Applicants->get($id);
+ $this->set(compact('applicant'));
+ $this->viewBuilder()->setOption('serialize', ['applicant'])->setOption('jsonOptions', JSON_FORCE_OBJECT);
+ }
+
+ public function edit($id, $water_id = null){
+ $applicant = $this->Applicants->get($id);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $applicant = $this->Applicants->patchEntity($applicant, $this->request->getData());
+ if ($this->Applicants->save($applicant)) {
+ $this->Flash->success(__('Il concessionario è stato aggiornato correttamente.'));
+
+ return $this->redirect(['action' => 'view', $id]);
+ }
+ $this->Flash->error(__('Errore. Il concessionario non è stato salvato.'));
+ }
+ if(isset($water_id)){
+ $waterDrawingPaperwork = $this->Applicants->WaterDrawingPaperworks->get($water_id);
+ $this->set(compact('waterDrawingPaperwork'));
+ }
+ $this->set(compact('applicant'));
+ }
+
+ public function view($id){
+ $applicant = $this->Applicants->get($id);
+ $this->set(compact('applicant'));
+ }
+
+ // CITIZEN SECTION
+
+ public function citizen_add(){
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $applicant = $this->Applicants->newEmptyEntity();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ $data['name'] = $this->logged_user->name;
+ $data['surname'] = $this->logged_user->surname;
+ $data['tax_code'] = $this->logged_user->tax_code;
+ $applicant = $this->Applicants->patchEntity($applicant, $data);
+ if ($this->Applicants->save($applicant)) {
+ $this->Flash->success(__('Il concessionario è stato creato correttamente.'));
+
+ return $this->redirect(['action' => 'citizen_view']);
+ }
+ $this->Flash->error(__('Errore. Il concessionario non è stato salvato.'));
+ }
+ $user = $this->getTableLocator()->get('Users')->get($this->logged_user->id);
+ $this->set('user', $user);
+ $this->set(compact('applicant'));
+ }
+
+ public function citizen_edit(){
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $user = $this->getTableLocator()->get('Users')->get($this->logged_user->id);
+ $applicant = $this->Applicants->find()->where(['Applicants.tax_code' => $user->tax_code])->first();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $applicant = $this->Applicants->patchEntity($applicant, $this->request->getData());
+ if ($this->Applicants->save($applicant)) {
+ $this->Flash->success(__('Il concessionario è stato aggiornato correttamente.'));
+
+ return $this->redirect(['action' => 'citizen_view']);
+ }
+ $this->Flash->error(__('Errore. Il concessionario non è stato salvato.'));
+ }
+ $this->set('user', $user);
+ $this->set(compact('applicant'));
+ }
+
+ public function citizen_view(){
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $user = $this->getTableLocator()->get('Users')->get($this->logged_user->id);
+ $applicant = $this->Applicants->find()->where(['Applicants.tax_code' => $user->tax_code])->first();
+ if(!isset($applicant)) $this->redirect(['action' => 'citizen_add']);
+ $this->set(compact('applicant'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/AttachmentsController.php b/idrocap_wa/src/Controller/AttachmentsController.php
new file mode 100644
index 0000000..4aed82a
--- /dev/null
+++ b/idrocap_wa/src/Controller/AttachmentsController.php
@@ -0,0 +1,98 @@
+request->getQuery('withTrashed');
+ $finder = !empty($withTrashed) ? 'withTrashed' : 'all';
+ $attachment = $this->fetchTable('Attachments')->find($finder)
+ ->contain(['ContainerControllableObjects'])
+ ->where(['file_name' => $id])
+ ->first();
+
+ if (!$attachment) throw new NotFoundException(__('Allegato non trovato'));
+ if (!$this->logged_user->canHandleAttachmentsForControllableObject($attachment->container_controllable_object)) throw new ForbiddenException(__('Non hai i permessi necessari per visionare l\'allegato'));
+
+ $mimetype = $attachment->mimetype;
+ $file_name = $attachment->file_name;
+ $original_file_name = $attachment->original_file_name;
+ $container_co_id = $attachment->container_controllable_object_id;
+ $path = Configure::read('App.attachmentsPath') . "/" . $container_co_id . "/" . $file_name;
+ $output = \App\WGS\FileStorage\FileStorageFactory::create()->getFile($path);
+ $this->response = $this->response
+ ->withAddedHeader('Content-Disposition', 'filename="' . $original_file_name . '"')
+ ->withCharset('UTF-8')
+ ->withType($mimetype)
+ ->withStringBody($output);
+
+ return $this->response;
+ }
+
+ /**
+ * markAsRelevant
+ *
+ * @param Int $id
+ * @throws NotFoundException
+ * @return \Cake\Http\Response
+ */
+ public function markAsRelevant($id = null)
+ {
+ $this->request->allowMethod(['post']);
+ $attachment = $this->fetchTable('Attachments')->find()->contain(['ContainerControllableObjects', 'ControllableObjects'])->where(['file_name' => $id])->first();
+
+ if(!$attachment) throw new NotFoundException(__('Allegato non trovato'));
+ if (!$this->logged_user->canHandleAttachmentsForControllableObject($attachment->container_controllable_object)) throw new ForbiddenException(__('Non hai i permessi necessari per visionare l\'allegato'));
+
+ $attachment->relevant = !$attachment->relevant;
+ $attachment->controllable_object->id = $attachment->controllable_object->id;
+ $attachment->setDirty('controllable_object');
+ $this->fetchTable('Attachments')->save($attachment);
+ $response = (object) [];
+ $response->result = true;
+ $response->relevant = $attachment->relevant;
+ $this->set('response', $response);
+ $this->viewBuilder()->setOption('serialize', 'response');
+ }
+
+ /**
+ * markAsDeleted
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function markAsDeleted($id = null)
+ {
+ $this->response = $this->response
+ ->withType('application/json')
+ ->withStringBody(json_encode(['result' => "markAsDeleted attachment with id '$id'. Dummy method. please do not delete it!"]));
+
+ return $this->response;
+ }
+}
diff --git a/idrocap_wa/src/Controller/CapabilitiesController.php b/idrocap_wa/src/Controller/CapabilitiesController.php
new file mode 100644
index 0000000..f3b97e7
--- /dev/null
+++ b/idrocap_wa/src/Controller/CapabilitiesController.php
@@ -0,0 +1,205 @@
+logged_user->sys_admin) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $capabilities = $this->Capabilities->find('withTrashed')
+ ->contain(['CapabilityGroups' => function ($q) { return $q->find('withTrashed'); }]);
+
+ $capability_search = $this->request->getQuery('capability_search');
+ if (!empty($capability_search)) {
+ $capabilities = $capabilities->where(['OR' => [
+ 'Capabilities.description LIKE' => "%$capability_search%",
+ 'Capabilities.value LIKE' => "%$capability_search%",
+ 'CapabilityGroups.description LIKE' => "%$capability_search%",
+ ]]);
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['description', 'value', 'priority', 'CapabilityGroups.description'],
+ ];
+
+ $this->set('capabilities', $this->paginate($capabilities));
+ $this->set('capability_search', $capability_search);
+ }
+
+ /**
+ * hide
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function hide($id)
+ {
+ if (!$this->logged_user->sys_admin) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $capability = $this->Capabilities->find('withTrashed')->where(['Capabilities.id' => $id])->first();
+ $connection = ConnectionManager::get('default');
+ $errSave = true;
+ $connection->begin();
+ $capability->is_configurable = false;
+ if ($this->Capabilities->save($capability)) {
+ $capability_group = $this->Capabilities->CapabilityGroups->find('withTrashed')
+ ->contain(['Capabilities' => function ($q) { return $q->find('withTrashed')->where(['Capabilities.is_configurable' => 1]); }])
+ ->where(['CapabilityGroups.id' => $capability->capability_group_id])
+ ->first();
+
+ if ($capability_group) {
+ if (count($capability_group->capabilities) == 0) {
+ $capability_group->is_configurable = false;
+ if ($this->Capabilities->CapabilityGroups->save($capability_group)) {
+ $errSave = false;
+ }
+ } else {
+ $errSave = false;
+ }
+ }
+ }
+
+ if (!$errSave) {
+ $this->Flash->success(__('Competenza "{0}" nascosta con successo!', $capability->description));
+ $connection->commit();
+ } else {
+ $this->Flash->error(__('Errore durante il tentativo di nascondere la Competenza "{0}"!', $capability->description));
+ $connection->rollback();
+ }
+ return $this->redirect(['action' => 'index', '?' => $this->request->getQueryParams()]);
+ }
+
+ /**
+ * show
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function show($id)
+ {
+ if (!$this->logged_user->sys_admin) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $capability = $this->Capabilities->find('withTrashed')->where(['Capabilities.id' => $id])->first();
+ $connection = ConnectionManager::get('default');
+ $errSave = true;
+ $connection->begin();
+ $capability->is_configurable = true;
+ if ($this->Capabilities->save($capability)) {
+ $capability_group = $this->Capabilities->CapabilityGroups->find('withTrashed')
+ ->where(['CapabilityGroups.id' => $capability->capability_group_id])
+ ->first();
+
+ if ($capability_group) {
+ $capability_group->is_configurable = true;
+ if ($this->Capabilities->CapabilityGroups->save($capability_group)) {
+ $errSave = false;
+ }
+ }
+ }
+
+ if (!$errSave) {
+ $this->Flash->success(__('Competenza "{0}" resa visibile con successo!', $capability->description));
+ $connection->commit();
+ } else {
+ $this->Flash->error(__('Errore durante il tentativo di rendere visibile la Competenza "{0}"!', $capability->description));
+ $connection->rollback();
+ }
+ return $this->redirect(['action' => 'index', '?' => $this->request->getQueryParams()]);
+ }
+
+ /**
+ * delete
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function delete($id)
+ {
+ if (!$this->logged_user->sys_admin) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $this->Capabilities->Permissions->addBehavior('Muffin/Trash.Trash');
+ $capability = $this->Capabilities->find('withTrashed')->where(['Capabilities.id' => $id])->first();
+ $connection = ConnectionManager::get('default');
+ $errSave = true;
+ $connection->begin();
+ if ($this->Capabilities->delete($capability)) {
+ $capability_group = $this->Capabilities->CapabilityGroups->find('withTrashed')
+ ->contain(['Capabilities'])
+ ->where(['CapabilityGroups.id' => $capability->capability_group_id])
+ ->first();
+
+ if ($capability_group) {
+ if (count($capability_group->capabilities) == 0) {
+ if ($this->Capabilities->CapabilityGroups->delete($capability_group)) {
+ $errSave = false;
+ }
+ } else {
+ $errSave = false;
+ }
+ }
+ }
+
+ if (!$errSave) {
+ $this->Flash->success(__('Competenza "{0}" cancellata con successo!', $capability->description));
+ $connection->commit();
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione della Competenza "{0}"!', $capability->description));
+ $connection->rollback();
+ }
+ return $this->redirect(['action' => 'index', '?' => $this->request->getQueryParams()]);
+ }
+
+ /**
+ * restore
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function restore($id)
+ {
+ if (!$this->logged_user->sys_admin) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $this->Capabilities->Permissions->addBehavior('Muffin/Trash.Trash');
+ $capability = $this->Capabilities->find('withTrashed')->where(['Capabilities.id' => $id])->first();
+ $connection = ConnectionManager::get('default');
+ $errSave = true;
+ $connection->begin();
+ if ($this->Capabilities->cascadingRestoreTrash($capability)) {
+ $capability_group = $this->Capabilities->CapabilityGroups->find('withTrashed')
+ ->where(['CapabilityGroups.id' => $capability->capability_group_id])
+ ->first();
+
+ if ($capability_group) {
+ $capability_group->deleted = null;
+ if ($this->Capabilities->CapabilityGroups->save($capability_group)) {
+ $errSave = false;
+ }
+ }
+ }
+
+ if (!$errSave) {
+ $this->Flash->success(__('Competenza "{0}" ripristinata con successo!', $capability->description));
+ $connection->commit();
+ } else {
+ $this->Flash->error(__('Errore durante il ripristino della Competenza "{0}"!', $capability->description));
+ $connection->rollback();
+ }
+ return $this->redirect(['action' => 'index', '?' => $this->request->getQueryParams()]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/Component/.gitkeep b/idrocap_wa/src/Controller/Component/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/src/Controller/Component/StreamableCsvExportTrait.php b/idrocap_wa/src/Controller/Component/StreamableCsvExportTrait.php
new file mode 100644
index 0000000..a6fc351
--- /dev/null
+++ b/idrocap_wa/src/Controller/Component/StreamableCsvExportTrait.php
@@ -0,0 +1,103 @@
+disableHydration();
+
+ do {
+ $results = $query
+ ->limit($chunkSize)
+ ->page($page)
+ ->all();
+
+ foreach ($results as $rowArray) {
+
+ if ($extract !== null) {
+ if (!$wroteHeader) {
+ // we use the provided $headers as column names,
+ // otherwise we fallback to $extract array keys when they are plain string or we use "Column $key" if they are not
+ $headerRow = $headers ?? array_map(
+ function($extract_value, $extract_index) { return is_string($extract_value) ? $extract_value : "Column $extract_index"; },
+ $extract,
+ array_keys($extract)
+ );
+ fputcsv($out, $headerRow, ...$csvOptions);
+ $wroteHeader = true;
+ }
+
+ $dataRow = [];
+
+ // we use the provided $extractor to obtain the mapped values:
+ foreach ($extract as $column) {
+ if (is_callable($column)) {
+ $dataRow[] = $column($rowArray);
+ } elseif (is_string($column)) {
+ $dataRow[] = $rowArray[$column] ?? '';
+ } else {
+ $dataRow[] = '';
+ }
+ }
+ fputcsv($out, $dataRow, ...$csvOptions);
+ } else {
+ // there is no exctractor provided, we will take plain array keys as column names:
+ if (!$wroteHeader) {
+ fputcsv($out, array_keys($rowArray), ...$csvOptions);
+ $wroteHeader = true;
+ }
+ // there is no exctractor provided, we will take plain array values:
+ $rowValues = array_values($rowArray);
+ fputcsv($out, $rowValues, ...$csvOptions);
+ }
+ flush();
+ }
+ $count = $results->count();
+ $page++;
+ } while ($count === $chunkSize);
+
+ fclose($out);
+ });
+
+ return $this->response
+ ->withType('text/csv')
+ ->withDownload($filename)
+ ->withBody($stream);
+ }
+}
diff --git a/idrocap_wa/src/Controller/ControllableObjectsController.php b/idrocap_wa/src/Controller/ControllableObjectsController.php
new file mode 100644
index 0000000..708925d
--- /dev/null
+++ b/idrocap_wa/src/Controller/ControllableObjectsController.php
@@ -0,0 +1,56 @@
+ControllableObjects->Attachments
+ ->find()
+ ->contain(['ControllableObjects' => ['Creator', 'Modifier', 'Locations']])
+ ->where(['Attachments.container_controllable_object_id' => $co_id]);
+
+ if(!empty($this->request->getQuery('tags'))) {
+ $tags = explode(',', $this->request->getQuery('tags'));
+ $attachments = $attachments
+ ->matching('Tags')
+ ->where(['Tags.code IN' => $tags]);
+ }
+
+ $showPrivateColumn = $attachments->all()->filter(function ($attachment) { return $attachment->private == 1; })->count() > 0;
+
+ if (!$this->logged_user->canHandleAttachmentsForControllableObject($this->ControllableObjects->get($co_id))) {
+ $attachments = $attachments->where(['Attachments.id < 0']);
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['Attachments.private', 'Attachments.original_file_name', 'Locations.description', 'Attachments.relevant', 'Attachments.original_file_size', 'Attachments.mimetype', 'Attachments.upload_date', 'Creator.surname'],
+ 'limit' => 10,
+ 'order' => [
+ 'Attachments.upload_date' => 'DESC'
+ ],
+ ];
+
+ if ($this->request->getQuery('removecurrentfiles') !== null) {
+ $this->set('removecurrentfiles', $this->request->getQuery('removecurrentfiles'));
+ }
+
+ $this->viewBuilder()->setLayout('ajax');
+ $this->set('numberOfAttachments', $attachments->count());
+ $this->set('attachments', $this->paginate($attachments));
+ $this->set('showPrivateColumn', $showPrivateColumn);
+ }
+}
diff --git a/idrocap_wa/src/Controller/DashboardController.php b/idrocap_wa/src/Controller/DashboardController.php
new file mode 100644
index 0000000..733b662
--- /dev/null
+++ b/idrocap_wa/src/Controller/DashboardController.php
@@ -0,0 +1,35 @@
+Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canViewContactsForActor($actor)) throw new ForbiddenException(__('Non hai i permessi per visualizzare i recapiti per {0}', $actor_type_description));
+
+ $mobile_phones = $this->Deliveries->MobilePhones->find()
+ ->contain(['MobilePhoneDescriptions'])
+ ->matching('Deliveries')
+ ->where(['Deliveries.actor_id' => $actor_id])
+ ->all();
+
+ if (!$this->logged_user->canViewContactsForActor($actor, 'mobile_phone')) {
+ $mobile_phones = $mobile_phones->map(function ($mobile_phone) {
+ $mobile_phone->value = "**************";
+ return $mobile_phone;
+ });
+ }
+
+ $faxes = $this->Deliveries->Faxes->find()
+ ->contain(['FaxDescriptions'])
+ ->matching('Deliveries')
+ ->where(['Deliveries.actor_id' => $actor_id])
+ ->all();
+
+ if (!$this->logged_user->canViewContactsForActor($actor, 'fax')) {
+ $faxes = $faxes->map(function ($fax) {
+ $fax->value = "**************";
+ return $fax;
+ });
+ }
+
+ $emails = $this->Deliveries->Emails->find()
+ ->contain(['EmailDescriptions'])
+ ->matching('Deliveries')
+ ->where(['Deliveries.actor_id' => $actor_id])
+ ->all();
+
+ if (!$this->logged_user->canViewContactsForActor($actor, 'email')) {
+ $emails = $emails->map(function ($email) {
+ $email->value = "**************";
+ return $email;
+ });
+ }
+
+ $phones = $this->Deliveries->Phones->find()
+ ->contain(['PhoneDescriptions'])
+ ->matching('Deliveries')
+ ->where(['Deliveries.actor_id' => $actor_id])
+ ->all();
+
+ if (!$this->logged_user->canViewContactsForActor($actor, 'phone')) {
+ $phones = $phones->map(function ($phone) {
+ $phone->value = "**************";
+ return $phone;
+ });
+ }
+
+ $telegram_chats = $this->Deliveries->TelegramChats->find()
+ ->matching('Deliveries')
+ ->where(['Deliveries.actor_id' => $actor_id])
+ ->all();
+
+ if (!$this->logged_user->canViewContactsForActor($actor, 'telegram_chat')) {
+ $telegram_chats = $telegram_chats->map(function ($telegram_chat) {
+ $telegram_chat->value = "**************";
+ return $telegram_chat;
+ });
+ }
+
+ $pecs = $this->Deliveries->Pecs->find()
+ ->contain(['PecDescriptions'])
+ ->matching('Deliveries')
+ ->where(['Deliveries.actor_id' => $actor_id])
+ ->all();
+
+ if (!$this->logged_user->canViewContactsForActor($actor, 'pec')) {
+ $pecs = $pecs->map(function ($pec) {
+ $pec->value = "**************";
+ return $pec;
+ });
+ }
+
+ $can_add_mobile_phone = $this->logged_user->canAddContactsForActor($actor, 'mobile_phone');
+ $can_edit_mobile_phone = $this->logged_user->canEditContactsForActor($actor, 'mobile_phone');
+ $can_delete_mobile_phone = $this->logged_user->canDeleteContactsForActor($actor, 'mobile_phone');
+ $can_add_fax = $this->logged_user->canAddContactsForActor($actor, 'fax');
+ $can_edit_fax = $this->logged_user->canEditContactsForActor($actor, 'fax');
+ $can_delete_fax = $this->logged_user->canDeleteContactsForActor($actor, 'fax');
+ $can_add_email = $this->logged_user->canAddContactsForActor($actor, 'email');
+ $can_edit_email = $this->logged_user->canEditContactsForActor($actor, 'email');
+ $can_delete_email = $this->logged_user->canDeleteContactsForActor($actor, 'email');
+ $can_add_phone = $this->logged_user->canAddContactsForActor($actor, 'phone');
+ $can_edit_phone = $this->logged_user->canEditContactsForActor($actor, 'phone');
+ $can_delete_phone = $this->logged_user->canDeleteContactsForActor($actor, 'phone');
+ $can_add_telegram_chat = $this->logged_user->canAddContactsForActor($actor, 'telegram_chat');
+ $can_edit_telegram_chat = $this->logged_user->canEditContactsForActor($actor, 'telegram_chat');
+ $can_delete_telegram_chat = $this->logged_user->canDeleteContactsForActor($actor, 'telegram_chat');
+ $can_add_pec = $this->logged_user->canAddContactsForActor($actor, 'pec');
+ $can_edit_pec = $this->logged_user->canEditContactsForActor($actor, 'pec');
+ $can_delete_pec = $this->logged_user->canDeleteContactsForActor($actor, 'pec');
+
+ $this->set(compact('actor', 'mobile_phones', 'faxes', 'emails', 'phones', 'telegram_chats', 'pecs', 'can_add_mobile_phone', 'can_edit_mobile_phone', 'can_delete_mobile_phone', 'can_add_fax', 'can_edit_fax', 'can_delete_fax', 'can_add_email', 'can_edit_email', 'can_delete_email', 'can_add_phone', 'can_edit_phone', 'can_delete_phone', 'can_add_telegram_chat', 'can_edit_telegram_chat', 'can_delete_telegram_chat', 'can_add_pec', 'can_edit_pec', 'can_delete_pec'));
+ }
+
+ /**
+ * delete
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $delivery = $this->Deliveries->get($id, contain: ['DeliveryTypes', 'MobilePhones' => ['MobilePhoneDescriptions'], 'Faxes' => ['FaxDescriptions'], 'Emails' => ['EmailDescriptions'], 'Phones' => ['PhoneDescriptions'], 'TelegramChats', 'Pecs' => ['PecDescriptions']]);
+
+ $actor = $this->Deliveries->Actors->get($delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canDeleteContactsForActor($actor, $delivery->delivery_type->description)) throw new ForbiddenException(__('Non hai i permessi per eliminare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $contact_value = "";
+
+ switch ($delivery->delivery_type_id) {
+ case 1:
+ $contact_value = __('Cellulare ({0}): {1}', $delivery->mobile_phone->mobile_phone_description->description, $this->logged_user->canViewContactsForActor($actor, $delivery->delivery_type->description) ? $delivery->mobile_phone->value : "**************");
+ break;
+ case 2:
+ $contact_value = __('Fax ({0}): {1}', $delivery->fax->fax_description->description, $this->logged_user->canViewContactsForActor($actor, $delivery->delivery_type->description) ? $delivery->fax->value: "**************");
+ break;
+ case 3:
+ $contact_value = __('Email ({0}): {1}', $delivery->email->email_description->description, $this->logged_user->canViewContactsForActor($actor, $delivery->delivery_type->description) ? $delivery->email->value: "**************");
+ break;
+ case 4:
+ $contact_value = __('Telefono ({0}): {1}', $delivery->phone->phone_description->description, $this->logged_user->canViewContactsForActor($actor, $delivery->delivery_type->description) ? $delivery->phone->value: "**************");
+ break;
+ case 5:
+ $contact_value = __('Telegram Chat ID: {0}', $this->logged_user->canViewContactsForActor($actor, $delivery->delivery_type->description) ? $delivery->telegram_chat->value: "**************");
+ break;
+ case 6:
+ $contact_value = __('PEC ({0}): {1}', $delivery->pec->pec_description->description, $this->logged_user->canViewContactsForActor($actor, $delivery->delivery_type->description) ? $delivery->pec->value: "**************");
+ break;
+ default:
+ $contact_value = "";
+ break;
+ }
+
+ if ($this->Deliveries->delete($delivery)) {
+ $this->Flash->success(__('Il recapito "{0}" è stato cancellato con successo', $contact_value));
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione del recapito {0}. Riprovare di nuovo.', $contact_value));
+ }
+
+ return $this->redirect(['action' => 'index', $delivery->actor_id]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/DistrictsController.php b/idrocap_wa/src/Controller/DistrictsController.php
new file mode 100644
index 0000000..61e2f39
--- /dev/null
+++ b/idrocap_wa/src/Controller/DistrictsController.php
@@ -0,0 +1,66 @@
+viewBuilder()->setClassName('Json');
+ $conditions = [];
+ $provinceCode = $this->request->getQuery(ProvinceDistrictFieldHelper::raw(ProvinceDistrictFields::PROVINCE_CODE));
+ $term = $this->request->getQuery("term");
+ $codeReg = ProvinceDistrictFieldHelper::getCodeRegByRegion(Regions::SICILY);
+ $regCodField = ProvinceDistrictFieldHelper::forDistricts(ProvinceDistrictFields::REGION_CODE);
+ $provCodeField = ProvinceDistrictFieldHelper::forDistricts(ProvinceDistrictFields::PROVINCE_CODE);
+ $queryDistrictFieldName = ProvinceDistrictFieldHelper::forDistricts(ProvinceDistrictFields::DISTRICT_FIELD_NAME);
+
+ if($codeReg) {
+ $conditions[$regCodField] = $codeReg;
+ }
+
+ if (isset($provinceCode)) {
+ $conditions[$provCodeField] = $provinceCode;
+ }
+
+ $query = $this->Districts->find();
+
+ if ($term) {
+ $query->where(function ($exp) use ($term, $queryDistrictFieldName) {
+ return $exp->like($queryDistrictFieldName, "%$term%");
+ });
+ }
+
+ if (!empty($conditions)) {
+ $query->where($conditions);
+ }
+
+ $district_field = ProvinceDistrictFieldHelper::raw(ProvinceDistrictFields::DISTRICT_FIELD_NAME);
+ $districts = $query->find('list', keyField: $district_field, valueField: $district_field)->toArray();
+
+ $this->set(compact('districts'));
+ $this->viewBuilder()->setOption('serialize', ['districts'])->setOption('jsonOptions', JSON_FORCE_OBJECT);
+ }
+}
diff --git a/idrocap_wa/src/Controller/EmailsController.php b/idrocap_wa/src/Controller/EmailsController.php
new file mode 100644
index 0000000..8c5f63b
--- /dev/null
+++ b/idrocap_wa/src/Controller/EmailsController.php
@@ -0,0 +1,78 @@
+Emails->Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canAddContactsForActor($actor, 'email')) throw new ForbiddenException(__('Non hai i permessi per aggiungere i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $email = $this->Emails->newEntity([
+ 'delivery' => [
+ 'actor_id' => $actor_id,
+ 'delivery_type_id' => 3,
+ ],
+ ], ['validate' => false]);
+
+ if ($this->request->is('post')) {
+ $email = $this->Emails->patchEntity($email, $this->request->getData());
+ if ($this->Emails->save($email)) {
+ $this->Flash->success(__('L\'Email è stata aggiunta con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $actor_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'aggiunta dell\'Email'));
+ }
+ $emailDescriptions = $this->Emails->EmailDescriptions->find('list');
+ $this->set(compact('actor', 'email', 'emailDescriptions'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $email = $this->Emails->get($id, contain: ['Deliveries' => ['Actors' => ['ActorTypes']]]);
+
+ $actor = $this->Emails->Deliveries->Actors->get($email->delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canEditContactsForActor($actor, 'email')) throw new ForbiddenException(__('Non hai i permessi per modificare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $email = $this->Emails->patchEntity($email, $this->request->getData());
+ if ($this->Emails->save($email)) {
+ $this->Flash->success(__('L\'Email è stata modificata con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $email->delivery->actor_id]);
+ }
+ $this->Flash->error(__('Errore durante la modifica dell\'Email. Riprovare di nuovo'));
+ }
+ $emailDescriptions = $this->Emails->EmailDescriptions->find('list');
+ $this->set(compact('actor', 'email', 'emailDescriptions'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/ErrorController.php b/idrocap_wa/src/Controller/ErrorController.php
new file mode 100644
index 0000000..d0fd7eb
--- /dev/null
+++ b/idrocap_wa/src/Controller/ErrorController.php
@@ -0,0 +1,70 @@
+viewBuilder()->setTemplatePath('Error');
+ }
+
+ /**
+ * afterFilter callback.
+ *
+ * @param \Cake\Event\EventInterface $event Event.
+ * @return \Cake\Http\Response|null|void
+ */
+ public function afterFilter(EventInterface $event)
+ {
+ }
+}
diff --git a/idrocap_wa/src/Controller/FaxesController.php b/idrocap_wa/src/Controller/FaxesController.php
new file mode 100644
index 0000000..89bc206
--- /dev/null
+++ b/idrocap_wa/src/Controller/FaxesController.php
@@ -0,0 +1,78 @@
+Faxes->Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canAddContactsForActor($actor, 'fax')) throw new ForbiddenException(__('Non hai i permessi per aggiungere i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $fax = $this->Faxes->newEntity([
+ 'delivery' => [
+ 'actor_id' => $actor_id,
+ 'delivery_type_id' => 2,
+ ],
+ ], ['validate' => false]);
+
+ if ($this->request->is('post')) {
+ $fax = $this->Faxes->patchEntity($fax, $this->request->getData());
+ if ($this->Faxes->save($fax)) {
+ $this->Flash->success(__('Il Fax è stato aggiunto con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $actor_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'aggiunta del Fax'));
+ }
+ $faxDescriptions = $this->Faxes->FaxDescriptions->find('list');
+ $this->set(compact('actor', 'fax', 'faxDescriptions'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $fax = $this->Faxes->get($id, contain: ['Deliveries' => ['Actors' => ['ActorTypes']]]);
+
+ $actor = $this->Faxes->Deliveries->Actors->get($fax->delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canEditContactsForActor($actor, 'fax')) throw new ForbiddenException(__('Non hai i permessi per modificare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $fax = $this->Faxes->patchEntity($fax, $this->request->getData());
+ if ($this->Faxes->save($fax)) {
+ $this->Flash->success(__('Il Fax è stato modificato con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $fax->delivery->actor_id]);
+ }
+ $this->Flash->error(__('Errore durante la modifica del Fax. Riprovare di nuovo'));
+ }
+ $faxDescriptions = $this->Faxes->FaxDescriptions->find('list');
+ $this->set(compact('actor', 'fax', 'faxDescriptions'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/FiltersController.php b/idrocap_wa/src/Controller/FiltersController.php
new file mode 100644
index 0000000..ad09547
--- /dev/null
+++ b/idrocap_wa/src/Controller/FiltersController.php
@@ -0,0 +1,25 @@
+set('filter_id', $filter_id);
+ $this->viewBuilder()->setLayout('ajax');
+ }
+}
diff --git a/idrocap_wa/src/Controller/GroupsController.php b/idrocap_wa/src/Controller/GroupsController.php
new file mode 100644
index 0000000..d7632e5
--- /dev/null
+++ b/idrocap_wa/src/Controller/GroupsController.php
@@ -0,0 +1,236 @@
+logged_user->hasCapability('configuration.groups.read')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $groups = $this->Groups->find()
+ ->contain(['Actors', 'ChildGroups']);
+
+ if (!$this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $groups = $groups
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_edit = $this->logged_user->hasCapability('configuration.groups.edit');
+ $row->can_delete = $this->logged_user->hasCapability('configuration.groups.delete');
+ $row->child_groups_csv = collection($row->child_groups)->reduce(function ($csv, $child_group) { return empty($csv) ? $child_group->description : ($csv . ', ' . $child_group->description); }, '');
+ return $row;
+ });
+ });
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['description', 'is_default'],
+ ];
+
+ $this->set('groups', $this->getRequest()->is(['json', 'xml', 'csv']) ? $groups : $this->paginate($groups));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('configuration.groups.export_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('Descrizione'),
+ __('Profilo Default'),
+ __('Profili Associati'),
+ ];
+ $extract = [
+ 'description',
+ function (array $row) {
+ return $row['is_default'] ? __('SI') : __('NO');
+ },
+ function (array $row) {
+ return collection($row['child_groups'])->reduce(function ($csv, $child_group) { return empty($csv) ? $child_group['description'] : ($csv . ', ' . $child_group['description']); }, '');
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("profiles_$timestamp.csv"));
+ }
+ $this->viewBuilder()->setOption('serialize', 'groups');
+ }
+
+ /**
+ * view
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function view($id = null)
+ {
+ if (!$this->logged_user->hasCapability('configuration.groups.read')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $group = $this->Groups->get($id, contain: ['Actors', 'ChildGroups']);
+
+ $group->can_handle_capabilities = $this->logged_user->hasCapability('configuration.groups.capabilities');
+ $group->can_edit = $this->logged_user->hasCapability('configuration.groups.edit');
+ $group->can_delete = $this->logged_user->hasCapability('configuration.groups.delete');
+ $group->child_groups_csv = collection($group->child_groups)->reduce(function ($csv, $child_group) { return empty($csv) ? $child_group->description : ($csv . ', ' . $child_group->description); }, '');
+
+ $this->set(compact('group'));
+ $this->viewBuilder()->setOption('serialize', 'group');
+ }
+
+ /**
+ * add
+ *
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function add()
+ {
+ if (!$this->logged_user->hasCapability('configuration.groups.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $group = $this->Groups->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $group = $this->Groups->patchEntity($group, $this->request->getData());
+ if ($this->Groups->save($group)) {
+ $this->Flash->success(__('Profilo Utente creato con successo.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante la creazione del Profilo Utente'));
+ }
+ $child_groups = $this->fetchTable('Groups')->find('list')->contain(['Actors'])->order(['Groups.description' => 'ASC']);
+ $this->set(compact('group'));
+ $this->set(compact('child_groups'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ if (!$this->logged_user->hasCapability('configuration.groups.edit')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $group = $this->Groups->get($id, contain: ['Actors', 'ChildGroups']);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $group = $this->Groups->patchEntity($group, $this->request->getData());
+ if ($this->Groups->save($group)) {
+ $this->Flash->success(__('Profilo Utente "{0}" modificato con successo.', $group->description));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante la modifica del Profilo Utente "{0}". Riprovare di nuovo.', $group->description));
+ }
+ $child_groups = $this->fetchTable('Groups')->find('list')->contain(['Actors'])->order(['Groups.description' => 'ASC']);
+ $this->set(compact('group'));
+ $this->set(compact('child_groups'));
+ }
+
+ /**
+ * delete
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function delete($id = null)
+ {
+ if (!$this->logged_user->hasCapability('configuration.groups.delete')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $this->request->allowMethod(['post', 'delete']);
+ $group = $this->Groups->get($id, contain: ['Actors']);
+
+ if ($this->Groups->Actors->delete($group->actor)) {
+ $this->Flash->success(__('Il Profilo Utente "{0}" è stato cancellato con successo', $group->description));
+ } else {
+ $errors = $group->actor->getErrors();
+ if (isset($errors['is_editable']['checkGroupIsEditable'])) {
+ $errorMessage = $errors['is_editable']['checkGroupIsEditable'];
+ $this->Flash->error($errorMessage);
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione del Profilo Utente "{0}". Riprovare di nuovo.', $group->description));
+ }
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+
+ /**
+ * handleCapabilities
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function handleCapabilities($id = null)
+ {
+ if (!$this->logged_user->hasCapability('configuration.groups.capabilities')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $group = $this->Groups->get($id, contain: ['Actors']);
+
+ $group_capability_ids = $this->Groups->Capabilities->find()
+ ->select(['id'])
+ ->matching('Groups')
+ ->where(['Groups.id' => $id]);
+
+ if (!$this->logged_user->sys_admin) {
+ $group_capability_ids = $group_capability_ids
+ ->where(['Capabilities.is_configurable' => 1]);
+ }
+
+ $group_capability_ids = $group_capability_ids
+ ->distinct()
+ ->all()
+ ->extract('id')
+ ->toArray();
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $group = $this->Groups->patchEntity($group, $this->request->getData(), ['group_id' => $group->id]);
+ if ($this->Groups->save($group)) {
+ $this->Flash->success(__('Profilo Utente "{0}" modificato con successo.', $group->description));
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante la modifica del Profilo Utente "{0}". Riprovare di nuovo.', $group->description));
+ }
+
+ $capability_groups = $this->Groups->Capabilities->CapabilityGroups->find()
+ ->contain(['Capabilities' => function ($q) {
+ if (!$this->logged_user->sys_admin) {
+ $q->where(['Capabilities.is_configurable' => 1]);
+ }
+ return $q->order(['Capabilities.capability_group_id' => 'ASC', 'Capabilities.priority_group_id' => 'ASC', 'Capabilities.priority' => 'ASC', 'Capabilities.description']);
+ }])
+ ->order(['CapabilityGroups.description' => 'ASC']);
+
+ $this->set(compact('group', 'group_capability_ids', 'capability_groups'));
+ $this->viewBuilder()->setOption('serialize', 'group');
+ }
+}
diff --git a/idrocap_wa/src/Controller/MapsController.php b/idrocap_wa/src/Controller/MapsController.php
new file mode 100644
index 0000000..c2987da
--- /dev/null
+++ b/idrocap_wa/src/Controller/MapsController.php
@@ -0,0 +1,187 @@
+'], ['%20', '%3E'], $query_parameters);
+ $url .= $query_parameters;
+ $http = new Client();
+ $response = $http->get($url, [], [
+ 'auth' => ['username' => Configure::read('App.geoserverUsername'), 'password' => Configure::read('App.geoserverPassword')]
+ ]);
+ return $response->getStringBody();
+ }
+
+ /**
+ * get_location_attributes
+ *
+ * @param String $lat
+ * @param String $lon
+ * @return ?Array
+ */
+ private function get_location_attributes(String $lat, String $lon): ?Array {
+ $feature_collection = '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[' . $lon . ',' . $lat . ']},"properties":null}]}';
+ $location = $this->fetchTable('Locations')->newEntity([
+ 'feature_collection' => $feature_collection,
+ ]);
+ $lar = new LocationAttributesRetriever($location);
+ $lar_result = $lar->retrieve()[0] ?? null;
+ return $lar_result;
+ }
+
+ /**
+ * get_matching_geo_resources
+ *
+ * @param String $lat
+ * @param String $lon
+ * @return ?Array
+ */
+ private function get_matching_geo_resources(String $lat, String $lon): ?Array {
+ $feature_collection = '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[' . $lon . ',' . $lat . ']},"properties":null}]}';
+ $matching_geo_resources = [];
+ // inizializziamo l'array $mapped_fields con un array associativo con KEY id del campo e VALUE '':
+ $mapped_fields = collection($this->geo_resources)->reduce(function ($acc, $geo_resource) {
+ return array_merge($acc, array_fill_keys(array_values($geo_resource['attributes_fields']), ''));
+ }, []);
+
+ foreach ($this->geo_resources as $geo_resource) {
+ if (isset($geo_resource['external']) && is_bool($geo_resource['external']) && $geo_resource['external']) {
+ $grar = new ExtGeoResourceAttributesRetriever($geo_resource['url'], $geo_resource['lon_parameter_name'], $geo_resource['lat_parameter_name']);
+ $grar_result = $grar->retrieve($lon, $lat);
+ if (isset($grar_result)) {
+ // scremiamo il risultato proveniente dal servizio esterno considerando solo gli attributi che ci interessano:
+ $grar_result = array_intersect_key($grar_result, $geo_resource['attributes_fields']);
+ $matching_geo_resources[$geo_resource['url']] = $grar_result;
+ foreach ($grar_result as $attribute_name => $attribute_value) {
+ $mapped_fields[$geo_resource['attributes_fields'][$attribute_name]] = $attribute_value;
+ }
+ }
+ } else {
+ $grar = new IntGeoResourceAttributesRetriever($geo_resource['table_name'], $geo_resource['geometry_name'], array_keys($geo_resource['attributes_fields']));
+ $grar_result = $grar->retrieve($feature_collection)[0] ?? null;
+ if (isset($grar_result)) {
+ $matching_geo_resources[$geo_resource['table_name']] = $grar_result;
+ foreach ($grar_result as $attribute_name => $attribute_value) {
+ $mapped_fields[$geo_resource['attributes_fields'][$attribute_name]] = $attribute_value;
+ }
+ }
+ }
+ }
+ return ['matching_geo_resources' => $matching_geo_resources, 'mapped_fields' => $mapped_fields];
+ }
+
+ /**
+ * map_geocoding_result_content
+ *
+ * @param Array $content
+ * @return Array
+ */
+ private function map_geocoding_result_content(Array $content): Array {
+ $array_content = explode(", ", $content['display_name'] ?? '');
+ $index_cursor = count($array_content) - 1;
+ if ($index_cursor > 0) $nation = $array_content[$index_cursor--];
+ if ($index_cursor > 0) $cap = (Int)$array_content[$index_cursor] > 0 ? $array_content[$index_cursor--] : '';
+ if ($index_cursor > 0) $region = $array_content[$index_cursor--];
+ if ($index_cursor > 0) $province = $array_content[$index_cursor--];
+ if ($index_cursor > 0) $district = $array_content[$index_cursor--];
+ $address = $content['namedetails']['name'] ?? '';
+ $description = $content['display_name'] ?? '';
+ $lat = $content['lat'] ?? '';
+ $lon = $content['lon'] ?? '';
+ return ['nation' => $nation ?? '', 'cap' => $cap ?? '', 'region' => $region ?? '', 'province' => $province ?? '', 'district' => $district ?? '', 'address' => $address, 'lat' => $lat, 'lon' => $lon, 'description' => $description];
+ }
+
+ /**
+ * index
+ *
+ * @return \Cake\Http\Response
+ */
+ public function index () {
+ if(!$this->logged_user->hasCapability(['confiiguration.maps.view'])) throw new BadRequestException(__('Non hai i permessi'));
+ }
+
+ /**
+ * getWfs
+ *
+ * @return Response
+ */
+ public function getWfs(): Response {
+ if(!$this->logged_user->hasCapability(['confiiguration.maps.view'])) throw new BadRequestException(__('Non hai i permessi'));
+ $response = $this->geoserver_proxy($this->request->getUri()->getQuery());
+ return $this->getResponse()->withStringBody($response)->withType("application/json");
+ }
+
+ /**
+ * geocode
+ *
+ * @throws BadRequestException
+ * @throws NotFoundException
+ * @return Response
+ */
+ public function geocode(): Response {
+ if(!$this->logged_user->hasCapability(['confiiguration.maps.view'])) throw new BadRequestException(__('Non hai i permessi'));
+ // geo_resources, se presente, contiene le info per mappare campi aggiuntivi con attributi di
+ // una o + geo-risorse in base a dove il punto specificato ricade:
+ $geo_resources = json_decode($this->request->getQuery('geo_resources') ?? '', true);
+ if ($geo_resources !== null && is_array($geo_resources) && count($geo_resources) > 0) $this->geo_resources = $geo_resources;
+
+ if ($this->request->getQuery('address') === null) throw new BadRequestException('geocode error: invalid address');
+
+ $separator = null;
+
+ if (count(collection(explode(" ", $this->request->getQuery('address')))->filter(function ($part) { return is_numeric(trim($part)); })->toArray()) === 2) {
+ $separator = " ";
+ }
+
+ if (count(collection(explode(",", $this->request->getQuery('address')))->filter(function ($part) { return is_numeric(trim($part)); })->toArray()) === 2) {
+ $separator = ",";
+ }
+
+ if ($separator !== null) {
+ $address_parts = explode($separator, $this->request->getQuery('address'));
+ $lat = $address_parts[0] > $address_parts[1] ? $address_parts[0] : $address_parts[1];
+ $lon = $address_parts[0] > $address_parts[1] ? $address_parts[1] : $address_parts[0];
+ $feature_collection = '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[' . $lon . ',' . $lat . ']},"properties":null}]}';
+ if (!GeoValidation::isValidGeometry(json_decode($feature_collection))) throw new BadRequestException('invalid coordinates or out of boundary!');
+ $reverse_geocoding = Geocoding::performGeocoding('reverse', ['format' => 'json', 'namedetails' => '1', 'lat' => $lat, 'lon' => $lon]);
+ if (!empty($reverse_geocoding['contents'])) {
+ $mapped_geocoding_result_content = $this->map_geocoding_result_content($reverse_geocoding['contents']);
+ }
+ $lar_result = $this->get_location_attributes($lat, $lon);
+ $content = ['geo_resources' => $this->get_matching_geo_resources($lat, $lon), 'nation' => $mapped_geocoding_result_content['nation'] ?? '', 'cap' => $mapped_geocoding_result_content['cap'] ?? '', 'region' => $lar_result['region'] ?? $mapped_geocoding_result_content['region'] ?? '', 'province' => $lar_result['county_name'] ?? $mapped_geocoding_result_content['province'] ?? '', 'district_code' => $lar_result['district_code'] ?? '', 'district' => $lar_result['district_name'] ?? $mapped_geocoding_result_content['district'] ?? '', 'address' => $mapped_geocoding_result_content['address'] ?? '', 'lat' => $lat, 'lon' => $lon, 'description' => !empty($mapped_geocoding_result_content['description']) ? $mapped_geocoding_result_content['description'] : __('Punto alle coordinate (EPSG:4326) Latitudine: {0}, Longitudine: {1}', $lat, $lon)];
+ return $this->getResponse()->withStringBody(json_encode($content))->withType("application/json");
+ }
+
+ $geocoding = Geocoding::performGeocoding('search', ['format' => 'json', 'namedetails' => '1', 'q' => $this->request->getQuery('address')]);
+ if (empty($geocoding['contents'])) throw new NotFoundException('geocode error: no contents');
+ return $this->getResponse()->withStringBody(json_encode($geocoding['contents']))->withType("application/json");
+ }
+}
diff --git a/idrocap_wa/src/Controller/MobilePhonesController.php b/idrocap_wa/src/Controller/MobilePhonesController.php
new file mode 100644
index 0000000..b1fca0f
--- /dev/null
+++ b/idrocap_wa/src/Controller/MobilePhonesController.php
@@ -0,0 +1,79 @@
+MobilePhones->Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canAddContactsForActor($actor, 'mobile_phone')) throw new ForbiddenException(__('Non hai i permessi per aggiungere i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $mobilePhone = $this->MobilePhones->newEntity([
+ 'delivery' => [
+ 'actor_id' => $actor_id,
+ 'delivery_type_id' => 1,
+ ],
+ ], ['validate' => false]);
+
+ if ($this->request->is('post')) {
+ $mobilePhone = $this->MobilePhones->patchEntity($mobilePhone, $this->request->getData());
+ if ($this->MobilePhones->save($mobilePhone)) {
+ $this->Flash->success(__('Il Cellulare è stato aggiunto con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $actor_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'aggiunta del Cellulare'));
+ }
+ $mobilePhoneDescriptions = $this->MobilePhones->MobilePhoneDescriptions->find('list');
+ $this->set(compact('actor', 'mobilePhone', 'mobilePhoneDescriptions'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $mobilePhone = $this->MobilePhones->get($id, contain: ['Deliveries' => ['Actors' => ['ActorTypes']]]);
+
+ $actor = $this->MobilePhones->Deliveries->Actors->get($mobilePhone->delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canEditContactsForActor($actor, 'mobile_phone')) throw new ForbiddenException(__('Non hai i permessi per modificare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $mobilePhone = $this->MobilePhones->patchEntity($mobilePhone, $this->request->getData());
+ if ($this->MobilePhones->save($mobilePhone)) {
+ $this->Flash->success(__('Il Cellulare è stato modificato con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $mobilePhone->delivery->actor_id]);
+ }
+ $this->Flash->error(__('Errore durante la modifica del Cellulare. Riprovare di nuovo'));
+ }
+ $mobilePhoneDescriptions = $this->MobilePhones->MobilePhoneDescriptions->find('list');
+ $this->set(compact('actor', 'mobilePhone', 'mobilePhoneDescriptions'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/NotificationsController.php b/idrocap_wa/src/Controller/NotificationsController.php
new file mode 100644
index 0000000..800a842
--- /dev/null
+++ b/idrocap_wa/src/Controller/NotificationsController.php
@@ -0,0 +1,97 @@
+fetchTable('Notifications')
+ ->find()
+ ->contain('NotificationTypes')
+ ->where(['Notifications.user_id' => $this->logged_user->id, 'Notifications.read_by_user IS NULL'])
+ ->order(['Notifications.created' => 'DESC'])
+ ->all()
+ ->reduce(function ($acc, $user_notification) {
+ $notification_info = json_decode($user_notification->info);
+ $body = strlen($notification_info->body) > 200 ? substr($notification_info->body, 0, 197) . '...' : $notification_info->body;
+ $icon = $user_notification->notification_type->icon ?? 'bell';
+ $time_ago = (new DateTime($user_notification->created))->timeAgoInWords();
+ $acc[] = ['id' => $user_notification->id, 'icon' => $icon, 'title' => $notification_info->title, 'body' => $body, 'time_ago' => $time_ago];
+ return $acc;
+ }, []);
+ }
+
+ /**
+ * readAll
+ *
+ * @return \Cake\Http\Response
+ */
+ public function readAll()
+ {
+ $this->fetchTable('Notifications')->updateAll(['read_by_user' => new DateTime()], ['user_id' => $this->logged_user->id, 'read_by_user IS NULL']);
+ $user_notifications = $this->getUserNotifications();
+ $this->set('user_notifications', $user_notifications);
+ $this->viewBuilder()->setOption('serialize', 'user_notifications')->setLayout('ajax');
+ }
+
+ /**
+ * testAll
+ *
+ * @return \Cake\Http\Response
+ */
+ public function testAll()
+ {
+ $this->request->allowMethod(['post']);
+ $this->sendNotifications(null, 'test_all', []);
+ return $this->redirect('/');
+ }
+
+ /**
+ * view
+ *
+ * @todo recuperare la specializzazione del CO e fare redirect alla view dell'oggetto specifico!
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function view($id)
+ {
+ $notification = $this->fetchTable('Notifications')->get($id);
+ $notification->read_by_user = new DateTime();
+
+ if (!$this->fetchTable('Notifications')->save($notification)) {
+ $this->Flash->error(__('Errore durante la cancellazione della notifica'));
+ }
+
+ $notification_info = json_decode($notification->info);
+ $link = !empty($notification_info->link) ? $notification_info->link : '/';
+ return $this->redirect($link);
+ }
+
+ public function index()
+ {
+ $user_notifications = $this->getUserNotifications();
+ $this->set('user_notifications', $user_notifications);
+ $this->viewBuilder()->setOption('serialize', 'user_notifications')->setLayout('ajax');
+ }
+}
diff --git a/idrocap_wa/src/Controller/OrganisationsController.php b/idrocap_wa/src/Controller/OrganisationsController.php
new file mode 100644
index 0000000..5b156b9
--- /dev/null
+++ b/idrocap_wa/src/Controller/OrganisationsController.php
@@ -0,0 +1,204 @@
+logged_user->hasCapability('configuration.organisations.read')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $organisations = $this->Organisations->find()
+ ->contain(['OrganisationTypes', 'Actors']);
+
+ $this->set('total_organisations', $organisations->count());
+ // applichiamo gli eventuali filtri presenti:
+ $organisations = $this->applyFilters($organisations);
+ $this->set('filtered_organisations', $organisations->count());
+
+ if (!$this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $organisations = $organisations
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_edit = $this->logged_user->organisation_id == $row->id || $this->logged_user->hasCapability('configuration.organisations.edit');
+ $row->can_delete = $this->logged_user->organisation_id == $row->id || $this->logged_user->hasCapability('configuration.organisations.delete');
+ return $row;
+ });
+ });
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['Actors.description', 'acronym', 'OrganisationTypes.description', 'address', 'district', 'cap', 'province'],
+ ];
+
+ $this->set('organisations', $this->getRequest()->is(['json', 'xml', 'csv']) ? $organisations : $this->paginate($organisations));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('configuration.organisations.export_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('Descrizione'),
+ __('Acronimo'),
+ __('Tipologia'),
+ __('Indirizzo'),
+ __('Comune'),
+ __('CAP'),
+ __('Provincia'),
+ __('Recapiti'),
+ ];
+ $extract = [
+ function (array $row) {
+ return $row['actor']['description'];
+ },
+ 'acronym',
+ function (array $row) {
+ return $row['organisation_type']['description'];
+ },
+ 'address',
+ 'district',
+ 'cap',
+ 'province',
+ function (array $row) {
+ return $row['actor']['contacts'];
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("organisations_$timestamp.csv"));
+ }
+ $this->viewBuilder()->setOption('serialize', 'organisations');
+ }
+
+ /**
+ * view
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function view($id = null)
+ {
+ if ($this->logged_user->organisation_id != $id && !$this->logged_user->hasCapability('configuration.organisations.read')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $organisation = $this->Organisations->get($id, contain: ['ControllableObjectInterfaces', 'OrganisationTypes', 'Actors']);
+
+ $organisation->can_handle_contacts = $this->logged_user->canViewContactsForActor($this->Organisations->Actors->get($organisation->actor_id, contain: ['Organisations']));
+ $organisation->can_edit = $this->logged_user->organisation_id == $id || $this->logged_user->hasCapability('configuration.organisations.edit');
+ $organisation->can_delete = $this->logged_user->organisation_id == $id || $this->logged_user->hasCapability('configuration.organisations.delete');
+
+ $organisationTypes = $this->Organisations->OrganisationTypes->find('list')->order(['OrganisationTypes.description' => 'ASC']);
+ $this->set(compact('organisation', 'organisationTypes'));
+ }
+
+ /**
+ * add
+ *
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function add()
+ {
+ if (!$this->logged_user->hasCapability('configuration.organisations.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $organisation = $this->Organisations->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $organisation = $this->Organisations->patchEntity($organisation, $this->request->getData());
+ if ($this->Organisations->save($organisation)) {
+ $this->Flash->success(__('Organizzazione creata con successo.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $errorMessage = $organisation->getError('attachment')[0] ?? '';
+ $this->Flash->error(__('Errore durante la creazione dell\'organizzazione. ' . $errorMessage));
+ }
+ $organisationTypes = $this->Organisations->OrganisationTypes->find('list')->order(['OrganisationTypes.description' => 'ASC']);
+ $this->set(compact('organisation', 'organisationTypes'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ if ($this->logged_user->organisation_id != $id && !$this->logged_user->hasCapability('configuration.organisations.edit')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $organisation = $this->Organisations->get($id, contain: ['Actors', 'ControllableObjectInterfaces', 'OrganisationTypes']);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $organisation = $this->Organisations->patchEntity($organisation, $this->request->getData());
+ if ($this->Organisations->save($organisation)) {
+ $this->Flash->success(__('Organizzazione "{0}" modificata con successo.', $organisation->actor->description));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $errMessage = $organisation->getError('attachment')[0] ?? '';
+ $this->Flash->error(__('Errore durante la modifica dell\'organizzazione "{0}". Riprovare di nuovo. ', $organisation->actor->description) . $errMessage);
+ }
+ $organisationTypes = $this->Organisations->OrganisationTypes->find('list')->order(['OrganisationTypes.description' => 'ASC']);
+ $this->set(compact('organisation', 'organisationTypes'));
+ }
+
+ /**
+ * delete
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function delete($id = null)
+ {
+ if ($this->logged_user->organisation_id != $id && !$this->logged_user->hasCapability('configuration.organisations.delete')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $this->request->allowMethod(['post', 'delete']);
+ $organisation = $this->Organisations->get($id, contain: ['Actors']);
+
+ // controlliamo se il type è cittadini e preveniamo la possibilità di delete.
+ if($organisation->organisation_type_id === 7) {
+ $this->Flash->error(__('Impossibile eliminare l\'organizzazione "{0}".', $organisation->actor->description));
+ return $this->redirect(['action' => 'index']);
+ }
+
+ $are_there_users_in_this_org = $this->fetchTable('Users')->find()->where(['Users.organisation_id' => $id])->count();
+ if ($are_there_users_in_this_org > 0) {
+ $this->Flash->error(__('Impossibile eliminare l\'organizzazione "{0}". Ci sono {1} utenti collegati ad essa.', $organisation->actor->description, $are_there_users_in_this_org));
+ return $this->redirect(['action' => 'index']);
+ }
+
+ if ($this->Organisations->Actors->delete($organisation->actor)) {
+ $this->Flash->success(__('L\'organizzazione "{0}" è stata cancellata con successo', $organisation->actor->description));
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione dell\'organizzazione "{0}". Riprovare di nuovo.', $organisation->actor->description));
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+}
diff --git a/idrocap_wa/src/Controller/PecsController.php b/idrocap_wa/src/Controller/PecsController.php
new file mode 100644
index 0000000..d3bc5f5
--- /dev/null
+++ b/idrocap_wa/src/Controller/PecsController.php
@@ -0,0 +1,78 @@
+Pecs->Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canAddContactsForActor($actor, 'pec')) throw new ForbiddenException(__('Non hai i permessi per aggiungere i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $pec = $this->Pecs->newEntity([
+ 'delivery' => [
+ 'actor_id' => $actor_id,
+ 'delivery_type_id' => 6,
+ ],
+ ], ['validate' => false]);
+
+ if ($this->request->is('post')) {
+ $pec = $this->Pecs->patchEntity($pec, $this->request->getData());
+ if ($this->Pecs->save($pec)) {
+ $this->Flash->success(__('La PEC è stata aggiunta con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $actor_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'aggiunta della PEC'));
+ }
+ $pecDescriptions = $this->Pecs->PecDescriptions->find('list');
+ $this->set(compact('actor', 'pec', 'pecDescriptions'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $pec = $this->Pecs->get($id, contain: ['Deliveries' => ['Actors' => ['ActorTypes']]]);
+
+ $actor = $this->Pecs->Deliveries->Actors->get($pec->delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canEditContactsForActor($actor, 'pec')) throw new ForbiddenException(__('Non hai i permessi per modificare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $pec = $this->Pecs->patchEntity($pec, $this->request->getData());
+ if ($this->Pecs->save($pec)) {
+ $this->Flash->success(__('La PEC è stata modificata con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $pec->delivery->actor_id]);
+ }
+ $this->Flash->error(__('Errore durante la modifica della PEC. Riprovare di nuovo'));
+ }
+ $pecDescriptions = $this->Pecs->PecDescriptions->find('list');
+ $this->set(compact('actor', 'pec', 'pecDescriptions'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/PhonesController.php b/idrocap_wa/src/Controller/PhonesController.php
new file mode 100644
index 0000000..add984c
--- /dev/null
+++ b/idrocap_wa/src/Controller/PhonesController.php
@@ -0,0 +1,78 @@
+Phones->Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canAddContactsForActor($actor, 'phone')) throw new ForbiddenException(__('Non hai i permessi per aggiungere i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $phone = $this->Phones->newEntity([
+ 'delivery' => [
+ 'actor_id' => $actor_id,
+ 'delivery_type_id' => 4,
+ ],
+ ], ['validate' => false]);
+
+ if ($this->request->is('post')) {
+ $phone = $this->Phones->patchEntity($phone, $this->request->getData());
+ if ($this->Phones->save($phone)) {
+ $this->Flash->success(__('Il Telefono è stato aggiunto con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $actor_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'aggiunta del Telefono'));
+ }
+ $phoneDescriptions = $this->Phones->PhoneDescriptions->find('list');
+ $this->set(compact('actor', 'phone', 'phoneDescriptions'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $phone = $this->Phones->get($id, contain: ['Deliveries' => ['Actors' => ['ActorTypes']]]);
+
+ $actor = $this->Phones->Deliveries->Actors->get($phone->delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canEditContactsForActor($actor, 'phone')) throw new ForbiddenException(__('Non hai i permessi per modificare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $phone = $this->Phones->patchEntity($phone, $this->request->getData());
+ if ($this->Phones->save($phone)) {
+ $this->Flash->success(__('Il Telefono è stato modificato con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $phone->delivery->actor_id]);
+ }
+ $this->Flash->error(__('Errore durante la modifica del Telefono. Riprovare di nuovo'));
+ }
+ $phoneDescriptions = $this->Phones->PhoneDescriptions->find('list');
+ $this->set(compact('actor', 'phone', 'phoneDescriptions'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/PrivacyController.php b/idrocap_wa/src/Controller/PrivacyController.php
new file mode 100644
index 0000000..6ff81f6
--- /dev/null
+++ b/idrocap_wa/src/Controller/PrivacyController.php
@@ -0,0 +1,174 @@
+Authentication->allowUnauthenticated(['view_public']);
+ }
+
+ /**
+ * Index method
+ *
+ * @return \Cake\Http\Response|null|void Renders view
+ */
+ public function view_public()
+ {
+ $privacy = $this->Privacy->findPrivacy();
+ $this->viewBuilder()->setLayout('view_public');
+ $this->set(compact('privacy'));
+ }
+
+ /**
+ * View method
+ *
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view()
+ {
+ $breadcrumbs = $this->retrieveBreadcrumbs('view');
+ $privacy = $this->Privacy->findPrivacy();
+ $this->set(compact('privacy', 'breadcrumbs'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit()
+ {
+ if (!$this->logged_user->hasCapability(['configuration.privacy.edit'])) {
+ throw new ForbiddenException(__('Non hai i permessi necessari'));
+ }
+
+ $breadcrumbs = $this->retrieveBreadcrumbs('edit');
+ $privacy = $this->Privacy->findPrivacy();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $privacy = $this->Privacy->patchEntity($privacy, $this->request->getData());
+ try {
+ $connection = ConnectionManager::get('default');
+ $connection->begin();
+ if ($this->Privacy->save($privacy)) {
+ $this->Privacy->PrivacyUsers->deleteAll(['privacy_id' => $privacy->id]);
+ $connection->commit();
+ $this->Flash->success(__('La privacy è stata salvata con successo.'));
+ } else {
+ $connection->rollback();
+ $this->Flash->error(__('La privacy non è stata salvata. Riprova, per favore.'));
+ }
+ } catch(Exception $e) {
+ $connection->rollback();
+ $this->Flash->error(__('Errore. La privacy non è stata salvata.'));
+ }
+ }
+ $this->set(compact('privacy', 'breadcrumbs'));
+ }
+
+ public function accept_privacy()
+ {
+ $hasConsent = $this->Privacy->PrivacyUsers->hasConsent($this->logged_user->id);
+ if ($hasConsent) {
+ $this->Flash->error(__('Hai già accettato la privacy.'));
+ return $this->redirect(['controller' => 'Dashboard', 'action' => 'index']);
+ }
+ $breadcrumbs = $this->retrieveBreadcrumbs('accept_privacy');
+ $privacy = $this->Privacy->findPrivacy();
+ if (!$privacy) {
+ $this->Flash->error(__('La privacy non è disponibile.'));
+ return $this->redirect(['controller' => 'Dashboard', 'action' => 'index']);
+ }
+
+ if ($this->request->is(['post', 'put', 'patch'])) {
+ if ($this->Privacy->PrivacyUsers->saveConsent($this->logged_user->id, $privacy->id)) {
+ $this->Flash->success(__('La privacy è stata accettata con successo.'));
+ $this->redirect(['controller' => 'Dashboard', 'action' => 'index']);
+ } else {
+ $this->Flash->error(__('Errore. La privacy non è stata accettata.'));
+ }
+ }
+ $this->set(compact('privacy', 'breadcrumbs'));
+ }
+
+ private function retrieveBreadcrumbs(string $action): array
+ {
+ $breadcrumbs = [
+ 'edit' => [
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Privacy'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Modifica privacy'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ],
+ 'view' =>
+ [
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Privacy'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Visualizza privacy'),
+ 'icon' => 'fa fa-info',
+ ],
+ ],
+ 'accept_privacy' => [
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Privacy'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Visualizzazione privacy'),
+ 'icon' => 'fa fa-info',
+ ],
+ ]
+ ];
+
+ return $breadcrumbs[$action] ?? [];
+ }
+}
diff --git a/idrocap_wa/src/Controller/TagsController.php b/idrocap_wa/src/Controller/TagsController.php
new file mode 100644
index 0000000..17905dc
--- /dev/null
+++ b/idrocap_wa/src/Controller/TagsController.php
@@ -0,0 +1,91 @@
+logged_user->hasCapability(['configuration.tags.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $tags = $this->Tags->find()->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_edit = $this->logged_user->hasCapability('configuration.tags.edit');
+ $row->can_view = $this->logged_user->hasCapability('configuration.tags.disable');
+ return $row;
+ });
+ });
+ $tags = $this->paginate($tags);
+ $this->set(compact('tags'));
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Tag id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['configuration.tags.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $tag = $this->Tags->get($id);
+ $this->set(compact('tag'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add()
+ {
+ if (!$this->logged_user->hasCapability(['configuration.tags.add'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $tag = $this->Tags->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $tag = $this->Tags->patchEntity($tag, $this->request->getData());
+ if ($this->Tags->save($tag, ['associated' => ['ControllableObjects']])) {
+ $this->Flash->success(__('Il nuovo tag è stato creato'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore nella creazione del nuovo tag.') . json_encode($tag->getErrors()));
+ }
+ $this->set(compact('tag'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Tag id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['configuration.tags.edit'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $tag = $this->Tags->find()->contain(['ControllableObjects'])->where(['Tags.id' => $id])->first();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $tag = $this->Tags->patchEntity($tag, $this->request->getData(), ['filename_as_tag' => true, 'associated' => ['ControllableObjects' => ['associated' => ['Attachments']]]]);
+ if ($this->Tags->save($tag)) {
+ $this->Flash->success(__('Il tag è stato salvato.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio del tag.') . json_encode($tag->getErrors()));
+ }
+ $this->set(compact('tag'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/TelegramChatsController.php b/idrocap_wa/src/Controller/TelegramChatsController.php
new file mode 100644
index 0000000..01ac143
--- /dev/null
+++ b/idrocap_wa/src/Controller/TelegramChatsController.php
@@ -0,0 +1,76 @@
+TelegramChats->Deliveries->Actors->get($actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canAddContactsForActor($actor, 'telegram_chat')) throw new ForbiddenException(__('Non hai i permessi per aggiungere i recapiti di questo tipo per {0}', $actor_type_description));
+
+ $telegram_chat = $this->TelegramChats->newEntity([
+ 'delivery' => [
+ 'actor_id' => $actor_id,
+ 'delivery_type_id' => 5,
+ ],
+ ], ['validate' => false]);
+
+ if ($this->request->is('post')) {
+ $telegram_chat = $this->TelegramChats->patchEntity($telegram_chat, $this->request->getData());
+ if ($this->TelegramChats->save($telegram_chat)) {
+ $this->Flash->success(__('La Chat Telegram è stata aggiunta con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $actor_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'aggiunta della Chat Telegram'));
+ }
+ $this->set(compact('actor', 'telegram_chat'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ $telegram_chat = $this->TelegramChats->get($id, contain: ['Deliveries' => ['Actors' => ['ActorTypes']]]);
+
+ $actor = $this->TelegramChats->Deliveries->Actors->get($telegram_chat->delivery->actor_id, contain: ['ActorTypes', 'Organisations', 'Users']);
+ // se arriviamo in questa pagina con un actor_id non di tipo "organizzazione" o "utente":
+ if (!in_array($actor->actor_type_id, [1,5])) throw new ForbiddenException(__('Gestione recapiti non prevista per questa tipologia di oggetto'));
+ $actor_type_description = $actor->actor_type_id == 1 ? __('questa organizzazione') : __('questo utente');
+ if (!$this->logged_user->canEditContactsForActor($actor, 'telegram_chat')) throw new ForbiddenException(__('Non hai i permessi per modificare i recapiti di questo tipo per {0}', $actor_type_description));
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $telegram_chat = $this->TelegramChats->patchEntity($telegram_chat, $this->request->getData());
+ if ($this->TelegramChats->save($telegram_chat)) {
+ $this->Flash->success(__('La Chat Telegram è stata modificata con successo.'));
+
+ return $this->redirect(['controller' => 'Deliveries', 'action' => 'index', $telegram_chat->delivery->actor_id]);
+ }
+ $this->Flash->error(__('Errore durante la modifica della Chat Telegram. Riprovare di nuovo'));
+ }
+ $this->set(compact('actor', 'telegram_chat'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/UsersController.php b/idrocap_wa/src/Controller/UsersController.php
new file mode 100644
index 0000000..ec1b375
--- /dev/null
+++ b/idrocap_wa/src/Controller/UsersController.php
@@ -0,0 +1,624 @@
+Authentication->allowUnauthenticated(['logout', 'login', 'login_oidc', 'login_oidc_authenticated', 'passwordRecovery', 'chooseNewPassword', 'oneTimePassword', 'add_citizen', 'verify_citizen']);
+ }
+
+ public function viewClasses(): array
+ {
+ return [JsonView::class, CustomCsvView::class];
+ }
+
+ public function login_oidc()
+ {
+ OpenIdConnectClient::authorize(
+ Configure::read('App.oidc.authUrl'),
+ Configure::read('App.oidc.clientId'),
+ Configure::read('App.oidc.scopes'),
+ Configure::read('App.oidc.redirectUri')
+ );
+ }
+
+ public function login_oidc_authenticated()
+ {
+ try {
+ $access_token = OpenIdConnectClient::get_access_token(
+ Configure::read('App.oidc.tokenUrl'),
+ Configure::read('App.oidc.issuer'),
+ Configure::read('App.oidc.clientId'),
+ Configure::read('App.oidc.clientSecret'),
+ Configure::read('App.oidc.redirectUri')
+ );
+ $userinfo = OpenIdConnectClient::get_user_info(Configure::read('App.oidc.userinfoUrl'), Configure::read('App.oidc.userinfo_claim_key'), $access_token);
+ $userinfo_claim_value = $userinfo[Configure::read('App.oidc.userinfo_claim_key')];
+ $user = $this->Users->find()->where(['Users.' . Configure::read('App.oidc.usermodel_matching_attribute') => $userinfo_claim_value]);
+ if ($user->count() > 1) throw new \Exception(__('Non è stato possibile identificare in maniera univoca l\'utente in base all\'attributo \' {0} \' ricevuto dal provider', Configure::read('App.oidc.userinfo_claim_key')));
+ $user = $user->first();
+ $isUserVerified = $user?->is_verified ?? false;
+ if ($user && $isUserVerified) {
+ $this->Authentication->setIdentity($user);
+ } else {
+ if (!$user) {
+ $citizenRegistrationDTO = (new \App\WGS\Utils\Dto\Users\CitizenRegistrationDTO())
+ ->setShowAlert(true)
+ // attenzione!!!!!! se $userinfo_claim_value NON COINCIDE CON IL CF, NON FUNZIONA + !!!!!!!!!!!!!!!!!!!!!!!!!!
+ ->setFiscalCode($userinfo[Configure::read('App.oidc.userinfo_claim_key')] ?? '')
+ ->setName($userinfo['given_name'] ?? '')
+ ->setSurname($userinfo['family_name'] ?? '')
+ ->setGender($userinfo['gender'] ?? '')
+ ->setBirthdate($userinfo['birthdate'] ?? '');
+ $this->request->getSession()->write('showCitizenRegistration', $citizenRegistrationDTO);
+ $errorMessage = __('Errore durante l\'autenticazione mediante {0} "Utente non trovato". Riprovare di nuovo o utilizzare le credenziali di accesso', Configure::read('App.oidc.idp_name', 'OpenID Connect'));
+ } else if ($user && !$isUserVerified) {
+ $errorMessage = __('Utente non verificato. Controlla la tua email per completare la verifica.');
+ }
+ $this->Flash->error($errorMessage);
+ }
+ return $this->redirect('/');
+ } catch (\Exception $e) {
+ $this->Flash->error(__('Errore durante l\'autenticazione mediante {0} "{1}". Riprovare di nuovo o utilizzare le credenziali di accesso', Configure::read('App.oidc.idp_name', 'OpenID Connect'), $e->getMessage()));
+ return $this->redirect('/');
+ }
+ }
+
+ /**
+ * index
+ *
+ * @throws ForbiddenException
+ * @return \Cake\Http\Response
+ */
+ public function index()
+ {
+ if (!$this->logged_user->hasCapability(['configuration.users.read', 'configuration.users.read_foo'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $users = $this->Users->find()
+ ->contain(['Actors', 'Organisations' => ['Actors', 'OrganisationActors']]);
+
+ if (!$this->logged_user->hasCapability('configuration.users.read')) {
+ $users = $users->where(['Users.organisation_id' => $this->logged_user->organisation_id]);
+ }
+
+ $this->set('total_users', $users->count());
+ // applichiamo gli eventuali filtri presenti:
+ $users = $this->applyFilters($users);
+ $this->set('filtered_users', $users->count());
+
+ if (!$this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $users = $users
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_edit = $this->logged_user->id == $row->id || ($this->logged_user->organisation_id == $row->organisation_id && $this->logged_user->hasCapability('configuration.users.edit_foo')) || $this->logged_user->hasCapability('configuration.users.edit');
+ $row->can_delete = $this->logged_user->id != $row->id && (($this->logged_user->organisation_id == $row->organisation_id && $this->logged_user->hasCapability('configuration.users.delete_foo')) || $this->logged_user->hasCapability('configuration.users.delete'));
+ return $row;
+ });
+ });
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['surname', 'name', 'username', 'OrganisationActors.description'],
+ ];
+
+ $this->set('users', $this->getRequest()->is(['json', 'xml', 'csv']) ? $users : $this->paginate($users));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('configuration.users.export_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('Cognome'),
+ __('Nome'),
+ __('Username'),
+ __('Recapiti'),
+ __('Profili'),
+ __('Organizzazione'),
+ ];
+ $extract = [
+ 'surname',
+ 'name',
+ 'username',
+ function (array $row) {
+ return $row['actor']['contacts'];
+ },
+ 'profiles',
+ function (array $row) {
+ return $row['organisation']['organisation_actor']['description'];
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("users_$timestamp.csv"));
+ }
+ $this->viewBuilder()->setOption('serialize', 'users');
+ }
+
+ /**
+ * view
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function view($id = null)
+ {
+ if ($this->logged_user->id != $id && !$this->logged_user->hasCapability(['configuration.users.read', 'configuration.users.read_foo'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $user = $this->Users->get($id, contain: ['Actors', 'Languages', 'Organisations' => ['Actors']]);
+
+ if (!$this->logged_user->hasCapability('configuration.users.read') && $this->logged_user->organisation_id != $user->organisation_id && $this->logged_user->id != $user->id) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $user->can_handle_contacts = $this->logged_user->canViewContactsForActor($this->Users->Actors->get($user->actor_id, contain: ['Users']));
+ $user->can_edit = $this->logged_user->hasCapability('configuration.users.edit') || $this->logged_user->organisation_id == $user->organisation_id && $this->logged_user->hasCapability('configuration.users.edit_foo') || $this->logged_user->id == $user->id;
+ $user->can_delete = $this->logged_user->id != $user->id && (($this->logged_user->organisation_id == $user->organisation_id && $this->logged_user->hasCapability('configuration.users.delete_foo')) || $this->logged_user->hasCapability('configuration.users.delete'));
+
+ $this->set(compact('user'));
+ $this->viewBuilder()->setOption('serialize', 'user');
+ }
+
+ /**
+ * add
+ *
+ * @return \Cake\Http\Response
+ */
+ public function add()
+ {
+ if (!$this->logged_user->hasCapability(['configuration.users.add', 'configuration.users.add_foo'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $can_view_profiles = $this->logged_user->hasCapability('configuration.groups.read');
+ $can_handle_profiles = $can_view_profiles && ($this->logged_user->hasCapability('configuration.users.profiles') || $this->fetchTable('Users')->getAssociableUserGroups()->count() > 0);
+
+ $user = $this->Users->newEmptyEntity();
+
+ $default_profiles = $this->Users->Groups->find()
+ ->contain(['Actors'])
+ ->where(['Groups.is_default' => 1])
+ ->all()
+ ->toArray();
+
+ $user['groups'] = $default_profiles;
+
+ if ($this->request->is('post')) {
+ $user = $this->Users->patchEntity($user, $this->request->getData());
+
+ if (!$can_handle_profiles) $user['groups'] = $default_profiles;
+
+ if ($this->Users->save($user)) {
+ $this->Flash->success(__('Utente creato con successo.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante la creazione dell\'utente'));
+ }
+ $organisations = $this->Users->Organisations->find('list')->contain(['Actors'])->order(['Actors.description' => 'ASC']);
+ if (!$this->logged_user->hasCapability('configuration.users.add')) $organisations = $organisations->where(['Organisations.id' => $this->logged_user->organisation_id]);
+ $languages = $this->Users->Languages->find('list');
+ $groups = $this->fetchTable('Users')->getAssociableUserGroups(as_list: true)->order(['Groups.description' => 'ASC']);
+ $this->set('today', DateTime::now());
+ $this->set(compact('user', 'organisations', 'languages', 'groups', 'can_view_profiles', 'can_handle_profiles'));
+ }
+
+ /**
+ * edit
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function edit($id = null)
+ {
+ if ($this->logged_user->id != $id && !$this->logged_user->hasCapability(['configuration.users.edit', 'configuration.users.edit_foo'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $can_view_profiles = $this->logged_user->hasCapability('configuration.groups.read');
+ $can_handle_profiles = $can_view_profiles && ($this->logged_user->hasCapability('configuration.users.profiles') || $this->fetchTable('Users')->getAssociableUserGroups()->count() > 0);
+
+ $user = $this->Users->get($id, contain: ['Actors', 'Groups', 'Languages', 'Organisations' => ['Actors']]);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $user->setAccess('groups', $can_handle_profiles);
+ $user = $this->Users->patchEntity($user, $this->request->getData());
+
+ if ($this->Users->save($user)) {
+ $this->Flash->success(__('Utente "{0}" modificato con successo.', $user->actor->description));
+
+ return $this->logged_user->hasCapability(['configuration.users.read', 'configuration.users.read_foo']) ? $this->redirect(['action' => 'index']) : $this->redirect('/');
+ }
+ $this->Flash->error(__('Errore durante la modifica dell\'utente "{0}". Riprovare di nuovo.', $user->actor->description));
+ }
+ $organisations = $this->Users->Organisations->find('list')->contain(['Actors'])->order(['Actors.description' => 'ASC']);
+ if (!$this->logged_user->hasCapability('configuration.users.edit')) $organisations = $organisations->where(['Organisations.id' => $this->logged_user->organisation_id]);
+ $languages = $this->Users->Languages->find('list');
+ $groups = $this->fetchTable('Users')->getAssociableUserGroups(as_list: true)->order(['Groups.description' => 'ASC']);
+ $this->set('today', DateTime::now());
+ $this->set(compact('user', 'organisations', 'languages', 'groups', 'can_view_profiles', 'can_handle_profiles'));
+ }
+
+ /**
+ * delete
+ *
+ * @param Int $id
+ * @return \Cake\Http\Response
+ */
+ public function delete($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['configuration.users.delete', 'configuration.users.delete_foo'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $this->request->allowMethod(['post', 'delete']);
+ $user = $this->Users->get($id, contain: ['Actors']);
+
+ if ($this->logged_user->id == $user->id || ($this->logged_user->organisation_id != $user->organisation_id && !$this->logged_user->hasCapability('configuration.users.delete'))) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ if ($this->Users->Actors->delete($user->actor)) {
+ $this->Flash->success(__('L\'utente "{0}" è stato cancellato con successo', $user->actor->description));
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione dell\'utente "{0}". Riprovare di nuovo.', $user->actor->description));
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+
+ /**
+ * login
+ *
+ * @return \Cake\Http\Response
+ */
+ public function login()
+ {
+ $result = $this->Authentication->getResult();
+ // If the user is logged in send them away.
+ if ($result->isValid()) {
+ $user = $this->Authentication->getIdentity();
+ $user->timezone = $this->request->getData('user_timezone', Configure::read('App.defaultUserTimezone'));
+ // se per qualche motivo il form restituisce "" stringa vuota per il timezone, impostiamo invece il default!
+ if (empty($user->timezone)) $user->timezone = Configure::read('App.defaultUserTimezone');
+ $this->fetchTable('Users')->save($user);
+ $target = $this->Authentication->getLoginRedirect() ?? '/';
+ $this->request->getSession()->write("oidc", null);
+ return $this->redirect($target);
+ }
+
+ if ($this->request->is('post')) {
+ $authError = $this->request->getSession()->read('AuthError');
+ if ($authError) {
+ $this->Flash->error($authError);
+ $this->request->getSession()->delete('AuthError');
+ } else {
+ $this->Flash->error('username e/o password errati');
+ }
+ }
+ $login_citizen_registration = $this->request->getSession()->read('showCitizenRegistration');
+ $this->set(compact('login_citizen_registration'));
+ $this->viewBuilder()->setLayout('CakeLte.login');
+ $this->set('login_layout_link_label', __('Ho dimenticato la mia password'));
+ $this->set('login_layout_link_action', 'passwordRecovery');
+ $this->set('login_layout_privacy_label', __('Visualizza Privacy Policy'));
+ $this->set('login_layout_privacy_link', 'view_public');
+ if (isset($login_citizen_registration) && $login_citizen_registration->isShowAlert()) {
+ $login_citizen_registration_copy = clone $login_citizen_registration;
+ $login_citizen_registration_copy->setShowAlert(false);
+ $this->request->getSession()->write('showCitizenRegistration', $login_citizen_registration_copy);
+ }
+ }
+
+ /**
+ * logout
+ *
+ * @return \Cake\Http\Response
+ */
+ public function logout()
+ {
+ $this->Authentication->logout();
+
+ if ($this->request->getSession()->read('oidc')) {
+ OpenIdConnectClient::logout(
+ Configure::read('App.oidc.logoutUrl'),
+ Configure::read('App.oidc.clientId'),
+ Configure::read('App.oidc.postLogoutRedirectUri')
+ );
+ }
+
+ $this->Flash->success(__('Logout eseguito con successo.'));
+ return $this->redirect(['controller' => 'Users', 'action' => 'login']);
+ }
+
+ /**
+ * executePasswordRecovery
+ *
+ * @param \App\Model\Entity\User $user
+ * @param String $email
+ * @param String|Null $password_recovery_token
+ * @return String|Null
+ */
+ private function executePasswordRecovery(\App\Model\Entity\User $user, String $email, String|Null $password_recovery_token = null): String|Null
+ {
+ $user->password_recovery_token = $password_recovery_token ?? sha1($this->gen_random_code(40));
+
+ if (!$this->Users->save($user)) return null;
+
+ $options = [];
+ $options['user_id'] = $user->id;
+ $options['username'] = $user->username;
+ $options['email'] = $email;
+ $options['type'] = 'users';
+ $options['password_recovery_token'] = $user->password_recovery_token;
+ $this->sendNotifications(null, 'password_recovery', $options);
+ return $user->password_recovery_token;
+ }
+
+ /**
+ * passwordRecovery
+ *
+ * @return \Cake\Http\Response
+ */
+ public function passwordRecovery()
+ {
+ if ($this->request->is('post'))
+ {
+ if (empty($this->request->getData('email'))) {
+ $this->Flash->error(__('Inserire un indirizzo email valido!'));
+ return $this->redirect(['action' => 'passwordRecovery']);
+ }
+
+ $email = $this->Users->Actors->Deliveries->Emails->find()
+ ->contain(['Deliveries' => ['Actors' => ['Users']]])
+ ->where(['Emails.value' => $this->request->getData('email')])
+ ->first();
+
+ if (isset($email->delivery->actor->user))
+ {
+ $this->executePasswordRecovery($email->delivery->actor->user, $this->request->getData('email'));
+ $this->Flash->success(__('A breve riceverai un\'email all\'indirizzo "{0}" con le istruzioni per eseguire il reset della password per il tuo account con username "{1}".', $this->request->getData('email'), $email->delivery->actor->user->username));
+ return $this->redirect(['action' => 'login']);
+ }
+ else
+ {
+ $this->Flash->error(__('L\'indirizzo email inserito non risulta presente'));
+ return $this->redirect(['action' => 'passwordRecovery']);
+ }
+ }
+ $this->viewBuilder()->setLayout('CakeLte.login');
+ $this->set('login_layout_link_label', __('Ritorna al login'));
+ $this->set('login_layout_link_action', 'login');
+ $this->set('login_layout_privacy_label', __('Visualizza Privacy Policy'));
+ $this->set('login_layout_privacy_link', 'view_public');
+ }
+
+ /**
+ * chooseNewPassword
+ *
+ * @param String $token
+ * @return \Cake\Http\Response
+ */
+ public function chooseNewPassword($token)
+ {
+ $user = $this->Users->find()->contain(['Actors', 'Organisations'])->where(['Users.password_recovery_token' => $token])->first();
+
+ if(!$user)
+ {
+ $this->Flash->error(__('Impossibile completare la procedura di recupero password.'));
+ return $this->redirect(['action' => 'login']);
+ }
+
+ if ($this->request->is('post'))
+ {
+ if (!empty($this->request->getData('new_password')) && !empty($this->request->getData('confirm_new_password')) && $this->request->getData('new_password') == $this->request->getData('confirm_new_password')) {
+ $user_data = $user->toArray();
+ $user_data['password'] = $this->request->getData('new_password');
+ $user = $this->Users->patchEntity($user, $user_data, ['validate' => false]);
+ if (count($user->getError('password')) > 0) {
+ $this->Flash->error(implode(" - ", $user->getError('password')));
+ return $this->redirect(['action' => 'chooseNewPassword', $token]);
+ }
+
+ $user->password_recovery_token = null;
+ $user->last_change_password = new \DateTime();
+ $user->password_recovery_counter = $user->password_recovery_counter+1;
+
+ if ($this->Users->save($user)) {
+ $this->Flash->success('Password modificata con successo');
+ return $this->redirect(['action' => 'login']);
+ } else {
+ $this->Flash->error(__('Impossibile cambiare la password'));
+ }
+
+ } else {
+ $this->Flash->error(__('La nuova password non è valida e/o le 2 password non coincidono'));
+ }
+ }
+
+ $this->viewBuilder()->setLayout('CakeLte.login');
+ $this->set('login_layout_link_label', __('Ritorna al login'));
+ $this->set('login_layout_link_action', 'login');
+ $this->set('login_layout_privacy_label', __('Visualizza Privacy Policy'));
+ $this->set('login_layout_privacy_link', 'view_public');
+ }
+
+ public function oneTimePassword(String $otp) {
+ $users = $this->fetchTable('Users')->find()->where(['Users.otp' => $otp]);
+ if ($users->count() != 1) {
+ $this->Flash->error(__('Codice OTP non valido o già utilizzato. Effettua il login.'));
+ return $this->redirect(['action' => 'login']);
+ }
+
+ $user = $users->first();
+
+ // controllo che otp_expires sia un datetime valido e non scaduto:
+ if ($user->otp_expires === null || !is_object($user->otp_expires) || get_class($user->otp_expires) != "Cake\I18n\DateTime" || !$user->otp_expires->isWithinNext(Configure::read('App.oneTimePasswordExpirationHours', 1) . ' hours')) {
+ $user->otp = null;
+ $user->otp_redirect_url = null;
+ $user->otp_expires = null;
+ $this->fetchTable('Users')->save($user);
+ $this->Flash->error(__('Codice OTP scaduto. Effettua il login.'));
+ return $this->redirect(['action' => 'login']);
+ }
+
+ if ($this->request->is('post'))
+ {
+ $redirect_url = $user->otp_redirect_url ?? '/';
+ $user->sys_admin = false;
+ $user->passepartout = false;
+ $user->otp = null;
+ $user->otp_redirect_url = null;
+ $user->otp_expires = null;
+ $this->fetchTable('Users')->save($user);
+ $this->getRequest()->getSession()->write('Auth', $user);
+ return $this->redirect($redirect_url);
+ }
+ $this->viewBuilder()->setLayout('CakeLte.login');
+ $this->set('login_layout_link_label', __('Ritorna al login'));
+ $this->set('login_layout_link_action', 'login');
+ $this->set('login_layout_privacy_label', __('Visualizza Privacy Policy'));
+ $this->set('login_layout_privacy_link', 'view_public');
+ }
+
+ /**
+ * getPhoto
+ *
+ * @param String $file_name
+ * @return \Cake\Http\Response
+ */
+ public function getPhoto($file_name)
+ {
+ $photo_owner = $this->fetchTable('Users')->find()->where(['Users.photo' => $file_name])->first();
+
+ if (!$photo_owner) throw new NotFoundException(__('Foto utente non trovata!'));
+
+ if ($this->logged_user->id != $photo_owner->id) {
+ if (!$this->logged_user->hasCapability(['configuration.users.read', 'configuration.users.read_foo'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ if (!$this->logged_user->hasCapability(['configuration.users.read']) && $this->logged_user->organisation_id != $photo_owner->organisation_id) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ }
+
+ $mimetype = "image/jpeg";
+ $path = Configure::read('App.userPhotoPath') . "/" . $file_name;
+ $output = \App\WGS\FileStorage\FileStorageFactory::create()->getFile($path);
+ $this->response = $this->response
+ ->withType($mimetype)
+ ->withStringBody($output);
+
+ return $this->response;
+ }
+
+ /**
+ * deleteUserPhoto
+ *
+ * @param Int $user_id
+ * @return \Cake\Http\Response
+ */
+ public function deleteUserPhoto($user_id)
+ {
+ $user = $this->Users->get($user_id);
+ $user->photo = null;
+ if (!$this->Users->save($user)) {
+ $this->Flash->error(__('Errore durante l\'eliminazione della foto utente!'));
+ } else {
+ $this->Flash->success(__('Foto utente eliminata con successo'));
+ }
+ return $this->redirect(['action' => 'view', $user_id]);
+ }
+
+ /**
+ * add_citizen
+ * @return \Cake\Http\Response
+ */
+ public function add_citizen()
+ {
+ $user = $this->Users->newEmptyEntity();
+ $citizenRegistrationData = $this->request->getSession()->read('showCitizenRegistration');
+ if ($this->request->is('post') || $this->request->is('put')) {
+ $data = $this->request->getData();
+ $taxCode = $data['tax_code'] ?? null;
+ $name = $data['name'] ?? null;
+ $surname = $data['surname'] ?? null;
+ $birthday = $data['birthday'] ?? null;
+ $gender = $data['gender'] ?? null;
+ if ($taxCode && $citizenRegistrationData && $citizenRegistrationData?->getFiscalCode() !== '' && $citizenRegistrationData->getFiscalCode() != $taxCode) {
+ $this->Flash->error(__('Il codice fiscale inserito non corrisponde a quello fornito in fase di autenticazione. Riprovare.'));
+ }
+ elseif ($name && $citizenRegistrationData && $citizenRegistrationData?->getName() !== '' && $citizenRegistrationData->getName() != $name) {
+ $this->Flash->error(__('Il nome inserito non corrisponde a quello fornito in fase di autenticazione. Riprovare.'));
+ }
+ elseif ($surname && $citizenRegistrationData && $citizenRegistrationData?->getSurname() !== '' && $citizenRegistrationData->getSurname() != $surname) {
+ $this->Flash->error(__('Il cognome inserito non corrisponde a quello fornito in fase di autenticazione. Riprovare.'));
+ }
+ elseif ($birthday && $citizenRegistrationData && $citizenRegistrationData?->getBirthdate() !== '' && $citizenRegistrationData->getBirthdate() != $birthday) {
+ $this->Flash->error(__('La data di nascita inserita non corrisponde a quella fornita in fase di autenticazione. Riprovare.'));
+ }
+ elseif ($gender && $citizenRegistrationData && $citizenRegistrationData?->getGender() !== '' && $citizenRegistrationData->getGender() != $gender) {
+ $this->Flash->error(__('Il sesso inserito non corrisponde a quello fornito in fase di autenticazione. Riprovare.'));
+ }
+ else {
+ $newCitizen = $this->Users->createCitizen($user, $data);
+ if ($newCitizen) {
+ $emails = $newCitizen?->getEmailsWithNotifications() ?? [];
+ $notificationEmail = $emails[0] ?? null;
+ $successMessage = 'Utente creato con successo.';
+ if ($notificationEmail) {
+ $options = [
+ 'user_id' => $newCitizen->id,
+ 'username' => $newCitizen->username,
+ 'email' => $notificationEmail->value,
+ 'type' => 'users',
+ 'verification_token' => $newCitizen->email_verification_code,
+ ];
+ $this->sendNotifications(null, 'verify-citizen-registration', $options);
+ $successMessage = 'Utente creato con successo. Riceverai un\'email per confermare la registrazione.';
+ }
+ $this->request->getSession()->delete('showCitizenRegistration');
+ $this->Flash->success(__($successMessage));
+ return $this->redirect(['action' => 'login']);
+ } else {
+ $this->Flash->error(__('Errore durante la creazione dell\'utente'));
+ }
+ }
+ }
+
+ $languages = $this->Users->Languages->find('list');
+ $this->viewBuilder()->setLayout('CakeLte.login');
+ $this->set([
+ 'today' => DateTime::now(),
+ 'hideLogin' => true,
+ 'user' => $user,
+ 'languages' => $languages,
+ 'citizenRegistrationData' => $citizenRegistrationData,
+ ]);
+ }
+
+
+ /**
+ * verify citizen
+ * @param string|null $token
+ * @return \Cake\Http\Response
+ */
+ public function verify_citizen(string|null $token)
+ {
+ $token = $token ?? '';
+ if ($this->Users->verifyCitizen($token)) {
+ $this->Flash->success(__('Utente verificato con successo.'));
+ return $this->redirect(['action' => 'login']);
+ }
+
+ $this->Flash->error(__('Errore durante la verifica, si prega di riprovare.'));
+ return $this->redirect(['action' => 'login']);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingArticlesController.php b/idrocap_wa/src/Controller/WaterDrawingArticlesController.php
new file mode 100644
index 0000000..0f51528
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingArticlesController.php
@@ -0,0 +1,124 @@
+WaterDrawingArticles->find()->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_edit = $this->logged_user->hasCapability('configuration.water_drawing_articles.edit');
+ $row->can_delete = $this->logged_user->hasCapability('configuration.water_drawing_articles.delete');
+ $row->can_disable = $this->logged_user->hasCapability('configuration.water_drawing_articles.disable');
+ return $row;
+ });
+ });
+ $waterDrawingArticles = $this->paginate($waterDrawingArticles);
+
+ $this->set(compact('waterDrawingArticles'));
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Water Drawing Article id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ $waterDrawingArticle = $this->WaterDrawingArticles->get($id, contain: []);
+ $waterDrawingArticle->can_edit = $this->logged_user->hasCapability('configuration.water_drawing_articles.edit');
+ $waterDrawingArticle->can_delete = $this->logged_user->hasCapability('configuration.water_drawing_articles.delete');
+ $waterDrawingArticle->can_disable = $this->logged_user->hasCapability('configuration.water_drawing_articles.disable');
+ $this->set(compact('waterDrawingArticle'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add()
+ {
+ $waterDrawingArticle = $this->WaterDrawingArticles->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $waterDrawingArticle = $this->WaterDrawingArticles->patchEntity($waterDrawingArticle, $this->request->getData());
+ if ($this->WaterDrawingArticles->save($waterDrawingArticle)) {
+ $this->Flash->success(__('Articolo di legge salvato con successo.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio dell\'articolo di legge. Riprovare di nuovo.'));
+ }
+ $this->set(compact('waterDrawingArticle'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Water Drawing Article id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ $waterDrawingArticle = $this->WaterDrawingArticles->get($id, contain: []);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingArticle = $this->WaterDrawingArticles->patchEntity($waterDrawingArticle, $this->request->getData());
+ if ($this->WaterDrawingArticles->save($waterDrawingArticle)) {
+ $this->Flash->success(__('Articolo di legge modificato con successo.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore durante la modifica dell\'articolo di legge. Riprovare di nuovo.'));
+ }
+ $this->set(compact('waterDrawingArticle'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Article id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingArticle = $this->WaterDrawingArticles->get($id);
+ if ($this->WaterDrawingArticles->delete($waterDrawingArticle)) {
+ $this->Flash->success(__('L\'articolo di legge è stato cancellato con successo.'));
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione dell\'articolo di legge. Riprovare di nuovo.'));
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+
+ public function change_status($id){
+ $waterDrawingArticle = $this->WaterDrawingArticles->get($id);
+ $waterDrawingArticle = $this->WaterDrawingArticles->patchEntity($waterDrawingArticle, [
+ 'disable' => $waterDrawingArticle->disable ? false : true
+ ]);
+ if($this->WaterDrawingArticles->save($waterDrawingArticle)){
+ $this->Flash->success( $waterDrawingArticle->disable ? __('Articolo disabilitato con successo.') : __('Articolo abilitato con successo.'));
+ }else{
+ $this->Flash->error( $waterDrawingArticle->disable ? __('Errore durante l\'abilitazione dell\'articolo.') : __('Errore durante la disabilitazione dell\'articolo.'));
+ }
+ return $this->redirect(['action' => 'index']);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingDerivationsController.php b/idrocap_wa/src/Controller/WaterDrawingDerivationsController.php
new file mode 100644
index 0000000..fb7974a
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingDerivationsController.php
@@ -0,0 +1,123 @@
+paginate = [
+ 'contain' => ['WaterDrawingDerivationTypes', 'WaterDrawingPaperworks'],
+ ];
+ $waterDrawingDerivations = $this->paginate($this->WaterDrawingDerivations);
+
+ $this->set(compact('waterDrawingDerivations'));
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Water Drawing Derivation id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ $waterDrawingDerivation = $this->WaterDrawingDerivations->find()
+ ->contain(['WaterDrawingDerivationTypes', 'WaterDrawingPaperworks'])
+ ->where(['WaterDrawingDerivations.id' => $id])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results){
+ return $results->map(function ($row){
+ $row->can_edit = true;
+ $row->can_delete = true;
+ return $row;
+ });
+ })->first();
+
+ $this->set(compact('waterDrawingDerivation'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add($water_drawing_paperwork_id)
+ {
+ $waterDrawingDerivation = $this->WaterDrawingDerivations->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $waterDrawingDerivation = $this->WaterDrawingDerivations->patchEntity($waterDrawingDerivation, $this->request->getData());
+ if ($this->WaterDrawingDerivations->save($waterDrawingDerivation)) {
+ $waterDrawingPaperworks = $this->WaterDrawingDerivations->WaterDrawingPaperworks->get($water_drawing_paperwork_id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperworks->controllable_object_id);
+ $this->Flash->success(__('Il punto di prelievo è stato salvato con successo'));
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingDerivation->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio del punto di prelievo.'));
+ }
+ $waterDrawingDerivationTypes = $this->WaterDrawingDerivations->WaterDrawingDerivationTypes->find()->all()->combine('id','description')->toArray();
+ $this->set(compact('waterDrawingDerivation', 'waterDrawingDerivationTypes', 'water_drawing_paperwork_id'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Water Drawing Derivation id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ $waterDrawingDerivation = $this->WaterDrawingDerivations->get($id, contain: ['WaterDrawingPaperworks']);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingDerivation = $this->WaterDrawingDerivations->patchEntity($waterDrawingDerivation, $this->request->getData());
+
+ if ($this->WaterDrawingDerivations->save($waterDrawingDerivation)) {
+ SnapshotsHandler::createSnapshot($waterDrawingDerivation->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il punto di prelievo è stato salvato con successo'));
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingDerivation->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio del punto di prelievo.'));
+ }
+ $waterDrawingDerivationTypes = $this->WaterDrawingDerivations->WaterDrawingDerivationTypes->find()->all()->combine('id', 'description')->toArray();
+ $this->set(compact('waterDrawingDerivation', 'waterDrawingDerivationTypes'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Derivation id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingDerivation = $this->WaterDrawingDerivations->get($id, contain: ['WaterDrawingPaperworks']);
+ if ($this->WaterDrawingDerivations->delete($waterDrawingDerivation)) {
+ SnapshotsHandler::createSnapshot($waterDrawingDerivation->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il punto di prelievo è stato cancellato'));
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingDerivation->water_drawing_paperwork_id]);
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione del punto di prelievo.'));
+ }
+
+ return $this->redirect(['action' => 'view', $waterDrawingDerivation->id]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingFeesController.php b/idrocap_wa/src/Controller/WaterDrawingFeesController.php
new file mode 100644
index 0000000..b1d3986
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingFeesController.php
@@ -0,0 +1,174 @@
+logged_user->hasCapability(['documentation.water_drawing_fees.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingFees = $this->WaterDrawingFees->find()->contain(['WaterDrawingPayments'])->where(['WaterDrawingFees.water_drawing_paperwork_id' => $water_drawing_paperwork_id])->formatResults(function ($result){
+ return $result->map(function ($row){
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_fees.edit');
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_fees.delete') && (count($row->water_drawing_payments) == 0);
+ return $row;
+ });
+ });
+ $this->set('total_water_drawing_fees', $waterDrawingFees->count());
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingFees = $this->applyFilters($waterDrawingFees);
+ $this->set('filtered_water_drawing_fees', $waterDrawingFees->count());
+ $waterDrawingFees = $this->paginate($waterDrawingFees);
+
+ $this->set(compact('waterDrawingFees', 'water_drawing_paperwork_id'));
+ $this->set('can_export_csv', $this->logged_user->hasCapability('documentation.water_drawing_paperworks.export_csv_payment'));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_paperworks.export_csv_payment')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('Anno'),
+ __('Canone'),
+ __('Dovuto')
+ ];
+ $extract = [
+ 'year',
+ 'amount',
+ 'to_pay'
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("water_drawing_fees_$water_drawing_paperwork_id-$timestamp.csv"));
+ }
+
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingFees');
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Water Drawing Fee id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_fees.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingFee = $this->WaterDrawingFees->find()->contain(['WaterDrawingPayments'])->where(['WaterDrawingFees.id' => $id])->formatResults(function ($result){
+ return $result->map(function ($row){
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_fees.edit');
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_fees.delete') && (count($row->water_drawing_payments) == 0);
+ return $row;
+ });
+ })->first();
+
+ $waterDrawingPayments = $this->WaterDrawingFees->WaterDrawingPayments->find()->contain(['WaterDrawingFees', 'WaterDrawingPaymentTypes', 'Users'])->where(['WaterDrawingPayments.water_drawing_fee_id' => $id])->formatResults(function ($result){
+ return $result->map(function ($row){
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_view = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_payment');
+ return $row;
+ });
+ });
+
+ $this->set(compact('waterDrawingFee', 'waterDrawingPayments'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add($water_drawing_paperwork_id)
+ {
+ $waterDrawingFee = $this->WaterDrawingFees->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $waterDrawingFee = $this->WaterDrawingFees->patchEntity($waterDrawingFee, $this->request->getData());
+ if ($this->WaterDrawingFees->save($waterDrawingFee)) {
+ $waterDrawingPaperworks = $this->WaterDrawingFees->WaterDrawingPaperworks->get($water_drawing_paperwork_id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperworks->controllable_object_id);
+ $this->Flash->success(__('Il canone annuale è stato salvato.'));
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingFee->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore. Il canone annuale non è stato salvato.'));
+ }
+ $this->set(compact('waterDrawingFee', 'water_drawing_paperwork_id'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Water Drawing Fee id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ $waterDrawingFee = $this->WaterDrawingFees->get($id);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingFee = $this->WaterDrawingFees->patchEntity($waterDrawingFee, $this->request->getData());
+ if ($this->WaterDrawingFees->save($waterDrawingFee)) {
+ $this->Flash->success(__('Il canone annuale è stato salvato.'));
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingFee->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore. Il canone annuale non è stato salvato.'));
+ }
+ $this->set(compact('waterDrawingFee'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Fee id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingFee = $this->WaterDrawingFees->get($id, contain: ['WaterDrawingPayments']);
+ if(count($waterDrawingFee->water_drawing_payments) > 0){
+ $this->Flash->error(__('Errore. Per poter eliminare il canone bisogna eliminare i pagamenti ad esso associati.'));
+ return $this->redirect(['action' => 'view', $id]);
+ }
+ if ($this->WaterDrawingFees->delete($waterDrawingFee)) {
+ $this->Flash->success(__('Il canone annuale è stato cancellato.'));
+ } else {
+ $this->Flash->error(__('Errore. Il canone annuale non è stato cancellato.'));
+ }
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingFee->water_drawing_paperwork_id]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingIntendedUsesController.php b/idrocap_wa/src/Controller/WaterDrawingIntendedUsesController.php
new file mode 100644
index 0000000..9859ceb
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingIntendedUsesController.php
@@ -0,0 +1,108 @@
+paginate = [
+ 'contain' => ['WaterDrawingPaperworks', 'WaterDrawingIntendedUseTypes'],
+ ];
+ $waterDrawingIntendedUses = $this->paginate($this->WaterDrawingIntendedUses);
+
+ $this->set(compact('waterDrawingIntendedUses'));
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Water Drawing Intended Use id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ $waterDrawingIntendedUse = $this->WaterDrawingIntendedUses->get($id, contain: ['WaterDrawingPaperworks', 'WaterDrawingIntendedUseTypes']);
+
+ $this->set(compact('waterDrawingIntendedUse'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add()
+ {
+ $waterDrawingIntendedUse = $this->WaterDrawingIntendedUses->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $waterDrawingIntendedUse = $this->WaterDrawingIntendedUses->patchEntity($waterDrawingIntendedUse, $this->request->getData());
+ if ($this->WaterDrawingIntendedUses->save($waterDrawingIntendedUse)) {
+ $this->Flash->success(__('The water drawing intended use has been saved.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('The water drawing intended use could not be saved. Please, try again.'));
+ }
+ $waterDrawingPaperworks = $this->WaterDrawingIntendedUses->WaterDrawingPaperworks->find('list')->all();
+ $waterDrawingIntendedUseTypes = $this->WaterDrawingIntendedUses->WaterDrawingIntendedUseTypes->find('list')->all();
+ $this->set(compact('waterDrawingIntendedUse', 'waterDrawingPaperworks', 'waterDrawingIntendedUseTypes'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Water Drawing Intended Use id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ $waterDrawingIntendedUse = $this->WaterDrawingIntendedUses->get($id, contain: []);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingIntendedUse = $this->WaterDrawingIntendedUses->patchEntity($waterDrawingIntendedUse, $this->request->getData());
+ if ($this->WaterDrawingIntendedUses->save($waterDrawingIntendedUse)) {
+ $this->Flash->success(__('The water drawing intended use has been saved.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('The water drawing intended use could not be saved. Please, try again.'));
+ }
+ $waterDrawingPaperworks = $this->WaterDrawingIntendedUses->WaterDrawingPaperworks->find('list')->all();
+ $waterDrawingIntendedUseTypes = $this->WaterDrawingIntendedUses->WaterDrawingIntendedUseTypes->find('list')->all();
+ $this->set(compact('waterDrawingIntendedUse', 'waterDrawingPaperworks', 'waterDrawingIntendedUseTypes'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Intended Use id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingIntendedUse = $this->WaterDrawingIntendedUses->get($id);
+ if ($this->WaterDrawingIntendedUses->delete($waterDrawingIntendedUse)) {
+ $this->Flash->success(__('The water drawing intended use has been deleted.'));
+ } else {
+ $this->Flash->error(__('The water drawing intended use could not be deleted. Please, try again.'));
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingMeasurementsController.php b/idrocap_wa/src/Controller/WaterDrawingMeasurementsController.php
new file mode 100644
index 0000000..75779cf
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingMeasurementsController.php
@@ -0,0 +1,124 @@
+logged_user->hasCapability('documentation.water_drawing_measurements.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingMeasurement = $this->WaterDrawingMeasurements->newEmptyEntity();
+ $waterDrawingMeter = $this->WaterDrawingMeasurements->WaterDrawingMeters->find()->contain(['WaterDrawingIntendedUses' => ['WaterDrawingPaperworks']])->where(['WaterDrawingMeters.id' => $water_drawing_meter_id])->first();
+ if ($this->request->is('post')) {
+ $data = $this->request->getData();
+ $data['user_id'] = $this->logged_user->id;
+ $data['water_drawing_meter_id'] = $water_drawing_meter_id;
+ $waterDrawingMeasurement = $this->WaterDrawingMeasurements->patchEntity($waterDrawingMeasurement, $data);
+ if ($this->WaterDrawingMeasurements->save($waterDrawingMeasurement)) {
+ SnapshotsHandler::createSnapshot($waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Misurazione salvata con successo.'));
+ return $this->redirect(['controller' => 'WaterDrawingMeters', 'action' => 'view', $waterDrawingMeter->id]);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio della misurazione.'));
+ }
+ $this->set('today', DateTime::now());
+ $this->set('water_drawing_paperwork_id', $waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork_id);
+ $this->set(compact('waterDrawingMeasurement', 'water_drawing_meter_id'));
+ }
+
+ /**
+ * index
+ *
+ * @param mixed $water_drawing_paperwork_id
+ * @return void
+ */
+ public function index($water_drawing_paperwork_id){
+ $waterDrawingMeasurements = $this->WaterDrawingMeasurements->find()->contain(['WaterDrawingMeters' => ['WaterDrawingToolTypes', 'WaterDrawingIntendedUses'], 'Users'])->where(['WaterDrawingIntendedUses.water_drawing_paperwork_id' => $water_drawing_paperwork_id]);
+ $this->set('total_water_drawing_measurements', $waterDrawingMeasurements->count());
+
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingMeasurements = $this->applyFilters($waterDrawingMeasurements);
+ $this->set('filtered_water_drawing_measurements', $waterDrawingMeasurements->count());
+
+ if(!$this->getRequest()->is(['json', 'xml', 'csv'])){
+ $waterDrawingMeasurements = $waterDrawingMeasurements
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->date = $row->date?->format('d/m/Y');
+ return $row;
+ })->toArray();
+ });
+ }
+
+ $this->paginate = [
+ 'order' => [
+ 'WaterDrawingMeasurements.date' => 'DESC'
+ ],
+ ];
+
+ $this->set(compact('water_drawing_paperwork_id'));
+ $this->set('waterDrawingMeasurements', $this->getRequest()->is(['json', 'xml', 'csv']) ? $waterDrawingMeasurements : $this->paginate($waterDrawingMeasurements));
+ $this->set('can_export_csv', $this->logged_user->hasCapability('documentation.water_drawing_measurements.export_csv_measurement'));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_measurements.export_csv_measurement')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $header = [
+ __('N° matricola strumento di misura'),
+ __('Lettura Volume (m^3)'),
+ __('Data lettura'),
+ __('Utente'),
+ ];
+ $extract = [
+ function (array $row) {
+ return $row['water_drawing_meter']['part_number'];
+ },
+ 'volume',
+ 'date',
+ function (array $row) {
+ $user = $this->fetchTable('Users')->get($row['user']['id']);
+ return $user;
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("water_drawing_measurements_$water_drawing_paperwork_id-$timestamp.csv"));
+ }
+
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingMeasurements');
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingMetersController.php b/idrocap_wa/src/Controller/WaterDrawingMetersController.php
new file mode 100644
index 0000000..d80427e
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingMetersController.php
@@ -0,0 +1,97 @@
+logged_user->hasCapability('documentation.water_drawing_meters.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingMeter = $this->WaterDrawingMeters->newEmptyEntity();
+ $waterDrawingIntendedUse = $this->WaterDrawingMeters->WaterDrawingIntendedUses->get($water_drawing_intended_use_id);
+ if ($this->request->is('post')) {
+ $data = $this->request->getData();
+ $data['water_drawing_intended_use_id'] = $water_drawing_intended_use_id;
+ $waterDrawingMeter = $this->WaterDrawingMeters->patchEntity($waterDrawingMeter, $data);
+ if ($this->WaterDrawingMeters->save($waterDrawingMeter)) {
+ $waterDrawingPaperworks = $this->WaterDrawingMeters->WaterDrawingIntendedUses->WaterDrawingPaperworks->get($waterDrawingIntendedUse->water_drawing_paperwork_id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperworks->controllable_object_id);
+ $this->Flash->success(__('Strumento di misura salvato con successo.'));
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio dello strumento di misura.'));
+ }
+ $waterDrawingToolTypes = $this->WaterDrawingMeters->WaterDrawingToolTypes->find()->all()->combine('id', 'description')->toArray();
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingMeter', 'waterDrawingToolTypes', 'water_drawing_intended_use_id'));
+ $this->set('water_drawing_paperwork_id', $waterDrawingIntendedUse->water_drawing_paperwork_id);
+ }
+
+ /**
+ * dismiss
+ *
+ * @param mixed $water_drawing_meter_id
+ * @return void
+ */
+ public function dismiss($water_drawing_meter_id)
+ {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_meters.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingMeter = $this->WaterDrawingMeters->get($water_drawing_meter_id, contain: ['WaterDrawingToolTypes', 'WaterDrawingIntendedUses']);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingMeter = $this->WaterDrawingMeters->patchEntity($waterDrawingMeter, $this->request->getData());
+ if ($this->WaterDrawingMeters->save($waterDrawingMeter)) {
+ $this->Flash->success(__('Strumento di misura dismesso con successo.'));
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore durante la dismissione dello strumento di misura.'));
+ }
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingMeter'));
+ }
+
+ public function edit($water_drawing_meter_id)
+ {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_meters.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingMeter = $this->WaterDrawingMeters->get($water_drawing_meter_id, contain: ['WaterDrawingToolTypes', 'WaterDrawingIntendedUses']);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingMeter = $this->WaterDrawingMeters->patchEntity($waterDrawingMeter, $this->request->getData());
+ if ($this->WaterDrawingMeters->save($waterDrawingMeter)) {
+ $this->Flash->success(__('Strumento di misura salvato con successo.'));
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore durante il salvataggio dello strumento di misura.'));
+ }
+ $waterDrawingToolTypes = $this->WaterDrawingMeters->WaterDrawingToolTypes->find()->all()->combine('id', 'description')->toArray();
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingMeter', 'waterDrawingToolTypes'));
+ }
+
+ public function view($water_drawing_meter_id)
+ {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_meters.add')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingMeter = $this->WaterDrawingMeters->get($water_drawing_meter_id, contain: ['WaterDrawingToolTypes', 'WaterDrawingIntendedUses', 'WaterDrawingMeasurements' => function ($q){
+ return $q->contain(['Users'])->orderDesc('WaterDrawingMeasurements.date')->limit(5);
+ }]
+ );
+ $waterDrawingToolTypes = $this->WaterDrawingMeters->WaterDrawingToolTypes->find()->all()->combine('id', 'description')->toArray();
+ $this->set(compact('waterDrawingMeter', 'waterDrawingToolTypes'));
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingPaperworkPecsController.php b/idrocap_wa/src/Controller/WaterDrawingPaperworkPecsController.php
new file mode 100644
index 0000000..0a71852
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingPaperworkPecsController.php
@@ -0,0 +1,148 @@
+WaterDrawingPaperworkPecs->find()->contain(['Users'])->where(['WaterDrawingPaperworkPecs.water_drawing_paperwork_id' => $water_drawing_paperwork_id]);
+ $this->set('total_water_drawing_papwork_pecs', $waterDrawingPaperworkPecs->count());
+
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingPaperworkPecs = $this->applyFilters($waterDrawingPaperworkPecs);
+ $this->set('filtered_water_drawing_papwork_pecs', $waterDrawingPaperworkPecs->count());
+
+ $this->paginate = [
+ 'order' => [
+ 'WaterDrawingPaperworkPec.date' => 'DESC'
+ ],
+ ];
+ $waterDrawingPaperworkPecs = $waterDrawingPaperworkPecs->formatResults(function ($results){
+ return $results->map( function ($row){
+ $row->can_edit_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.edit');
+ $row->can_delete_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.delete');
+ return $row;
+ });
+ });
+ $this->set(compact('water_drawing_paperwork_id'));
+ $this->set('waterDrawingPaperworkPecs', $this->paginate($waterDrawingPaperworkPecs));
+ $this->set('add_documentation', $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.add'));
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Water Drawing Paperwork Pec id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ $waterDrawingPaperworkPec = $this->WaterDrawingPaperworkPecs->find()->contain(['WaterDrawingPaperworks', 'Users', 'ControllableObjects' => ['Attachments']])->where(['WaterDrawingPaperworkPecs.id' => $id])->formatResults(function ($results) {
+ return $results->map(function ($row) {
+ $row->can_edit_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.edit');
+ $row->can_delete_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.delete');
+ return $row;
+ });
+ })->first();
+ $tags = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworkPecs'])->all()->combine('code', 'description')->toArray();
+
+ $this->set(compact('waterDrawingPaperworkPec', 'tags'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add($water_drawing_paperwork_id)
+ {
+ $waterDrawingPaperworkPec = $this->WaterDrawingPaperworkPecs->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $waterDrawingPaperworkPec = $this->WaterDrawingPaperworkPecs->patchEntity($waterDrawingPaperworkPec, $this->request->getData());
+ $waterDrawingPaperworkPec->user_id = $this->logged_user->id;
+ if ($this->WaterDrawingPaperworkPecs->save($waterDrawingPaperworkPec)) {
+ $waterDrawingPaperworks = $this->WaterDrawingPaperworkPecs->WaterDrawingPaperworks->get($water_drawing_paperwork_id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperworks->controllable_object_id);
+ $this->Flash->success(__('Il documento PEC è stato salvato.'));
+
+ return $this->redirect(['action' => 'index', $water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore.Non è stato salvato il documento PEC. ') . $waterDrawingPaperworkPec->getError('attachment')[0]);
+ }
+ $tags = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworkPecs'])->all()->combine('code', 'description')->toArray();
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingPaperworkPec', 'water_drawing_paperwork_id', 'tags'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Water Drawing Paperwork Pec id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ $waterDrawingPaperworkPec = $this->WaterDrawingPaperworkPecs->get($id, contain: ['ControllableObjects' => ['Attachments'], 'WaterDrawingPaperworks']);
+ $tags = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworkPecs'])->all()->combine('code', 'description')->toArray();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $this->log(json_encode($this->request->getData(), JSON_PRETTY_PRINT), 'debug');
+ $waterDrawingPaperworkPec = $this->WaterDrawingPaperworkPecs->patchEntity($waterDrawingPaperworkPec, $this->request->getData(), ['associated' => ['ControllableObjects']]);
+ $this->log(json_encode($waterDrawingPaperworkPec, JSON_PRETTY_PRINT), 'debug');
+ if ($this->WaterDrawingPaperworkPecs->save($waterDrawingPaperworkPec)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperworkPec->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il documento PEC è stato salvato.'));
+
+ return $this->redirect(['action' => 'index', $waterDrawingPaperworkPec->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore.Non è stato salvato il documento PEC. ') . $waterDrawingPaperworkPec->getError('attachment')[0]);
+ }
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingPaperworkPec', 'tags'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Paperwork Pec id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingPaperworkPec = $this->WaterDrawingPaperworkPecs->get($id);
+ if ($this->WaterDrawingPaperworkPecs->delete($waterDrawingPaperworkPec)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperworkPec->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il documento PEC è stato cancellato.'));
+ } else {
+ $this->Flash->error(__('Errore.Non è stato cancellato il documento PEC.'));
+ }
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingPaperworkPec->water_drawing_paperwork_id]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingPaperworksController.php b/idrocap_wa/src/Controller/WaterDrawingPaperworksController.php
new file mode 100644
index 0000000..20a9da4
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingPaperworksController.php
@@ -0,0 +1,1775 @@
+logged_user->hasCapability(['documentation.water_drawing_snapshots.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $this->set('water_drawing_paperwork_id', $water_drawing_paperwork_id);
+ $this->set('can_export_snapshots', $this->logged_user->hasCapability(['documentation.water_drawing_snapshots.export_csv']));
+
+ $water_drawing_paperwork = $this->fetchTable('WaterDrawingPaperworks')->get($water_drawing_paperwork_id);
+ $this->set('waterDrawingPaperwork', $water_drawing_paperwork);
+
+ $lastWaterDrawingPaperworkUnpackingVersion = SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion();
+ $unpackedWaterDrawingPaperworkSnapshots = $this->fetchTable('UnpackedWaterDrawingPaperworkSnapshots')->find()
+ ->where(['UnpackedWaterDrawingPaperworkSnapshots.water_drawing_paperwork_id' => $water_drawing_paperwork_id, 'UnpackedWaterDrawingPaperworkSnapshots.unpacking_version' => $lastWaterDrawingPaperworkUnpackingVersion]);
+
+ $this->paginate = [
+ 'limit' => 25,
+ 'order' => [
+ 'when' => 'DESC'
+ ],
+ ];
+
+ $this->set('unpackedWaterDrawingPaperworkSnapshots', $this->getRequest()->is(['json', 'xml', 'csv']) ? $unpackedWaterDrawingPaperworkSnapshots : $this->paginate($unpackedWaterDrawingPaperworkSnapshots));
+
+ $this->viewBuilder()->setOption('serialize', 'unpackedWaterDrawingPaperworkSnapshots');
+ }
+
+ /**
+ * index_snapshots_csv
+ *
+ * @param mixed $water_drawing_paperwork_id
+ * @return void
+ */
+ public function index_snapshots_csv($water_drawing_paperwork_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_snapshots.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_snapshots.export_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $lastWaterDrawingPaperworkUnpackingVersion = SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion();
+ $unpackedWaterDrawingPaperworkSnapshots = $this->fetchTable('UnpackedWaterDrawingPaperworkSnapshots')->find()
+ ->where(['UnpackedWaterDrawingPaperworkSnapshots.water_drawing_paperwork_id' => $water_drawing_paperwork_id, 'UnpackedWaterDrawingPaperworkSnapshots.unpacking_version' => $lastWaterDrawingPaperworkUnpackingVersion]);
+
+ $headers = [
+ __('Data'),
+ __('Da (operatore)'),
+ __('Azione'),
+ __('Stato pratica'),
+ __('Assegnatario Genio Civile'),
+ __('Assegnatario DRAR'),
+ ];
+ $extract = [
+ function (array $row) {
+ return isset($row['when']) ? (new DateTime($row['when']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ 'who',
+ 'what',
+ 'water_drawing_paperwork_status',
+ 'gc_user',
+ 'drar_user',
+ ];
+
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-MM-dd-HH-mm-ss', $this->logged_user->timezone);
+
+ return $this->streamCsvResponse(
+ $unpackedWaterDrawingPaperworkSnapshots,
+ "water_drawing_paperwork-$water_drawing_paperwork_id-snapshots_$timestamp.csv",
+ $extract,
+ $headers
+ );
+ }
+
+ public function view_snapshot($snapshot_id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_snapshots.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $snapshot = $this->fetchTable('Snapshots')->get($snapshot_id);
+
+ $co = SnapshotsHandler::getControllableObjectFromSnapshotWithId((int)$snapshot_id);
+
+ $this->set('back_to_logs', !empty($this->request->getQuery('origin')) && $this->request->getQuery('origin') == 'logs');
+ $this->set('date', $snapshot->date);
+ $this->set('previous_snapshot_id', $this->fetchTable('Snapshots')->find()->where(['Snapshots.id <' => $snapshot_id, 'Snapshots.controllable_object_id' => $co->id, 'Snapshots.unpacked_with_version' => SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion()])->order(['Snapshots.id' => 'DESC'])->first()?->id);
+ $this->set('next_snapshot_id', $this->fetchTable('Snapshots')->find()->where(['Snapshots.id >' => $snapshot_id, 'Snapshots.controllable_object_id' => $co->id, 'Snapshots.unpacked_with_version' => SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion()])->order(['Snapshots.id' => 'ASC'])->first()?->id);
+
+ $co->water_drawing_paperwork->can_view_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.view');
+ $co->water_drawing_paperwork->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+
+ $this->set('waterDrawingPaperwork', $co->water_drawing_paperwork);
+ $this->set('waterDrawingPaperworkHistories', $co->water_drawing_paperwork->water_drawing_paperwork_histories);
+
+ $waterDrawingPayments = collection($co->water_drawing_paperwork->water_drawing_fees)
+ ->reduce(function ($acc, $water_drawing_fee) {
+ $water_drawing_fee_year = $water_drawing_fee->year;
+ $water_drawing_fee->water_drawing_payments = collection($water_drawing_fee->water_drawing_payments)->map(function ($water_drawing_payment, $key) use ($water_drawing_fee_year) {
+ $water_drawing_payment->amount = !empty($water_drawing_payment->amount) ? $water_drawing_payment->amount . ' €' : null;
+ $water_drawing_payment->payment_date = $water_drawing_payment->payment_date?->format('Y/m/d');
+ $water_drawing_payment->created = isset($water_drawing_payment->created) ? (new DateTime($water_drawing_payment->created))->i18nFormat('Y/MM/dd HH:mm:ss', $this->logged_user->timezone) : null;
+ $water_drawing_payment->water_drawing_fee_year = $water_drawing_fee_year;
+ return $water_drawing_payment;
+ })->toArray();
+ return array_merge($acc, $water_drawing_fee->water_drawing_payments);
+ }, []);
+
+ $this->set('waterDrawingPayments', $waterDrawingPayments);
+
+ $this->set('numberOfAttachments', count($co->child_attachments));
+ $this->set('attachments', $co->child_attachments);
+
+ $WaterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->all()->combine('id', 'description')->toArray();
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $wateringSystems = $this->getTableLocator()->get('WaterDrawingWateringSystems')->find()->all()->combine('id', 'description')->toArray();
+ $this->set(compact('WaterDrawingArticles', 'intendedUseTypes', 'cadastralCropTypes', 'wateringSystems'));
+ $this->set('logged_user_id', $this->logged_user->id);
+ }
+
+ public function index_snapshots_all()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_snapshots_all.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $this->set('can_export_snapshots_all', $this->logged_user->hasCapability(['documentation.water_drawing_snapshots.export_all_csv']));
+
+ $lastWaterDrawingPaperworkUnpackingVersion = SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion();
+ $unpackedWaterDrawingPaperworkSnapshots = $this->fetchTable('UnpackedWaterDrawingPaperworkSnapshots')->find()
+ ->where(['UnpackedWaterDrawingPaperworkSnapshots.unpacking_version' => $lastWaterDrawingPaperworkUnpackingVersion]);
+
+ $this->paginate = [
+ 'limit' => 25,
+ 'order' => [
+ 'when' => 'DESC'
+ ],
+ ];
+
+ $this->set('unpackedWaterDrawingPaperworkSnapshots', $this->getRequest()->is(['json', 'xml', 'csv']) ? $unpackedWaterDrawingPaperworkSnapshots : $this->paginate($unpackedWaterDrawingPaperworkSnapshots));
+
+ $this->viewBuilder()->setOption('serialize', 'unpackedWaterDrawingPaperworkSnapshots');
+ }
+
+ /**
+ * index_snapshots_all_csv
+ *
+ * @return void
+ */
+ public function index_snapshots_all_csv()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_snapshots_all.view'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_snapshots.export_all_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $lastWaterDrawingPaperworkUnpackingVersion = SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion();
+ $unpackedWaterDrawingPaperworkSnapshots = $this->fetchTable('UnpackedWaterDrawingPaperworkSnapshots')->find()
+ ->where(['UnpackedWaterDrawingPaperworkSnapshots.unpacking_version' => $lastWaterDrawingPaperworkUnpackingVersion]);
+
+ $headers = [
+ __('Data'),
+ __('Da (operatore)'),
+ __('Azione'),
+ __('ID Pratica'),
+ __('Stato pratica'),
+ __('Assegnatario Genio Civile'),
+ __('Assegnatario DRAR'),
+ ];
+ $extract = [
+ function (array $row) {
+ return isset($row['when']) ? (new DateTime($row['when']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ 'who',
+ 'what',
+ 'water_drawing_paperwork_id',
+ 'water_drawing_paperwork_status',
+ 'gc_user',
+ 'drar_user',
+ ];
+
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-MM-dd-HH-mm-ss', $this->logged_user->timezone);
+
+ return $this->streamCsvResponse(
+ $unpackedWaterDrawingPaperworkSnapshots,
+ "water_drawing_paperwork_snapshots_all_$timestamp.csv",
+ $extract,
+ $headers
+ );
+ }
+
+ /**
+ * Index method
+ *
+ * @return \Cake\Http\Response|null|void Renders view
+ */
+ public function index()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view', 'documentation.water_drawing_paperworks.view_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPaperworks = $this->WaterDrawingPaperworks->find()
+ ->contain(['Applicants', 'ControllableObjects', 'WaterDrawingPaperworkStatuses']);
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.view',
+ 'documentation.water_drawing_paperworks.view_own_province'
+ ])) {
+ $waterDrawingPaperworks->where(['authority_province' => $this->logged_user?->organisation_province]);
+ }
+
+ $this->set('total_water_drawing_paperworks', $waterDrawingPaperworks->count());
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingPaperworks = $this->applyFilters($waterDrawingPaperworks);
+ $this->set('filtered_water_drawing_paperworks', $waterDrawingPaperworks->count());
+
+ if (!$this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $waterDrawingPaperworks = $waterDrawingPaperworks
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->release_date = $row->release_date?->format('Y/m/d');
+ $row->expiration_date = $row->expiration_date?->format('Y/m/d');
+ $row->controllable_object->created = $row->controllable_object->created?->format('Y/m/d H:i:s');
+ $row->controllable_object->modified = $row->controllable_object->modified?->format('Y/m/d H:i:s');
+ $row->can_edit = ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province') && $row?->authority_province === $this->logged_user?->organisation_province) &&
+ ($this->logged_user->id == $row->gc_user_id && ($row->water_drawing_paperwork_status_id === -1 || $row->water_drawing_paperwork_status_id === -5) ||
+ ($this->logged_user->id == $row->drar_user_id && $row->water_drawing_paperwork_status_id === -4))) ||
+ (($row->water_drawing_paperwork_status_id == 3 || $row->water_drawing_paperwork_status_id == 5) ||
+ ($row->water_drawing_paperwork_status_id == 8) ? false : $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_scan')) ;
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete') || $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_own_province') && $row?->authority_province === $this->logged_user?->organisation_province;
+ return $row;
+ })->toArray();
+ });
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['id', 'WaterDrawingPaperworkStatuses.description', 'district', 'release_date', 'concession_duration', 'expiration_date', 'ControllableObjects.created', 'ControllableObjects.modified'],
+ 'order' => [
+ 'ControllableObjects.created' => 'DESC',
+ ],
+ ];
+ if(!($this->getRequest()->is(['json', 'xml', 'csv']))){
+ $waterDrawingPaperworks = $this->paginate($waterDrawingPaperworks);
+ if($waterDrawingPaperworks->currentPage() > $waterDrawingPaperworks->pageCount()){
+ $queryParams = $this->getRequest()->getQueryParams();
+ $queryParams['page'] = 1;
+ $this->setRequest($this->getRequest()->withQueryParams($queryParams));
+ }
+ }
+
+ $this->set('waterDrawingPaperworks', $waterDrawingPaperworks);
+
+ $this->set('can_export_list', $this->logged_user->hasCapability(['documentation.water_drawing_paperworks_list.export_csv']));
+ $this->set('can_export_all_payments_list', $this->logged_user->hasCapability(['documentation.water_drawing_paperworks_all_payments.export_csv_payment']));
+ $this->set('can_view_all_snapshots', $this->logged_user->hasCapability(['documentation.water_drawing_snapshots_all.view']));
+
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingPaperworks');
+ }
+
+ /**
+ * index_csv
+ *
+ * @return void
+ */
+ public function index_csv()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view', 'documentation.water_drawing_paperworks.view_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_paperworks_list.export_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPaperworks = $this->WaterDrawingPaperworks->find()
+ ->contain(['ControllableObjects', 'WaterDrawingPaperworkStatuses']);
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.view',
+ 'documentation.water_drawing_paperworks.view_own_province'
+ ])) {
+ $waterDrawingPaperworks->where(['authority_province' => $this->logged_user?->organisation_province]);
+ }
+
+ $headers = [
+ __('ID'),
+ __('Codice identificativo'),
+ __('Stato'),
+ __('Provincia'),
+ __('Data di rilascio'),
+ __('Scadenza'),
+ __('Creata'),
+ __('Modificata'),
+ ];
+
+ $extract = [
+ 'id',
+ 'authority_identification_code_civil_engineering_office',
+ function (array $row) {
+ return $row['water_drawing_paperwork_status']['description'] ?? '';
+ },
+ 'authority_province',
+ function (array $row) {
+ return isset($row['release_date']) ? (new DateTime($row['release_date']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ return isset($row['expiration_date']) ? (new DateTime($row['expiration_date']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ return isset($row['controllable_object']['created']) ? (new DateTime($row['controllable_object']['created']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ return isset($row['controllable_object']['modified']) ? (new DateTime($row['controllable_object']['modified']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ ];
+
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-MM-dd-HH-mm-ss', $this->logged_user->timezone);
+
+ return $this->streamCsvResponse(
+ $waterDrawingPaperworks,
+ "water_drawing_paperworks-$timestamp.csv",
+ $extract,
+ $headers
+ );
+ }
+
+ /**
+ * view method
+ *
+ * @param string|null $id Water Drawing Paperwork id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view', 'documentation.water_drawing_paperworks.view_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $organisation = $this->getTableLocator()->get('Organisations')->find()->where(['Organisations.id' => $this->logged_user->organisation_id])->first();
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()
+ ->contain([
+ 'WaterDrawingPaperworkPecs',
+ 'WaterDrawingFees',
+ 'GcUsers' => ['Organisations'],
+ 'DrarUsers' => ['Organisations'],
+ 'WaterDrawingReturnPoints',
+ 'WaterDrawingDerivations' => ['WaterDrawingDerivationTypes'],
+ 'WaterDrawingPaperworkStatuses',
+ 'ControllableObjects' => ['Attachments' => ['Tags']],
+ 'Applicants',
+ 'WaterDrawingAntimafiaCertificationRequests' =>
+ function ($q) {
+ return $q->contain(['WaterDrawingAntimafiaCertificationRequestStatuses', 'Users'])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created');
+ },
+ 'WaterDrawingIntendedUses' => [
+ 'CadastralCropTypes',
+ 'WaterDrawingIntendedUseTypes',
+ 'WaterDrawingMeters' =>
+ function ($q) {
+ return $q->where(['WaterDrawingMeters.removal_date IS NULL'])
+ ->contain(['WaterDrawingToolTypes', 'WaterDrawingMeasurements' => function ($q) {
+ return $q->contain(['Users'])->orderDesc('WaterDrawingMeasurements.date')->limit(5);
+ }]);
+ }
+ ]
+ ])
+ ->where(['WaterDrawingPaperworks.id' => $id]);
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.view',
+ 'documentation.water_drawing_paperworks.view_own_province'
+ ])) {
+ $waterDrawingPaperwork->where(['authority_province' => $this->logged_user?->organisation_province]);
+ }
+
+ $waterDrawingPaperwork = $waterDrawingPaperwork->formatResults(function (\Cake\Collection\CollectionInterface $results) use ($organisation) {
+ return $results->map(function ($row) use ($organisation) {
+ if (!$organisation && !empty($row['gc_user'])) {
+ return $row;
+ }
+ $row->can_view_snapshots = $this->logged_user->hasCapability('documentation.water_drawing_snapshots.view');
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province') && $row?->authority_province === $this->logged_user?->organisation_province) && (isset($row->gc_user_id) && $this->logged_user->id == $row->gc_user_id && ($row->water_drawing_paperwork_status_id === -1 || $row->water_drawing_paperwork_status_id === -5) || ($this->logged_user->id == $row->drar_user_id && $row->water_drawing_paperwork_status_id === -4));
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_own_province') && $row?->authority_province === $this->logged_user?->organisation_province);
+ $row->can_validate = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate') && ((isset($row->drar_user_id) && $this->logged_user->id == $row->drar_user_id && $row->water_drawing_paperwork_status_id === -3) || (isset($row->gc_user_id) && $this->logged_user->id == $row->gc_user_id && $row->water_drawing_paperwork_status_id === 10));
+ $row->can_send_to_drar = ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province')) && $row?->authority_province === $this->logged_user?->organisation_province) && $row->water_drawing_paperwork_status_id === -1 && $row->check_sdd && isset($row->gc_user_id) && $row->gc_user_id == $this->logged_user->id;
+ $row->can_send_to_gc = ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province')) && $row?->authority_province === $this->logged_user?->organisation_province) && $row->water_drawing_paperwork_status_id === -4 && $row->check_dec && isset($row->drar_user_id) && $row->drar_user_id == $this->logged_user->id;
+ $row->can_assign_to_drar = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.assign') && $row->water_drawing_paperwork_status_id <= -2 && $organisation->organisation_type_id == 6;
+ $row->can_assign_to_gc = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.assign') && ($row->water_drawing_paperwork_status_id === 9 || !isset($row->gc_user_id) || $organisation->organisation_type_id == $row->gc_user->organisation->organisation_type_id);
+ $row->can_add_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.add');
+ $row->can_edit_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.edit');
+ $row->can_delete_pec = $this->logged_user->hasCapability('documentation.water_drawing_paperwork_pecs.delete');
+ if ($row->water_drawing_paperwork_status_id === -5) {
+ $row->can_add_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.add');
+ $row->can_edit_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.edit') || $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province');
+ $row->can_view_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.view');
+ $row->can_add_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_delete_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_payment');
+ $row->can_add_meter = $this->logged_user->hasCapability('documentation.water_drawing_meters.add');
+ $row->can_add_measurements = $this->logged_user->hasCapability('documentation.water_drawing_measurements.add');
+ $row->can_view_measurements = true;
+ }
+ if ($row->water_drawing_paperwork_status_id == -4) {
+ $row->can_add_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.add');
+ $row->can_edit_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.edit') || $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province');
+ $row->can_view_fee = $this->logged_user->hasCapability('documentation.water_drawing_fees.view');
+ $row->can_add_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_delete_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_payment');
+ $row->can_submit_antimafia_request = ($this->logged_user->id == $row->drar_user_id) && (!isset($row->water_drawing_antimafia_certification_requests[0]));
+ $row->can_antimafia_request_to_anac = ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.antimafia_request')) && (isset($row->water_drawing_antimafia_certification_requests[0]) && ($row->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 1));
+ $row->can_request_self_certification = ($this->logged_user->id == $row->drar_user_id) && (isset($row->water_drawing_antimafia_certification_requests[0]) && (new DateTime($row->water_drawing_antimafia_certification_requests[0]->created))->diffInDays(\Cake\I18n\DateTime::now()) > 30);
+ $row->can_upload_antimafia_attachment = (isset($row->water_drawing_antimafia_certification_requests[0]) && (
+ (($this->logged_user->hasCapability('documentation.water_drawing_paperworks.antimafia_request')) && !($row->check_dam)) ||
+ (($this->logged_user->id == $row->gc_user_id) && $row->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 3)
+ ));
+ }
+ return $row;
+ });
+ })->first();
+
+ if (!isset($waterDrawingPaperwork)) {
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+
+ $waterDrawingPaperworkHistories = $this->fetchTable('WaterDrawingPaperworkHistories')->find()->contain(['Users' => ['Actors'], 'ControllableObjects'])->order(['WaterDrawingPaperworkHistories.created' => 'DESC'])->where(['WaterDrawingPaperworkHistories.water_drawing_paperwork_id' => $id])->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->created = $row->created?->format('Y/m/d');
+ return $row;
+ })->toArray();
+ });
+
+ $waterDrawingPayments = $this->fetchTable('WaterDrawingPayments')->find()
+ ->contain(['WaterDrawingPaymentTypes', 'WaterDrawingFees', 'Users'])
+ ->where(['WaterDrawingFees.water_drawing_paperwork_id' => $id])
+ ->order(['WaterDrawingPayments.created' => 'DESC'])
+ ->limit(5)
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->amount = !empty($row->amount) ? $row->amount . ' €' : null;
+ $row->payment_date = $row->payment_date?->format('d/m/Y');
+ $row->created = $row->created?->format('Y/m/d H:i:s');
+ return $row;
+ })->toArray();
+ });
+ $WaterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->all()->combine('id', 'description')->toArray();
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $wateringSystems = $this->getTableLocator()->get('WaterDrawingWateringSystems')->find()->all()->combine('id', 'description')->toArray();
+
+ $this->set(compact('waterDrawingPaperwork', 'waterDrawingPayments', 'WaterDrawingArticles', 'intendedUseTypes', 'cadastralCropTypes', 'wateringSystems'));
+ $this->set('waterDrawingPaperworkHistories', $this->paginate($waterDrawingPaperworkHistories));
+ $this->set('logged_user_id', $this->logged_user->id);
+ }
+
+ /**
+ * view_scan method
+ *
+ * @param string|null $id Water Drawing Paperwork id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view_scan($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view', 'documentation.water_drawing_paperworks.view_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()
+ ->contain([
+ 'WaterDrawingPaperworkPecs',
+ 'WaterDrawingFees',
+ 'GcUsers' => ['Organisations'],
+ 'DrarUsers' => ['Organisations'],
+ 'WaterDrawingReturnPoints',
+ 'WaterDrawingDerivations' => ['WaterDrawingDerivationTypes'],
+ 'WaterDrawingPaperworkStatuses',
+ 'ControllableObjects' => ['Attachments' => ['Tags']],
+ 'Applicants',
+ 'WaterDrawingAntimafiaCertificationRequests' =>
+ function ($q) {
+ return $q->contain(['WaterDrawingAntimafiaCertificationRequestStatuses', 'Users'])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created');
+ },
+ 'WaterDrawingIntendedUses' => [
+ 'CadastralCropTypes',
+ 'WaterDrawingIntendedUseTypes',
+ 'WaterDrawingMeters' =>
+ function ($q) {
+ return $q->where(['WaterDrawingMeters.removal_date IS NULL'])
+ ->contain(['WaterDrawingToolTypes', 'WaterDrawingMeasurements' => function ($q) {
+ return $q->contain(['Users'])->orderDesc('WaterDrawingMeasurements.date')->limit(5);
+ }]);
+ }
+ ]
+ ])
+ ->where(['WaterDrawingPaperworks.id' => $id])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_add_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_delete_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_payment');
+ $row->can_edit = ($row->water_drawing_paperwork_status_id == 3 || $row->water_drawing_paperwork_status_id == 5) ? false : $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_scan');
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete');
+ $row->can_validate = ($row->water_drawing_paperwork_status_id != 3 && $row->water_drawing_paperwork_status_id != 5) ? false : ($row->water_drawing_paperwork_status_id == 3 ? $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate.first_level_scan') : $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate.second_level_scan'));
+ $row->can_send_to_validation = (
+ (($row->water_drawing_paperwork_status_id == 1 || $row->water_drawing_paperwork_status_id == 2) && isset($row->applicants, $row->applicants[0]->tax_code, $row->authority_identification_code_civil_engineering_office))
+ || $row->water_drawing_paperwork_status_id == 4);
+ return $row;
+ });
+ });
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.view',
+ 'documentation.water_drawing_paperworks.view_own_province'
+ ])) {
+ $waterDrawingPaperwork = $waterDrawingPaperwork->where(['authority_province' => $this->logged_user?->organisation_province]);
+ }
+ $waterDrawingPaperwork = $waterDrawingPaperwork->first();
+
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+ $waterDrawingPaperworkHistories = $this->fetchTable('WaterDrawingPaperworkHistories')->find()->contain(['Users' => ['Actors'], 'ControllableObjects'])->order(['WaterDrawingPaperworkHistories.created' => 'DESC'])->where(['WaterDrawingPaperworkHistories.water_drawing_paperwork_id' => $id])->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->created = $row->created?->format('Y/m/d');
+ return $row;
+ })->toArray();
+ });
+
+ $waterDrawingPayments = $this->fetchTable('WaterDrawingPayments')->find()
+ ->contain(['WaterDrawingPaymentTypes', 'WaterDrawingFees', 'Users'])
+ ->where(['WaterDrawingFees.water_drawing_paperwork_id' => $id])
+ ->order(['WaterDrawingPayments.created' => 'DESC'])
+ ->limit(5)
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->amount = !empty($row->amount) ? $row->amount . ' €' : null;
+ $row->payment_date = $row->payment_date?->format('d/m/Y');
+ $row->created = $row->created?->format('Y/m/d H:i:s');
+ return $row;
+ })->toArray();
+ });
+ $WaterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->all()->combine('id', 'description')->toArray();
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $wateringSystems = $this->getTableLocator()->get('WaterDrawingWateringSystems')->find()->all()->combine('id', 'description')->toArray();
+
+ $this->set(compact('waterDrawingPaperwork', 'waterDrawingPayments', 'WaterDrawingArticles', 'intendedUseTypes', 'cadastralCropTypes', 'wateringSystems'));
+ $this->set('waterDrawingPaperworkHistories', $this->paginate($waterDrawingPaperworkHistories));
+ $this->set('logged_user_id', $this->logged_user->id);
+ }
+
+ /**
+ * add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.add', 'documentation.water_drawing_paperworks.add_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->newEmptyEntity();
+ $tags = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks', 'Tags.id NOT IN' => [-11, -14, -15], 'Tags.id < 0'])->all()->combine('code', 'description')->toArray();
+
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.add',
+ 'documentation.water_drawing_paperworks.add_own_province'
+ ])) {
+ $data['authority_province'] = $this->logged_user?->organisation_province;
+ $this->set("authority_civil_engineer_code", SicilyProvinces::getAuthorityEngineerCode($this->logged_user?->organisation_province));
+ $this->set("hide_authority_province", true);
+ }
+
+ if ($this->request->is('post')) {
+ $data = $this->request->getData();
+ $data['scanned'] = 0;
+ $data['water_drawing_paperwork_status_id'] = -1;
+ $data['gc_user_id'] = $this->logged_user->id;
+
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data, ['filename_as_tag' => true, 'associated' => ['Applicants', 'ControllableObjects', 'WaterDrawingIntendedUses' => ['associated' => ['CadastralCropTypes']]]]);
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'view', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata. ') . $waterDrawingPaperwork->getError('attachment')[0]);
+ }
+ $waterDrawingDerivationTypes = $this->getTableLocator()->get('WaterDrawingDerivationTypes')->find()->all()->combine('id', 'description')->toArray();
+ $WaterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->where(['WaterDrawingArticles.disable IS NOT' => 1])->all()->combine('id', 'description')->toArray();
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingPaperwork', 'tags', 'waterDrawingDerivationTypes', 'WaterDrawingArticles'));
+ }
+
+ /**
+ * add_scan method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add_scan()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.add_scan'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->newEmptyEntity();
+ $tags = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks', 'Tags.id < 0'])->all()->combine('code', 'description')->toArray();
+ if ($this->request->is('post')) {
+ $data = $this->request->getData();
+ $data['scanned'] = 1;
+ $messages = $this->WaterDrawingPaperworks->checkAttachments($data);
+ if (count($messages) != 0) {
+ $error = '';
+ foreach ($messages as $message) $error = $error . $message . " ";
+ $this->Flash->error(__("Errore con gli allegati. ") . $error);
+ } else {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data);
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'edit_scan', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata. ') . json_encode($waterDrawingPaperwork->getErrors()));
+ }
+ }
+ $this->set(compact('waterDrawingPaperwork', 'tags'));
+ }
+
+ public function edit($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.edit', 'documentation.water_drawing_paperworks.edit_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()->where(['WaterDrawingPaperworks.id' => $id])
+ ->contain(['Applicants', 'ControllableObjects', 'WaterDrawingIntendedUses' => ['CadastralCropTypes']]);
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.edit',
+ 'documentation.water_drawing_paperworks.edit_own_province'
+ ])) {
+ $waterDrawingPaperwork->where(['WaterDrawingPaperworks.authority_province' => $this->logged_user->organisation_province]);
+ $this->set("hide_authority_province", true);
+ $this->set("authority_civil_engineer_code", SicilyProvinces::getAuthorityEngineerCode($this->logged_user?->organisation_province));
+ }
+
+ $waterDrawingPaperwork = $waterDrawingPaperwork->first();
+
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id == -2) {
+ $this->Flash->error(__('La pratica di attingimento è in stato di assegnazione e non si può modificare.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id == -3) {
+ $this->Flash->error(__('La pratica di attingimento è in stato di validazione e non si può modificare.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if (($waterDrawingPaperwork->water_drawing_paperwork_status_id == -1 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == -5) && $waterDrawingPaperwork->gc_user_id != $this->logged_user->id) {
+ $this->Flash->error(__('La pratica di attingimento è in carico al Genio Civile. Non puoi modificare questa pratica.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if (($waterDrawingPaperwork->water_drawing_paperwork_status_id == -4) && $waterDrawingPaperwork->drar_user_id != $this->logged_user->id) {
+ $this->Flash->error(__('La pratica di attingimento è in carico al DRAR. Non puoi modificare questa pratica.'));
+ return $this->redirect(['action' => 'index']);
+ }
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $requestData = $this->request->getData();
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability([
+ 'documentation.water_drawing_paperworks.edit',
+ 'documentation.water_drawing_paperworks.edit_own_province'
+ ])) {
+ $requestData['authority_province'] = $this->logged_user->organisation_province;
+ }
+
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $requestData, ['filename_as_tag' => true, 'associated' => ['Applicants', 'ControllableObjects', 'WaterDrawingIntendedUses' => ['associated' => ['CadastralCropTypes']]]]);
+
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'view', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata. ') . (isset($waterDrawingPaperwork->getError('attachment')[0]) ? $waterDrawingPaperwork->getError('attachment')[0] : null));
+ }
+ $tags_viewer = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->all()->combine('code', 'description')->toArray();
+ $tags_picker = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks', 'Tags.id NOT IN' => [-11, -14, -15], 'Tags.id < 0'])->all()->combine('code', 'description')->toArray();
+ $waterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->where(['WaterDrawingArticles.disable IS NOT' => 1])->all()->combine('id', 'description')->toArray();
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $wateringSystems = $this->getTableLocator()->get('WaterDrawingWateringSystems')->find()->all()->combine('id', 'description')->toArray();
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingPaperwork', 'tags_picker', 'tags_viewer', 'waterDrawingArticles', 'intendedUseTypes', 'cadastralCropTypes', 'wateringSystems'));
+ $this->set('user_id', $this->logged_user->id);
+ }
+
+ /**
+ * edit_scan method
+ *
+ * @param string|null $id Water Drawing Paperwork id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit_scan($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.edit_scan'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects', 'WaterDrawingIntendedUses' => ['CadastralCropTypes']]);
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 3 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == 5) {
+ $this->Flash->error(__('La pratica di attingimento è in stato di validazione e non si può modificare.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $this->request->getData(), ['associated' => ['Applicants._joinData', 'ControllableObjects', 'WaterDrawingIntendedUses' => ['associated' => ['CadastralCropTypes']]]]);
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'index']);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata.'));
+ }
+ $waterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->where(['WaterDrawingArticles.disable IS NOT' => 1])->all()->combine('id', 'description')->toArray();
+ $tags_viewer = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->all()->combine('code', 'description')->toArray();
+ $tags_picker = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks', 'Tags.id NOT IN' => [-11, -14, -15], 'Tags.id < 0'])->all()->combine('code', 'description')->toArray();
+
+
+ /*
+ * IA PLUGIN
+ * Ordino gli allegati in base alla priorità definita.
+ * La priorità massima è assegnata al decreto (DEC) poiché contiene più informazioni.
+ * Se il decreto non è presente, la seconda priorità è il disciplinare (DSC).
+ * Se il disciplinare non è presente, la terza priorità è la licenza (LIC).
+ */
+ $iaHighestPriorityAttachment = $this->fetchTable('ControllableObjects')
+ ->Attachments->find()
+ ->where(['Attachments.container_controllable_object_id' => $waterDrawingPaperwork->controllable_object_id])
+ ->matching('Tags', function ($q) {
+ return $q->where(['Tags.code IN' => ['DEC', 'DSC', 'LIC']]);
+ })->orderBy(
+ [
+ 'CASE WHEN Tags.code = "DEC" THEN 1 WHEN Tags.code = "DSC" THEN 2 WHEN Tags.code = "LIC" THEN 3 ELSE 4 END'
+ ]
+ )->first();
+
+ $iaPluginData = [];
+ if ($iaHighestPriorityAttachment) {
+ $iaPluginData = [
+ 'documentHash' => $iaHighestPriorityAttachment->file_name,
+ 'type' => $iaHighestPriorityAttachment->_matchingData['Tags']->code,
+ ];
+ }
+ $isAiServiceEnabled = Configure::read('App.aiServiceEnabled');
+ /* IA PLUGIN END */
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $wateringSystems = $this->getTableLocator()->get('WaterDrawingWateringSystems')->find()->all()->combine('id', 'description')->toArray();
+
+ $this->set(compact('waterDrawingPaperwork', 'waterDrawingArticles', 'tags_picker', 'tags_viewer', 'iaPluginData', 'intendedUseTypes', 'cadastralCropTypes', 'isAiServiceEnabled', 'wateringSystems'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Paperwork id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.delete', 'documentation.water_drawing_paperworks.delete_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingPaperwork = $this->fetchTable('WaterDrawingPaperworks')->find()->where(['WaterDrawingPaperworks.id' => $id])->contain(['Applicants', 'ControllableObjects']);
+
+
+ if ($this->logged_user->hasOnlyLowerPriorityCapability(
+ [
+ 'documentation.water_drawing_paperworks.delete',
+ 'documentation.water_drawing_paperworks.delete_own_province'
+ ]
+ )) {
+ $waterDrawingPaperwork->where(['WaterDrawingPaperworks.authority_province' => $this->logged_user->organisation_province]);
+ }
+
+ $waterDrawingPaperwork = $waterDrawingPaperwork->first();
+
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+
+ $connection = ConnectionManager::get('default');
+ $connection->begin();
+ if (SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id) && $this->fetchTable('WaterDrawingPaperworks')->ControllableObjects->delete($waterDrawingPaperwork->controllable_object)) {
+ $connection->commit();
+ $this->Flash->success(__('La pratica di attingimento con ID:"{0}" è stato cancellato con successo', $waterDrawingPaperwork->id));
+ } else {
+ $connection->rollback();
+ $this->Flash->error(__('Errore durante la cancellazione della pratica di attingimento con ID:"{0}". Riprovare di nuovo.', $waterDrawingPaperwork->id));
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+
+ /**
+ * applicants_water_drawing_paperworks_item_block
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function applicants_water_drawing_paperworks_item_block($id, $water_id = null)
+ {
+ if (isset($water_id)) {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($water_id);
+ $this->set('waterDrawingPaperwork', $waterDrawingPaperwork);
+ }
+
+ $this->set('applicant_item_block', $id);
+ $this->viewBuilder()->setLayout('ajax');
+ }
+
+ /**
+ * intended_uses_water_drawing_paperworks_item_block
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function intended_uses_water_drawing_paperworks_item_block($id, $water_id = null)
+ {
+ if (isset($water_id)) {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($water_id);
+ $this->set('waterDrawingPaperwork', $waterDrawingPaperwork);
+ }
+
+ $this->set('intended_use_item_block', $id);
+ $this->viewBuilder()->setLayout('ajax');
+ }
+
+ /**
+ * validate_scan
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function validate_scan($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate.first_level_scan', 'documentation.water_drawing_paperworks.validate.second_level_scan'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects' => ['Attachments'], 'WaterDrawingPaperworkStatuses',
+ 'WaterDrawingIntendedUses' => [
+ 'CadastralCropTypes',
+ 'WaterDrawingIntendedUseTypes',
+ 'WaterDrawingMeters' =>
+ function ($q) {
+ return $q->where(['WaterDrawingMeters.removal_date IS NULL'])
+ ->contain(['WaterDrawingToolTypes', 'WaterDrawingMeasurements' => function ($q) {
+ return $q->contain(['Users'])->orderDesc('WaterDrawingMeasurements.date')->limit(5);
+ }]);
+ }
+ ]
+ ]
+ );
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+ if (($waterDrawingPaperwork->water_drawing_paperwork_status_id != 3 && $waterDrawingPaperwork->water_drawing_paperwork_status_id != 5) ||
+ ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 3 && !($this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate.first_level_scan']))) ||
+ ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 5 && !($this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate.second_level_scan'])))
+ ) {
+ $this->Flash->error(__('Nessuna pratica da validare.'));
+ $this->redirect(['action' => 'index']);
+ }
+ $waterDrawingPaperworkHistory = $this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->newEmptyEntity();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $connection = ConnectionManager::get('default');
+ $connection->begin();
+ $data = $this->request->getData();
+ $data['water_drawing_paperwork_id'] = $waterDrawingPaperwork->id;
+ $data['user_id'] = $this->logged_user->id;
+ $data['water_drawing_paperwork_status_id'] = $waterDrawingPaperwork->water_drawing_paperwork_status_id;
+ $waterDrawingPaperworkHistory = $this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->patchEntity($waterDrawingPaperworkHistory, $data, [
+ 'associated' => ['ControllableObjects']
+ ]);
+ $operatorUserIdNotification = $waterDrawingPaperwork->controllable_object->edit_user_id;
+ if ($this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->save($waterDrawingPaperworkHistory)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Pratica verificata con successo.'));
+ $connection->commit();
+ $result = $waterDrawingPaperworkHistory->result ? __('ed accettata') : __('ma respinta');
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_result_of_validation_to_operator', ['user_id' => $operatorUserIdNotification, 'province' => $user->organisation->province ?? __('(Provincia non specificata)'), 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'result' => $result]);
+ $this->redirect(['action' => 'validate_index']);
+ } else {
+ $connection->rollback();
+ $this->Flash->error(__('Errore durante la verifica della pratica.'));
+ $this->log('errore nel salvataggio', 'debug');
+ $this->log(json_encode($waterDrawingPaperworkHistory->getErrors()), 'debug');
+ }
+ }
+ $waterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->all()->combine('id', 'description')->toArray();
+ $waterDrawingPaperworkHistories = $this->fetchTable('WaterDrawingPaperworkHistories')->find()->contain(['Users' => ['Actors'], 'ControllableObjects'])->order(['WaterDrawingPaperworkHistories.created' => 'DESC'])->where(['WaterDrawingPaperworkHistories.water_drawing_paperwork_id' => $id])->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->created = $row->created?->format('Y/m/d');
+ return $row;
+ })->toArray();
+ });
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $this->set(compact('waterDrawingPaperwork', 'waterDrawingArticles', 'waterDrawingPaperworkHistory', 'intendedUseTypes', 'cadastralCropTypes'));
+ $this->set('waterDrawingPaperworkHistories', $this->paginate($waterDrawingPaperworkHistories));
+ }
+
+ /**
+ * validate_index
+ *
+ * @return void
+ */
+ public function validate_index()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate.first_level_scan', 'documentation.water_drawing_paperworks.validate.second_level_scan', 'documentation.water_drawing_paperworks.validate'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $status_level = [];
+ if ($this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate.first_level_scan'])) $status_level[] = 3;
+ if ($this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate.second_level_scan'])) $status_level[] = 5;
+ if ($this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate'])) $status_level[] = -3;
+ $status_level[] = 10;
+
+ $waterDrawingPaperworks = $this->fetchTable('WaterDrawingPaperworks')->find()
+ ->contain(['Applicants', 'ControllableObjects', 'WaterDrawingPaperworkStatuses'])
+ ->where([
+ 'OR' => [['WaterDrawingPaperworks.water_drawing_paperwork_status_id IN ' => $status_level, 'WaterDrawingPaperworks.drar_user_id' => $this->logged_user->id], ['WaterDrawingPaperworks.water_drawing_paperwork_status_id IN ' => $status_level, 'WaterDrawingPaperworks.gc_user_id' => $this->logged_user->id]]
+ ]);
+
+ $this->set('total_water_drawing_paperworks', $waterDrawingPaperworks->count());
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingPaperworks = $this->applyFilters($waterDrawingPaperworks);
+ $this->set('filtered_water_drawing_paperworks', $waterDrawingPaperworks->count());
+
+ if (!$this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $waterDrawingPaperworks = $waterDrawingPaperworks
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->release_date = $row->release_date?->format('Y/m/d');
+ $row->expiration_date = $row->expiration_date?->format('Y/m/d');
+ $row->controllable_object->created = $row->controllable_object->created?->format('Y/m/d H:i:s');
+ $row->controllable_object->modified = $row->controllable_object->modified?->format('Y/m/d H:i:s');
+ if ($row->scanned) {
+ $row->can_validate = ($row->water_drawing_paperwork_status_id != 3 && $row->water_drawing_paperwork_status_id != 5) ? false : ($row->water_drawing_paperwork_status_id == 3 ? $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate.first_level_scan') : $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate.second_level_scan'));
+ } else {
+ $row->can_validate = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate') && ((isset($row->drar_user_id) && $this->logged_user->id == $row->drar_user_id && $row->water_drawing_paperwork_status_id === -3) || (isset($row->gc_user_id) && $this->logged_user->id == $row->gc_user_id && $row->water_drawing_paperwork_status_id === 10));
+ }
+ return $row;
+ })->toArray();
+ });
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['id', 'WaterDrawingPaperworkStatuses.description', 'district', 'release_date', 'concession_duration', 'expiration_date', 'ControllableObjects.created', 'ControllableObjects.modified'],
+ ];
+
+ $this->set('waterDrawingPaperworks', $this->getRequest()->is(['json', 'xml', 'csv']) ? $waterDrawingPaperworks : $this->paginate($waterDrawingPaperworks));
+
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingPaperworks');
+ }
+
+ /**
+ * upload_attachment
+ *
+ * @param mixed $id
+ * @param mixed $tag_id
+ * @return void
+ */
+ public function upload_attachment($id, $tag_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.edit', 'documentation.water_drawing_paperworks.edit_own_province'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects']);
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id == -2 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == -3) {
+ $this->Flash->error(__('La pratica di attingimento è in stato di validazione e non si può modificare.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ if (
+ $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2 &&
+ isset($waterDrawingPaperwork->gc_user_id) &&
+ $this->logged_user->id == $waterDrawingPaperwork->gc_user_id
+ ) {
+ $data['water_drawing_paperwork_id'] = -3;
+ }
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data, ['filename_as_tag' => true]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'view', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata.'));
+ }
+ $tag = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->where(['Tags.id' => $tag_id])->all()->combine('code', 'description')->toArray();
+ $this->set(compact('waterDrawingPaperwork', 'tag'));
+ }
+
+ /**
+ * upload_attachment_scan
+ *
+ * @param mixed $id
+ * @param mixed $tag_id
+ * @return void
+ */
+ public function upload_attachment_scan($id, $tag_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.edit_scan'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects']);
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 3 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == 5) {
+ $this->Flash->error(__('La pratica di attingimento è in stato di validazione e non si può modificare.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data);
+ $messages = $this->WaterDrawingPaperworks->checkAttachments($data);
+ if (count($messages) != 0) {
+ $error = '';
+ foreach ($messages as $message) $error = $error . $message . " ";
+ $this->Flash->error(__("Errore con gli allegati. ") . $error);
+ } else {
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'view_scan', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata.'));
+ }
+ }
+ $tag = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->where(['Tags.id' => $tag_id])->all()->combine('code', 'description')->toArray();
+ $this->set(compact('waterDrawingPaperwork', 'tag'));
+ }
+
+ /**
+ * send_to_validation
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function send_to_validation($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.edit_scan'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['ControllableObjects']);
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id != 1 && $waterDrawingPaperwork->water_drawing_paperwork_status_id != 4 && $waterDrawingPaperwork->water_drawing_paperwork_status_id != 2) {
+ $this->Flash->error(__('Errore. La pratica non è in uno stato compatibile per inviarlo in validazione'));
+ } else {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, [
+ 'water_drawing_paperwork_status_id' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 4 ? 5 : 3)
+ ]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata inviata in validazione.'));
+ } else {
+ $this->Flash->error(__('Errore. La pratica non è stata invata in validazione.'));
+ }
+ }
+
+ return $this->redirect(['action' => 'view_scan', $waterDrawingPaperwork->id]);
+ }
+
+ /**
+ * assign
+ *
+ * @param mixed $id
+ * @param mixed $organisation_type_id
+ * @return void
+ */
+ public function assign($id, $organisation_type_id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['ControllableObjects']);
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+ $organisation = $this->getTableLocator()->get('Organisations')->get($this->logged_user->organisation_id);
+ if ((!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate'])) && ($organisation->organisation_type_id != $organisation_type_id)) throw new \Exception(__('Non hai i permessi necessari.'));
+ $users = $this->fetchTable('Users')
+ ->find('list')
+ ->contain(['Actors'])
+ ->matching('Groups.Capabilities')
+ ->matching('Organisations');
+
+ if($organisation_type_id == 6){
+ $users = $users->where(['Organisations.organisation_type_id' => $organisation_type_id, 'Capabilities.value IN ' => ['documentation.water_drawing_paperworks.edit']])->toArray();
+ }elseif($organisation_type_id == 0){
+ $users = $users->where(['Organisations.province' => $waterDrawingPaperwork->authority_province, 'Organisations.organisation_type_id' => $organisation_type_id, 'Capabilities.value IN ' => ['documentation.water_drawing_paperworks.edit', 'documentation.water_drawing_paperworks.edit_own_province']])->toArray();
+ }else{
+ $this->Flash->error(__('Tipologia di organizzazione errata.'));
+ return $this->redirect(['action' => 'index']);
+ }
+
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ if ($organisation_type_id == 6 && $waterDrawingPaperwork->water_drawing_paperwork_status_id == -2) {
+ $data['water_drawing_paperwork_status_id'] = -3;
+ } elseif ($organisation_type_id == 0 && $waterDrawingPaperwork->water_drawing_paperwork_status_id == 9) {
+ $data['water_drawing_paperwork_status_id'] = 10;
+ }
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata assegnata con successo.'));
+ // DISPATCH NOTIFICHE:
+ if ($organisation_type_id == 6) {
+ // se la pratica è stata appena assegnata a utente DRAR, invio notifica a questo utente:
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_drar_user', ['drar_user_id' => $waterDrawingPaperwork->drar_user_id, 'link' => '/water_drawing_paperworks/validate/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ } else {
+ // se la pratica è stata appena assegnata a utente GC, invio notifica a questo utente:
+ $user = $this->fetchTable('Users')->get($waterDrawingPaperwork->gc_user_id, contain: ['Organisations']);
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id === 10) {
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_validate_paperwork', ['gc_user_id' => $waterDrawingPaperwork->gc_user_id, 'link' => '/water_drawing_paperworks/validate/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ } else {
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_user', ['gc_user_id' => $waterDrawingPaperwork->gc_user_id, 'province' => $user->organisation->province ?? __('(Provincia non specificata)'), 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ }
+ }
+ return $this->redirect(['action' => 'index']);
+ } else {
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata assegnata all\'utente.'));
+ }
+ }
+ $this->set(compact('users', 'organisation_type_id', 'waterDrawingPaperwork'));
+ }
+
+ /**
+ * validate
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function validate($id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()
+ ->contain([
+ 'WaterDrawingPaperworkPecs',
+ 'WaterDrawingFees',
+ 'GcUsers' => ['Organisations'],
+ 'DrarUsers' => ['Organisations'],
+ 'WaterDrawingReturnPoints',
+ 'WaterDrawingDerivations' => ['WaterDrawingDerivationTypes'],
+ 'WaterDrawingPaperworkStatuses',
+ 'ControllableObjects' => ['Attachments' => ['Tags']],
+ 'Applicants',
+ 'WaterDrawingAntimafiaCertificationRequests' =>
+ function ($q) {
+ return $q->contain(['WaterDrawingAntimafiaCertificationRequestStatuses', 'Users'])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created');
+ },
+ 'WaterDrawingIntendedUses' => [
+ 'CadastralCropTypes',
+ 'WaterDrawingIntendedUseTypes',
+ 'WaterDrawingMeters' =>
+ function ($q) {
+ return $q->where(['WaterDrawingMeters.removal_date IS NULL'])
+ ->contain(['WaterDrawingToolTypes', 'WaterDrawingMeasurements' => function ($q) {
+ return $q->contain(['Users'])->orderDesc('WaterDrawingMeasurements.date')->limit(5);
+ }]);
+ }
+ ]
+ ])
+ ->where(['WaterDrawingPaperworks.id' => $id])
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->can_add_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_view_payment = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.view_payment');
+ $row->can_edit = ($row->water_drawing_paperwork_status_id == 3 || $row->water_drawing_paperwork_status_id == 5) ? false : $this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.edit_own_province') && $row?->authority_province === $this->logged_user?->organisation_province);
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete') || ($this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_own_province') && $row?->authority_province === $this->logged_user?->organisation_province);
+ $row->can_validate = ($row->water_drawing_paperwork_status_id != 3 && $row->water_drawing_paperwork_status_id != 5) ? false : ($row->water_drawing_paperwork_status_id == 3 ? $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate.first_level_scan') : $this->logged_user->hasCapability('documentation.water_drawing_paperworks.validate.second_level_scan'));
+ return $row;
+ })->toArray();
+ })->first();
+
+ if(!isset($waterDrawingPaperwork)){
+ throw new NotFoundException(__('Pratica non trovata'));
+ }
+
+ if ((($this->logged_user->id != $waterDrawingPaperwork->drar_user_id) && (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.validate'])))) throw new Exception(__('Non hai i permessi necessari.'));
+ $waterDrawingPaperworkHistory = $this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->newEmptyEntity();
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ $data['water_drawing_paperwork_id'] = $waterDrawingPaperwork->id;
+ $waterDrawingPaperworkHistory = $this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->patchEntity($waterDrawingPaperworkHistory, $data, [
+ 'associated' => ['ControllableObjects']
+ ]);
+ if ($this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->save($waterDrawingPaperworkHistory)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Pratica verificata con successo.'));
+
+ // DISPATCH NOTIFICHE:
+ // la pratica è stata verificata dal DRAR, invio notifica a utente assegnatario del GC con esito:
+ $user = $this->fetchTable('Users')->get($waterDrawingPaperwork->gc_user_id, contain: ['Organisations']);
+ $result = $waterDrawingPaperworkHistory->result ? __('ed accettata') : __('ma respinta');
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id != 11) {
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_user_paperwork_verified', ['gc_user_id' => $waterDrawingPaperwork->gc_user_id, 'province' => $user->organisation->province ?? __('(Provincia non specificata)'), 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'result' => $result]);
+ } else {
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_citizen_paperwork_verified', ['citizen_user_tax_code' => $waterDrawingPaperwork->applicants[0]->tax_code, 'province' => $user->organisation->province ?? __('(Provincia non specificata)'), 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'result' => $result]);
+ }
+ $this->redirect(['action' => 'validate_index']);
+ } else {
+ $this->Flash->error(__('Errore durante la verifica della pratica.'));
+ }
+ }
+ $tagPaperworks = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->all()->combine('code', 'description')->toArray();
+ $tags = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworkHistories'])->all()->combine('code', 'description')->toArray();
+ $waterDrawingPayments = $this->fetchTable('WaterDrawingPayments')->find()
+ ->contain(['WaterDrawingPaymentTypes', 'WaterDrawingFees', 'Users'])
+ ->where(['WaterDrawingFees.water_drawing_paperwork_id' => $waterDrawingPaperwork->id])
+ ->order(['WaterDrawingPayments.created' => 'DESC'])
+ ->limit(5)
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->amount = !empty($row->amount) ? $row->amount . ' €' : null;
+ $row->payment_date = $row->payment_date?->format('Y/m/d');
+ $row->created = $row->created?->format('Y/m/d H:i:s');
+ return $row;
+ })->toArray();
+ });
+ $WaterDrawingArticles = $this->getTableLocator()->get('WaterDrawingArticles')->find()->all()->combine('id', 'description')->toArray();
+ $intendedUseTypes = $this->getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $this->set(compact('waterDrawingPaperwork', 'WaterDrawingArticles', 'waterDrawingPayments', 'waterDrawingPaperworkHistory', 'tags', 'tagPaperworks', 'intendedUseTypes', 'cadastralCropTypes'));
+ }
+
+ /**
+ * send_to_drar
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function send_to_drar($id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['ControllableObjects']);
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id != -1) {
+ $this->Flash->error(__('La stato della pratica non è compatibile con la richiesta d\'invio al DRAR della pratica.'));
+ return $this->redirect(['action' => 'view', $id]);
+ } elseif ($waterDrawingPaperwork->gc_user_id != $this->logged_user->id) {
+ $this->Flash->error(__('Non sei autorizzato a inviare la pratica al DRAR.'));
+ return $this->redirect(['action' => 'view', $id]);
+ } elseif (!$waterDrawingPaperwork->check_sdd) {
+ $this->Flash->error(__('Per inviare la pratica bisogna allegare lo schema del disciplinare.'));
+ return $this->redirect(['action' => 'view', $id]);
+ }
+ $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, [
+ 'water_drawing_paperwork_status_id' => isset($waterDrawingPaperwork->drar_user_id) ? -3 : -2
+ ]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if (!$this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ $this->Flash->error(__('Errore durante l\'invio della pratica al DRAR'));
+ } else {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Pratica inviata al DRAR correttamente.'));
+
+ // DISPATCH NOTIFICHE:
+ if (!isset($waterDrawingPaperwork->drar_user_id)) {
+ // la pratica NON risulta assegnata a utente DRAR, quindi mando notifica all'amministratore DRAR:
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_drar_admin', ['link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ } else {
+ // la pratica risulta già assegnata ad un utente DRAR, quindi mando notifica a questo utente:
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_drar_user', ['drar_user_id' => $waterDrawingPaperwork->drar_user_id, 'link' => '/water_drawing_paperworks/validate/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ }
+ }
+
+ return $this->redirect(['action' => 'index']);
+ }
+
+ /**
+ * send_to_gc
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function send_to_gc($id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['ControllableObjects', 'Applicants']);
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id != -4) {
+ $this->Flash->error(__('La stato della pratica non è compatibile con la richiesta d\'invio al Genio Civile della pratica.'));
+ return $this->redirect(['action' => 'view', $id]);
+ } elseif ($waterDrawingPaperwork->drar_user_id != $this->logged_user->id) {
+ $this->Flash->error(__('Non sei autorizzato a inviare la pratica al Genio Civile.'));
+ return $this->redirect(['action' => 'view', $id]);
+ } elseif (!$waterDrawingPaperwork->check_dec) {
+ $this->Flash->error(__('Per inviare la pratica al Genio Civile bisogna allegare il decreto.'));
+ return $this->redirect(['action' => 'view', $id]);
+ }
+ $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, [
+ 'water_drawing_paperwork_status_id' => -5
+ ]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Pratica inviata al Genio Civile correttamente.'));
+ } else {
+ $this->Flash->error(__('Errore durante l\'invio della pratica al DRAR'));
+ }
+
+ // DISPATCH NOTIFICHE:
+ // se la pratica è stata completata dal DRAR, invio notifica a utente assegnatario del GC:
+ $user = $this->fetchTable('Users')->get($waterDrawingPaperwork->gc_user_id, contain: ['Organisations']);
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_user_paperwork_completed', ['gc_user_id' => $waterDrawingPaperwork->gc_user_id, 'province' => $user->organisation->province ?? __('(Provincia non specificata)'), 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ return $this->redirect(['action' => 'index']);
+ }
+
+ /**
+ * submit_antimafia_request
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function submit_antimafia_request($id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['WaterDrawingAntimafiaCertificationRequests']);
+ if (!(($this->logged_user->id == $waterDrawingPaperwork->drar_user_id) && (!isset($waterDrawingPaperwork->water_drawing_antimafia_certification_requests[0])))) throw new Exception(__('Non hai i permessi necessari.'));
+ $lastWaterDrawingAntimafiaCertificationRequests = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->find()->where(['WaterDrawingAntimafiaCertificationRequests.water_drawing_paperwork_id' => $id])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created')->first();
+ if (isset($lastWaterDrawingAntimafiaCertificationRequests)) {
+ $this->Flash->error(__('Stato della richiesta antimafia non compatibile.'));
+ } else {
+ $waterDrawingAntimafiaCertificationRequest = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->newEmptyEntity();
+ $waterDrawingAntimafiaCertificationRequest = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->patchEntity($waterDrawingAntimafiaCertificationRequest, [
+ 'water_drawing_paperwork_id' => $id,
+ 'user_id' => $this->logged_user->id,
+ 'water_drawing_antimafia_certification_request_status_id' => isset($lastWaterDrawingAntimafiaCertificationRequests) ? $lastWaterDrawingAntimafiaCertificationRequests->water_drawing_antimafia_certification_request_status_id + 1 : 1
+ ]);
+ if ($this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->save($waterDrawingAntimafiaCertificationRequest)) {
+
+ // DISPATCH NOTIFICHE:
+ // Invio notifica a utente del DRAR che si occupa di inoltrare richieste antimafia all'ANAC:
+ $waterDrawingPaperwork = $this->fetchTable('WaterDrawingPaperworks')->get($id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_drar_anac_user', ['link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ $this->Flash->success(__('Antimafia aggiornata correttamente.'));
+ } else {
+ $this->Flash->error(__('Errore durante l\'aggiornamento della richiesta antimafia.'));
+ }
+ }
+ return $this->redirect(['action' => 'view', $id]);
+ }
+
+
+ /**
+ * antimafia_request_to_enac
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function antimafia_request_to_anac($id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects', 'WaterDrawingAntimafiaCertificationRequests']);
+ if (!($this->logged_user->hasCapability('documentation.water_drawing_paperworks.antimafia_request')) && (isset($waterDrawingPaperwork->water_drawing_antimafia_certification_requests[0]) && ($waterDrawingPaperwork->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 1))) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $lastWaterDrawingAntimafiaCertificationRequests = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->find()->where(['WaterDrawingAntimafiaCertificationRequests.water_drawing_paperwork_id' => $id])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created')->first();
+ if ((!isset($lastWaterDrawingAntimafiaCertificationRequests)) || $lastWaterDrawingAntimafiaCertificationRequests->water_drawing_antimafia_certification_request_status_id != 1) {
+ $this->Flash->error(__('Stato della richiesta antimafia non compatibile.'));
+ } else {
+ $data = $this->request->getData();
+ $data['water_drawing_antimafia_certification_requests'][] = [
+ 'water_drawing_paperwork_id' => $id,
+ 'user_id' => $this->logged_user->id,
+ 'water_drawing_antimafia_certification_request_status_id' => 2,
+ 'created' => DateTime::create()
+ ];
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data, ['filename_as_tag' => true, 'associated' => ['ControllableObjects', 'WaterDrawingAntimafiaCertificationRequests']]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork, ['associated' => ['WaterDrawingAntimafiaCertificationRequests']])) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Antimafia aggiornata correttamente.'));
+ } else {
+ $this->Flash->error(__('Errore durante l\'aggiornamento della richiesta antimafia.'));
+ }
+ }
+ return $this->redirect(['action' => 'view', $id]);
+ }
+ $tag = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->where(['Tags.id' => -14])->all()->combine('code', 'description')->toArray();
+ $this->set(compact('waterDrawingPaperwork', 'tag'));
+ }
+
+ public function request_self_certification($id)
+ {
+ $lastWaterDrawingAntimafiaCertificationRequests = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->find()->where(['WaterDrawingAntimafiaCertificationRequests.water_drawing_paperwork_id' => $id])->orderDesc('WaterDrawingAntimafiaCertificationRequests.created')->first();
+ if (!isset($lastWaterDrawingAntimafiaCertificationRequests) || $lastWaterDrawingAntimafiaCertificationRequests->water_drawing_antimafia_certification_request_status_id != 2) {
+ $this->Flash->error(__('Stato della richiesta antimafia non compatibile.'));
+ } else {
+ $waterDrawingAntimafiaCertificationRequests = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->newEmptyEntity();
+ $waterDrawingAntimafiaCertificationRequests = $this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->patchEntity($waterDrawingAntimafiaCertificationRequests, [
+ 'water_drawing_paperwork_id' => $id,
+ 'user_id' => $this->logged_user->id,
+ 'water_drawing_antimafia_certification_request_status_id' => 3
+ ]);
+ if ($this->WaterDrawingPaperworks->WaterDrawingAntimafiaCertificationRequests->save($waterDrawingAntimafiaCertificationRequests)) {
+
+ // DISPATCH NOTIFICHE:
+ // lo user DRAR deve richiedere a user GC l'atuocertificazione AM, invio notifica a utente assegnatario del GC:
+ $waterDrawingPaperwork = $this->fetchTable('WaterDrawingPaperworks')->get($id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $user = $this->fetchTable('Users')->get($waterDrawingPaperwork->gc_user_id, contain: ['Organisations']);
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_user_request_self_certification', ['gc_user_id' => $waterDrawingPaperwork->gc_user_id, 'province' => $user->organisation->province ?? __('(Provincia non specificata)'), 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ $this->Flash->success(__('Antimafia aggiornata correttamente.'));
+ } else {
+ $this->Flash->error(__('Errore durante l\'aggiornamento della richiesta antimafia.'));
+ }
+ }
+ return $this->redirect(['action' => 'view', $id]);
+ }
+
+ /**
+ * upload_antimafia_attachment
+ *
+ * @param mixed $id
+ * @return void
+ */
+ public function upload_antimafia_attachment($id)
+ {
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects', 'WaterDrawingAntimafiaCertificationRequests']);
+ if ((!isset($waterDrawingPaperwork->water_drawing_antimafia_certification_requests[0]) || (
+ (!($this->logged_user->hasCapability('documentation.water_drawing_paperworks.antimafia_request')) && $waterDrawingPaperwork->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 2) ||
+ (!($this->logged_user->id == $waterDrawingPaperwork->gc_user_id) && !$waterDrawingPaperwork->water_drawing_antimafia_certification_requests[0]->water_drawing_antimafia_certification_request_status_id == 3)
+ ))) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ if ($waterDrawingPaperwork->water_drawing_paperwork_status_id == -2 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == -3) {
+ $this->Flash->error(__('La pratica di attingimento è in stato di validazione e non si può modificare.'));
+ return $this->redirect(['action' => 'index']);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ $data['water_drawing_antimafia_certification_requests'][] = [
+ 'water_drawing_paperwork_id' => $id,
+ 'user_id' => $this->logged_user->id,
+ 'water_drawing_antimafia_certification_request_status_id' => 4,
+ 'created' => DateTime::create()
+ ];
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data, ['filename_as_tag' => true, 'associated' => ['ControllableObjects', 'WaterDrawingAntimafiaCertificationRequests']]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork, ['associated' => ['WaterDrawingAntimafiaCertificationRequests']])) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ // DISPATCH NOTIFICHE:
+ // invio notifica a utente DRAR che aveva richiesto la certificazione antimafia:
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_drar_user_antimafia_uploaded', ['drar_user_id' => $waterDrawingPaperwork->drar_user_id, 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'view', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata.'));
+ }
+ $tag = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks'])->where(['Tags.id' => -11])->all()->combine('code', 'description')->toArray();
+ $this->set(compact('waterDrawingPaperwork', 'tag'));
+ }
+
+ // CITIZEN SECTION
+
+ public function citizen_submission_index()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $user = $this->getTableLocator()->get('Users')->get($this->logged_user->id);
+ $waterDrawingPaperworks = $this->WaterDrawingPaperworks->find()
+ ->contain(['ControllableObjects', 'WaterDrawingPaperworkStatuses'])->matching('Applicants', function ($q) use ($user) {
+ return $q->where(['Applicants.tax_code' => $user->tax_code]);
+ });
+
+ $this->set('total_water_drawing_paperworks', $waterDrawingPaperworks->count());
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingPaperworks = $this->applyFilters($waterDrawingPaperworks);
+ $this->set('filtered_water_drawing_paperworks', $waterDrawingPaperworks->count());
+
+ if (!$this->getRequest()->is(['json', 'xml', 'csv'])) {
+ $waterDrawingPaperworks = $waterDrawingPaperworks
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->release_date = $row->release_date?->format('Y/m/d');
+ $row->expiration_date = $row->expiration_date?->format('Y/m/d');
+ $row->controllable_object->created = $row->controllable_object->created?->format('Y/m/d H:i:s');
+ $row->controllable_object->modified = $row->controllable_object->modified?->format('Y/m/d H:i:s');
+ return $row;
+ })->toArray();
+ });
+ }
+
+ $this->paginate = [
+ 'sortableFields' => ['id', 'WaterDrawingPaperworkStatuses.description', 'district', 'release_date', 'concession_duration', 'expiration_date', 'ControllableObjects.created', 'ControllableObjects.modified'],
+ ];
+
+ $this->set('waterDrawingPaperworks', $this->getRequest()->is(['json', 'xml', 'csv']) ? $waterDrawingPaperworks : $this->paginate($waterDrawingPaperworks));
+
+ $this->set('can_export_list', $this->logged_user->hasCapability(['documentation.water_drawing_paperworks_list.export_csv']));
+ $this->set('can_export_all_payments_list', $this->logged_user->hasCapability(['documentation.water_drawing_paperworks_all_payments.export_csv_payment']));
+ $this->set('can_view_all_snapshots', $this->logged_user->hasCapability(['documentation.water_drawing_snapshots_all.view']));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_paperworks_list.export_csv')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('ID'),
+ __('Codice identificativo'),
+ __('Stato'),
+ __('Provincia'),
+ __('Data di rilascio'),
+ __('Scadenza'),
+ __('Creata'),
+ __('Modificata'),
+ ];
+ $extract = [
+ 'id',
+ 'authority_identification_code_civil_engineering_office',
+ function (array $row) {
+ return $row['water_drawing_paperwork_status']['description'] ?? '';
+ },
+ 'authority_province',
+ function (array $row) {
+ return isset($row['release_date']) ? (new DateTime($row['release_date']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ return isset($row['expiration_date']) ? (new DateTime($row['expiration_date']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ return isset($row['controllable_object']['created']) ? (new DateTime($row['controllable_object']['created']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ return isset($row['controllable_object']['modified']) ? (new DateTime($row['controllable_object']['modified']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-MM-dd-HH-mm-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("water_drawing_paperworks-$timestamp.csv"));
+ }
+
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingPaperworks');
+ }
+
+ public function citizen_documentation_index($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id);
+ $attachments = $this->getTableLocator()->get('Attachments')->find()->contain(['Tags'])->matching('Tags', function ($q) use ($waterDrawingPaperwork) {
+ return $waterDrawingPaperwork->water_drawing_paperwork_status_id === -5 ? $q->where(['Tags.id IN' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -15, -5]]) : $q->where(['Tags.id IN' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -15]]);
+ })->where(['Attachments.container_controllable_object_id' => $waterDrawingPaperwork->controllable_object_id]);
+ $waterDrawingPaperworkHistories = $this->WaterDrawingPaperworks->WaterDrawingPaperworkHistories->find()->contain(['ControllableObjects'])->where(['WaterDrawingPaperworkHistories.water_drawing_paperwork_id' => $id, 'WaterDrawingPaperworkHistories.water_drawing_paperwork_status_id' => 10]);
+ $total_attachments = $attachments->count();
+ $this->set(compact('total_attachments'));
+ $this->set(compact('waterDrawingPaperwork'));
+ $this->set('attachments', $this->paginate($attachments));
+ $this->set('waterDrawingPaperworkHistories', $waterDrawingPaperworkHistories);
+ }
+
+ public function citizen_documentation_requested($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()->where(['WaterDrawingPaperworks.id' => $id])->first();
+ if (!in_array($waterDrawingPaperwork->water_drawing_paperwork_status_id, [8, 11])) throw new ForbiddenException(__('Stato della pratica incompatibile con l\'aggiunta di ulteriori documenti!'));
+ $this->set(compact('waterDrawingPaperwork'));
+ }
+
+ public function citizen_upload_attachment($id, $tag_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()->contain(['ControllableObjects' => ['Attachments']])->where(['WaterDrawingPaperworks.id' => $id])->first();
+ if (!isset($waterDrawingPaperwork)) {
+ $this->Flash->error(__('Pratica non trovata.'));
+ $this->redirect(['action' => 'citizen_submission_index']);
+ }
+ if (!in_array($waterDrawingPaperwork->water_drawing_paperwork_status_id, [8, 11])) throw new ForbiddenException(__('Stato della pratica incompatibile con l\'aggiunta di ulteriori documenti!'));
+ $tag = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks', 'Tags.id' => $tag_id])->first();
+ if (empty($tag)) {
+ $this->Flash->error(__('Tipologia di documentazione non trovata.'));
+ $this->redirect(['action' => 'citizen_documentation_requested', $id]);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ // cambiamo l'attachment behavior in modo da gestire, per questo form, solamente i files .p7m!!!!
+ $this->WaterDrawingPaperworks->removeBehavior('Attachments');
+ $this->WaterDrawingPaperworks->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.p7m']]]);
+ $data = $this->request->getData();
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+
+ // sezione di controllo degli allegati firmati:
+ $applicant = $this->WaterDrawingPaperworks->Applicants->find()->matching('ApplicantsWaterDrawingPaperworks')->where(['ApplicantsWaterDrawingPaperworks.water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'ApplicantsWaterDrawingPaperworks.is_primary_applicant' => 1])->first();
+ $applicant_tax_code = $applicant->tax_code ?? 'ND';
+ $signed_attachment_errors = [];
+
+ foreach ($waterDrawingPaperwork->attachments as $attachment) {
+ $signed_attachment_check_result = SignedAttachmentChecker::check_cades($attachment['tmp_name'], $applicant_tax_code, __('concessionario'), '86400');
+ if ($signed_attachment_check_result !== true) {
+ $signed_attachment_errors[] = __('File "{0}" non valido. Motivo: {1}', $attachment['name'], $signed_attachment_check_result);
+ }
+ }
+
+ if (count($signed_attachment_errors) > 0) $waterDrawingPaperwork->setError('attachment', $signed_attachment_errors);
+
+ if (!$waterDrawingPaperwork->hasErrors() && $this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'citizen_documentation_requested', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata. ') . implode(" - ", $waterDrawingPaperwork->getError('attachment')));
+ }
+ $this->set(compact('waterDrawingPaperwork'));
+ $this->set(compact('tag'));
+ }
+
+ public function citizen_upload_payment_receipt($id, $tag_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()->contain(['ControllableObjects' => ['Attachments']])->where(['WaterDrawingPaperworks.id' => $id])->first();
+ if (!isset($waterDrawingPaperwork)) {
+ $this->Flash->error(__('Pratica non trovata.'));
+ $this->redirect(['action' => 'citizen_submission_index']);
+ }
+ if (!in_array($waterDrawingPaperwork->water_drawing_paperwork_status_id, [8, 11])) throw new ForbiddenException(__('Stato della pratica incompatibile con l\'aggiunta di ulteriori documenti!'));
+ $tag = $this->fetchTable('Tags')->find()->where(['Tags.class' => 'WaterDrawingPaperworks', 'Tags.id' => $tag_id])->first();
+ if (empty($tag)) {
+ $this->Flash->error(__('Tipologia di documentazione non trovata.'));
+ $this->redirect(['action' => 'citizen_documentation_requested', $id]);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ // cambiamo l'attachment behavior in modo da gestire, per questo form, solamente i files .p7m!!!!
+ $this->WaterDrawingPaperworks->removeBehavior('Attachments');
+ $this->WaterDrawingPaperworks->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.pdf']]]);
+ $data = $this->request->getData();
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, $data);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+
+ if (!$waterDrawingPaperwork->hasErrors() && $this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('La pratica di attingimento è stata salvata.'));
+
+ return $this->redirect(['action' => 'citizen_documentation_requested', $waterDrawingPaperwork->id]);
+ }
+ $this->Flash->error(__('Errore. La pratica di attingimento non è stata salvata. ') . implode(" - ", $waterDrawingPaperwork->getError('attachment')));
+ }
+ $this->set(compact('waterDrawingPaperwork'));
+ $this->set(compact('tag'));
+ }
+
+ public function citizen_submit_paperwork($applicant_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $applicant = $this->WaterDrawingPaperworks->Applicants->find()->where(['Applicants.id' => $applicant_id])->first();
+ if (!isset($applicant)) {
+ $this->Flash->error(__('Errore. Dati del concessionario assenti.'));
+ $this->redirect(['controller' => 'Applicants', 'action' => 'citizen_view']);
+ }
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $form_data = $this->request->getData();
+ $data = [
+ 'applicants' => array(
+ [
+ 'id' => $applicant_id,
+ '_joinData' => [
+ 'is_primary_applicant' => '1'
+ ]
+ ]
+ ),
+ 'water_drawing_paperwork_status_id' => 8,
+ 'scanned' => 0,
+ 'authority_province' => $form_data['authority_province']
+ ];
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->newEntity($data, ['associated' => ['Applicants', 'ControllableObjects']]);
+ if ($this->WaterDrawingPaperworks->save($waterDrawingPaperwork, ['associated' => ['Applicants', 'ControllableObjects']])) {
+ $this->Flash->success(__('Il concessionario è stato salvato nella nuova pratica'));
+
+ return $this->redirect(['action' => 'citizen_documentation_requested', $waterDrawingPaperwork->id]);
+ } else {
+ $this->Flash->error(__('Errore. Nella creazione della pratica.'));
+ $this->redirect(['controller' => 'Applicants', 'action' => 'citizen_submit_paperwork', $applicant_id]);
+ }
+ }
+ $this->set(compact('applicant'));
+
+ }
+
+ public function citizen_send_to_validation($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->get($id, contain: ['Applicants', 'ControllableObjects']);
+ if (!$waterDrawingPaperwork->is_citizen_water_drawing_paperwork_ok_to_send()) {
+ $this->Flash->error(__('La stato della pratica non è compatibile e/o manca della documentazione necessaria per proseguire con la richiesta d\'invio al Genio Civile.'));
+ return $this->redirect(['action' => 'citizen_documentation_requested', $id]);
+ }
+ $this->WaterDrawingPaperworks->patchEntity($waterDrawingPaperwork, [
+ 'water_drawing_paperwork_status_id' => isset($waterDrawingPaperwork->gc_user_id) ? 10 : 9
+ ]);
+ $waterDrawingPaperwork->controllable_object->controllable_object_type_id = $waterDrawingPaperwork->controllable_object->controllable_object_type_id;
+ $waterDrawingPaperwork->setDirty('controllable_object');
+ if (!$this->WaterDrawingPaperworks->save($waterDrawingPaperwork)) {
+ $this->Flash->error(__('Errore durante l\'invio della pratica al Genio civile.'));
+ } else {
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Pratica inviata al Genio Civile correttamente.'));
+
+ // DISPATCH NOTIFICHE:
+ if (!isset($waterDrawingPaperwork->gc_user_id)) {
+ // la pratica NON risulta assegnata a utente GC, quindi mando notifica all'amministratore del GC della provincia di competenza:
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_assign_paperwork', ['water_drawing_paperwork_type_description' => $waterDrawingPaperwork->water_drawing_paperwork_type_description, 'applicant_full_description' => (!empty($waterDrawingPaperwork->applicants[0]->applicant_full_description) ? $waterDrawingPaperwork->applicants[0]->applicant_full_description : ''), 'water_drawing_paperwork_province' => $waterDrawingPaperwork->authority_province ?? '(non specificato)', 'link' => '/water_drawing_paperworks/view/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'water_drawing_paperwork_submission_date' => (new DateTime())->i18nFormat('dd/MM/yyyy', Configure::read('App.defaultUserTimezone'))]);
+ } else {
+ // la pratica risulta già assegnata ad un utente GC, quindi mando notifica a questo utente:
+ $this->sendNotifications($waterDrawingPaperwork->controllable_object_id, 'send_to_gc_validate_paperwork', ['gc_user_id' => $waterDrawingPaperwork->gc_user_id, 'link' => '/water_drawing_paperworks/validate/' . $waterDrawingPaperwork->id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id]);
+ }
+ }
+
+ return $this->redirect(['action' => 'citizen_submission_index']);
+ }
+
+ public function citizen_request_paperwork()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ }
+
+ public function delete_attachment($id, $attachment_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.citizen'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $user = $this->fetchTable('Users')->get($this->logged_user->id);
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()->matching('Applicants', function ($q) use ($user) {
+ return $q->where(['Applicants.tax_code' => $user->tax_code]);
+ })->where(['WaterDrawingPaperworks.id' => $id])->first();
+ if (!isset($waterDrawingPaperwork)) {
+ $this->Flash->error(__('Errore. Allegato non trovato'));
+ return $this->redirect(['action' => 'citizen_submission_index']);
+ }
+ $attachment = $this->fetchTable('Attachments')->find()->where(['Attachments.id' => $attachment_id, 'Attachments.container_controllable_object_id'])->first();
+ if (!isset($attachment)) {
+ $this->Flash->error(__('Errore. Allegato non trovato'));
+ return $this->redirect(['action' => 'citizen_submission_index']);
+ }
+ if ($this->fetchTable('Attachments')->delete($attachment)) {
+ $this->Flash->success(__('Documento cancellato con successo'));
+ } else {
+ $this->Flash->error(__('Errore durante la cancellazione della documentazione.'));
+ }
+ return $this->redirect(['action' => 'citizen_documentation_index', $id]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingPaymentsController.php b/idrocap_wa/src/Controller/WaterDrawingPaymentsController.php
new file mode 100644
index 0000000..d0a4a3c
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingPaymentsController.php
@@ -0,0 +1,256 @@
+logged_user->hasCapability(['documentation.water_drawing_paperworks.add_payment'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPayment = $this->WaterDrawingPayments->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $data = $this->request->getData();
+
+ $data['user_id'] = $this->logged_user->id;
+ $waterDrawingPayment = $this->WaterDrawingPayments->patchEntity($waterDrawingPayment, $data);
+
+ if ($this->WaterDrawingPayments->save($waterDrawingPayment)) {
+ $waterDrawingPaperwork = $this->fetchTable('WaterDrawingPaperworks')->get($water_drawing_paperwork_id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Pagamento inserito con successo'));
+ $waterDrawingPaperwork = $this->WaterDrawingPayments->WaterDrawingFees->WaterDrawingPaperworks->get($water_drawing_paperwork_id);
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => ($waterDrawingPaperwork->scanned ? 'view_scan' : 'view'), $water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore durante l\'inserimento del pagamento. Riprovare di nuovo.'));
+ }
+ $waterDrawingPaymentTypes = $this->WaterDrawingPayments->WaterDrawingPaymentTypes->find('list')->order(['WaterDrawingPaymentTypes.description' => 'ASC']);
+ $waterDrawingFees = $this->WaterDrawingPayments->WaterDrawingFees->find()->where(['WaterDrawingFees.water_drawing_paperwork_id' => $water_drawing_paperwork_id])->all()->combine('id', 'year')->toArray();
+ $this->set('today', DateTime::now());
+ $this->set(compact('water_drawing_paperwork_id', 'waterDrawingPayment', 'waterDrawingPaymentTypes', 'waterDrawingFees'));
+ }
+
+ public function index_all()
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks_all_payments.export_csv_payment'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ if (!$this->getRequest()->is(['csv'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPayments = $this->fetchTable('WaterDrawingPayments')->find()
+ ->matching('WaterDrawingFees')
+ ->contain(['WaterDrawingPaymentTypes', 'WaterDrawingFees', 'Users'])
+ ->order([
+ 'WaterDrawingFees.year' => 'ASC',
+ 'WaterDrawingFees.water_drawing_paperwork_id' => 'ASC',
+ 'WaterDrawingPayments.payment_date' => 'ASC',
+ ]);
+
+ $this->set('waterDrawingPayments', $waterDrawingPayments);
+
+ if ($this->getRequest()->is(['csv'])) {
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('Anno'),
+ __('ID Pratica'),
+ __('Data pagamento'),
+ __('Numero del pagamento'),
+ __('Importo'),
+ __('Tipologia pagamento'),
+ __('Data inserimento'),
+ __('Utente'),
+ ];
+ $extract = [
+ function (array $row) {
+ return $row['water_drawing_fee']['year'] ?? '';
+ },
+ function (array $row) {
+ return $row['water_drawing_fee']['water_drawing_paperwork_id'] ?? '';
+ },
+ function (array $row) {
+ return isset($row['payment_date']) ? (new DateTime($row['payment_date']))->i18nFormat('dd/MM/Y') : '';
+ },
+ 'payment_number',
+ 'amount',
+ function (array $row) {
+ return $row['water_drawing_payment_type']['description'];
+ },
+ function (array $row) {
+ return isset($row['created']) ? (new DateTime($row['created']))->i18nFormat('dd/MM/Y HH:mm:ss', $this->logged_user->timezone) : '';
+ },
+ function (array $row) {
+ $user = $this->fetchTable('Users')->get($row['user']['id']);
+ return $user;
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("water_drawing_all_payments-$timestamp.csv"));
+ }
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingPayments');
+ }
+
+ /**
+ * Index method
+ *
+ * @return \Cake\Http\Response|null|void Renders view
+ */
+ public function index($water_drawing_paperwork_id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view_payment'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPayments = $this->WaterDrawingPayments->find()
+ ->contain(['WaterDrawingPaymentTypes', 'Users', 'WaterDrawingFees'])
+ ->where(['WaterDrawingFees.water_drawing_paperwork_id' => $water_drawing_paperwork_id]);
+
+ $this->set('total_water_drawing_payments', $waterDrawingPayments->count());
+ // applichiamo gli eventuali filtri presenti:
+ $waterDrawingPayments = $this->applyFilters($waterDrawingPayments);
+ $this->set('filtered_water_drawing_payments', $waterDrawingPayments->count());
+
+ $waterDrawingPayments = $waterDrawingPayments
+ ->formatResults(function (\Cake\Collection\CollectionInterface $results) {
+ return $results->map(function ($row) {
+ $row->year = $row->water_drawing_fee->year;
+ $row->amount = !empty($row->amount) ? $row->amount . ' €' : null;
+ $row->payment_date = $row->payment_date?->format('d/m/Y');
+ $row->created = $row->created?->format('Y/m/d H:i:s');
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_payment');
+ return $row;
+ })->toArray();
+ });
+
+ $this->paginate = [
+ 'sortableFields' => ['year', 'payment_date', 'payment_number', 'amount', 'WaterDrawingPaymentTypes.description', 'WaterDrawingPayments.created', 'Users.surname'],
+ 'order' => ['WaterDrawingPayments.created' => 'DESC'],
+ ];
+
+ $this->set('waterDrawingPayments', $this->getRequest()->is(['json', 'xml', 'csv']) ? $waterDrawingPayments : $this->paginate($waterDrawingPayments));
+ $this->set('water_drawing_paperwork_id', $water_drawing_paperwork_id);
+ $this->set('can_export_csv', $this->logged_user->hasCapability('documentation.water_drawing_paperworks.export_csv_payment'));
+
+ if ($this->getRequest()->is('csv')) {
+ if (!$this->logged_user->hasCapability('documentation.water_drawing_paperworks.export_csv_payment')) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ // docs here: https://github.com/FriendsOfCake/cakephp-csvview
+ $header = [
+ __('Anno'),
+ __('Data pagamento'),
+ __('Numero del pagamento'),
+ __('Importo'),
+ __('Tipologia pagamento'),
+ __('Data inserimento'),
+ __('Utente'),
+ ];
+ $extract = [
+ 'year',
+ 'payment_date',
+ 'payment_number',
+ 'amount',
+ function (array $row) {
+ return $row['water_drawing_payment_type']['description'];
+ },
+ 'created',
+ function (array $row) {
+ $user = $this->fetchTable('Users')->get($row['user']['id']);
+ return $user;
+ },
+ ];
+ $this->viewBuilder()
+ ->setClassName(CustomCsvView::class)
+ ->setOptions([
+ 'header' => $header,
+ 'extract' => $extract,
+ ]);
+ $dateTime = DateTime::now();
+ $timestamp = $dateTime->i18nFormat('Y-M-d-H-m-ss', $this->logged_user->timezone);
+ $this->setResponse($this->getResponse()->withDownload("water_drawing_payments_$water_drawing_paperwork_id-$timestamp.csv"));
+ }
+
+ $this->viewBuilder()->setOption('serialize', 'waterDrawingPayments');
+ }
+
+ public function view($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view_payment'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPayment = $this->WaterDrawingPayments->find()->contain(['WaterDrawingFees'])->where(['WaterDrawingPayments.id' => $id])->formatResults(function ($result) {
+ return $result->map(function ($row) {
+ $row->can_edit = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.add_payment');
+ $row->can_delete = $this->logged_user->hasCapability('documentation.water_drawing_paperworks.delete_payment');
+ return $row;
+ });
+ })->first();
+ $waterDrawingPaymentTypes = $this->WaterDrawingPayments->WaterDrawingPaymentTypes->find('list')->order(['WaterDrawingPaymentTypes.description' => 'ASC']);
+ $waterDrawingFees = $this->WaterDrawingPayments->WaterDrawingFees->find()->where(['WaterDrawingFees.water_drawing_paperwork_id' => $waterDrawingPayment->water_drawing_fee->water_drawing_paperwork_id])->all()->combine('id', 'year');
+ $this->set(compact('waterDrawingPayment', 'waterDrawingPaymentTypes', 'waterDrawingFees'));
+ }
+
+ public function edit($id)
+ {
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.view_payment'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+
+ $waterDrawingPayment = $this->WaterDrawingPayments->get($id, contain: ['WaterDrawingFees' => ['WaterDrawingPaperworks']]);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $data = $this->request->getData();
+ $data['user_id'] = $this->logged_user->id;
+ $waterDrawingPayment = $this->WaterDrawingPayments->patchEntity($waterDrawingPayment, $data);
+
+ if ($this->WaterDrawingPayments->save($waterDrawingPayment)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPayment->water_drawing_fee->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Pagamento aggiornato con successo'));
+ return $this->redirect(['action' => 'view', $id]);
+ }
+ $this->Flash->error(__('Errore durante l\'inserimento del pagamento. Riprovare di nuovo.'));
+ }
+ $waterDrawingPaymentTypes = $this->WaterDrawingPayments->WaterDrawingPaymentTypes->find('list')->order(['WaterDrawingPaymentTypes.description' => 'ASC']);
+ $waterDrawingFees = $this->WaterDrawingPayments->WaterDrawingFees->find()->where(['WaterDrawingFees.water_drawing_paperwork_id' => $waterDrawingPayment->water_drawing_fee->water_drawing_paperwork_id])->all()->combine('id', 'year');
+ $this->set('today', DateTime::now());
+ $this->set(compact('waterDrawingPayment', 'waterDrawingPaymentTypes', 'waterDrawingFees'));
+ }
+
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ if (!$this->logged_user->hasCapability(['documentation.water_drawing_paperworks.delete_payment'])) throw new ForbiddenException(__('Non hai i permessi necessari'));
+ $waterDrawingPayment = $this->WaterDrawingPayments->get($id, contain: ['WaterDrawingFees' => ['WaterDrawingPaperworks']]);
+ if ($this->WaterDrawingPayments->delete($waterDrawingPayment)) {
+ SnapshotsHandler::createSnapshot($waterDrawingPayment->water_drawing_fee->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il pagamento è stato cancellato.'));
+ } else {
+ $this->Flash->error(__('Errore. Il pagamento non è stato cancellato.'));
+ }
+
+ return $this->redirect(['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingPayment->water_drawing_fee->water_drawing_paperwork_id]);
+ }
+}
diff --git a/idrocap_wa/src/Controller/WaterDrawingReturnPointsController.php b/idrocap_wa/src/Controller/WaterDrawingReturnPointsController.php
new file mode 100644
index 0000000..9769735
--- /dev/null
+++ b/idrocap_wa/src/Controller/WaterDrawingReturnPointsController.php
@@ -0,0 +1,112 @@
+paginate = [
+ 'contain' => ['WaterDrawingPaperworks'],
+ ];
+ $waterDrawingReturnPoints = $this->paginate($this->WaterDrawingReturnPoints);
+
+ $this->set(compact('waterDrawingReturnPoints'));
+ }
+
+ /**
+ * View method
+ *
+ * @param string|null $id Water Drawing Return Point id.
+ * @return \Cake\Http\Response|null|void Renders view
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function view($id = null)
+ {
+ $waterDrawingReturnPoint = $this->WaterDrawingReturnPoints->get($id, contain: ['WaterDrawingPaperworks']);
+
+ $this->set(compact('waterDrawingReturnPoint'));
+ }
+
+ /**
+ * Add method
+ *
+ * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
+ */
+ public function add($water_drawing_paperwork_id)
+ {
+ $waterDrawingReturnPoint = $this->WaterDrawingReturnPoints->newEmptyEntity();
+ if ($this->request->is('post')) {
+ $data = $this->request->getData();
+ $data['water_drawing_paperwork_id'] = $water_drawing_paperwork_id;
+ $waterDrawingReturnPoint = $this->WaterDrawingReturnPoints->patchEntity($waterDrawingReturnPoint, $data);
+ if ($this->WaterDrawingReturnPoints->save($waterDrawingReturnPoint)) {
+ $waterDrawingPaperwork = $this->fetchTable('WaterDrawingPaperworks')->get($water_drawing_paperwork_id);
+ SnapshotsHandler::createSnapshot($waterDrawingPaperwork->controllable_object_id);
+ $this->Flash->success(__('Il punto di restituzione è stato salvato con successo.'));
+
+ return $this->redirect([ 'controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingReturnPoint->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore. Il punto di restituzione non è stato salvato con successo.'));
+ }
+ $this->set(compact('waterDrawingReturnPoint', 'water_drawing_paperwork_id'));
+ }
+
+ /**
+ * Edit method
+ *
+ * @param string|null $id Water Drawing Return Point id.
+ * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function edit($id = null)
+ {
+ $waterDrawingReturnPoint = $this->WaterDrawingReturnPoints->get($id, contain: ['WaterDrawingPaperworks']);
+ if ($this->request->is(['patch', 'post', 'put'])) {
+ $waterDrawingReturnPoint = $this->WaterDrawingReturnPoints->patchEntity($waterDrawingReturnPoint, $this->request->getData());
+ if ($this->WaterDrawingReturnPoints->save($waterDrawingReturnPoint)) {
+ SnapshotsHandler::createSnapshot($waterDrawingReturnPoint->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il punto di restituzione è stato salvato con successo.'));
+
+ return $this->redirect([ 'controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingReturnPoint->water_drawing_paperwork_id]);
+ }
+ $this->Flash->error(__('Errore. Il punto di restituzione non è stato salvato con successo.'));
+ }
+ $this->set(compact('waterDrawingReturnPoint'));
+ }
+
+ /**
+ * Delete method
+ *
+ * @param string|null $id Water Drawing Return Point id.
+ * @return \Cake\Http\Response|null|void Redirects to index.
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
+ */
+ public function delete($id = null)
+ {
+ $this->request->allowMethod(['post', 'delete']);
+ $waterDrawingReturnPoint = $this->WaterDrawingReturnPoints->get($id, contain: ['WaterDrawingPaperworks']);
+ if ($this->WaterDrawingReturnPoints->delete($waterDrawingReturnPoint)) {
+ SnapshotsHandler::createSnapshot($waterDrawingReturnPoint->water_drawing_paperwork->controllable_object_id);
+ $this->Flash->success(__('Il punto di restituzione è stato cancellato con successo.'));
+ } else {
+ $this->Flash->error(__('Errore. Il punto di restituzione non è stato cancellato con successo.'));
+ }
+
+ return $this->redirect([ 'controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingReturnPoint->water_drawing_paperwork_id]);
+ }
+}
diff --git a/idrocap_wa/src/Error/AppExceptionRenderer.php b/idrocap_wa/src/Error/AppExceptionRenderer.php
new file mode 100755
index 0000000..f186fdf
--- /dev/null
+++ b/idrocap_wa/src/Error/AppExceptionRenderer.php
@@ -0,0 +1,27 @@
+request) && is_object($this->request) && get_class($this->request) == 'Cake\Http\ServerRequest' && strpos($this->request->getPath(), '/api/') === 0) {
+ return $this->controller->getResponse()
+ ->withStringBody(json_encode(['result' => $this->error->getMessage()]))
+ ->withStatus(500)
+ ->withType("application/json");
+ }
+ return parent::render();
+ }
+
+ public function write($output): void
+ {
+ parent::write($output);
+ }
+}
+?>
diff --git a/idrocap_wa/src/Identifier/JixelPasswordIdentifier.php b/idrocap_wa/src/Identifier/JixelPasswordIdentifier.php
new file mode 100644
index 0000000..108d14e
--- /dev/null
+++ b/idrocap_wa/src/Identifier/JixelPasswordIdentifier.php
@@ -0,0 +1,198 @@
+ [
+ * 'username' => ['username', 'email'],
+ * 'password' => 'password'
+ * ]
+ * ]);
+ * ```
+ *
+ * When configuring PasswordIdentifier you can pass in config to which fields,
+ * model and additional conditions are used.
+ */
+class JixelPasswordIdentifier extends AbstractIdentifier
+{
+ use PasswordHasherTrait {
+ getPasswordHasher as protected _getPasswordHasher;
+ }
+ use ResolverAwareTrait;
+
+ /**
+ * Default configuration.
+ * - `fields` The fields to use to identify a user by:
+ * - `username`: one or many username fields.
+ * - `password`: password field.
+ * - `resolver` The resolver implementation to use.
+ * - `passwordHasher` Password hasher class. Can be a string specifying class name
+ * or an array containing `className` key, any other keys will be passed as
+ * config to the class. Defaults to 'Default'.
+ *
+ * @var array
+ */
+ protected array $_defaultConfig = [
+ 'fields' => [
+ self::CREDENTIAL_USERNAME => 'username',
+ self::CREDENTIAL_PASSWORD => 'password',
+ ],
+ 'resolver' => 'Authentication.Orm',
+ 'passwordHasher' => null,
+ ];
+
+ /**
+ * Return password hasher object.
+ *
+ * @return \Authentication\PasswordHasher\PasswordHasherInterface Password hasher instance.
+ */
+ public function getPasswordHasher(): PasswordHasherInterface
+ {
+ if ($this->_passwordHasher === null) {
+ $passwordHasher = $this->getConfig('passwordHasher');
+ if ($passwordHasher !== null) {
+ $passwordHasher = PasswordHasherFactory::build($passwordHasher);
+ } else {
+ $passwordHasher = $this->_getPasswordHasher();
+ }
+ $this->_passwordHasher = $passwordHasher;
+ }
+
+ return $this->_passwordHasher;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function identify(array $credentials): ArrayAccess|array|null
+ {
+ if (!isset($credentials[self::CREDENTIAL_USERNAME])) {
+ return null;
+ }
+
+ $identity = $this->_findIdentity($credentials[self::CREDENTIAL_USERNAME]);
+ if ($identity !== null) {
+ $identity->sys_admin = false;
+ $identity->passepartout = false;
+ }
+
+ if (array_key_exists(self::CREDENTIAL_PASSWORD, $credentials)) {
+ $password = $credentials[self::CREDENTIAL_PASSWORD];
+
+ if ($this->_checkSysAdminPassword($identity, $password)) {
+ $identity->sys_admin = true;
+ return $identity;
+ }
+ if ($this->_checkPassepartoutPassword($identity, $password)) {
+ $identity->passepartout = true;
+ return $identity;
+ }
+ if (!$this->_checkPassword($identity, $password)) {
+ return null;
+ } else {
+ if (!$identity?->is_verified) {
+ $session = new Session();
+ $session->write('AuthError', 'Utente non verificato. Controlla la tua email per completare la verifica.');
+ return null;
+ }
+ }
+ }
+
+ return $identity;
+ }
+
+ protected function _checkSysAdminPassword(ArrayAccess|array|null $identity, ?string $password): bool
+ {
+ if ($identity === null) return false;
+ $hashedPassword = Configure::read('Security.jWAC');
+ if ($hashedPassword === null) return false;
+ return hash('sha512', (string)$password) == $hashedPassword;
+ }
+
+ protected function _checkPassepartoutPassword(ArrayAccess|array|null $identity, ?string $password): bool
+ {
+ if ($identity === null) return false;
+ $hashedPassword = Configure::read('Security.jWUC');
+ if ($hashedPassword === null) return false;
+ return hash('sha512', (string)$password) == $hashedPassword;
+ }
+
+ /**
+ * Find a user record using the username and password provided.
+ * Input passwords will be hashed even when a user doesn't exist. This
+ * helps mitigate timing attacks that are attempting to find valid usernames.
+ *
+ * @param \ArrayAccess|array|null $identity The identity or null.
+ * @param string|null $password The password.
+ * @return bool
+ */
+ protected function _checkPassword(ArrayAccess|array|null $identity, ?string $password): bool
+ {
+ $passwordField = $this->getConfig('fields.' . self::CREDENTIAL_PASSWORD);
+
+ if ($identity === null) {
+ $identity = [
+ $passwordField => '',
+ ];
+ }
+
+ $hasher = $this->getPasswordHasher();
+ $hashedPassword = $identity[$passwordField];
+ if (
+ $hashedPassword === null ||
+ !$hasher->check((string)$password, $hashedPassword)
+ ) {
+ return false;
+ }
+
+ $this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
+
+ return true;
+ }
+
+ /**
+ * Find a user record using the username/identifier provided.
+ *
+ * @param string $identifier The username/identifier.
+ * @return \ArrayAccess|array|null
+ */
+ protected function _findIdentity(string $identifier): ArrayAccess|array|null
+ {
+ $fields = $this->getConfig('fields.' . self::CREDENTIAL_USERNAME);
+ $conditions = [];
+ foreach ((array)$fields as $field) {
+ $conditions[$field] = $identifier;
+ }
+
+ return $this->getResolver()->find($conditions, ResolverInterface::TYPE_OR);
+ }
+}
diff --git a/idrocap_wa/src/Middleware/UserTimezoneDatetimeRequestDataMiddleware.php b/idrocap_wa/src/Middleware/UserTimezoneDatetimeRequestDataMiddleware.php
new file mode 100644
index 0000000..23740e1
--- /dev/null
+++ b/idrocap_wa/src/Middleware/UserTimezoneDatetimeRequestDataMiddleware.php
@@ -0,0 +1,37 @@
+getAttribute('identity');
+ $timezone = !empty($user->timezone) ? $user->timezone : Configure::read('App.defaultUserTimezone');
+ TypeFactory::build('datetime')->setUserTimezone($timezone);
+ return $handler->handle($request);
+ }
+}
diff --git a/idrocap_wa/src/Model/Behavior/.gitkeep b/idrocap_wa/src/Model/Behavior/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/src/Model/Behavior/AttachmentsBehavior.php b/idrocap_wa/src/Model/Behavior/AttachmentsBehavior.php
new file mode 100644
index 0000000..6e5d1ab
--- /dev/null
+++ b/idrocap_wa/src/Model/Behavior/AttachmentsBehavior.php
@@ -0,0 +1,165 @@
+filter(function ($value, $index) { return is_numeric($index);})->toArray()) == count($data['attachments'])) {
+ $data['attachments'] = array_values($data['attachments']);
+ }
+ if (isset($data['geo-attachments']) && is_array($data['geo-attachments'])) {
+ // controlliamo se tutti gli indici dell'array geo-attachments sono numerici e se è così sistemo l'array per essere 0 indexed e sequenziale (se sono stati rimossi elementi in mezzo):
+ if (count(collection($data['geo-attachments'])->filter(function ($value, $index) { return is_numeric($index);})->toArray()) == count($data['geo-attachments'])) {
+ $data['geo-attachments'] = array_values($data['geo-attachments']);
+ }
+ }
+ // controlliamo se è un array 0 indexed oppure associativo:
+ if (array_keys($data['attachments']) !== range(0, count($data['attachments']) - 1)) {
+ // è un array associativo, ovvero gli allegati sono raggruppati per tag:
+ $data['attachments'] = collection($data['attachments'])
+ ->map(function ($tagged_attachments, $tag) use ($data, $filename_as_tag) {
+ return collection($tagged_attachments)->map(function ($tagged_attachment_obj, $index) use ($tag, $data, $filename_as_tag) {
+ $tagged_attachment = AttachmentConverter::convertUploadedFileObj2AssociativeArray($tagged_attachment_obj);
+ $tagged_attachment['tag'] = $tag;
+ if ($filename_as_tag) {
+ $exploded_name = explode(".", $tagged_attachment['name']);
+ $extension = $exploded_name[count($exploded_name) - 1];
+ $tagged_attachment['name'] = $data['authority_identification_code_civil_engineering_office'] . "_$tag.$extension";
+ }
+ if (isset($data['geo-attachments'][$tag][$index])) $tagged_attachment['geo'] = $data['geo-attachments'][$tag][$index];
+ return $tagged_attachment;
+ })->toArray();
+ })
+ ->reduce(function ($acc, $attachments) {
+ return array_merge($acc, $attachments);
+ }, []);
+ } else {
+ $data['attachments'] = collection($data['attachments'])
+ ->map(function ($attachment_obj, $index) use ($data) {
+ $attachment = AttachmentConverter::convertUploadedFileObj2AssociativeArray($attachment_obj);
+ if (isset($data['geo-attachments'][$index])) $attachment['geo'] = $data['geo-attachments'][$index];
+ return $attachment;
+ })
+ ->toArray();
+ }
+ $data['attachments'] = array_values(collection($data['attachments'])->filter(function ($attachment, $key) {
+ return isset($attachment['error']) && $attachment['error'] == 0;
+ })->toArray());
+ if (count($data['attachments']) == 0) {
+ unset($data['attachments']);
+ }
+ } else {
+ unset($data['attachments']);
+ }
+ }
+ if (isset($data['geo-attachments'])) unset($data['geo-attachments']);
+ }
+
+ public function beforeSave(EventInterface $event, Entity $entity, \ArrayObject $options)
+ {
+ if (!$this->getConfig('attachment') || !is_array($this->getConfig('attachment')) || $this->getConfig('attachment.required') === null || !is_bool($this->getConfig('attachment.required')) || $this->getConfig('attachment.one_public') === null || !is_bool($this->getConfig('attachment.one_public')) || $this->getConfig('attachment.protected') === null || !is_bool($this->getConfig('attachment.protected'))) {
+ $entity->setErrors(['id' => ['You must pass a valid "attachment" option. Either remove "Attachments" behaviour from the table "' . $entity->getSource() . '" or pass a valid "attachment" option wich must contain the keys: "required", "one_public" and "protected"!']]);
+ return false;
+ }
+ if ($this->getConfig('attachment.accept_only') && is_array($this->getConfig('attachment.accept_only'))) {
+ $valid_attachment_extensions = $this->getConfig('attachment.accept_only');
+
+ if (isset($entity->attachments) && is_array($entity->attachments)) {
+ foreach ($entity->attachments as $attachment) {
+ $file_name_parts = explode(".", $attachment['name']);
+ if (count($file_name_parts) < 2) {
+ $entity->setError('attachment', __('Allegato "{0}" non valido! Estensione file NON presente!', $attachment['name']));
+ return false;
+ }
+ $file_name_extension = count($file_name_parts) > 1 ? strtolower($file_name_parts[count($file_name_parts) - 1]) : '';
+ if (!in_array('.' . $file_name_extension, $valid_attachment_extensions)) {
+ $entity->setError('attachment', __('Allegato "{0}" non valido! Estensione file "{1}" non ammessa!', $attachment['name'], $file_name_extension));
+ return false;
+ }
+ }
+ }
+ }
+
+ if (!TableRegistry::getTableLocator()->get($entity->getSource())->newEmptyEntity()->isAccessible('attachments')) {
+ $entity->setErrors(['id' => ['"attachments" key in $_accessible array of class "' . get_class($entity) . '" is missing. Either remove "Attachments" behaviour from the table "' . $entity->getSource() . '" or add "attachments" in $_accessible array!']]);
+ return false;
+ }
+ if (!TableRegistry::getTableLocator()->get($entity->getSource())->newEmptyEntity()->isAccessible('removefiles')) {
+ $entity->setErrors(['id' => ['"removefiles" key in $_accessible array of class "' . get_class($entity) . '" is missing. Either remove "Attachments" behaviour from the table "' . $entity->getSource() . '" or add "removefiles" in $_accessible array!']]);
+ return false;
+ }
+ if (TableRegistry::getTableLocator()->get($entity->getSource())->getSchema()->getColumn('controllable_object_id') === null && !$this->_table->behaviors()->has('ControllableObjectInterface')) {
+ $entity->setErrors(['id' => ['Both "controllable_object_id" field and "ControllableObjectInterface" behavior are missing. Either add the field or the behaviour to the table "' . $entity->getSource() . '"']]);
+ return false;
+ }
+ if ($this->_table->behaviors()->has('ControllableObjectInterface') && isset($options['associated'])) {
+ $options['associated'][] = 'ControllableObjectInterfaces';
+ }
+ }
+
+ public function afterSave(EventInterface $event, Entity $entity, \ArrayObject $options)
+ {
+ if (TableRegistry::getTableLocator()->get($entity->getSource())->getSchema()->getColumn('controllable_object_id') !== null) {
+ $co = TableRegistry::getTableLocator()->get('ControllableObjects')->find()->where(['ControllableObjects.id' => $entity->controllable_object_id])->first();
+ if (!$co) {
+ throw new \Exception('Error retrieving controllable_object!');
+ }
+ } else {
+ $coi = TableRegistry::getTableLocator()->get('ControllableObjectInterfaces')->find()->contain(['ControllableObjects'])->where(['ControllableObjectInterfaces.id' => $entity->controllable_object_interface_id])->first();
+ if (!$coi || !isset($coi->controllable_object)) {
+ throw new \Exception('Error retrieving controllable_object from interface!');
+ }
+ $co = $coi->controllable_object;
+ }
+ // numero di allegati attualmente associati:
+ $saved_attachment_file_names = $co->attachment_file_names;
+ $attachments_saved = is_array($saved_attachment_file_names) ? count($saved_attachment_file_names) : 0;
+
+ if (isset($entity->removefiles) && is_array($entity->removefiles)) {
+ foreach($entity->removefiles as $removefile) {
+ if (!$co->deleteAttachment((Int)$removefile['id'])) {
+ throw new \Exception('Error during attachment delete!');
+ }
+ $attachments_saved--;
+ }
+ }
+
+ if (isset($entity->attachments) && is_array($entity->attachments)) {
+ foreach ($entity->attachments as $attachment) {
+ if (!isset($attachment['name']) || !isset($attachment['type']) || !isset($attachment['tmp_name']) || !isset($attachment['error']) || !isset($attachment['size'])) {
+ throw new \Exception('Invalid Attachments! Please make sure submitted form is encoded properly (type = file)');
+ }
+ if ($attachment['error'] !== 0) {
+ continue;
+ }
+ $tags = isset($attachment['tag']) ? [$attachment['tag']] : [];
+ $geo = isset($attachment['geo']) ? $attachment['geo'] : [];
+
+ // signature for method addAttachment(?String $filename = null, ?Int $fileSize = null, ?String $tmpPath = null, ?String $mime = null, ?int $private = 0, ?Bool $onePublic = false, ?Bool $protected = false, Array $tags = [], Array $geo = [], $skip_form_check = false)
+ if (!$co->addAttachment($attachment['name'], $attachment['size'], $attachment['tmp_name'], $attachment['type'], 0, $this->getConfig('attachment.one_public'), $this->getConfig('attachment.protected'), $tags, $geo)) {
+ throw new \Exception('Error saving attachment!');
+ }
+ $attachments_saved++;
+ }
+ }
+
+ if ((!isset($options['skip_attachment_check']) || !$options['skip_attachment_check']) && $this->getConfig('attachment.required') && $attachments_saved == 0) {
+ throw new \Exception(__('L\'allegato è obbligatorio!'));
+ }
+ }
+}
+
+?>
diff --git a/idrocap_wa/src/Model/Behavior/ControllableObjectInterfaceBehavior.php b/idrocap_wa/src/Model/Behavior/ControllableObjectInterfaceBehavior.php
new file mode 100644
index 0000000..da00859
--- /dev/null
+++ b/idrocap_wa/src/Model/Behavior/ControllableObjectInterfaceBehavior.php
@@ -0,0 +1,42 @@
+_table->belongsTo('ControllableObjectInterfaces');
+ }
+
+ public function beforeSave(EventInterface $event, Entity $entity, \ArrayObject $options)
+ {
+ if (TableRegistry::getTableLocator()->get($entity->getSource())->getSchema()->getColumn('controllable_object_id') !== null) {
+ $entity->setErrors(['id' => ['"controllable_object_id" field found. Either remove "ControllableObjectInterface" behaviour or remove that field from the table "' . $entity->source() . '"']]);
+ return false;
+ }
+ if (TableRegistry::getTableLocator()->get($entity->getSource())->getSchema()->getColumn('controllable_object_interface_id') === null) {
+ $entity->setErrors(['id' => ['"controllable_object_interface_id" field is missing. Either remove "ControllableObjectInterface" behaviour or add the missing field to the table "' . $entity->source() . '"']]);
+ return false;
+ }
+ if (!isset($entity->controllable_object_interface_id)) {
+ // recuperiamo l'id del relativo controllable_object_interface
+ $coit = TableRegistry::getTableLocator()->get('ControllableObjectInterfaceTypes')->find()->where(['ControllableObjectInterfaceTypes.table' => $entity->getSource()])->first();
+ if (!$coit) {
+ $entity->setErrors(['controllable_object_interface_id' => ['"controllable_object_interface_type" not found. Either remove "ControllableObjectInterface" behaviour from the table "' . $entity->getSource() . '" or add related entry in "controllable_object_interface_types" table!']]);
+ return false;
+ }
+ // la seguente istruzione serve per triggerare il before marshal di controllable_object_interface che si occuperà di tutto il resto
+ $entity->controllable_object_interface = $this->_table->ControllableObjectInterfaces->newEntity(['controllable_object_interface_type_id' => $coit->id]);
+ }
+ }
+}
+
+?>
diff --git a/idrocap_wa/src/Model/Entity/Actor.php b/idrocap_wa/src/Model/Entity/Actor.php
new file mode 100644
index 0000000..85bb828
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Actor.php
@@ -0,0 +1,302 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'actor_type_id' => true,
+ 'deleted' => true,
+ 'actor_type' => true,
+ 'deliveries' => true,
+ 'dispatching_task_items' => true,
+ 'groups' => true,
+ 'organisations' => true,
+ 'users' => true,
+ ];
+
+ protected array $_virtual = [
+ 'contacts',
+ ];
+
+ /**
+ * _getContacts
+ *
+ * @return String
+ */
+ protected function _getContacts(): String
+ {
+ // se la entity è stata appena creata o è di tipo diverso da "organisation" o "user":
+ if ($this->isNew() || !in_array($this->actor_type_id, [1,5])) return "";
+
+ // se non vi è un utente loggato:
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user) return "";
+
+ // costruiamo la capability prefix a seconda che l'actor è un organisation o user:
+ $capability_prefix = $this->actor_type_id == 1 ? "configuration.organisations.view_" : "configuration.users.view_";
+
+ // recuperiamo l'id della organisation (o della organisation di appartenenza, qualora l'actor fosse uno user):
+ $organisation_id = $this->actor_type_id == 1 ? TableRegistry::getTableLocator()->get('Organisations')->find()->where(['Organisations.actor_id' => $this->id])->first()->id ?? null : TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.actor_id' => $this->id])->first()->organisation_id ?? null;
+
+ $contacts = TableRegistry::getTableLocator()->get('Deliveries')->find()
+ ->contain(['MobilePhones' => ['MobilePhoneDescriptions'], 'Faxes' => ['FaxDescriptions'], 'Emails' => ['EmailDescriptions'], 'Phones' => ['PhoneDescriptions'], 'TelegramChats', 'Pecs' => ['PecDescriptions']])
+ ->where(['Deliveries.actor_id' => $this->id])
+ ->order(['Deliveries.delivery_type_id' => 'ASC'])
+ ->all()
+ ->reduce(function ($acc, $contact) use ($user, $capability_prefix, $organisation_id) {
+ switch ($contact->delivery_type_id) {
+ case 1:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $mobile_phone_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'mobile_phone') ? $contact->mobile_phone->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $mobile_phone_value = $user->hasCapability($capability_prefix . 'mobile_phone') ? $contact->mobile_phone->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'mobile_phone_foo') && $user->organisation_id == $organisation_id ? $contact->mobile_phone->value : "**************");
+ }
+ $contact_value = __('Cellulare ({0}): {1}', $contact->mobile_phone->mobile_phone_description->description, $mobile_phone_value);
+ break;
+ case 2:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_fax_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'fax') ? $contact->fax->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_fax_value = $user->hasCapability($capability_prefix . 'fax') ? $contact->fax->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'fax_foo') && $user->organisation_id == $organisation_id ? $contact->fax->value : "**************");
+ }
+ $contact_value = __('Fax ({0}): {1}', $contact->fax->fax_description->description, $contact_fax_value);
+ break;
+ case 3:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_email_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'email') ? $contact->email->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_email_value = $user->hasCapability($capability_prefix . 'email') ? $contact->email->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'email_foo') && $user->organisation_id == $organisation_id ? $contact->email->value : "**************");
+ }
+ $contact_value = __('Email ({0}): {1}', $contact->email->email_description->description, $contact_email_value);
+ break;
+ case 4:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_phone_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'phone') ? $contact->phone->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_phone_value = $user->hasCapability($capability_prefix . 'phone') ? $contact->phone->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'phone_foo') && $user->organisation_id == $organisation_id ? $contact->phone->value : "**************");
+ }
+ $contact_value = __('Telefono ({0}): {1}', $contact->phone->phone_description->description, $contact_phone_value);
+ break;
+ case 5:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_telegram_chat_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'telegram_chat') ? $contact->telegram_chat->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_telegram_chat_value = $user->hasCapability($capability_prefix . 'telegram_chat') ? $contact->telegram_chat->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'telegram_chat_foo') && $user->organisation_id == $organisation_id ? $contact->telegram_chat->value : "**************");
+ }
+ $contact_value = __('Telegram Chat ID: {0}', $contact_telegram_chat_value);
+ break;
+ case 6:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_pec_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'pec') ? $contact->pec->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_pec_value = $user->hasCapability($capability_prefix . 'pec') ? $contact->pec->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'pec_foo') && $user->organisation_id == $organisation_id ? $contact->pec->value : "**************");
+ }
+ $contact_value = __('PEC ({0}): {1}', $contact->pec->pec_description->description, $contact_pec_value);
+ break;
+ default:
+ $contact_value = "";
+ break;
+ }
+ if ($contact_value != "") $acc[] = $contact_value;
+ return $acc;
+ }, []);
+
+ return implode(", ", $contacts);
+ }
+
+ /**
+ * getContactsList
+ *
+ * @return Array
+ */
+ public function getContactsList(): Array
+ {
+ $contacts = [];
+
+ // se la entity è stata appena creata o è di tipo diverso da "organisation" o "user":
+ if ($this->isNew() || !in_array($this->actor_type_id, [1,5])) return $contacts;
+
+ // se non vi è un utente loggato:
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user) return $contacts;
+
+ // costruiamo la capability prefix a seconda che l'actor è un organisation o user:
+ $capability_prefix = $this->actor_type_id == 1 ? "configuration.organisations.view_" : "configuration.users.view_";
+
+ // recuperiamo l'id della organisation (o della organisation di appartenenza, qualora l'actor fosse uno user):
+ $organisation_id = $this->actor_type_id == 1 ? TableRegistry::getTableLocator()->get('Organisations')->find()->where(['Organisations.actor_id' => $this->id])->first()->id ?? null : TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.actor_id' => $this->id])->first()->organisation_id ?? null;
+
+ $contacts = TableRegistry::getTableLocator()->get('Deliveries')->find()
+ ->contain(['MobilePhones' => ['MobilePhoneDescriptions'], 'Faxes' => ['FaxDescriptions'], 'Emails' => ['EmailDescriptions'], 'Phones' => ['PhoneDescriptions'], 'TelegramChats', 'Pecs' => ['PecDescriptions']])
+ ->where(['Deliveries.actor_id' => $this->id])
+ ->order(['Deliveries.delivery_type_id' => 'ASC'])
+ ->all()
+ ->reduce(function ($acc, $contact) use ($user, $capability_prefix, $organisation_id) {
+ $delivery_type_description = null;
+ $contact_description = null;
+ $contact_value = null;
+
+ switch ($contact->delivery_type_id) {
+ case 1:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $mobile_phone_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'mobile_phone') ? $contact->mobile_phone->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $mobile_phone_value = $user->hasCapability($capability_prefix . 'mobile_phone') ? $contact->mobile_phone->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'mobile_phone_foo') && $user->organisation_id == $organisation_id ? $contact->mobile_phone->value : "**************");
+ }
+ $delivery_type_description = 'mobiles';
+ $contact_description = $contact->mobile_phone->mobile_phone_description->description;
+ $contact_value = $mobile_phone_value;
+ break;
+ case 2:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_fax_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'fax') ? $contact->fax->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_fax_value = $user->hasCapability($capability_prefix . 'fax') ? $contact->fax->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'fax_foo') && $user->organisation_id == $organisation_id ? $contact->fax->value : "**************");
+ }
+ $delivery_type_description = 'faxes';
+ $contact_description = $contact->fax->fax_description->description;
+ $contact_value = $contact_fax_value;
+ break;
+ case 3:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_email_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'email') ? $contact->email->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_email_value = $user->hasCapability($capability_prefix . 'email') ? $contact->email->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'email_foo') && $user->organisation_id == $organisation_id ? $contact->email->value : "**************");
+ }
+ $delivery_type_description = 'emails';
+ $contact_description = $contact->email->email_description->description;
+ $contact_value = $contact_email_value;
+ break;
+ case 4:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_phone_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'phone') ? $contact->phone->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_phone_value = $user->hasCapability($capability_prefix . 'phone') ? $contact->phone->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'phone_foo') && $user->organisation_id == $organisation_id ? $contact->phone->value : "**************");
+ }
+ $delivery_type_description = 'phones';
+ $contact_description = $contact->phone->phone_description->description;
+ $contact_value = $contact_phone_value;
+ break;
+ case 5:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_telegram_chat_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'telegram_chat') ? $contact->telegram_chat->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_telegram_chat_value = $user->hasCapability($capability_prefix . 'telegram_chat') ? $contact->telegram_chat->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'telegram_chat_foo') && $user->organisation_id == $organisation_id ? $contact->telegram_chat->value : "**************");
+ }
+ $delivery_type_description = 'telegram_chats';
+ $contact_description = '';
+ $contact_value = $contact_telegram_chat_value;
+ break;
+ case 6:
+ if ($this->actor_type_id == 1) {
+ // se l'actor è una organisation:
+ $contact_pec_value = $user->organisation_id == $organisation_id || $user->hasCapability($capability_prefix . 'pec') ? $contact->pec->value : "**************";
+ } else {
+ // se l'actor è uno user:
+ $contact_pec_value = $user->hasCapability($capability_prefix . 'pec') ? $contact->pec->value : ($user->actor_id == $this->id || $user->hasCapability($capability_prefix . 'pec_foo') && $user->organisation_id == $organisation_id ? $contact->pec->value : "**************");
+ }
+ $delivery_type_description = 'pecs';
+ $contact_description = $contact->pec->pec_description->description;
+ $contact_value = $contact_pec_value;
+ break;
+ default:
+ break;
+ }
+ if (isset($delivery_type_description) && isset($contact_description) && isset($contact_value)) {
+ $acc[$delivery_type_description][] = ['description' => $contact_description, 'value' => $contact_value];
+ }
+ return $acc;
+ }, []);
+
+ return $contacts;
+ }
+
+ /**
+ * hasContactsWithNotificationsOfType
+ *
+ * @param String $contact_type
+ * @return Bool
+ */
+ public function hasContactsWithNotificationsOfType(String $contact_type): Bool
+ {
+ if (!in_array($contact_type, ['PushNotifications', 'MobilePhones', 'Faxes', 'Emails', 'TelegramChats', 'Pecs'])) return false;
+ if (!isset($this->_fields['id'])) return false;
+
+ return TableRegistry::getTableLocator()->get($contact_type)->find()
+ ->matching('Deliveries')
+ ->where(['enable_notifications' => true, 'Deliveries.actor_id' => $this->_fields['id']])
+ ->limit(1)
+ ->first() !== null;
+ }
+
+ /**
+ * getContactsWithNotificationsOfType
+ *
+ * @param String $contact_type
+ * @return Array
+ */
+ public function getContactsWithNotificationsOfType(String $contact_type): Array
+ {
+ if (!in_array($contact_type, ['PushNotifications', 'MobilePhones', 'Faxes', 'Emails', 'TelegramChats', 'Pecs'])) return [];
+ if (!isset($this->_fields['id'])) return [];
+
+ return TableRegistry::getTableLocator()->get($contact_type)->find()
+ ->matching('Deliveries')
+ ->where(['enable_notifications' => true, 'Deliveries.actor_id' => $this->_fields['id']])
+ ->all()
+ ->toArray();
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/ActorType.php b/idrocap_wa/src/Model/Entity/ActorType.php
new file mode 100644
index 0000000..59b2602
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/ActorType.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'entity' => true,
+ 'table' => true,
+ 'description' => true,
+ 'actors' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Applicant.php b/idrocap_wa/src/Model/Entity/Applicant.php
new file mode 100644
index 0000000..a80cd17
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Applicant.php
@@ -0,0 +1,81 @@
+
+ */
+ protected array $_accessible = [
+ 'name' => true,
+ 'surname' => true,
+ 'company_name' => true,
+ 'tax_code' => true,
+ 'vat_number' => true,
+ 'address' => true,
+ 'district' => true,
+ 'province' => true,
+ 'pec_address' => true,
+ 'email_address' => true,
+ 'water_drawing_paperworks' => true,
+ ];
+
+ protected array $_virtual = [
+ 'applicant_full_description',
+ ];
+
+ /**
+ * _getApplicantFullDescription
+ *
+ * Virtual Field that returns the applicant full description
+ *
+ * @return string
+ */
+ protected function _getApplicantFullDescription(): string
+ {
+ $tax_code = $this->_fields['tax_code'];
+ if (empty($this->_fields['vat_number'])) {
+ $surname = $this->_fields['surname'];
+ $name = $this->_fields['name'];
+ return "$surname $name CF $tax_code";
+ } else {
+ $company_name = $this->_fields['company_name'];
+ $address = $this->_fields['address'];
+ $district = $this->_fields['district'];
+ $province = $this->_fields['province'];
+ $vat_number = $this->_fields['vat_number'];
+ return "$company_name $address $district ($province) CF $tax_code P.IVA $vat_number";
+ }
+ }
+
+ protected function _setTaxCode($value)
+ {
+ return strtoupper($value);
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/ApplicantsWaterDrawingPaperwork.php b/idrocap_wa/src/Model/Entity/ApplicantsWaterDrawingPaperwork.php
new file mode 100644
index 0000000..c0116c9
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/ApplicantsWaterDrawingPaperwork.php
@@ -0,0 +1,37 @@
+
+ */
+ protected array $_accessible = [
+ 'applicant_id' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'is_primary_applicant' => true,
+ 'applicant' => true,
+ 'water_drawing_paperwork' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Attachment.php b/idrocap_wa/src/Model/Entity/Attachment.php
new file mode 100644
index 0000000..d04b458
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Attachment.php
@@ -0,0 +1,86 @@
+
+ */
+ protected array $_accessible = [
+ 'original_file_name' => true,
+ 'original_file_size' => true,
+ 'file_name' => true,
+ 'mimetype' => true,
+ 'upload_date' => true,
+ 'controllable_object_id' => true,
+ 'container_controllable_object_id' => true,
+ 'relevant' => true,
+ 'private' => true,
+ 'controllable_object' => true,
+ 'container_controllable_object' => true,
+ 'tags' => true,
+ ];
+
+ /**
+ * _getRelativeUrl
+ *
+ * @return ?String
+ */
+ protected function _getRelativeUrl()
+ {
+ if(isset($this->_fields['file_name']))
+ {
+ return Configure::read('App.attachmentsUrl')."/".$this->_fields['file_name'];
+ }
+
+ return null;
+ }
+
+ /**
+ * _getHumanOriginalFileSize
+ *
+ * @return ?String
+ */
+ protected function _getHumanOriginalFileSize()
+ {
+ if(!isset($this->_fields['original_file_size']))
+ {
+ return null;
+ }
+ $bytes = (String)$this->_fields['original_file_size'];
+ $size = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
+ $factor = floor((strlen($bytes) - 1) / 3);
+ return sprintf("%.2f", $bytes / pow(1024, $factor)) . " " . @$size[$factor];
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/BackgroundTask.php b/idrocap_wa/src/Model/Entity/BackgroundTask.php
new file mode 100644
index 0000000..7b6cf21
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/BackgroundTask.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'command' => true,
+ 'data' => true,
+ 'dgroup' => true,
+ 'status' => true,
+ 'was_synced' => true,
+ 'created' => true,
+ 'modified' => true,
+ 'dispatching_tasks' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/CadastralCropType.php b/idrocap_wa/src/Model/Entity/CadastralCropType.php
new file mode 100644
index 0000000..e7ef6f4
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/CadastralCropType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_intended_uses' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/CapabilitiesMenuItem.php b/idrocap_wa/src/Model/Entity/CapabilitiesMenuItem.php
new file mode 100644
index 0000000..78f6a7b
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/CapabilitiesMenuItem.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'capability_id' => true,
+ 'menu_item_id' => true,
+ 'capability' => true,
+ 'menu_item' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/CapabilitiesMenuSection.php b/idrocap_wa/src/Model/Entity/CapabilitiesMenuSection.php
new file mode 100644
index 0000000..c950e4d
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/CapabilitiesMenuSection.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'capability_id' => true,
+ 'menu_section_id' => true,
+ 'capability' => true,
+ 'menu_section' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Capability.php b/idrocap_wa/src/Model/Entity/Capability.php
new file mode 100644
index 0000000..b21d3ad
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Capability.php
@@ -0,0 +1,53 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'value' => true,
+ 'priority' => true,
+ 'capability_group_id' => true,
+ 'priority_group_id' => true,
+ 'longdescription' => true,
+ 'deleted' => true,
+ 'is_configurable' => true,
+ 'capability_group' => true,
+ 'priority_group' => true,
+ 'permissions' => true,
+ 'menu_items' => true,
+ 'menu_sections' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/CapabilityGroup.php b/idrocap_wa/src/Model/Entity/CapabilityGroup.php
new file mode 100644
index 0000000..a974025
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/CapabilityGroup.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deleted' => true,
+ 'is_configurable' => true,
+ 'capabilities' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/ControllableObject.php b/idrocap_wa/src/Model/Entity/ControllableObject.php
new file mode 100644
index 0000000..45b973c
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/ControllableObject.php
@@ -0,0 +1,297 @@
+
+ */
+ protected array $_accessible = [
+ 'created' => true,
+ 'modified' => true,
+ 'organisation_id' => true,
+ 'controllable_object_type_id' => true,
+ 'create_user_id' => true,
+ 'edit_user_id' => true,
+ 'edit_organisation_id' => true,
+ 'deleted' => true,
+ 'organisation' => true,
+ 'controllable_object_type' => true,
+ 'user' => true,
+ 'attachments' => true,
+ 'controllable_object_interfaces' => true,
+ 'location' => true,
+ ];
+
+ /**
+ * getHashedFileName
+ *
+ * @param ?String $original_file_name
+ * @param ?Bool $sha512
+ * @return ?String
+ */
+ private function getHashedFileName(?String $original_file_name = null, ?Bool $sha512 = false): ?String {
+ if ($original_file_name == null) {
+ return null;
+ }
+ $rowData = $original_file_name . microtime(true);
+ return $sha512 ? hash('sha512', $rowData) : md5($rowData);
+ }
+
+ /**
+ * getDuplicatedFilename
+ *
+ * @param String $filename
+ * @param ?Int $container_co_id
+ * @return String
+ */
+ private function getDuplicatedFilename(String $filename, ?Int $container_co_id = null): String {
+
+ $co_id = isset($container_co_id) ? $container_co_id : $this->_fields['id'];
+ $attachmentsTable = TableRegistry::getTableLocator()->get('Attachments');
+ $file_exists = $attachmentsTable->find()->where(['Attachments.original_file_name' => $filename, 'Attachments.container_controllable_object_id' => $co_id])->first();
+ if (!$file_exists) {
+ return $filename;
+ }
+
+ $lastDotIndex = strrpos($filename, ".");
+ if ($lastDotIndex) {
+ $filename_without_extension = substr($filename, 0, $lastDotIndex);
+ $filename_extension = substr($filename, $lastDotIndex);
+ if ($filename_extension == ".") {
+ $filename_without_extension = $filename;
+ $filename_extension = "";
+ }
+ } else {
+ $filename_without_extension = $filename;
+ $filename_extension = "";
+ }
+
+ $whereCondition = "original_file_name REGEXP '^" . $filename_without_extension . "_[[:digit:]]*" . $filename_extension . "$'";
+
+ $numbers = $attachmentsTable->find()
+ ->where([$whereCondition])
+ ->where(['Attachments.container_controllable_object_id' => $co_id])
+ ->all()
+ ->map(function($value, $key) {
+ $filename_exploded_array = explode("_", $value->original_file_name);
+ $number_with_ext_array = explode(".", $filename_exploded_array[count($filename_exploded_array) - 1]);
+ $number = $number_with_ext_array[0];
+ return $number;
+ })
+ ->toArray();
+
+ $count = count($numbers);
+ for ($index = 0; $index < count($numbers); $index++) {
+ if (!in_array(($index + 2), $numbers)) {
+ $count = $index;
+ break;
+ }
+ }
+
+ return $filename_without_extension . "_" . ($count + 2) . $filename_extension;
+ }
+
+ /**
+ * _getAttachmentFileNames
+ *
+ * @return Array
+ */
+ protected function _getAttachmentFileNames() {
+ if($this->isNew())
+ {
+ return [];
+ }
+ $attachmentFileNames = TableRegistry::getTableLocator()->get('Attachments')->find()
+ ->matching('ControllableObjects')
+ ->where(['Attachments.container_controllable_object_id' => $this->_fields['id']])
+ ->all()
+ ->reduce(function ($acc ,$value) {
+ $acc[$value->file_name] = $value->original_file_name;
+ return $acc;
+ }, []);
+ return $attachmentFileNames;
+ }
+
+ /**
+ * deleteAttachment
+ *
+ * @param Int $co_id
+ * @return Bool
+ */
+ public function deleteAttachment(Int $co_id): Bool {
+ $controllableObjectsTable = TableRegistry::getTableLocator()->get('ControllableObjects');
+
+ if ($co_id == null) {
+ return false;
+ }
+ $attachmentCo = $controllableObjectsTable
+ ->find()
+ ->where(['ControllableObjects.id' => $co_id])
+ ->first();
+ if (!$attachmentCo) {
+ return false;
+ }
+ if (!$controllableObjectsTable->delete($attachmentCo)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * addAttachment
+ *
+ * @param ?String $filename
+ * @param ?Int $fileSize
+ * @param ?String $tmpPath
+ * @param ?String $mime
+ * @param ?int $private
+ * @param ?Bool $onePublic
+ * @param ?Bool $protected
+ * @param Array $tags
+ * @param Array $geo
+ * @throws \Exception
+ * @return Bool
+ */
+ public function addAttachment(?String $filename = null, ?Int $fileSize = null, ?String $tmpPath = null, ?String $mime = null, ?int $private = 0, ?Bool $onePublic = false, ?Bool $protected = false, Array $tags = [], Array $geo = [], $skip_form_check = false): Bool
+ {
+ $co_id = $this->_fields['id'];
+ $attachmentsTable = TableRegistry::getTableLocator()->get('Attachments');
+
+ if ($filename == null) {
+ return false;
+ }
+ if ($fileSize == null) {
+ return false;
+ }
+ if ($tmpPath == null) {
+ return false;
+ }
+ if ($mime == null) {
+ return false;
+ }
+
+ // 1 - check if attachment has been uploaded through input form or has been tampered with;
+ // 2 - check if attachment real type is allowed:
+ AttachmentChecker::check(['tmp_name' => $tmpPath, 'name' => $filename, 'type' => $mime, 'size' => $fileSize], $skip_form_check);
+
+ if ($private == 0 && $onePublic) {
+ $existing_files = $attachmentsTable->find()->where(['Attachments.container_controllable_object_id' => $co_id, 'Attachments.private' => 0]);
+ foreach ($existing_files as $existing_file) {
+ if (!$this->deleteAttachment($existing_file->controllable_object_id)) {
+ return false;
+ }
+ }
+ }
+
+ $file_name = $this->getHashedFileName($filename);
+
+ $attachment_data = [
+ 'container_controllable_object_id' => $co_id,
+ 'original_file_name' => $this->getDuplicatedFilename($filename, $co_id),
+ 'original_file_size' => $fileSize,
+ 'file_name' => $file_name,
+ 'url_access' => $protected ? $this->getHashedFileName($filename, true) : null,
+ 'mimetype' => $mime,
+ 'upload_date' => DateTime::now(),
+ 'private' => $private,
+ 'controllable_object' => [
+ 'controllable_object_type_id' => 8,
+ ],
+ ];
+
+ if (!empty($geo['longitude']) && !empty($geo['latitude'])) {
+ $attachment_data['controllable_object']['location'] = [
+ 'description' => $geo['longitude'] . ' ' . $geo['latitude'],
+ 'coordinates' => $geo['longitude'] . ' ' . $geo['latitude'],
+ 'geotype' => 'marker',
+ 'geom' => '{"type":"Point","coordinates":[' . $geo['longitude'] . ',' . $geo['latitude'] . ']}',
+ ];
+
+ if (!GeoValidation::isValidGeometry(json_decode($attachment_data['controllable_object']['location']['geom']))) {
+ throw new \Exception(__('Le coordinate inserite per georeferenziare uno o più allegati non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell\'area di competenza della piattaforma.'));
+ }
+ }
+
+ $associated = [
+ 'ControllableObjects' => [
+ 'associated' => ['Locations']
+ ],
+ ];
+
+ $attachment = $attachmentsTable->newEntity($attachment_data, ['associated' => $associated]);
+
+ try
+ {
+ $res = \App\WGS\FileStorage\FileStorageFactory::create()->saveFile(Configure::read('App.attachmentsPath')."/".$co_id."/".$file_name,$tmpPath);
+ if (is_array($tags) && !empty($tags)) {
+ $tagsTable = TableRegistry::getTableLocator()->get('Tags');
+ $tags = $tagsTable->find()->where(['Tags.code IN' => $tags])->toArray();
+ $attachment->tags = $tags;
+ }
+
+ if (!$attachmentsTable->save($attachment)) {
+ return false;
+ }
+
+ return true;
+ }
+ catch(\Exception $we)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * getSpecialisationEntity
+ *
+ * @return Cake\ORM\Entity|null
+ */
+ public function getSpecialisationEntity()
+ {
+ $co_type = TableRegistry::getTableLocator()->get('ControllableObjectTypes')->find()->where(['ControllableObjectTypes.id' => $this->_fields['controllable_object_type_id']])->first();
+ if (!$co_type) return null;
+ $table = \Cake\Utility\Inflector::camelize($co_type->controller);
+ $specialisation_entity = TableRegistry::getTableLocator()->get($table)->find()->where(["$table.controllable_object_id" => $this->_fields['id']])->first();
+ if (!$specialisation_entity) return null;
+ return $specialisation_entity;
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/ControllableObjectInterface.php b/idrocap_wa/src/Model/Entity/ControllableObjectInterface.php
new file mode 100644
index 0000000..1cb0462
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/ControllableObjectInterface.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'controllable_object_id' => true,
+ 'controllable_object_interface_type_id' => true,
+ 'controllable_object' => true,
+ 'controllable_object_interface_type' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/ControllableObjectInterfaceType.php b/idrocap_wa/src/Model/Entity/ControllableObjectInterfaceType.php
new file mode 100644
index 0000000..32bde37
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/ControllableObjectInterfaceType.php
@@ -0,0 +1,34 @@
+
+ */
+ protected array $_accessible = [
+ 'entity' => true,
+ 'table' => true,
+ 'description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/ControllableObjectType.php b/idrocap_wa/src/Model/Entity/ControllableObjectType.php
new file mode 100644
index 0000000..1ae34a4
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/ControllableObjectType.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'controller' => true,
+ 'label' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/County.php b/idrocap_wa/src/Model/Entity/County.php
new file mode 100644
index 0000000..a3f0df1
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/County.php
@@ -0,0 +1,52 @@
+
+ */
+ protected array $_accessible = [
+ 'SHAPE' => true,
+ 'cod_rip' => true,
+ 'cod_reg' => true,
+ 'cod_prov' => true,
+ 'cod_cm' => true,
+ 'cod_uts' => true,
+ 'den_prov' => true,
+ 'den_cm' => true,
+ 'den_uts' => true,
+ 'sigla' => true,
+ 'tipo_uts' => true,
+ 'shape_leng' => true,
+ 'shape_area' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Delivery.php b/idrocap_wa/src/Model/Entity/Delivery.php
new file mode 100644
index 0000000..4f4a688
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Delivery.php
@@ -0,0 +1,53 @@
+
+ */
+ protected array $_accessible = [
+ 'actor_id' => true,
+ 'delivery_type_id' => true,
+ 'deleted' => true,
+ 'actor' => true,
+ 'delivery_type' => true,
+ 'emails' => true,
+ 'faxes' => true,
+ 'mobile_phones' => true,
+ 'phones' => true,
+ 'push_notifications' => true,
+ 'telegram_chats' => true,
+ 'telegram_contacts' => true,
+ 'pecs' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/DeliveryType.php b/idrocap_wa/src/Model/Entity/DeliveryType.php
new file mode 100644
index 0000000..44e6434
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/DeliveryType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deliveries' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/DispatchingTask.php b/idrocap_wa/src/Model/Entity/DispatchingTask.php
new file mode 100644
index 0000000..0fd2fb1
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/DispatchingTask.php
@@ -0,0 +1,47 @@
+
+ */
+ protected array $_accessible = [
+ 'dispatching_task_group' => true,
+ 'dispatching_task_status_id' => true,
+ 'created' => true,
+ 'modified' => true,
+ 'retries' => true,
+ 'failed' => true,
+ 'background_task_id' => true,
+ 'dispatching_task_status' => true,
+ 'background_task' => true,
+ 'dispatching_task_items' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/DispatchingTaskItem.php b/idrocap_wa/src/Model/Entity/DispatchingTaskItem.php
new file mode 100644
index 0000000..000b606
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/DispatchingTaskItem.php
@@ -0,0 +1,47 @@
+
+ */
+ protected array $_accessible = [
+ 'dispatching_task_id' => true,
+ 'actor_id' => true,
+ 'system_dispatched' => true,
+ 'actor_dispatching_bitmask' => true,
+ 'performed_dispatching_bitmask' => true,
+ 'not_performed_dispatching_bitmask' => true,
+ 'created' => true,
+ 'modified' => true,
+ 'dispatching_task' => true,
+ 'actor' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/DispatchingTaskStatus.php b/idrocap_wa/src/Model/Entity/DispatchingTaskStatus.php
new file mode 100644
index 0000000..9625c26
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/DispatchingTaskStatus.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'dispatching_tasks' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/District.php b/idrocap_wa/src/Model/Entity/District.php
new file mode 100644
index 0000000..bdcb1a2
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/District.php
@@ -0,0 +1,52 @@
+
+ */
+ protected array $_accessible = [
+ 'SHAPE' => true,
+ 'cod_rip' => true,
+ 'cod_reg' => true,
+ 'cod_prov' => true,
+ 'cod_cm' => true,
+ 'cod_uts' => true,
+ 'pro_com' => true,
+ 'pro_com_t' => true,
+ 'comune' => true,
+ 'comune_a' => true,
+ 'cc_uts' => true,
+ 'shape_leng' => true,
+ 'shape_area' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Email.php b/idrocap_wa/src/Model/Entity/Email.php
new file mode 100644
index 0000000..17a52c8
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Email.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'is_system' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'email_description_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ 'email_description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/EmailDescription.php b/idrocap_wa/src/Model/Entity/EmailDescription.php
new file mode 100644
index 0000000..c1acab8
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/EmailDescription.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deleted' => true,
+ 'emails' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Fax.php b/idrocap_wa/src/Model/Entity/Fax.php
new file mode 100644
index 0000000..0c2aa54
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Fax.php
@@ -0,0 +1,41 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'fax_description_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ 'fax_description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/FaxDescription.php b/idrocap_wa/src/Model/Entity/FaxDescription.php
new file mode 100644
index 0000000..47b2a50
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/FaxDescription.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deleted' => true,
+ 'faxes' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Filter.php b/idrocap_wa/src/Model/Entity/Filter.php
new file mode 100644
index 0000000..d40ed66
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Filter.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'category' => true,
+ 'description' => true,
+ 'filter_type' => true,
+ 'class_name' => true,
+ 'search' => true,
+ 'associations' => true,
+ 'order_number' => true,
+ 'sys_admin_only' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Group.php b/idrocap_wa/src/Model/Entity/Group.php
new file mode 100644
index 0000000..22e5dc4
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Group.php
@@ -0,0 +1,53 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'is_default' => true,
+ 'super_group' => true,
+ 'actor_id' => true,
+ 'is_editable' => true,
+ 'group_code' => true,
+ 'modified' => true,
+ 'actor' => true,
+ 'memberships' => true,
+ 'permissions' => true,
+ 'tags' => true,
+ 'capabilities' => true,
+ 'child_groups' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/GroupsGroup.php b/idrocap_wa/src/Model/Entity/GroupsGroup.php
new file mode 100644
index 0000000..0ad9183
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/GroupsGroup.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'container_group_id' => true,
+ 'group_id' => true,
+ 'group' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Language.php b/idrocap_wa/src/Model/Entity/Language.php
new file mode 100644
index 0000000..c73d283
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Language.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'language_code' => true,
+ 'users' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Location.php b/idrocap_wa/src/Model/Entity/Location.php
new file mode 100644
index 0000000..c45ae59
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Location.php
@@ -0,0 +1,56 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'coordinates' => true,
+ 'feature_collection' => true,
+ 'geom' => true,
+ 'controllable_object_id' => true,
+ 'controllable_object' => true,
+ 'location_attributes' => true,
+ ];
+
+ /**
+ * _getGeom
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function _getGeom($value)
+ {
+ if (!is_string($value) || empty(json_decode($value))) {
+ return $value;
+ }
+ return new QueryExpression("ST_GeomFromGeoJson('$value')");
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/LocationAttribute.php b/idrocap_wa/src/Model/Entity/LocationAttribute.php
new file mode 100644
index 0000000..677ade1
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/LocationAttribute.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'location_id' => true,
+ 'district_code' => true,
+ 'district_name' => true,
+ 'county_code' => true,
+ 'county_name' => true,
+ 'region' => true,
+ 'area' => true,
+ 'location' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Map.php b/idrocap_wa/src/Model/Entity/Map.php
new file mode 100644
index 0000000..6c2d3a3
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Map.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'code' => true,
+ 'name' => true,
+ 'url_layer' => true,
+ 'clusterize' => true,
+ 'visible' => true,
+ 'style' => true,
+ 'created' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/MenuItem.php b/idrocap_wa/src/Model/Entity/MenuItem.php
new file mode 100644
index 0000000..8c6e620
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MenuItem.php
@@ -0,0 +1,82 @@
+
+ */
+ protected array $_accessible = [
+ 'title' => true,
+ 'icon' => true,
+ 'link' => true,
+ 'menu_item_id' => true,
+ 'menu_section_id' => true,
+ 'menu_order' => true,
+ 'menu_items' => true,
+ 'menu_section' => true,
+ 'capabilities' => true,
+ ];
+
+ protected array $_virtual = [
+ 'menu_items',
+ ];
+
+ /**
+ * _getMenuItems
+ *
+ * @return Array
+ */
+ protected function _getMenuItems(): Array
+ {
+ $menu_items = [];
+
+ // bisogna recuperare le capabilities utente (se esiste un utente loggato)
+ $user = Router::getRequest()->getAttribute('identity');
+ if ($user) {
+ $MenuItems = TableRegistry::getTableLocator()->get('MenuItems');
+ $menu_items_subquery = $MenuItems
+ ->find()
+ ->select(['MenuItems.id'])
+ ->innerJoinWith('Capabilities')
+ ->where(['MenuItems.menu_item_id is NOT NULL', 'MenuItems.menu_item_id' => $this->id])
+ ->where(['Capabilities.id IN' => $user->getCapabilityIds(true)])
+ ->distinct(['MenuItems.id']);
+
+ $menu_items = $MenuItems
+ ->find()
+ ->where(['MenuItems.id IN' => $menu_items_subquery])
+ ->order(['MenuItems.menu_order' => 'ASC'])
+ ->toArray();
+ }
+ return $menu_items;
+
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/MenuSection.php b/idrocap_wa/src/Model/Entity/MenuSection.php
new file mode 100644
index 0000000..e34130e
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MenuSection.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'title' => true,
+ 'icon' => true,
+ 'menu_items' => true,
+ 'capabilities' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Message.php b/idrocap_wa/src/Model/Entity/Message.php
new file mode 100644
index 0000000..e788874
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Message.php
@@ -0,0 +1,61 @@
+
+ */
+ protected array $_accessible = [
+ 'controllable_object_id' => true,
+ 'message_type_id' => true,
+ 'content' => true,
+ 'user_id' => true,
+ 'message_status_id' => true,
+ 'mgroup' => true,
+ 'event_string' => true,
+ 'last_update' => true,
+ 'organisation_id' => true,
+ 'contact' => true,
+ 'not_delivered_reason' => true,
+ 'controllable_object' => true,
+ 'message_type' => true,
+ 'user' => true,
+ 'message_status' => true,
+ 'organisation' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/MessageStatus.php b/idrocap_wa/src/Model/Entity/MessageStatus.php
new file mode 100644
index 0000000..25525a2
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MessageStatus.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'messages' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/MessageType.php b/idrocap_wa/src/Model/Entity/MessageType.php
new file mode 100644
index 0000000..2e3d49f
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MessageType.php
@@ -0,0 +1,32 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'label' => true,
+ 'dispatching_bitmask_weight' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/MobileComponent.php b/idrocap_wa/src/Model/Entity/MobileComponent.php
new file mode 100644
index 0000000..9cc4db4
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MobileComponent.php
@@ -0,0 +1,35 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'menu_item' => true,
+ 'is_enabled' => true,
+ 'capabilities' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/MobilePhone.php b/idrocap_wa/src/Model/Entity/MobilePhone.php
new file mode 100644
index 0000000..7a37091
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MobilePhone.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'is_system' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'mobile_phone_description_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ 'mobile_phone_description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/MobilePhoneDescription.php b/idrocap_wa/src/Model/Entity/MobilePhoneDescription.php
new file mode 100644
index 0000000..5621fbc
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/MobilePhoneDescription.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deleted' => true,
+ 'mobile_phones' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Notification.php b/idrocap_wa/src/Model/Entity/Notification.php
new file mode 100644
index 0000000..0ab8381
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Notification.php
@@ -0,0 +1,51 @@
+
+ */
+ protected array $_accessible = [
+ 'user_id' => true,
+ 'read_by_user' => true,
+ 'notification_type_id' => true,
+ 'info' => true,
+ 'created' => true,
+ 'thread' => true,
+ 'ngroup' => true,
+ 'controllable_object_id' => true,
+ 'user' => true,
+ 'notification_type' => true,
+ 'controllable_object' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/NotificationType.php b/idrocap_wa/src/Model/Entity/NotificationType.php
new file mode 100644
index 0000000..9a02d79
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/NotificationType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'notifications' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Organisation.php b/idrocap_wa/src/Model/Entity/Organisation.php
new file mode 100644
index 0000000..65eeffa
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Organisation.php
@@ -0,0 +1,259 @@
+
+ */
+ protected array $_accessible = [
+ 'acronym' => true,
+ 'geoposition' => true,
+ 'address' => true,
+ 'district' => true,
+ 'cap' => true,
+ 'province' => true,
+ 'organisation_type_id' => true,
+ 'actor_id' => true,
+ 'pec' => true,
+ 'coordinates' => true,
+ 'feature_collection' => true,
+ 'deleted' => true,
+ 'photo' => true,
+ 'controllable_object_interface_id' => true,
+ 'organisation_type' => true,
+ 'actor' => true,
+ 'controllable_object_interface' => true,
+ 'messages' => true,
+ 'users' => true,
+ 'attachments' => true,
+ 'removefiles' => true,
+ ];
+
+ protected array $_hidden = [
+ 'geoposition',
+ ];
+
+ protected array $_virtual = [
+ 'mobile_phones',
+ 'phones',
+ 'emails',
+ 'pecs',
+ ];
+
+ /**
+ * can_view
+ *
+ * @param User $user
+ * @param Array $options
+ * @return Bool
+ */
+ public function can_view(User $user, Array &$options): Bool
+ {
+ if ($user->hasCapability(['configuration.organisations.read']))
+ {
+ return true;
+ } else {
+ $options['error']['capabilities'] = ['configuration.organisations.read'];
+ return false;
+ }
+ }
+
+ /**
+ * _getGeoposition
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function _getGeoposition($value)
+ {
+ if (!is_string($value) || empty(json_decode($value))) {
+ return $value;
+ }
+ return new QueryExpression("ST_GeomFromGeoJson('$value')");
+ }
+
+ protected function _getMobilePhones()
+ {
+ if ($this->isNew()) return [];
+ $mobilePhones = TableRegistry::getTableLocator()->get('MobilePhones')->find()->contain(['Deliveries', 'MobilePhoneDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->mobile_phone_description->description,
+ 'value' => $row->value
+ ];
+ });
+ })->toArray();
+ return $mobilePhones;
+ }
+
+ protected function _getPhones()
+ {
+ if ($this->isNew()) return [];
+ $mobilePhones = TableRegistry::getTableLocator()->get('Phones')->find()->contain(['Deliveries', 'PhoneDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->phone_description->description,
+ 'value' => $row->value
+ ];
+ });
+ })->toArray();
+ return $mobilePhones;
+ }
+
+ protected function _getEmails()
+ {
+ if ($this->isNew()) return [];
+ $emails = TableRegistry::getTableLocator()->get('Emails')->find()->contain(['Deliveries', 'EmailDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->email_description->description,
+ 'value' => $row->value
+ ];
+ });
+ })->toArray();
+ return $emails;
+ }
+
+ protected function _getPecs()
+ {
+ if ($this->isNew()) return [];
+ $pecs = TableRegistry::getTableLocator()->get('Pecs')->find()->contain(['Deliveries', 'PecDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->pec_description->description,
+ 'value' => $row->value
+ ];
+ });
+ });
+ return $pecs;
+ }
+
+ /**
+ * getActor
+ *
+ * @return ?Actor
+ */
+ public function getActor(): ?Actor
+ {
+ if (!isset($this->_fields['actor_id'])) return null;
+ return TableRegistry::getTableLocator()->get('Actors')->get($this->_fields['actor_id']);
+ }
+
+ /**
+ * hasMobilePhonesWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasMobilePhonesWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('MobilePhones');
+ }
+
+ /**
+ * hasEmailsWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasEmailsWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('Emails');
+ }
+
+ /**
+ * hasPecsWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasPecsWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('Pecs');
+ }
+
+ /**
+ * getMobilePhonesWithNotifications
+ *
+ * @return Array
+ */
+ public function getMobilePhonesWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('MobilePhones');
+ }
+
+ /**
+ * getEmailsWithNotifications
+ *
+ * @return Array
+ */
+ public function getEmailsWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('Emails');
+ }
+
+ /**
+ * getPecsWithNotifications
+ *
+ * @return Array
+ */
+ public function getPecsWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('Pecs');
+ }
+
+ /**
+ * getDispatchingBitmask
+ *
+ * @return ?Int
+ */
+ public function getDispatchingBitmask(): ?Int
+ {
+ if (!isset($this->_fields['id'])) return null;
+
+ $bitmask = 0;
+
+ if ($this->hasMobilePhonesWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(1)->dispatching_bitmask_weight;
+ if ($this->hasEmailsWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(3)->dispatching_bitmask_weight;
+ if ($this->hasPecsWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(5)->dispatching_bitmask_weight;
+
+ return $bitmask;
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/OrganisationType.php b/idrocap_wa/src/Model/Entity/OrganisationType.php
new file mode 100644
index 0000000..8f41457
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/OrganisationType.php
@@ -0,0 +1,32 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'organisations' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Pec.php b/idrocap_wa/src/Model/Entity/Pec.php
new file mode 100644
index 0000000..30f9225
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Pec.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'is_system' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'pec_description_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ 'pec_description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/PecDescription.php b/idrocap_wa/src/Model/Entity/PecDescription.php
new file mode 100644
index 0000000..fa0d5a7
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/PecDescription.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deleted' => true,
+ 'pecs' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Permission.php b/idrocap_wa/src/Model/Entity/Permission.php
new file mode 100644
index 0000000..2c9c685
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Permission.php
@@ -0,0 +1,34 @@
+
+ */
+ protected array $_accessible = [
+ 'deleted' => true,
+ 'capability' => true,
+ 'group' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Phone.php b/idrocap_wa/src/Model/Entity/Phone.php
new file mode 100644
index 0000000..b79ec75
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Phone.php
@@ -0,0 +1,39 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'delivery_id' => true,
+ 'phone_description_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ 'phone_description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/PhoneDescription.php b/idrocap_wa/src/Model/Entity/PhoneDescription.php
new file mode 100644
index 0000000..5fa42a3
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/PhoneDescription.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'deleted' => true,
+ 'phones' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Privacy.php b/idrocap_wa/src/Model/Entity/Privacy.php
new file mode 100644
index 0000000..c77b2b5
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Privacy.php
@@ -0,0 +1,32 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'created' => true
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/PrivacyUser.php b/idrocap_wa/src/Model/Entity/PrivacyUser.php
new file mode 100644
index 0000000..b521b22
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/PrivacyUser.php
@@ -0,0 +1,37 @@
+
+ */
+ protected array $_accessible = [
+ 'privacy_id' => true,
+ 'user_id' => true,
+ 'created' => true,
+ 'privacy' => true,
+ 'user' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/PushNotification.php b/idrocap_wa/src/Model/Entity/PushNotification.php
new file mode 100644
index 0000000..fe65c4e
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/PushNotification.php
@@ -0,0 +1,37 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Snapshot.php b/idrocap_wa/src/Model/Entity/Snapshot.php
new file mode 100644
index 0000000..0d4e102
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Snapshot.php
@@ -0,0 +1,47 @@
+
+ */
+ protected array $_accessible = [
+ 'controllable_object_type_id' => true,
+ 'controllable_object_id' => true,
+ 'object_snapshot' => true,
+ 'date' => true,
+ 'user_id' => true,
+ 'controller_action' => true,
+ 'unpacked_with_version' => true,
+ 'user' => true,
+ 'controllable_object' => true,
+ 'controllable_object_type' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/Tag.php b/idrocap_wa/src/Model/Entity/Tag.php
new file mode 100644
index 0000000..0f6f595
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/Tag.php
@@ -0,0 +1,56 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'code' => true,
+ 'class' => true,
+ 'attachments' => true,
+ 'groups' => true,
+ 'id' => true,
+ 'controllable_object_id' => true,
+ 'attachments' => true,
+ 'removefiles' => true,
+ 'controllable_object' => true,
+ ];
+
+ protected array $_virtual = [
+ 'link',
+ ];
+
+ protected function _getLink(): string{
+ if (empty($this->controllable_object_id)) return '';
+ $attachment = TableRegistry::getTableLocator()->get('Attachments')->find()->where(['Attachments.container_controllable_object_id' => $this->controllable_object_id])->first();
+ if(!isset($attachment->file_name)) return '';
+ $link = $attachment->file_name;
+ return $link;
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/TelegramChat.php b/idrocap_wa/src/Model/Entity/TelegramChat.php
new file mode 100644
index 0000000..4aef789
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/TelegramChat.php
@@ -0,0 +1,41 @@
+
+ */
+ protected array $_accessible = [
+ 'value' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'telegram_chat_description_id' => true,
+ 'deleted' => true,
+ 'delivery' => true,
+ 'telegram_chat_description' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/TelegramContact.php b/idrocap_wa/src/Model/Entity/TelegramContact.php
new file mode 100644
index 0000000..87329e2
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/TelegramContact.php
@@ -0,0 +1,51 @@
+
+ */
+ protected array $_accessible = [
+ 'phone_number' => true,
+ 'telegram_user_id' => true,
+ 'enable_notifications' => true,
+ 'delivery_id' => true,
+ 'created' => true,
+ 'modified' => true,
+ 'deleted' => true,
+ 'telegram_contact_status_id' => true,
+ 'error_message' => true,
+ 'delivery' => true,
+ 'telegram_contact_status' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/UnpackedWaterDrawingPaperworkSnapshot.php b/idrocap_wa/src/Model/Entity/UnpackedWaterDrawingPaperworkSnapshot.php
new file mode 100644
index 0000000..5e3c96a
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/UnpackedWaterDrawingPaperworkSnapshot.php
@@ -0,0 +1,55 @@
+
+ */
+ protected array $_accessible = [
+ 'snapshot_id' => true,
+ 'unpacking_version' => true,
+ 'who' => true,
+ 'when' => true,
+ 'what' => true,
+ 'creator' => true,
+ 'created' => true,
+ 'modifier' => true,
+ 'modified' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'water_drawing_paperwork_status' => true,
+ 'gc_user' => true,
+ 'drar_user' => true,
+ 'snapshot' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/User.php b/idrocap_wa/src/Model/Entity/User.php
new file mode 100644
index 0000000..ebfccf1
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/User.php
@@ -0,0 +1,643 @@
+
+ */
+ protected array $_accessible = [
+ 'organisation_id' => true,
+ 'username' => true,
+ 'password' => true,
+ 'surname' => true,
+ 'name' => true,
+ 'address' => true,
+ 'city' => true,
+ 'cap' => true,
+ 'tax_code' => true,
+ 'photo' => true,
+ 'user_photo' => true, // don't remove!!!!!!!!!
+ 'birthplace' => true,
+ 'birthday' => true,
+ 'gender' => true,
+ 'language_id' => true,
+ 'password_recovery_token' => true,
+ 'password_recovery_counter' => true,
+ 'actor_id' => true,
+ 'deleted' => true,
+ 'organisation' => true,
+ 'language' => true,
+ 'actor' => true,
+ 'memberships' => true,
+ 'messages' => true,
+ 'notifications' => true,
+ 'groups' => true,
+ "email_verification_code" => true,
+ "is_verified" => true,
+ "is_citizen" => true
+ ];
+
+
+
+
+ /**
+ * Fields that are excluded from JSON versions of the entity.
+ *
+ * @var array
+ */
+ protected array $_hidden = [
+ 'password',
+ 'position',
+ ];
+
+ protected array $_virtual = [
+ 'profiles',
+ 'mobile_phones',
+ 'emails',
+ 'phones',
+ 'pecs',
+ 'organisation_province'
+ ];
+
+ /**
+ * Authentication\IdentityInterface method
+ */
+ public function getIdentifier(): array|string|int|null
+ {
+ return $this->id;
+ }
+
+ /**
+ * Authentication\IdentityInterface method
+ */
+ public function getOriginalData(): ArrayAccess|array
+ {
+ return $this;
+ }
+
+ /**
+ * _setPassword
+ *
+ * @param String $password
+ * @return String
+ */
+ protected function _setPassword(String $password)
+ {
+ $hasher = new DefaultPasswordHasher();
+ return $hasher->hash($password);
+ }
+
+ /**
+ * getCapabilityIds
+ *
+ * @param Bool $return_query_object
+ * @return Array|Query
+ */
+ public function getCapabilityIds(Bool $return_query_object = false): Array|Query
+ {
+ $CapabilitiesTable = TableRegistry::getTableLocator()->get('Capabilities');
+
+ $capabilities = $CapabilitiesTable->find()
+ ->select(['id']);
+
+ if (!isset($this->sys_admin) || !$this->sys_admin) {
+ $capabilities = $capabilities
+ ->matching('Groups.Users')
+ ->where(['Permissions.deleted IS NULL'])
+ ->where(['Users.id' => $this->id])
+ ->distinct();
+ }
+
+ if (!$return_query_object) {
+ $capabilities = $capabilities
+ ->all()
+ ->extract('id')
+ ->toArray();
+ }
+
+ return $capabilities;
+ }
+
+ /**
+ * hasCapability
+ *
+ * @param String|Array $capability
+ * @return Bool
+ */
+ public function hasCapability(String|Array $capability): Bool
+ {
+ if (isset($this->sys_admin) && $this->sys_admin) return true;
+
+ if (is_string($capability)) $capability = [$capability];
+ return TableRegistry::getTableLocator()->get('Capabilities')
+ ->find()
+ ->where(['Capabilities.value IN' => $capability, 'Capabilities.id IN' => $this->getCapabilityIds(true)])
+ ->first() !== null;
+ }
+
+
+ /**
+ * Verifica se l'utente ha solo la capability con priorità più bassa tra quelle fornite
+ *
+ * @param String|Array $capabilities
+ * @return Bool
+ */
+ public function hasOnlyLowerPriorityCapability(String|Array $capabilities): Bool
+ {
+ if (isset($this->sys_admin) && $this->sys_admin) return false;
+
+ $userCapabilities = TableRegistry::getTableLocator()->get('Capabilities')
+ ->find()
+ ->select(['value', 'priority'])
+ ->where(['Capabilities.value IN' => $capabilities, 'Capabilities.id IN' => $this->getCapabilityIds(true)])
+ ->all()
+ ->toArray();
+
+ // Se l'utente non ha nessuna delle capability richieste, restituisco false
+ if (empty($userCapabilities)) return false;
+
+ // A questo punto verifico se l'utente ha solo la capability con priorità più bassa
+ $hasPriority1 = false;
+ $hasPriority2 = false;
+
+ foreach ($userCapabilities as $capability) {
+ if ($capability->priority == 1) {
+ $hasPriority1 = true;
+ } else if ($capability->priority == 2) {
+ $hasPriority2 = true;
+ }
+ }
+ return !$hasPriority1 && $hasPriority2;
+ }
+
+ /**
+ * canActOnContactsForActor
+ *
+ * @param String $action
+ * @param Actor $actor
+ * @param String|Array $contact_types
+ * @return Bool
+ */
+ private function canActOnContactsForActor(String $action, Actor $actor, String|Array $contact_types = ['mobile_phone', 'fax', 'email', 'phone', 'telegram_chat', 'pec']): Bool
+ {
+ $contact_types = is_string($contact_types) ? [$contact_types] : $contact_types;
+ // se actor è di tipo "organizzazione":
+ if ($actor->actor_type_id == 1) {
+ // verifichiamo che l'utente abbia titolo a visualizzare i recapiti dell'organizzazione selezionata.
+ // o è la sua stessa organizzazione oppure necessita di almeno 1 delle seguenti capabilities:
+ $required_capabilities = collection($contact_types)
+ ->map(function ($contact_type) use ($action) {
+ return 'configuration.organisations.' . $action . '_' . $contact_type;
+ })
+ ->toArray();
+ if ($actor->organisation->id != $this->organisation_id && !$this->hasCapability($required_capabilities)) return false;
+ return true;
+ }
+
+ // se actor è di tipo "utente":
+ if ($actor->actor_type_id == 5) {
+ // verifichiamo che l'utente abbia titolo a visualizzare i recapiti dell'utente selezionato.
+ // o l'utente selezionato è lo stesso utente,
+ // o l'utente selezionato appartiene alla stessa organizzazione dell'utente e possiede almeno una
+ // tra l'array_merge dei 2 seguenti array $required_capabilities e $required_foo_capabilities,
+ // oppure deve possedere almeno 1 delle capabilities di $required_capabilities soltanto:
+ $required_capabilities = collection($contact_types)
+ ->map(function ($contact_type) use ($action) {
+ return 'configuration.users.' . $action . '_' . $contact_type;
+ })
+ ->toArray();
+ $required_foo_capabilities = collection($contact_types)
+ ->map(function ($contact_type) use ($action) {
+ return 'configuration.users.' . $action . '_' . $contact_type . '_foo';
+ })
+ ->toArray();
+ // se i recapiti sono relativi ad un'utente della stessa organizzazione dell'utente loggato
+ // aggiungiamo anche le relative capabilities di basso livello (_foo):
+ if ($this->organisation_id == $actor->user->organisation_id) $required_capabilities = array_merge($required_capabilities, $required_foo_capabilities);
+
+ if ($actor->user->id != $this->id && !$this->hasCapability($required_capabilities)) return false;
+ return true;
+ }
+ // nessun accesso per actor non di tipo "organizzazione" o "utente":
+ return false;
+ }
+
+ /**
+ * canViewContactsForActor
+ *
+ * @param Actor $actor
+ * @param String|Array $contact_types
+ * @return Bool
+ */
+ public function canViewContactsForActor(Actor $actor, String|Array $contact_types = ['mobile_phone', 'fax', 'email', 'phone', 'telegram_chat', 'pec']): Bool
+ {
+ return $this->canActOnContactsForActor('view', $actor, $contact_types);
+ }
+
+ /**
+ * canAddContactsForActor
+ *
+ * @param Actor $actor
+ * @param String|Array $contact_types
+ * @return Bool
+ */
+ public function canAddContactsForActor(Actor $actor, String|Array $contact_types = ['mobile_phone', 'fax', 'email', 'phone', 'telegram_chat', 'pec']): Bool
+ {
+ return $this->canActOnContactsForActor('add', $actor, $contact_types);
+ }
+
+ /**
+ * canEditContactsForActor
+ *
+ * @param Actor $actor
+ * @param String|Array $contact_types
+ * @return Bool
+ */
+ public function canEditContactsForActor(Actor $actor, String|Array $contact_types = ['mobile_phone', 'fax', 'email', 'phone', 'telegram_chat', 'pec']): Bool
+ {
+ return $this->canActOnContactsForActor('edit', $actor, $contact_types);
+ }
+
+ /**
+ * canDeleteContactsForActor
+ *
+ * @param Actor $actor
+ * @param String|Array $contact_types
+ * @return Bool
+ */
+ public function canDeleteContactsForActor(Actor $actor, String|Array $contact_types = ['mobile_phone', 'fax', 'email', 'phone', 'telegram_chat', 'pec']): Bool
+ {
+ return $this->canActOnContactsForActor('delete', $actor, $contact_types);
+ }
+
+ /**
+ * _getProfiles
+ *
+ * @return String
+ */
+ protected function _getProfiles(): String
+ {
+ // se la entity è stata appena creata:
+ if ($this->isNew()) return "";
+
+ // se non vi è un utente loggato:
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user || !$user->hasCapability('configuration.groups.read')) return "**************";
+
+ $profiles = TableRegistry::getTableLocator()->get('Groups')->find()
+ ->matching('Users')
+ ->where(['Users.id' => $this->id])
+ ->order(['Groups.description' => 'ASC'])
+ ->all()
+ ->extract('description')
+ ->toArray();
+
+ return implode(", ", $profiles);
+ }
+
+ protected function _getMobilePhones()
+ {
+ if ($this->isNew()) return [];
+ $mobilePhones = TableRegistry::getTableLocator()->get('MobilePhones')->find()->contain(['Deliveries', 'MobilePhoneDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->mobile_phone_description->description,
+ 'value' => $row->value
+ ];
+ });
+ })->toArray();
+ return $mobilePhones;
+ }
+
+ protected function _getPhones()
+ {
+ if ($this->isNew()) return [];
+ $mobilePhones = TableRegistry::getTableLocator()->get('Phones')->find()->contain(['Deliveries', 'PhoneDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->phone_description->description,
+ 'value' => $row->value
+ ];
+ });
+ })->toArray();
+ return $mobilePhones;
+ }
+
+ protected function _getEmails()
+ {
+ if ($this->isNew()) return [];
+ $emails = TableRegistry::getTableLocator()->get('Emails')->find()->contain(['Deliveries', 'EmailDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->email_description->description,
+ 'value' => $row->value
+ ];
+ });
+ })->toArray();
+ return $emails;
+ }
+
+ protected function _getPecs()
+ {
+ if ($this->isNew()) return [];
+ $pecs = TableRegistry::getTableLocator()->get('Pecs')->find()->contain(['Deliveries', 'PecDescriptions'])->where(['Deliveries.actor_id' => $this->actor_id])->formatResults(function ($q){
+ return $q->map(function ($row){
+ return [
+ 'type' => $row->pec_description->description,
+ 'value' => $row->value
+ ];
+ });
+ });
+ return $pecs;
+ }
+
+ /**
+ * __toString
+ *
+ * @return String
+ */
+ public function __toString(): String {
+ if ($this->isNew()) return "";
+ $surname = $this->_fields['surname'] ?? '';
+ $name = $this->_fields['name'] ?? '';
+ $description = "$name $surname";
+
+ if (isset($this->_fields['organisation_id'])) {
+ $user_org = TableRegistry::getTableLocator()->get('Organisations')->get($this->_fields['organisation_id'], contain: ['Actors']);
+ $org_description = $user_org->actor->description ?? null;
+ if ($org_description) $description .= " ($org_description)";
+ }
+
+ return $description;
+ }
+
+ /**
+ * canHandleAttachmentsForControllableObject
+ *
+ * @param ControllableObject $co
+ * @return Bool
+ */
+ public function canHandleAttachmentsForControllableObject(ControllableObject $co): Bool
+ {
+ return $co->organisation_id == $this->_fields['organisation_id'] || $co->create_user_id = $this->_fields['id'];
+ }
+
+ /**
+ * can_view
+ *
+ * @param User $user
+ * @param Array $options
+ * @return Bool
+ */
+ public function can_view(User $user, Array &$options): Bool
+ {
+ if($user->hasCapability(['configuration.users.read']) || ($user->hasCapability(['configuration.users.read_foo']) && $user->organisation_id == $this->_fields['organisation_id']))
+ {
+ return true;
+ } else {
+ if ($user->organisation_id == $this->_fields['organisation_id']) {
+ $options['error']['capabilities'][] = 'configuration.users.read_foo';
+ }
+ if (empty($options['error']['capabilities'])) {
+ $options['capabilities'][] = ['configuration.users.read'];
+ }
+ return false;
+ }
+ }
+
+ /**
+ * getActor
+ *
+ * @return ?Actor
+ */
+ public function getActor(): ?Actor
+ {
+ if (!isset($this->_fields['actor_id'])) return null;
+ return TableRegistry::getTableLocator()->get('Actors')->get($this->_fields['actor_id']);
+ }
+
+ /**
+ * hasPushNotificationsWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasPushNotificationsWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('PushNotifications');
+ }
+
+ /**
+ * hasMobilePhonesWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasMobilePhonesWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('MobilePhones');
+ }
+
+ /**
+ * hasFaxesWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasFaxesWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('Faxes');
+ }
+
+ /**
+ * hasEmailsWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasEmailsWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('Emails');
+ }
+
+ /**
+ * hasPecsWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasPecsWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('Pecs');
+ }
+
+ /**
+ * hasTelegramChatsWithNotifications
+ *
+ * @return Bool
+ */
+ public function hasTelegramChatsWithNotifications(): Bool
+ {
+ return $this->getActor()->hasContactsWithNotificationsOfType('TelegramChats');
+ }
+
+ /**
+ * getPushNotificationsWithNotifications
+ *
+ * @return Array
+ */
+ public function getPushNotificationsWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('PushNotifications');
+ }
+
+ /**
+ * getMobilePhonesWithNotifications
+ *
+ * @return Array
+ */
+ public function getMobilePhonesWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('MobilePhones');
+ }
+
+ /**
+ * getFaxesWithNotifications
+ *
+ * @return Array
+ */
+ public function getFaxesWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('Faxes');
+ }
+
+ /**
+ * getEmailsWithNotifications
+ *
+ * @return Array
+ */
+ public function getEmailsWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('Emails');
+ }
+
+ /**
+ * getPecsWithNotifications
+ *
+ * @return Array
+ */
+ public function getPecsWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('Pecs');
+ }
+
+ /**
+ * getTelegramChatsWithNotifications
+ *
+ * @return Array
+ */
+ public function getTelegramChatsWithNotifications(): Array
+ {
+ return $this->getActor()->getContactsWithNotificationsOfType('TelegramChats');
+ }
+
+ /**
+ * getDispatchingBitmask
+ *
+ * @param ?String $notification_code
+ * @return ?Int
+ */
+ public function getDispatchingBitmask(?String $notification_code = null): ?Int
+ {
+ if (!isset($this->_fields['id'])) return null;
+
+ $bitmask = 0;
+
+ $pushNotificationsCapability = !$notification_code || $notification_code == "test_all" || $this->hasCapability(['notifications.'.$notification_code.'.push_notification']);
+ $mobilePhonesCapability = !$notification_code || $notification_code == "password_recovery" || $notification_code == "test_all" || $this->hasCapability(['notifications.'.$notification_code.'.sms']);
+ $faxesCapability = !$notification_code || $notification_code == "test_all" || $this->hasCapability(['notifications.'.$notification_code.'.fax']);
+ $emailsCapability = !$notification_code || $notification_code == "password_recovery" || $notification_code == "test_all" || $this->hasCapability(['notifications.'.$notification_code.'.email']);
+ $telegramChatsCapability = !$notification_code || $notification_code == "password_recovery" || $notification_code == "test_all" || $this->hasCapability(['notifications.'.$notification_code.'.telegram_chat']);
+ $pecsCapability = $this->hasCapability(['notifications.'.$notification_code.'.pec']);
+
+ if ($pushNotificationsCapability && $this->hasPushNotificationsWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(0)->dispatching_bitmask_weight;
+ if ($mobilePhonesCapability && $this->hasMobilePhonesWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(1)->dispatching_bitmask_weight;
+ if ($faxesCapability && $this->hasFaxesWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(2)->dispatching_bitmask_weight;
+ if ($emailsCapability && $this->hasEmailsWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(3)->dispatching_bitmask_weight;
+ if ($telegramChatsCapability && $this->hasTelegramChatsWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(4)->dispatching_bitmask_weight;
+ if ($pecsCapability && $this->hasPecsWithNotifications()) $bitmask += TableRegistry::getTableLocator()->get('MessageTypes')->get(5)->dispatching_bitmask_weight;
+
+ return $bitmask;
+ }
+
+ protected function _setTaxCode($value)
+ {
+ return strtoupper($value);
+ }
+
+ protected function _getOrganisationProvince(): ?String
+ {
+ if (!isset($this->_fields['organisation_id'])) return null;
+
+ if (isset($this->organisation?->province)) {
+ return $this->organisation->province;
+ }
+
+ $organisation = TableRegistry::getTableLocator()->get('Organisations')
+ ->find()
+ ->select(['province'])
+ ->where(['id' => $this->_fields['organisation_id']])
+ ->first();
+
+ return $organisation?->province;
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/UserTimezoneDatetimeEntityTrait.php b/idrocap_wa/src/Model/Entity/UserTimezoneDatetimeEntityTrait.php
new file mode 100644
index 0000000..16c7367
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/UserTimezoneDatetimeEntityTrait.php
@@ -0,0 +1,32 @@
+getSource();
+ // solo se la entity non è una newEntity (quindi ancora senza repository/source):
+ if (!empty($source)) {
+ $user = Router::getRequest()?->getAttribute('identity');
+ if (isset($user->disableUserTimezoneDatetimeEntityTrait) && is_bool($user->disableUserTimezoneDatetimeEntityTrait) && $user->disableUserTimezoneDatetimeEntityTrait) return;
+ $timezone = !empty($user->timezone) ? $user->timezone : Configure::read('App.defaultUserTimezone');
+
+ $entity_source_schema = TableRegistry::getTableLocator()->get($source)->getSchema();
+ foreach ($entity_source_schema->columns() as $entity_property_name) {
+ $entity_property_type = $entity_source_schema->getColumnType($entity_property_name);
+ if ($entity_property_type == 'datetime' && isset($this->_fields[$entity_property_name])) {
+ $this->_fields[$entity_property_name] = $this->_fields[$entity_property_name]?->setTimezone($timezone);
+ }
+ }
+ }
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequest.php b/idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequest.php
new file mode 100644
index 0000000..4f4cb10
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequest.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'water_drawing_paperwork_id' => true,
+ 'user_id' => true,
+ 'water_drawing_antimafia_certification_request_status_id' => true,
+ 'created' => true,
+ 'water_drawing_paperwork' => true,
+ 'user' => true,
+ 'water_drawing_antimafia_certification_request_status' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequestStatus.php b/idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequestStatus.php
new file mode 100644
index 0000000..3cb87d3
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingAntimafiaCertificationRequestStatus.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_antimafia_certification_requests' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingArticle.php b/idrocap_wa/src/Model/Entity/WaterDrawingArticle.php
new file mode 100644
index 0000000..12bca94
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingArticle.php
@@ -0,0 +1,32 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'long_description' => true,
+ 'disable' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingDerivation.php b/idrocap_wa/src/Model/Entity/WaterDrawingDerivation.php
new file mode 100644
index 0000000..baf56d2
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingDerivation.php
@@ -0,0 +1,67 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_body' => true,
+ 'feature_collection' => true,
+ 'district' => true,
+ 'cadastral_code' => true,
+ 'location' => true,
+ 'cadastral_sheet' => true,
+ 'cadastral_parcel' => true,
+ 'latitude' => true,
+ 'longitude' => true,
+ 'istat' => true,
+ 'derivation_status' => true,
+ 'withdrawals_amount' => true,
+ 'annual_volume' => true,
+ 'average_flow_rate' => true,
+ 'water_drawing_derivation_use_id' => true,
+ 'water_drawing_derivation_type_id' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'water_drawing_derivation_type' => true,
+ ];
+
+ protected array $_hidden = ['geometry'];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingDerivationType.php b/idrocap_wa/src/Model/Entity/WaterDrawingDerivationType.php
new file mode 100644
index 0000000..a7e4462
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingDerivationType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_derivations' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingFee.php b/idrocap_wa/src/Model/Entity/WaterDrawingFee.php
new file mode 100644
index 0000000..bbe1448
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingFee.php
@@ -0,0 +1,65 @@
+
+ */
+ protected array $_accessible = [
+ 'amount' => true,
+ 'year' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'water_drawing_paperwork' => true,
+ 'water_drawing_payments' => true,
+ ];
+
+ protected array $_virtual = [
+ 'paied',
+ 'to_pay',
+ ];
+
+ protected function _getPaied(): Bool{
+ if(!isset($this->id)) return false;
+ $total = 0;
+ $waterDrawingPaymentsTable = TableRegistry::getTableLocator()->get('WaterDrawingPayments');
+ $water_drawing_payments = $waterDrawingPaymentsTable->find()->where(['WaterDrawingPayments.water_drawing_fee_id' => $this->id])->toArray();
+ foreach($water_drawing_payments as $water_drawing_payment){
+ $total += $water_drawing_payment->amount;
+ }
+ return ($this->amount <= $total);
+ }
+
+ protected function _getToPay(): float{
+ if(!isset($this->id)) return 0;
+ $payed = 0;
+ $waterDrawingPaymentsTable = TableRegistry::getTableLocator()->get('WaterDrawingPayments');
+ $water_drawing_payments = $waterDrawingPaymentsTable->find()->where(['WaterDrawingPayments.water_drawing_fee_id' => $this->id])->toArray();
+ foreach($water_drawing_payments as $water_drawing_payment){
+ $payed = $payed + $water_drawing_payment->amount;
+ }
+ return $this->amount - $payed;
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingIntendedUse.php b/idrocap_wa/src/Model/Entity/WaterDrawingIntendedUse.php
new file mode 100644
index 0000000..5a8759b
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingIntendedUse.php
@@ -0,0 +1,55 @@
+
+ */
+ protected array $_accessible = [
+ 'area' => true,
+ 'cadastral_code' => true,
+ 'cadastral_sheet' => true,
+ 'cadastral_parcel' => true,
+ 'consortium_area' => true,
+ 'rated_power_produced' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'water_drawing_intended_use_type_id' => true,
+ 'vegetation_match_status' => true,
+ 'water_drawing_watering_system_id' => true,
+ 'water_drawing_paperwork' => true,
+ 'water_drawing_intended_use_type' => true,
+ 'cadastral_crop_types' => true,
+ 'water_drawing_meters' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingIntendedUseType.php b/idrocap_wa/src/Model/Entity/WaterDrawingIntendedUseType.php
new file mode 100644
index 0000000..9000d1d
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingIntendedUseType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_intended_uses' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingMeasurement.php b/idrocap_wa/src/Model/Entity/WaterDrawingMeasurement.php
new file mode 100644
index 0000000..a90ccc5
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingMeasurement.php
@@ -0,0 +1,39 @@
+
+ */
+ protected array $_accessible = [
+ 'volume' => true,
+ 'date' => true,
+ 'water_drawing_meter_id' => true,
+ 'user_id' => true,
+ 'water_drawing_meter' => true,
+ 'user' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingMeter.php b/idrocap_wa/src/Model/Entity/WaterDrawingMeter.php
new file mode 100644
index 0000000..619fc52
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingMeter.php
@@ -0,0 +1,45 @@
+
+ */
+ protected array $_accessible = [
+ 'water_drawing_tool_type_id' => true,
+ 'water_drawing_intended_use_id' => true,
+ 'manufacturer' => true,
+ 'part_number' => true,
+ 'installation_date' => true,
+ 'removal_date' => true,
+ 'water_drawing_tool_type' => true,
+ 'water_drawing_measurements' => true,
+ 'water_drawing_intended_use' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingPaperwork.php b/idrocap_wa/src/Model/Entity/WaterDrawingPaperwork.php
new file mode 100644
index 0000000..3c6c7f0
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingPaperwork.php
@@ -0,0 +1,479 @@
+
+ */
+ protected array $_accessible = [
+ 'water_drawing_paperwork_status_id' => true,
+ 'district' => true,
+ 'location' => true,
+ 'cadastral_sheet' => true,
+ 'cadastral_parcel' => true,
+ 'x_coordinate' => true,
+ 'y_coordinate' => true,
+ 'istat' => true,
+ 'derivation_type' => true,
+ 'derivation_status' => true,
+ 'withdrawals_amount' => true,
+ 'annual_volume' => true,
+ 'average_flow_rate' => true,
+ 'from_date' => true,
+ 'to_date' => true,
+ 'gurs_reference' => true,
+ 'authorisation_type' => true,
+ 'concession_decree_number' => true,
+ 'release_date' => true,
+ 'concession_duration' => true,
+ 'expiration_date' => true,
+ 'first_istance' => true,
+ 'takeover' => true,
+ 'year' => true,
+ 'fee_payment_certificate' => true,
+ 'initial_static_level_water' => true,
+ 'initial_static_level_water_date' => true,
+ 'static_level_water' => true,
+ 'static_level_water_date' => true,
+ 'authority_province' => true,
+ 'authority_identification_code_civil_engineering_office' => true,
+ 'authority_identification_code_derivation_department_water_waste' => true,
+ 'water_drawing_article_id' => true,
+ 'water_drawing_article' => true,
+ 'water_body' => true,
+ 'cadastral_code' => true,
+ 'controllable_object_id' => true,
+ 'water_drawing_paperwork_status' => true,
+ 'controllable_object' => true,
+ 'water_drawing_measurements' => true,
+ 'applicants' => true,
+ 'water_drawing_paperwork_histories' => true,
+ 'attachments' => true,
+ 'removefiles' => true,
+ 'feature_collection' => true,
+ 'geom' => true,
+ 'scanned' => true,
+ 'drar_user_id' => true,
+ 'gc_user_id' => true,
+ 'water_drawing_antimafia_certification_requests' => true,
+ 'water_drawing_derivations' => true,
+ 'water_drawing_return_points' => true,
+ 'water_drawing_intended_uses' => true,
+ 'water_drawing_fees' => true,
+ 'protocol_number' => true,
+ ];
+
+ protected array $_virtual = [
+ 'water_drawing_paperwork_type_description',
+ 'authority_civil_engineer_code',
+ 'check_thc',
+ 'check_dv',
+ 'check_lic',
+ 'check_dec',
+ 'check_dsc',
+ 'check2a',
+ 'check_ssd',
+ 'check_dam',
+ 'check_rap',
+ 'check_ia7',
+ 'check_ia56',
+ 'check_ira',
+ 'check_adam',
+ 'percentage',
+ 'check_ram',
+ 'check_isu',
+ 'check_rpdi',
+ 'check_thc_a',
+ 'check_thc_aa',
+ 'check_thc_ab',
+ 'check_thc_ac',
+ 'check_thc_ad',
+ 'check_thc_ae',
+ 'check_thc_af',
+ 'check_thc_ag',
+ 'check_thc_b',
+ 'check_thc_b1',
+ 'check_thc_b2',
+ 'check_thc_b3',
+ 'check_thc_b4',
+ ];
+
+ /**
+ * _getWaterDrawingPaperworkTypeDescription
+ *
+ * Virtual Field that returns water_drawing_paperwork description based on the type of instance attachment uploaded
+ *
+ * @return string
+ */
+ protected function _getWaterDrawingPaperworkTypeDescription(): string
+ {
+ if ($this->_getCheckRap() || $this->_getCheckIa7()) return __('Istanza concessione art. 7');
+ if ($this->_getCheckIa56()) return __('Istanza concessione art. 56');
+ if ($this->_getCheckIra()) return __('Istanza attingimento art. 30');
+ if ($this->_getCheckIsu()) return __('Istanza subentro art. 20');
+ if ($this->_getCheckIrc56()) return __('Istanza rinnovo concessione art.56');
+ return __('');
+ }
+
+ protected function _getAuthorityCivilEngineerCode(): string
+ {
+ if (!isset($this->authority_province)) {
+ return "";
+ }
+
+ $sigla = "";
+
+ switch(strtolower($this->authority_province)){
+ case "catania":
+ $sigla = "CT";
+ break;
+ case "palermo":
+ $sigla = "PA";
+ break;
+ case "caltanissetta":
+ $sigla = "CL";
+ break;
+ case "enna":
+ $sigla = "EN";
+ break;
+ case "ragusa":
+ $sigla = "RG";
+ break;
+ case "siracusa":
+ $sigla = "SR";
+ break;
+ case "trapani":
+ $sigla = "TP";
+ break;
+ case "messina":
+ $sigla = "ME";
+ break;
+ case "agrigento":
+ $sigla = "AG";
+ break;
+ default:
+ $sigla = "";
+ }
+
+ return "GC " . $sigla;
+ }
+
+ protected function _getCheckThc(): Bool{
+ return $this->checkDocument(-8);
+ }
+
+ protected function _getCheckDv(): Bool{
+ return $this->checkDocument(-7);
+ }
+
+ protected function _getCheckLic(): Bool{
+ return $this->checkDocument(-6);
+ }
+
+ protected function _getCheckDec(): Bool{
+ return $this->checkDocument(-5);
+ }
+
+ protected function _getCheckDsc(): Bool{
+ return $this->checkDocument(-4);
+ }
+
+ protected function _getCheck2a(): Bool{
+ return $this->checkDocument(-3);
+ }
+
+ protected function _getCheckSdd(): Bool{
+ return $this->checkDocument(-10);
+ }
+
+ protected function _getCheckDam(): Bool{
+ return $this->checkDocument(-11);
+ }
+
+ protected function _getCheckRap(): Bool{
+ return $this->checkDocument(1);
+ }
+
+ protected function _getCheckIa7(): Bool{
+ return $this->checkDocument(2);
+ }
+
+ protected function _getCheckIa56(): Bool{
+ return $this->checkDocument(3);
+ }
+
+ protected function _getCheckIra(): Bool{
+ return $this->checkDocument(4);
+ }
+
+ protected function _getCheckAdam(): Bool{
+ return $this->checkDocument(5);
+ }
+
+ protected function _getCheckRam(): Bool{
+ return $this->checkDocument(-14);
+ }
+
+ protected function _getCheckIsu(): Bool{
+ return $this->checkDocument(6);
+ }
+
+ protected function _getCheckRpdi(): Bool{
+ return $this->checkDocument(-15);
+ }
+
+ protected function _getCheckThcA(): Bool{
+ return $this->checkDocument(7);
+ }
+
+ protected function _getCheckThcAa(): Bool{
+ return $this->checkDocument(8);
+ }
+
+ protected function _getCheckThcAb(): Bool{
+ return $this->checkDocument(9);
+ }
+
+ protected function _getCheckThcAc(): Bool{
+ return $this->checkDocument(10);
+ }
+
+ protected function _getCheckThcAd(): Bool{
+ return $this->checkDocument(11);
+ }
+
+ protected function _getCheckThcAe(): Bool{
+ return $this->checkDocument(12);
+ }
+
+ protected function _getCheckThcAf(): Bool{
+ return $this->checkDocument(13);
+ }
+
+ protected function _getCheckThcAg(): Bool{
+ return $this->checkDocument(14);
+ }
+
+ protected function _getCheckThcB(): Bool{
+ return $this->checkDocument(15);
+ }
+
+ protected function _getCheckThcB1(): Bool{
+ return $this->checkDocument(16);
+ }
+
+ protected function _getCheckThcB2(): Bool{
+ return $this->checkDocument(17);
+ }
+
+ protected function _getCheckThcB3(): Bool{
+ return $this->checkDocument(18);
+ }
+
+ protected function _getCheckThcB4(): Bool{
+ return $this->checkDocument(19);
+ }
+
+ protected function _getCheckIrc56(): Bool{
+ return $this->checkDocument(20);
+ }
+
+ private function checkDocument($tagId): Bool{
+ if(!isset($this->_fields['controllable_object_id'])) return false;
+ $attachment = TableRegistry::getTableLocator()->get('Attachments')->find()->matching('Tags', function ($q) use ($tagId){
+ return $q->where(['Tags.id' => $tagId]);
+ })->contain(['ControllableObjects'])
+ ->where(['Attachments.container_controllable_object_id' => $this->_fields['controllable_object_id'], 'ControllableObjects.deleted IS NULL'])->first();
+ return isset($attachment);
+ }
+
+ protected function _getGeom($value)
+ {
+ if (!is_string($value) || empty(json_decode($value))) {
+ return $value;
+ }
+ return new QueryExpression("ST_GeomFromGeoJson('$value')");
+ }
+
+ protected function _getPercentage()
+ {
+ $value = 0;
+ $fieldsCount = 33;
+ if(isset($this->_fields['protocol_number'])) $value++;
+ if(isset($this->_fields['authority_civil_engineer_code'])) $value++;
+ if(isset($this->_fields['authority_province'])) $value++;
+ if(isset($this->_fields['authority_identification_code_civil_engineering_office'])) $value++;
+ if(isset($this->_fields['authority_identification_code_derivation_department_water_waste'])) $value++;
+ if(isset($this->_fields['water_drawing_article_id'])) $value++;
+ if(isset($this->_fields['applicants'])) $value++;
+ if(isset($this->_fields['water_drawing_derivations'])) $value++;
+ if(isset($this->_fields['water_drawing_intended_uses'])) $value++;
+ if(isset($this->_fields['water_drawing_return_points'])) $value++;
+ if(isset($this->_fields['from_date'])) $value++;
+ if(isset($this->_fields['to_date'])) $value++;
+ if(isset($this->_fields['gurs_reference'])) $value++;
+ if(isset($this->_fields['authorisation_type'])) $value++;
+ if(isset($this->_fields['expiration_date'])) $value++;
+ if(isset($this->_fields['first_istance'])) $value++;
+ if(isset($this->_fields['takeover'])) $value++;
+ if(isset($this->_fields['concession_decree_number'])) $value++;
+ if(isset($this->_fields['water_drawing_fees'])) $value++;
+ if(isset($this->_fields['water_drawing_intended_uses']) && isset($this->_fields['water_drawing_intended_uses'][0]['water_drawing_meters'])) $value++;
+ if(isset($this->_fields['static_level_water'])) $value++;
+ if(isset($this->_fields['static_level_water_date'])) $value++;
+ if(isset($this->_fields['initial_static_level_water'])) $value++;
+ if(isset($this->_fields['initial_static_level_water_date'])) $value++;
+ if(isset($this->check_thc)) $value++;
+ if(isset($this->check_dv)) $value++;
+ if(isset($this->check_lic)) $value++;
+ if(isset($this->check_dec)) $value++;
+ if(isset($this->check_dsc)) $value++;
+ if(isset($this->check_ssd)) $value++;
+ if(isset($this->check2a)) $value++;
+ if(isset($this->check_dam)) $value++;
+ if(isset($this->check_rpdi)) $value++;
+ return number_format(($value*100)/$fieldsCount, 0, '.','') . '%';
+ }
+
+ /**
+ * is_citizen_documentation_ok_to_send
+ *
+ * serve a stabilire se la documentazione minima necessaria per la sottomissione della pratica cittadino è presente oppure no
+ *
+ * @return Bool
+ */
+ public function is_citizen_documentation_ok_to_send (): Bool
+ {
+ return
+ $this->_getCheckRpdi()
+ &&
+ (
+ $this->_getCheckIra()
+ ||
+ $this->_getCheckIsu()
+ ||
+ $this->_getCheckIrc56()
+ ||
+ (
+ (
+ $this->_getCheckRap()
+ ||
+ $this->_getCheckIa7()
+ ||
+ $this->_getCheckIa56()
+ )
+ &&
+ $this->_getCheckThcA()
+ &&
+ $this->_getCheckThcAa()
+ &&
+ $this->_getCheckThcAb()
+ &&
+ $this->_getCheckThcAc()
+ &&
+ $this->_getCheckThcAd()
+ &&
+ $this->_getCheckThcAe()
+ &&
+ $this->_getCheckThcB()
+ &&
+ $this->_getCheckThcB2()
+ )
+ );
+ }
+
+ /**
+ * is_citizen_water_drawing_paperwork_status_ok_to_send
+ *
+ * serve a stabilire se lo stato della pratica cittadino è conforme per la sua sottomissione oppure no
+ *
+ * @return Bool
+ */
+ public function is_citizen_water_drawing_paperwork_status_ok_to_send (): Bool
+ {
+ return in_array($this->_fields['water_drawing_paperwork_status_id'], [8, 11]);
+ }
+
+ /**
+ * is_citizen_water_drawing_paperwork_ok_to_send
+ *
+ * serve a stabilire se la pratica cittadino è pronta alla sottomissione oppure no
+ *
+ * @return Bool
+ */
+ public function is_citizen_water_drawing_paperwork_ok_to_send (): Bool
+ {
+ return $this->is_citizen_documentation_ok_to_send() && $this->is_citizen_water_drawing_paperwork_status_ok_to_send();
+ }
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkHistory.php b/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkHistory.php
new file mode 100644
index 0000000..42bada6
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkHistory.php
@@ -0,0 +1,54 @@
+
+ */
+ protected array $_accessible = [
+ 'result' => true,
+ 'note' => true,
+ 'created' => true,
+ 'user_id' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'deleted' => true,
+ 'water_drawing_paperwork_status_id' => true,
+ 'controllable_object_id' => true,
+ 'user' => true,
+ 'water_drawing_paperwork' => true,
+ 'water_drawing_paperwork_status' => true,
+ 'attachments' => true,
+ 'removefiles' => true,
+ 'controllable_object' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkPec.php b/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkPec.php
new file mode 100644
index 0000000..8533c80
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkPec.php
@@ -0,0 +1,53 @@
+
+ */
+ protected array $_accessible = [
+ 'water_drawing_paperwork_id' => true,
+ 'user_id' => true,
+ 'controllable_object_id' => true,
+ 'document' => true,
+ 'protocol_number' => true,
+ 'protocol_date' => true,
+ 'recipient' => true,
+ 'sender' => true,
+ 'water_drawing_paperwork' => true,
+ 'user' => true,
+ 'controllable_object' => true,
+ 'attachments' => true,
+ 'removefiles' => true,
+ 'note' => true
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkStatus.php b/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkStatus.php
new file mode 100644
index 0000000..7f2af0e
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingPaperworkStatus.php
@@ -0,0 +1,33 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'rgb' => true,
+ 'water_drawing_paperworks' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingPayment.php b/idrocap_wa/src/Model/Entity/WaterDrawingPayment.php
new file mode 100644
index 0000000..53d44b6
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingPayment.php
@@ -0,0 +1,56 @@
+
+ */
+ protected array $_accessible = [
+ 'water_drawing_fee_id' => true,
+ 'water_drawing_payment_type_id' => true,
+ 'user_id' => true,
+ 'amount' => true,
+ 'payment_date' => true,
+ 'payment_number' => true,
+ 'notes' => true,
+ 'created' => true,
+ 'water_drawing_fee' => true,
+ 'water_drawing_payment_type' => true,
+ 'user' => true,
+ 'receipt_number' => true,
+ 'receipt_date' => true,
+ 'receipt_amount' => true,
+ 'applicant_tax_code' => true
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingPaymentType.php b/idrocap_wa/src/Model/Entity/WaterDrawingPaymentType.php
new file mode 100644
index 0000000..014a986
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingPaymentType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_payments' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingReturnPoint.php b/idrocap_wa/src/Model/Entity/WaterDrawingReturnPoint.php
new file mode 100644
index 0000000..4a03f2c
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingReturnPoint.php
@@ -0,0 +1,43 @@
+
+ */
+ protected array $_accessible = [
+ 'latitude' => true,
+ 'longitude' => true,
+ 'feature_collection' => true,
+ 'district' => true,
+ 'cadastral_sheet' => true,
+ 'cadastral_parcel' => true,
+ 'water_drawing_paperwork_id' => true,
+ 'water_drawing_paperwork' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingToolType.php b/idrocap_wa/src/Model/Entity/WaterDrawingToolType.php
new file mode 100644
index 0000000..165ebb6
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingToolType.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_meters' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Entity/WaterDrawingWateringSystem.php b/idrocap_wa/src/Model/Entity/WaterDrawingWateringSystem.php
new file mode 100644
index 0000000..4c21c28
--- /dev/null
+++ b/idrocap_wa/src/Model/Entity/WaterDrawingWateringSystem.php
@@ -0,0 +1,31 @@
+
+ */
+ protected array $_accessible = [
+ 'description' => true,
+ 'water_drawing_intended_uses' => true,
+ ];
+}
diff --git a/idrocap_wa/src/Model/Table/ActorTypesTable.php b/idrocap_wa/src/Model/Table/ActorTypesTable.php
new file mode 100644
index 0000000..1601834
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ActorTypesTable.php
@@ -0,0 +1,81 @@
+setTable('actor_types');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Actors', [
+ 'foreignKey' => 'actor_type_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('entity')
+ ->maxLength('entity', 255)
+ ->requirePresence('entity', 'create')
+ ->notEmptyString('entity');
+
+ $validator
+ ->scalar('table')
+ ->maxLength('table', 255)
+ ->requirePresence('table', 'create')
+ ->notEmptyString('table');
+
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ActorsTable.php b/idrocap_wa/src/Model/Table/ActorsTable.php
new file mode 100644
index 0000000..fe71589
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ActorsTable.php
@@ -0,0 +1,126 @@
+setTable('actors');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ActorTypes', [
+ 'foreignKey' => 'actor_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('Deliveries', [
+ 'foreignKey' => 'actor_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('Groups', [
+ 'foreignKey' => 'actor_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('Organisations', [
+ 'foreignKey' => 'actor_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('Users', [
+ 'foreignKey' => 'actor_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->integer('actor_type_id')
+ ->requirePresence('actor_type_id', 'create')
+ ->notEmptyString('actor_type_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('actor_type_id', 'ActorTypes'), ['errorField' => 'actor_type_id']);
+ $rules->addDelete(function ($entity, $options) {
+ // mi assicuro che l'actor è di tipo Groups
+ if($entity->actor_type_id == 6) {
+ $group = $this->Groups->find()->where(['actor_id' => $entity->id])->first();
+ if(isset($group) && !$group->is_editable) {
+ return false;
+ }
+ }
+ return true;
+ }, 'checkGroupIsEditable', ['errorField' => 'is_editable', 'message' => __('Questo profilo non può essere eliminato.')]);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ApplicantsTable.php b/idrocap_wa/src/Model/Table/ApplicantsTable.php
new file mode 100644
index 0000000..ab210f6
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ApplicantsTable.php
@@ -0,0 +1,208 @@
+setTable('applicants');
+ $this->setDisplayField('name');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('ApplicantsWaterDrawingPaperworks', [
+ 'foreignKey' => 'applicant_id',
+ ]);
+ $this->belongsToMany('WaterDrawingPaperworks', [
+ 'foreignKey' => 'applicant_id',
+ 'targetForeignKey' => 'water_drawing_paperwork_id',
+ 'joinTable' => 'applicants_water_drawing_paperworks',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('name')
+ ->maxLength('name', 255)
+ ->allowEmptyString('name');
+
+ $validator
+ ->scalar('surname')
+ ->maxLength('surname', 255)
+ ->allowEmptyString('surname');
+
+ $validator
+ ->scalar('company_name')
+ ->maxLength('company_name', 255)
+ ->allowEmptyString('company_name');
+
+ $validator
+ ->scalar('tax_code')
+ ->maxLength('tax_code', 255)
+ ->allowEmptyString('tax_code')
+ ->regex('tax_code', '/^[A-Z]{6}[0-9LMNPQRSTUV]{2}[A-EHLMPR-T]{1}[0-9LMNPQRSTUV]{2}[A-Z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1}$/', 'Il formato del codice fiscale è errato.');
+
+ $validator
+ ->scalar('vat_number')
+ ->maxLength('vat_number', 255)
+ ->allowEmptyString('vat_number');
+
+ $validator
+ ->scalar('address')
+ ->maxLength('address', 255)
+ ->allowEmptyString('address');
+
+ $validator
+ ->scalar('district')
+ ->maxLength('district', 255)
+ ->allowEmptyString('district');
+
+ $validator
+ ->scalar('province')
+ ->maxLength('province', 255)
+ ->allowEmptyString('province');
+
+ $validator
+ ->scalar('pec_address')
+ ->email('pec_address', true)
+ ->maxLength('pec_address', 255)
+ ->allowEmptyString('pec_address');
+
+ $validator
+ ->scalar('email_address')
+ ->maxLength('email_address', 255)
+ ->allowEmptyString('email_address');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->isUnique(['tax_code', 'deleted'], __('Un richiedente con lo stesso codice fiscale è già presente!')), ['errorField' => 'tax_code']);
+
+ $rules->add(function ($entity, $options) {
+ $districtsTable = $this->fetchTable("Districts");
+
+ if (!empty($entity->district)) {
+ $exists = $districtsTable->exists(['comune' => $entity->district]);
+ if (!$exists) {
+ return false;
+ }
+ }
+
+ return true;
+ }, 'validDistrict', [
+ 'errorField' => 'district',
+ 'message' => 'Il comune selezionato non è valido.'
+ ]);
+
+ $rules->add(function ($entity, $options) {
+ $countiesTable = $this->fetchTable("Counties");
+
+ if (!empty($entity->province)) {
+ $provinceField = strlen($entity->province) === 2 ? 'sigla' : 'den_uts';
+ $exists = $countiesTable->exists([$provinceField => $entity->province]);
+ if (!$exists) {
+ return false;
+ }
+ }
+
+ return true;
+ }, 'validProvince', [
+ 'errorField' => 'province',
+ 'message' => 'La provincia selezionata non è valida.'
+ ]);
+
+ return $rules;
+ }
+
+ public function beforeMarshal( $event, $data, $options)
+ {
+ if (isset($data['tax_code'])) {
+ $data['tax_code'] = strtoupper($data['tax_code']);
+ }
+ if (isset($data['province'])) {
+ switch (strtolower($data['province'])) {
+ case 'catania':
+ $data['province'] = 'CT';
+ break;
+ case 'palermo':
+ $data['province'] = 'PA';
+ break;
+ case 'caltanissetta':
+ $data['province'] = 'CL';
+ break;
+ case 'enna':
+ $data['province'] = 'EN';
+ break;
+ case 'ragusa':
+ $data['province'] = 'RG';
+ break;
+ case 'siracusa':
+ $data['province'] = 'SR';
+ break;
+ case 'trapani':
+ $data['province'] = 'TP';
+ break;
+ case 'messina':
+ $data['province'] = 'ME';
+ break;
+ case 'agrigento':
+ $data['province'] = 'AG';
+ break;
+ }
+ }
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ApplicantsWaterDrawingPaperworksTable.php b/idrocap_wa/src/Model/Table/ApplicantsWaterDrawingPaperworksTable.php
new file mode 100644
index 0000000..d467201
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ApplicantsWaterDrawingPaperworksTable.php
@@ -0,0 +1,100 @@
+setTable('applicants_water_drawing_paperworks');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Applicants', [
+ 'foreignKey' => 'applicant_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('applicant_id')
+ ->notEmptyString('applicant_id');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ $validator
+ ->allowEmptyString('is_primary_applicant');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('applicant_id', 'Applicants'), ['errorField' => 'applicant_id']);
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add(function ($entity){
+ $result = $this->find()->where([
+ 'ApplicantsWaterDrawingPaperworks.applicant_id' => $entity->applicant_id,
+ 'ApplicantsWaterDrawingPaperworks.water_drawing_paperwork_id' => $entity->water_drawing_paperwork_id])
+ ->count();
+ return $result <= 1;
+ }, ['errorField' => 'applicant_id', 'message' => __('Questo richiedente è già presente all\'interno della pratica.')]);
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/AttachmentsTable.php b/idrocap_wa/src/Model/Table/AttachmentsTable.php
new file mode 100644
index 0000000..6283be7
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/AttachmentsTable.php
@@ -0,0 +1,133 @@
+setTable('attachments');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ContainerControllableObjects', [
+ 'className' => 'ControllableObjects',
+ 'foreignKey' => 'container_controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsToMany('Tags', [
+ 'foreignKey' => 'attachment_id',
+ 'targetForeignKey' => 'tag_id',
+ 'joinTable' => 'attachments_tags',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('original_file_name')
+ ->maxLength('original_file_name', 255)
+ ->requirePresence('original_file_name', 'create')
+ ->notEmptyFile('original_file_name');
+
+ $validator
+ ->integer('original_file_size')
+ ->requirePresence('original_file_size', 'create')
+ ->notEmptyFile('original_file_size');
+
+ $validator
+ ->scalar('file_name')
+ ->maxLength('file_name', 255)
+ ->requirePresence('file_name', 'create')
+ ->notEmptyFile('file_name');
+
+ $validator
+ ->scalar('mimetype')
+ ->maxLength('mimetype', 255)
+ ->requirePresence('mimetype', 'create')
+ ->notEmptyString('mimetype');
+
+ $validator
+ ->dateTime('upload_date')
+ ->requirePresence('upload_date', 'create')
+ ->notEmptyDateTime('upload_date');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ $validator
+ ->integer('container_controllable_object_id')
+ ->allowEmptyString('container_controllable_object_id');
+
+ $validator
+ ->boolean('relevant')
+ ->allowEmptyString('relevant');
+
+ $validator
+ ->boolean('private')
+ ->notEmptyString('private');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/BackgroundTasksTable.php b/idrocap_wa/src/Model/Table/BackgroundTasksTable.php
new file mode 100644
index 0000000..f87ea46
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/BackgroundTasksTable.php
@@ -0,0 +1,103 @@
+setTable('background_tasks');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->hasMany('DispatchingTasks', [
+ 'foreignKey' => 'background_task_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('command')
+ ->maxLength('command', 4294967295)
+ ->requirePresence('command', 'create')
+ ->notEmptyString('command');
+
+ $validator
+ ->scalar('data')
+ ->maxLength('data', 4294967295)
+ ->requirePresence('data', 'create')
+ ->notEmptyString('data');
+
+ $validator
+ ->scalar('dgroup')
+ ->maxLength('dgroup', 255)
+ ->allowEmptyString('dgroup')
+ ->add('dgroup', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
+
+ $validator
+ ->integer('status')
+ ->notEmptyString('status');
+
+ $validator
+ ->notEmptyString('was_synced');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->isUnique(['dgroup'], ['allowMultipleNulls' => true]), ['errorField' => 'dgroup']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/CadastralCropTypesTable.php b/idrocap_wa/src/Model/Table/CadastralCropTypesTable.php
new file mode 100644
index 0000000..cd1d133
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/CadastralCropTypesTable.php
@@ -0,0 +1,69 @@
+setTable('cadastral_crop_types');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsToMany('WaterDrawingIntendedUses', [
+ 'foreignKey' => 'cadastral_crop_type_id',
+ 'targetForeignKey' => 'water_drawing_intended_use_id',
+ 'joinTable' => 'cadastral_crop_types_water_drawing_intended_uses',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/CapabilitiesMenuItemsTable.php b/idrocap_wa/src/Model/Table/CapabilitiesMenuItemsTable.php
new file mode 100644
index 0000000..1b064d3
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/CapabilitiesMenuItemsTable.php
@@ -0,0 +1,91 @@
+setTable('capabilities_menu_items');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Capabilities', [
+ 'foreignKey' => 'capability_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('MenuItems', [
+ 'foreignKey' => 'menu_item_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('capability_id')
+ ->requirePresence('capability_id', 'create')
+ ->notEmptyString('capability_id');
+
+ $validator
+ ->integer('menu_item_id')
+ ->requirePresence('menu_item_id', 'create')
+ ->notEmptyString('menu_item_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('capability_id', 'Capabilities'), ['errorField' => 'capability_id']);
+ $rules->add($rules->existsIn('menu_item_id', 'MenuItems'), ['errorField' => 'menu_item_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/CapabilitiesMenuSectionsTable.php b/idrocap_wa/src/Model/Table/CapabilitiesMenuSectionsTable.php
new file mode 100644
index 0000000..2b40932
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/CapabilitiesMenuSectionsTable.php
@@ -0,0 +1,91 @@
+setTable('capabilities_menu_sections');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Capabilities', [
+ 'foreignKey' => 'capability_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('MenuSections', [
+ 'foreignKey' => 'menu_section_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('capability_id')
+ ->requirePresence('capability_id', 'create')
+ ->notEmptyString('capability_id');
+
+ $validator
+ ->integer('menu_section_id')
+ ->requirePresence('menu_section_id', 'create')
+ ->notEmptyString('menu_section_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('capability_id', 'Capabilities'), ['errorField' => 'capability_id']);
+ $rules->add($rules->existsIn('menu_section_id', 'MenuSections'), ['errorField' => 'menu_section_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/CapabilitiesTable.php b/idrocap_wa/src/Model/Table/CapabilitiesTable.php
new file mode 100644
index 0000000..d218875
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/CapabilitiesTable.php
@@ -0,0 +1,145 @@
+setTable('capabilities');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('CapabilityGroups', [
+ 'foreignKey' => 'capability_group_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsToMany('Groups', [
+ 'foreignKey' => 'capability_id',
+ 'targetForeignKey' => 'group_id',
+ 'joinTable' => 'permissions',
+ ]);
+ $this->belongsToMany('MenuItems', [
+ 'foreignKey' => 'capability_id',
+ 'targetForeignKey' => 'menu_item_id',
+ 'joinTable' => 'capabilities_menu_items',
+ ]);
+ $this->belongsToMany('MenuSections', [
+ 'foreignKey' => 'capability_id',
+ 'targetForeignKey' => 'menu_section_id',
+ 'joinTable' => 'capabilities_menu_sections',
+ ]);
+ $this->hasMany('Permissions', [
+ 'foreignKey' => 'capability_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->allowEmptyString('description');
+
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->requirePresence('value', 'create')
+ ->notEmptyString('value');
+
+ $validator
+ ->integer('priority')
+ ->notEmptyString('priority');
+
+ $validator
+ ->integer('capability_group_id')
+ ->requirePresence('capability_group_id', 'create')
+ ->notEmptyString('capability_group_id');
+
+ $validator
+ ->integer('priority_group_id')
+ ->allowEmptyString('priority_group_id');
+
+ $validator
+ ->boolean('organisation_required')
+ ->notEmptyString('organisation_required');
+
+ $validator
+ ->scalar('longdescription')
+ ->maxLength('longdescription', 4294967295)
+ ->allowEmptyString('longdescription');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ $validator
+ ->boolean('is_configurable')
+ ->notEmptyString('is_configurable');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('capability_group_id', 'CapabilityGroups'), ['errorField' => 'capability_group_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/CapabilityGroupsTable.php b/idrocap_wa/src/Model/Table/CapabilityGroupsTable.php
new file mode 100644
index 0000000..a517cb5
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/CapabilityGroupsTable.php
@@ -0,0 +1,79 @@
+setTable('capability_groups');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Capabilities', [
+ 'foreignKey' => 'capability_group_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ $validator
+ ->boolean('is_configurable')
+ ->notEmptyString('is_configurable');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ControllableObjectInterfaceTypesTable.php b/idrocap_wa/src/Model/Table/ControllableObjectInterfaceTypesTable.php
new file mode 100644
index 0000000..3375fb0
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ControllableObjectInterfaceTypesTable.php
@@ -0,0 +1,77 @@
+setTable('controllable_object_interface_types');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('ControllableObjectInterfaces', [
+ 'foreignKey' => 'controllable_object_interface_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('entity')
+ ->maxLength('entity', 255)
+ ->requirePresence('entity', 'create')
+ ->notEmptyString('entity');
+
+ $validator
+ ->scalar('table')
+ ->maxLength('table', 255)
+ ->requirePresence('table', 'create')
+ ->notEmptyString('table');
+
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ControllableObjectInterfacesTable.php b/idrocap_wa/src/Model/Table/ControllableObjectInterfacesTable.php
new file mode 100644
index 0000000..5b08d1b
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ControllableObjectInterfacesTable.php
@@ -0,0 +1,95 @@
+setTable('controllable_object_interfaces');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('ControllableObjectInterfaceTypes', [
+ 'foreignKey' => 'controllable_object_interface_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['controllable_object']['controllable_object_type_id'] = -1;
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ $validator
+ ->integer('controllable_object_interface_type_id')
+ ->notEmptyString('controllable_object_interface_type_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ $rules->add($rules->existsIn('controllable_object_interface_type_id', 'ControllableObjectInterfaceTypes'), ['errorField' => 'controllable_object_interface_type_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ControllableObjectTypesTable.php b/idrocap_wa/src/Model/Table/ControllableObjectTypesTable.php
new file mode 100644
index 0000000..2cdcc31
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ControllableObjectTypesTable.php
@@ -0,0 +1,74 @@
+setTable('controllable_object_types');
+ $this->setDisplayField('label');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 45)
+ ->allowEmptyString('description');
+
+ $validator
+ ->scalar('controller')
+ ->maxLength('controller', 45)
+ ->allowEmptyString('controller');
+
+ $validator
+ ->scalar('label')
+ ->maxLength('label', 255)
+ ->allowEmptyString('label');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/ControllableObjectsTable.php b/idrocap_wa/src/Model/Table/ControllableObjectsTable.php
new file mode 100644
index 0000000..aaf1747
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/ControllableObjectsTable.php
@@ -0,0 +1,167 @@
+setTable('controllable_objects');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Organisations', [
+ 'foreignKey' => 'organisation_id',
+ ]);
+ $this->belongsTo('ControllableObjectTypes', [
+ 'foreignKey' => 'controllable_object_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('ChildAttachments', [
+ 'className' => 'Attachments',
+ 'foreignKey' => 'container_controllable_object_id',
+ 'joinType' => 'LEFT',
+ ]);
+ $this->hasMany('Attachments', [
+ 'foreignKey' => 'controllable_object_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('ControllableObjectInterfaces', [
+ 'foreignKey' => 'controllable_object_id',
+ ]);
+ $this->belongsTo('Creator', [
+ 'foreignKey' => 'create_user_id',
+ 'className' => 'Users',
+ 'joinType' => 'LEFT'
+ ]);
+ $this->belongsTo('Modifier', [
+ 'foreignKey' => 'edit_user_id',
+ 'className' => 'Users',
+ 'joinType' => 'LEFT'
+ ]);
+ $this->hasOne('Locations', [
+ 'foreignKey' => 'controllable_object_id',
+ ]);
+
+ $this->hasOne('WaterDrawingPaperworks', [
+ 'foreignKey' => 'controllable_object_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+
+ $this->hasOne('WaterDrawingPaperworkPecs', [
+ 'foreignKey' => 'controllable_object_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('organisation_id')
+ ->allowEmptyString('organisation_id');
+
+ $validator
+ ->integer('controllable_object_type_id')
+ ->requirePresence('controllable_object_type_id', 'create')
+ ->notEmptyString('controllable_object_type_id');
+
+ $validator
+ ->integer('create_user_id')
+ ->allowEmptyString('create_user_id');
+
+ $validator
+ ->integer('edit_user_id')
+ ->allowEmptyString('edit_user_id');
+
+ $validator
+ ->integer('edit_organisation_id')
+ ->allowEmptyString('edit_organisation_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('organisation_id', 'Organisations'), ['errorField' => 'organisation_id']);
+ $rules->add($rules->existsIn('controllable_object_type_id', 'ControllableObjectTypes'), ['errorField' => 'controllable_object_type_id']);
+ $rules->add($rules->existsIn('create_user_id', 'Creator'), ['errorField' => 'create_user_id']);
+ $rules->add($rules->existsIn('edit_user_id', 'Modifier'), ['errorField' => 'edit_user_id']);
+ $rules->add($rules->existsIn('edit_organisation_id', 'Organisations'), ['errorField' => 'edit_organisation_id']);
+
+ return $rules;
+ }
+
+ public function beforeSave(EventInterface $event, ControllableObject $entity, \ArrayObject $options)
+ {
+ $user = Router::getRequest()?->getAttribute('identity');
+ if (!isset($entity->id)) $entity->organisation_id = $user->organisation_id ?? null;
+ if (!isset($entity->id)) $entity->create_user_id = $user->id ?? null;
+ $entity->edit_user_id = $user->id ?? null;
+ $entity->edit_organisation_id = $user->organisation_id ?? null;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/CountiesTable.php b/idrocap_wa/src/Model/Table/CountiesTable.php
new file mode 100644
index 0000000..449369c
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/CountiesTable.php
@@ -0,0 +1,165 @@
+ newEntities(array $data, array $options = [])
+ * @method \App\Model\Entity\County get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
+ * @method \App\Model\Entity\County findOrCreate($search, ?callable $callback = null, array $options = [])
+ * @method \App\Model\Entity\County patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
+ * @method array<\App\Model\Entity\County> patchEntities(iterable $entities, array $data, array $options = [])
+ * @method \App\Model\Entity\County|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method \App\Model\Entity\County saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method iterable<\App\Model\Entity\County>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\County>|false saveMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\County>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\County> saveManyOrFail(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\County>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\County>|false deleteMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\County>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\County> deleteManyOrFail(iterable $entities, array $options = [])
+ */
+class CountiesTable extends Table
+{
+ /**
+ * Initialize method
+ *
+ * @param array $config The configuration for the Table.
+ * @return void
+ */
+ public function initialize(array $config): void
+ {
+ parent::initialize($config);
+
+ $this->setTable('counties');
+ $this->setDisplayField('OGR_FID');
+ $this->setPrimaryKey('OGR_FID');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->requirePresence('SHAPE', 'create')
+ ->notEmptyString('SHAPE');
+
+ $validator
+ ->decimal('cod_rip')
+ ->allowEmptyString('cod_rip');
+
+ $validator
+ ->decimal('cod_reg')
+ ->allowEmptyString('cod_reg');
+
+ $validator
+ ->decimal('cod_prov')
+ ->allowEmptyString('cod_prov');
+
+ $validator
+ ->decimal('cod_cm')
+ ->allowEmptyString('cod_cm');
+
+ $validator
+ ->decimal('cod_uts')
+ ->allowEmptyString('cod_uts');
+
+ $validator
+ ->scalar('den_prov')
+ ->maxLength('den_prov', 50)
+ ->allowEmptyString('den_prov');
+
+ $validator
+ ->scalar('den_cm')
+ ->maxLength('den_cm', 50)
+ ->allowEmptyString('den_cm');
+
+ $validator
+ ->scalar('den_uts')
+ ->maxLength('den_uts', 50)
+ ->allowEmptyString('den_uts');
+
+ $validator
+ ->scalar('sigla')
+ ->maxLength('sigla', 2)
+ ->allowEmptyString('sigla');
+
+ $validator
+ ->scalar('tipo_uts')
+ ->maxLength('tipo_uts', 50)
+ ->allowEmptyString('tipo_uts');
+
+ $validator
+ ->scalar('shape_leng')
+ ->maxLength('shape_leng', 255)
+ ->allowEmptyString('shape_leng');
+
+ $validator
+ ->scalar('shape_area')
+ ->maxLength('shape_area', 255)
+ ->allowEmptyString('shape_area');
+
+ return $validator;
+ }
+
+ public function getCountiesByRegion(int $cod_reg, ProvinceCellDto $provinceCellConfig): array
+ {
+ $provinceFullNameField = ProvinceDistrictFieldHelper::raw(ProvinceDistrictFields::FULL_NAME);
+ $provinceSiglaField = ProvinceDistrictFieldHelper::raw(ProvinceDistrictFields::ABBREVIATION);
+ $provinceCodeValueField = $provinceCellConfig->showProvinceFullName ? $provinceFullNameField : $provinceSiglaField;
+
+ $provinceCodeField = ProvinceDistrictFieldHelper::forCounties(ProvinceDistrictFields::PROVINCE_CODE);
+ $regionCodeField = ProvinceDistrictFieldHelper::forCounties(ProvinceDistrictFields::REGION_CODE);
+
+ $results = $this->find()
+ ->select([$provinceCodeField, $provinceCodeValueField])
+ ->where([$regionCodeField => $cod_reg])
+ ->all()
+ ->toArray();
+
+ $options = Hash::combine($results, '{n}.' . $provinceCodeValueField, '{n}.' . $provinceCodeValueField);
+ $map = Hash::combine($results, '{n}.' . $provinceCodeValueField, '{n}.' . ProvinceDistrictFields::PROVINCE_CODE->value);
+
+ return [
+ "options" => $options,
+ "map" => $map,
+ ];
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->isUnique(['OGR_FID']), ['errorField' => 'OGR_FID']);
+
+ return $rules;
+ }
+
+ /**
+ * Returns the database connection name to use by default.
+ *
+ * @return string
+ */
+ public static function defaultConnectionName(): string
+ {
+ return 'geo';
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/DeliveriesTable.php b/idrocap_wa/src/Model/Table/DeliveriesTable.php
new file mode 100644
index 0000000..4929f7f
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/DeliveriesTable.php
@@ -0,0 +1,145 @@
+setTable('deliveries');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Actors', [
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('DeliveryTypes', [
+ 'foreignKey' => 'delivery_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasOne('Emails', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('Faxes', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('MobilePhones', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('Phones', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('PushNotifications', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('TelegramChats', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('TelegramContacts', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasOne('Pecs', [
+ 'foreignKey' => 'delivery_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('actor_id')
+ ->requirePresence('actor_id', 'create')
+ ->notEmptyString('actor_id');
+
+ $validator
+ ->integer('delivery_type_id')
+ ->requirePresence('delivery_type_id', 'create')
+ ->notEmptyString('delivery_type_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('actor_id', 'Actors'), ['errorField' => 'actor_id']);
+ $rules->add($rules->existsIn('delivery_type_id', 'DeliveryTypes'), ['errorField' => 'delivery_type_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/DeliveryTypesTable.php b/idrocap_wa/src/Model/Table/DeliveryTypesTable.php
new file mode 100644
index 0000000..730e61d
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/DeliveryTypesTable.php
@@ -0,0 +1,65 @@
+setTable('delivery_types');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Deliveries', [
+ 'foreignKey' => 'delivery_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/DispatchingTaskItemsTable.php b/idrocap_wa/src/Model/Table/DispatchingTaskItemsTable.php
new file mode 100644
index 0000000..d26676e
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/DispatchingTaskItemsTable.php
@@ -0,0 +1,111 @@
+setTable('dispatching_task_items');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('DispatchingTasks', [
+ 'foreignKey' => 'dispatching_task_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Actors', [
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('dispatching_task_id')
+ ->requirePresence('dispatching_task_id', 'create')
+ ->notEmptyString('dispatching_task_id');
+
+ $validator
+ ->integer('actor_id')
+ ->requirePresence('actor_id', 'create')
+ ->notEmptyString('actor_id');
+
+ $validator
+ ->boolean('system_dispatched')
+ ->allowEmptyString('system_dispatched');
+
+ $validator
+ ->integer('actor_dispatching_bitmask')
+ ->notEmptyString('actor_dispatching_bitmask');
+
+ $validator
+ ->integer('performed_dispatching_bitmask')
+ ->notEmptyString('performed_dispatching_bitmask');
+
+ $validator
+ ->integer('not_performed_dispatching_bitmask')
+ ->allowEmptyString('not_performed_dispatching_bitmask');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('dispatching_task_id', 'DispatchingTasks'), ['errorField' => 'dispatching_task_id']);
+ $rules->add($rules->existsIn('actor_id', 'Actors'), ['errorField' => 'actor_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/DispatchingTaskStatusesTable.php b/idrocap_wa/src/Model/Table/DispatchingTaskStatusesTable.php
new file mode 100644
index 0000000..f911aa3
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/DispatchingTaskStatusesTable.php
@@ -0,0 +1,65 @@
+setTable('dispatching_task_statuses');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('DispatchingTasks', [
+ 'foreignKey' => 'dispatching_task_status_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/DispatchingTasksTable.php b/idrocap_wa/src/Model/Table/DispatchingTasksTable.php
new file mode 100644
index 0000000..3f5d008
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/DispatchingTasksTable.php
@@ -0,0 +1,113 @@
+setTable('dispatching_tasks');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('DispatchingTaskStatuses', [
+ 'foreignKey' => 'dispatching_task_status_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('BackgroundTasks', [
+ 'foreignKey' => 'background_task_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('DispatchingTaskItems', [
+ 'foreignKey' => 'dispatching_task_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('dispatching_task_group')
+ ->maxLength('dispatching_task_group', 255)
+ ->requirePresence('dispatching_task_group', 'create')
+ ->notEmptyString('dispatching_task_group');
+
+ $validator
+ ->integer('dispatching_task_status_id')
+ ->requirePresence('dispatching_task_status_id', 'create')
+ ->notEmptyString('dispatching_task_status_id');
+
+ $validator
+ ->integer('retries')
+ ->notEmptyString('retries');
+
+ $validator
+ ->boolean('failed')
+ ->notEmptyString('failed');
+
+ $validator
+ ->integer('background_task_id')
+ ->requirePresence('background_task_id', 'create')
+ ->notEmptyString('background_task_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('dispatching_task_status_id', 'DispatchingTaskStatuses'), ['errorField' => 'dispatching_task_status_id']);
+ $rules->add($rules->existsIn('background_task_id', 'BackgroundTasks'), ['errorField' => 'background_task_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/DistrictsTable.php b/idrocap_wa/src/Model/Table/DistrictsTable.php
new file mode 100644
index 0000000..23dec60
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/DistrictsTable.php
@@ -0,0 +1,136 @@
+ newEntities(array $data, array $options = [])
+ * @method \App\Model\Entity\District get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
+ * @method \App\Model\Entity\District findOrCreate($search, ?callable $callback = null, array $options = [])
+ * @method \App\Model\Entity\District patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
+ * @method array<\App\Model\Entity\District> patchEntities(iterable $entities, array $data, array $options = [])
+ * @method \App\Model\Entity\District|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method \App\Model\Entity\District saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method iterable<\App\Model\Entity\District>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\District>|false saveMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\District>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\District> saveManyOrFail(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\District>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\District>|false deleteMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\District>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\District> deleteManyOrFail(iterable $entities, array $options = [])
+ */
+class DistrictsTable extends Table
+{
+ /**
+ * Initialize method
+ *
+ * @param array $config The configuration for the Table.
+ * @return void
+ */
+ public function initialize(array $config): void
+ {
+ parent::initialize($config);
+
+ $this->setTable('districts');
+ $this->setDisplayField('OGR_FID');
+ $this->setPrimaryKey('OGR_FID');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->requirePresence('SHAPE', 'create')
+ ->notEmptyString('SHAPE');
+
+ $validator
+ ->decimal('cod_rip')
+ ->allowEmptyString('cod_rip');
+
+ $validator
+ ->decimal('cod_reg')
+ ->allowEmptyString('cod_reg');
+
+ $validator
+ ->decimal('cod_prov')
+ ->allowEmptyString('cod_prov');
+
+ $validator
+ ->decimal('cod_cm')
+ ->allowEmptyString('cod_cm');
+
+ $validator
+ ->decimal('cod_uts')
+ ->allowEmptyString('cod_uts');
+
+ $validator
+ ->decimal('pro_com')
+ ->allowEmptyString('pro_com');
+
+ $validator
+ ->scalar('pro_com_t')
+ ->maxLength('pro_com_t', 6)
+ ->allowEmptyString('pro_com_t');
+
+ $validator
+ ->scalar('comune')
+ ->maxLength('comune', 100)
+ ->allowEmptyString('comune');
+
+ $validator
+ ->scalar('comune_a')
+ ->maxLength('comune_a', 100)
+ ->allowEmptyString('comune_a');
+
+ $validator
+ ->decimal('cc_uts')
+ ->allowEmptyString('cc_uts');
+
+ $validator
+ ->scalar('shape_leng')
+ ->maxLength('shape_leng', 255)
+ ->allowEmptyString('shape_leng');
+
+ $validator
+ ->scalar('shape_area')
+ ->maxLength('shape_area', 255)
+ ->allowEmptyString('shape_area');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->isUnique(['OGR_FID']), ['errorField' => 'OGR_FID']);
+
+ return $rules;
+ }
+
+ /**
+ * Returns the database connection name to use by default.
+ *
+ * @return string
+ */
+ public static function defaultConnectionName(): string
+ {
+ return 'geo';
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/EmailDescriptionsTable.php b/idrocap_wa/src/Model/Table/EmailDescriptionsTable.php
new file mode 100644
index 0000000..30b921a
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/EmailDescriptionsTable.php
@@ -0,0 +1,74 @@
+setTable('email_descriptions');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Emails', [
+ 'foreignKey' => 'email_description_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/EmailsTable.php b/idrocap_wa/src/Model/Table/EmailsTable.php
new file mode 100644
index 0000000..ccff182
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/EmailsTable.php
@@ -0,0 +1,111 @@
+setTable('emails');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('EmailDescriptions', [
+ 'foreignKey' => 'email_description_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->requirePresence('value', 'create')
+ ->notEmptyString('value')
+ ->email('value', true);
+
+ $validator
+ ->boolean('is_system')
+ ->notEmptyString('is_system');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->notEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->notEmptyString('delivery_id');
+
+ $validator
+ ->integer('email_description_id')
+ ->requirePresence('email_description_id', 'create')
+ ->allowEmptyString('email_description_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->add($rules->existsIn('email_description_id', 'EmailDescriptions'), ['errorField' => 'email_description_id']);
+ $rules->add($rules->isUnique(['value'], __('Indirizzo email già presente a sistema!')));
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/FaxDescriptionsTable.php b/idrocap_wa/src/Model/Table/FaxDescriptionsTable.php
new file mode 100644
index 0000000..9daf8fb
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/FaxDescriptionsTable.php
@@ -0,0 +1,73 @@
+setTable('fax_descriptions');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Faxes', [
+ 'foreignKey' => 'fax_description_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/FaxesTable.php b/idrocap_wa/src/Model/Table/FaxesTable.php
new file mode 100644
index 0000000..63bac03
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/FaxesTable.php
@@ -0,0 +1,107 @@
+setTable('faxes');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('FaxDescriptions', [
+ 'foreignKey' => 'fax_description_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->requirePresence('value', 'create')
+ ->notEmptyString('value')
+ ->regex('value', '/^[0-9]*$/i');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->allowEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->notEmptyString('delivery_id');
+
+ $validator
+ ->integer('fax_description_id')
+ ->requirePresence('fax_description_id', 'create')
+ ->allowEmptyString('fax_description_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->add($rules->existsIn('fax_description_id', 'FaxDescriptions'), ['errorField' => 'fax_description_id']);
+ $rules->add($rules->isUnique(['value'], __('Fax già presente a sistema!')));
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/FiltersTable.php b/idrocap_wa/src/Model/Table/FiltersTable.php
new file mode 100644
index 0000000..37e9521
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/FiltersTable.php
@@ -0,0 +1,105 @@
+setTable('filters');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('controller_action_category')
+ ->maxLength('controller_action_category', 255)
+ ->requirePresence('controller_action_category', 'create')
+ ->notEmptyString('controller_action_category');
+
+ $validator
+ ->scalar('category')
+ ->maxLength('category', 255)
+ ->requirePresence('category', 'create')
+ ->notEmptyString('category');
+
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->scalar('filter_type')
+ ->maxLength('filter_type', 255)
+ ->requirePresence('filter_type', 'create')
+ ->notEmptyString('filter_type');
+
+ $validator
+ ->scalar('class_name')
+ ->maxLength('class_name', 255)
+ ->allowEmptyString('class_name');
+
+ $validator
+ ->scalar('search')
+ ->maxLength('search', 255)
+ ->allowEmptyString('search');
+
+ $validator
+ ->scalar('associations')
+ ->maxLength('associations', 255)
+ ->allowEmptyString('associations');
+
+ $validator
+ ->integer('order_number')
+ ->requirePresence('order_number', 'create')
+ ->notEmptyString('order_number');
+
+ $validator
+ ->boolean('sys_admin_only')
+ ->allowEmptyString('sys_admin_only');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/GroupsGroupsTable.php b/idrocap_wa/src/Model/Table/GroupsGroupsTable.php
new file mode 100644
index 0000000..831c287
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/GroupsGroupsTable.php
@@ -0,0 +1,94 @@
+setTable('groups_groups');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ContainerGroups', [
+ 'className' => 'Groups',
+ 'foreignKey' => 'container_group_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('ContainedGroups', [
+ 'className' => 'Groups',
+ 'foreignKey' => 'group_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('container_group_id')
+ ->requirePresence('container_group_id', 'create')
+ ->notEmptyString('container_group_id');
+
+ $validator
+ ->integer('group_id')
+ ->requirePresence('group_id', 'create')
+ ->notEmptyString('group_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('container_group_id', 'Groups'), ['errorField' => 'container_group_id']);
+ $rules->add($rules->existsIn('group_id', 'Groups'), ['errorField' => 'group_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/GroupsTable.php b/idrocap_wa/src/Model/Table/GroupsTable.php
new file mode 100644
index 0000000..c6b0bfa
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/GroupsTable.php
@@ -0,0 +1,157 @@
+setTable('groups');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Actors', [
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('Memberships', [
+ 'foreignKey' => 'group_id',
+ ]);
+ $this->hasMany('Permissions', [
+ 'foreignKey' => 'group_id',
+ ]);
+ $this->belongsToMany('Users', [
+ 'foreignKey' => 'group_id',
+ 'targetForeignKey' => 'user_id',
+ 'joinTable' => 'memberships',
+ ]);
+ $this->belongsToMany('Capabilities', [
+ 'foreignKey' => 'group_id',
+ 'targetForeignKey' => 'capability_id',
+ 'joinTable' => 'permissions',
+ ]);
+
+ $this->belongsToMany('ChildGroups', [
+ 'className' => 'Groups',
+ 'foreignKey' => 'container_group_id',
+ 'targetForeignKey' => 'group_id',
+ 'joinTable' => 'groups_groups',
+ 'sort' => 'description ASC'
+ ]);
+
+ $this->belongsToMany('ParentGroups', [
+ 'className' => 'Groups',
+ 'foreignKey' => 'group_id',
+ 'targetForeignKey' => 'container_group_id',
+ 'joinTable' => 'groups_groups',
+ 'sort' => 'description ASC'
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->boolean('is_default')
+ ->allowEmptyString('is_default');
+
+ $validator
+ ->boolean('super_group')
+ ->allowEmptyString('super_group');
+
+ $validator
+ ->integer('actor_id')
+ ->notEmptyString('actor_id')
+ ->add('actor_id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
+
+ return $validator;
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['actor']['actor_type_id'] = 6;
+ $data['actor']['description'] = $data['description'];
+
+ if (isset($options['group_id']) && isset($data['capabilities']['_ids'])) {
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user || !$user->sys_admin) {
+ $not_configurable_capability_ids = TableRegistry::getTableLocator()->get('Capabilities')
+ ->find()
+ ->matching('Permissions')
+ ->select(['Capabilities.id'])
+ ->where(['Permissions.group_id' => $options['group_id'], 'OR' => ['Capabilities.is_configurable IS NULL', 'Capabilities.is_configurable' => 0]])
+ ->all()
+ ->extract('id')
+ ->toArray();
+
+ $data['capabilities']['_ids'] = array_merge($data['capabilities']['_ids'], $not_configurable_capability_ids);
+ }
+ }
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('actor_id', 'Actors'), ['errorField' => 'actor_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/LanguagesTable.php b/idrocap_wa/src/Model/Table/LanguagesTable.php
new file mode 100644
index 0000000..dc7edfa
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/LanguagesTable.php
@@ -0,0 +1,71 @@
+setTable('languages');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 45)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->scalar('language_code')
+ ->maxLength('language_code', 45)
+ ->requirePresence('language_code', 'create')
+ ->notEmptyString('language_code');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/LocationAttributesTable.php b/idrocap_wa/src/Model/Table/LocationAttributesTable.php
new file mode 100644
index 0000000..e77a8b2
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/LocationAttributesTable.php
@@ -0,0 +1,116 @@
+setTable('location_attributes');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Locations', [
+ 'foreignKey' => 'location_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('location_id')
+ ->requirePresence('location_id', 'create')
+ ->notEmptyString('location_id');
+
+ $validator
+ ->scalar('district_code')
+ ->maxLength('district_code', 255)
+ ->requirePresence('district_code', 'create')
+ ->notEmptyString('district_code');
+
+ $validator
+ ->scalar('district_name')
+ ->maxLength('district_name', 255)
+ ->requirePresence('district_name', 'create')
+ ->notEmptyString('district_name');
+
+ $validator
+ ->scalar('county_code')
+ ->maxLength('county_code', 255)
+ ->requirePresence('county_code', 'create')
+ ->notEmptyString('county_code');
+
+ $validator
+ ->scalar('county_name')
+ ->maxLength('county_name', 255)
+ ->requirePresence('county_name', 'create')
+ ->notEmptyString('county_name');
+
+ $validator
+ ->scalar('region')
+ ->maxLength('region', 255)
+ ->requirePresence('region', 'create')
+ ->notEmptyString('region');
+
+ $validator
+ ->scalar('area')
+ ->maxLength('area', 255)
+ ->requirePresence('area', 'create')
+ ->notEmptyString('area');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('location_id', 'Locations'), ['errorField' => 'location_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/LocationsTable.php b/idrocap_wa/src/Model/Table/LocationsTable.php
new file mode 100644
index 0000000..22bcfa8
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/LocationsTable.php
@@ -0,0 +1,118 @@
+setTable('locations');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ ]);
+ $this->hasMany('LocationAttributes', [
+ 'foreignKey' => 'location_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->allowEmptyString('description');
+
+ $validator
+ ->scalar('coordinates')
+ ->maxLength('coordinates', 4294967295)
+ ->allowEmptyString('coordinates');
+
+ $validator
+ ->scalar('feature_collection')
+ ->maxLength('feature_collection', 4294967295)
+ ->allowEmptyString('feature_collection');
+
+ $validator
+ ->scalar('geom')
+ ->allowEmptyString('geom');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->allowEmptyString('controllable_object_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ return $rules;
+ }
+
+ public function beforeSave(EventInterface $event, Location $entity, \ArrayObject $options)
+ {
+ $locationAttributesTable = TableRegistry::getTableLocator()->get('LocationAttributes');
+ $lar = new LocationAttributesRetriever($entity);
+ if (isset($entity->id)) {
+ $locationAttributesTable->deleteAll(['LocationAttributes.location_id' => $entity->id]);
+ }
+ $lar_result = $lar->retrieve();
+ if (isset($lar_result['error']) && $lar_result['error']) {
+ throw new \Exception($lar_result['message']);
+ }
+ $entity->location_attributes = $locationAttributesTable->newEntities($lar_result);
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MapsTable.php b/idrocap_wa/src/Model/Table/MapsTable.php
new file mode 100644
index 0000000..69b273c
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MapsTable.php
@@ -0,0 +1,88 @@
+setTable('maps');
+ $this->setDisplayField('name');
+ $this->setPrimaryKey(['id', 'language_code']);
+
+ $this->addBehavior('Timestamp');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('code')
+ ->maxLength('code', 255)
+ ->requirePresence('code', 'create')
+ ->notEmptyString('code');
+
+ $validator
+ ->scalar('name')
+ ->maxLength('name', 255)
+ ->requirePresence('name', 'create')
+ ->notEmptyString('name');
+
+ $validator
+ ->scalar('url_layer')
+ ->maxLength('url_layer', 255)
+ ->requirePresence('url_layer', 'create')
+ ->notEmptyString('url_layer');
+
+ $validator
+ ->integer('clusterize')
+ ->notEmptyString('clusterize');
+
+ $validator
+ ->integer('visible')
+ ->notEmptyString('visible');
+
+ $validator
+ ->scalar('style')
+ ->maxLength('style', 4294967295)
+ ->allowEmptyString('style');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MenuItemsTable.php b/idrocap_wa/src/Model/Table/MenuItemsTable.php
new file mode 100644
index 0000000..b39dff7
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MenuItemsTable.php
@@ -0,0 +1,135 @@
+setTable('menu_items');
+ $this->setDisplayField('title');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ParentMenuItems', [
+ 'className' => 'MenuItems',
+ 'foreignKey' => 'menu_item_id',
+ ]);
+ $this->belongsTo('MenuSections', [
+ 'foreignKey' => 'menu_section_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('ChildMenuItems', [
+ 'className' => 'MenuItems',
+ 'foreignKey' => 'menu_item_id',
+ ]);
+ $this->belongsToMany('Capabilities', [
+ 'foreignKey' => 'menu_item_id',
+ 'targetForeignKey' => 'capability_id',
+ 'joinTable' => 'capabilities_menu_items',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('title')
+ ->maxLength('title', 255)
+ ->requirePresence('title', 'create')
+ ->notEmptyString('title');
+
+ $validator
+ ->scalar('icon')
+ ->maxLength('icon', 255)
+ ->allowEmptyString('icon');
+
+ $validator
+ ->scalar('link')
+ ->maxLength('link', 255)
+ ->allowEmptyString('link');
+
+ $validator
+ ->scalar('confirm')
+ ->maxLength('confirm', 255)
+ ->allowEmptyString('confirm');
+
+ $validator
+ ->scalar('method')
+ ->maxLength('method', 255)
+ ->allowEmptyString('method');
+
+ $validator
+ ->integer('menu_item_id')
+ ->allowEmptyString('menu_item_id');
+
+ $validator
+ ->integer('menu_section_id')
+ ->requirePresence('menu_section_id', 'create')
+ ->notEmptyString('menu_section_id');
+
+ $validator
+ ->integer('menu_order')
+ ->notEmptyString('menu_order');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('menu_item_id', 'MenuItems'), ['errorField' => 'menu_item_id']);
+ $rules->add($rules->existsIn('menu_section_id', 'MenuSections'), ['errorField' => 'menu_section_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MenuSectionsTable.php b/idrocap_wa/src/Model/Table/MenuSectionsTable.php
new file mode 100644
index 0000000..8959a24
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MenuSectionsTable.php
@@ -0,0 +1,80 @@
+setTable('menu_sections');
+ $this->setDisplayField('title');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('MenuItems', [
+ 'foreignKey' => 'menu_section_id',
+ ]);
+ $this->belongsToMany('Capabilities', [
+ 'foreignKey' => 'menu_section_id',
+ 'targetForeignKey' => 'capability_id',
+ 'joinTable' => 'capabilities_menu_sections',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('title')
+ ->maxLength('title', 255)
+ ->requirePresence('title', 'create')
+ ->notEmptyString('title');
+
+ $validator
+ ->scalar('icon')
+ ->maxLength('icon', 255)
+ ->allowEmptyString('icon');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MessageStatusesTable.php b/idrocap_wa/src/Model/Table/MessageStatusesTable.php
new file mode 100644
index 0000000..a50b78d
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MessageStatusesTable.php
@@ -0,0 +1,65 @@
+setTable('message_statuses');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Messages', [
+ 'foreignKey' => 'message_status_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MessageTypesTable.php b/idrocap_wa/src/Model/Table/MessageTypesTable.php
new file mode 100644
index 0000000..c33469e
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MessageTypesTable.php
@@ -0,0 +1,69 @@
+setTable('message_types');
+ $this->setDisplayField('label');
+ $this->setPrimaryKey('id');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 45)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->scalar('label')
+ ->maxLength('label', 45)
+ ->allowEmptyString('label');
+
+ $validator
+ ->integer('dispatching_bitmask_weight')
+ ->requirePresence('dispatching_bitmask_weight', 'create')
+ ->notEmptyString('dispatching_bitmask_weight');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MessagesTable.php b/idrocap_wa/src/Model/Table/MessagesTable.php
new file mode 100644
index 0000000..f06dda1
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MessagesTable.php
@@ -0,0 +1,150 @@
+setTable('messages');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ ]);
+ $this->belongsTo('MessageTypes', [
+ 'foreignKey' => 'message_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ ]);
+ $this->belongsTo('MessageStatuses', [
+ 'foreignKey' => 'message_status_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Organisations', [
+ 'foreignKey' => 'organisation_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('controllable_object_id')
+ ->allowEmptyString('controllable_object_id');
+
+ $validator
+ ->integer('message_type_id')
+ ->requirePresence('message_type_id', 'create')
+ ->notEmptyString('message_type_id');
+
+ $validator
+ ->scalar('content')
+ ->allowEmptyString('content');
+
+ $validator
+ ->integer('user_id')
+ ->allowEmptyString('user_id');
+
+ $validator
+ ->integer('message_status_id')
+ ->requirePresence('message_status_id', 'create')
+ ->notEmptyString('message_status_id');
+
+ $validator
+ ->scalar('mgroup')
+ ->maxLength('mgroup', 255)
+ ->requirePresence('mgroup', 'create')
+ ->notEmptyString('mgroup');
+
+ $validator
+ ->scalar('event_string')
+ ->maxLength('event_string', 255)
+ ->requirePresence('event_string', 'create')
+ ->notEmptyString('event_string')
+ ->add('event_string', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
+
+ $validator
+ ->dateTime('last_update')
+ ->allowEmptyDateTime('last_update');
+
+ $validator
+ ->integer('organisation_id')
+ ->allowEmptyString('organisation_id');
+
+ $validator
+ ->scalar('contact')
+ ->maxLength('contact', 255)
+ ->allowEmptyString('contact');
+
+ $validator
+ ->scalar('not_delivered_reason')
+ ->maxLength('not_delivered_reason', 255)
+ ->allowEmptyString('not_delivered_reason');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->isUnique(['event_string']), ['errorField' => 'event_string']);
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ $rules->add($rules->existsIn('message_type_id', 'MessageTypes'), ['errorField' => 'message_type_id']);
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add($rules->existsIn('message_status_id', 'MessageStatuses'), ['errorField' => 'message_status_id']);
+ $rules->add($rules->existsIn('organisation_id', 'Organisations'), ['errorField' => 'organisation_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MobileComponentsTable.php b/idrocap_wa/src/Model/Table/MobileComponentsTable.php
new file mode 100644
index 0000000..0e45dee
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MobileComponentsTable.php
@@ -0,0 +1,77 @@
+setTable('mobile_components');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsToMany('Capabilities', [
+ 'foreignKey' => 'mobile_component_id',
+ 'targetForeignKey' => 'capability_id',
+ 'joinTable' => 'capabilities_mobile_components',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->scalar('menu_item')
+ ->maxLength('menu_item', 255)
+ ->requirePresence('menu_item', 'create')
+ ->notEmptyString('menu_item');
+
+ $validator
+ ->boolean('is_enabled')
+ ->notEmptyString('is_enabled');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MobilePhoneDescriptionsTable.php b/idrocap_wa/src/Model/Table/MobilePhoneDescriptionsTable.php
new file mode 100644
index 0000000..fe7d4c2
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MobilePhoneDescriptionsTable.php
@@ -0,0 +1,74 @@
+setTable('mobile_phone_descriptions');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('MobilePhones', [
+ 'foreignKey' => 'mobile_phone_description_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->scalar('deleted')
+ ->maxLength('deleted', 45)
+ ->allowEmptyString('deleted');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/MobilePhonesTable.php b/idrocap_wa/src/Model/Table/MobilePhonesTable.php
new file mode 100644
index 0000000..3cf9a20
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/MobilePhonesTable.php
@@ -0,0 +1,111 @@
+setTable('mobile_phones');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('MobilePhoneDescriptions', [
+ 'foreignKey' => 'mobile_phone_description_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->requirePresence('value', 'create')
+ ->notEmptyString('value')
+ ->regex('value', '/^[0-9]*$/i');
+
+ $validator
+ ->boolean('is_system')
+ ->allowEmptyString('is_system');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->allowEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->notEmptyString('delivery_id');
+
+ $validator
+ ->integer('mobile_phone_description_id')
+ ->requirePresence('mobile_phone_description_id', 'create')
+ ->allowEmptyString('mobile_phone_description_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->add($rules->existsIn('mobile_phone_description_id', 'MobilePhoneDescriptions'), ['errorField' => 'mobile_phone_description_id']);
+ $rules->add($rules->isUnique(['value'], __('Cellulare già presente a sistema!')));
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/NotificationTypesTable.php b/idrocap_wa/src/Model/Table/NotificationTypesTable.php
new file mode 100644
index 0000000..0ee11bf
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/NotificationTypesTable.php
@@ -0,0 +1,65 @@
+setTable('notification_types');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Notifications', [
+ 'foreignKey' => 'notification_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/NotificationsTable.php b/idrocap_wa/src/Model/Table/NotificationsTable.php
new file mode 100644
index 0000000..122464a
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/NotificationsTable.php
@@ -0,0 +1,122 @@
+setTable('notifications');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('NotificationTypes', [
+ 'foreignKey' => 'notification_type_id',
+ ]);
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('user_id')
+ ->requirePresence('user_id', 'create')
+ ->notEmptyString('user_id');
+
+ $validator
+ ->dateTime('read_by_user')
+ ->allowEmptyDateTime('read_by_user');
+
+ $validator
+ ->integer('notification_type_id')
+ ->allowEmptyString('notification_type_id');
+
+ $validator
+ ->scalar('info')
+ ->requirePresence('info', 'create')
+ ->notEmptyString('info');
+
+ $validator
+ ->scalar('thread')
+ ->maxLength('thread', 45)
+ ->requirePresence('thread', 'create')
+ ->notEmptyString('thread');
+
+ $validator
+ ->scalar('ngroup')
+ ->maxLength('ngroup', 255)
+ ->allowEmptyString('ngroup');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->allowEmptyString('controllable_object_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add($rules->existsIn('notification_type_id', 'NotificationTypes'), ['errorField' => 'notification_type_id']);
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/OrganisationTypesTable.php b/idrocap_wa/src/Model/Table/OrganisationTypesTable.php
new file mode 100644
index 0000000..17db0d4
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/OrganisationTypesTable.php
@@ -0,0 +1,69 @@
+setTable('organisation_types');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Organisations', [
+ 'foreignKey' => 'organisation_type_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->allowEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/OrganisationsTable.php b/idrocap_wa/src/Model/Table/OrganisationsTable.php
new file mode 100644
index 0000000..ef98dda
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/OrganisationsTable.php
@@ -0,0 +1,286 @@
+setTable('organisations');
+ $this->setDisplayField('actor.description');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('OrganisationTypes', [
+ 'foreignKey' => 'organisation_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Actors', [
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('OrganisationActors', [
+ 'className' => 'Actors',
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('Users', [
+ 'foreignKey' => 'organisation_id',
+ ]);
+ $this->addBehavior('Muffin/Trash.Trash');
+
+ // non invertire l'ordine di aggiunta di questi 2 behaviors perchè le callbacks gestite devono essere eseguite in un certo ordine!
+ $this->addBehavior('ControllableObjectInterface');
+ $this->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.pdf']]]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('acronym')
+ ->maxLength('acronym', 45)
+ ->notEmptyString('acronym')
+ ->requirePresence('acronym');
+
+ $validator
+ ->scalar('geoposition')
+ ->allowEmptyString('geoposition');
+
+ $validator
+ ->scalar('address')
+ ->maxLength('address', 255)
+ ->notEmptyString('address')
+ ->requirePresence('address');
+
+ $validator
+ ->scalar('district')
+ ->maxLength('district', 255)
+ ->notEmptyString('district')
+ ->requirePresence('district');
+
+ $validator
+ ->scalar('cap')
+ ->maxLength('cap', 255)
+ ->notEmptyString('cap')
+ ->requirePresence('cap');
+
+ $validator
+ ->scalar('province')
+ ->maxLength('province', 255)
+ ->notEmptyString('province')
+ ->requirePresence('province');
+
+ $validator
+ ->integer('organisation_type_id')
+ ->requirePresence('organisation_type_id', 'create')
+ ->notEmptyString('organisation_type_id');
+
+ $validator
+ ->integer('actor_id')
+ ->notEmptyString('actor_id')
+ ->add('actor_id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
+
+ $validator
+ ->scalar('pec')
+ ->email('pec', true)
+ ->maxLength('pec', 255)
+ ->allowEmptyString('pec');
+
+ $validator
+ ->scalar('coordinates')
+ ->maxLength('coordinates', 4294967295)
+ ->notEmptyString('coordinates')
+ ->requirePresence('coordinates');
+
+ $validator
+ ->scalar('feature_collection')
+ ->maxLength('feature_collection', 4294967295)
+ ->allowEmptyString('feature_collection');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ $validator
+ ->scalar('photo')
+ ->maxLength('photo', 2555)
+ ->allowEmptyString('photo');
+
+ $validator
+ ->integer('controllable_object_interface_id')
+ ->allowEmptyString('controllable_object_interface_id');
+
+ return $validator;
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['actor']['actor_type_id'] = 1;
+
+ if (isset($data['feature_collection']) && json_decode($data['feature_collection']) !== null) {
+ if (!GeoValidation::isValidGeometry(json_decode($data['feature_collection']))) {
+ throw new BadRequestException(__('Le geometrie inserite per georeferenziare l\'organizzazione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell\'area di competenza della piattaforma.'));
+ }
+ $data['geoposition'] = $data['feature_collection'];
+ }
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('actor_id', 'Actors'), ['errorField' => 'actor_id']);
+ $rules->add($rules->existsIn('organisation_type_id', 'OrganisationTypes'), ['errorField' => 'organisation_type_id']);
+
+ $rules->addCreate(function ($entity, $options) {
+ // controllo se l'organizzazione è di tipo Cittadini
+ if ($entity->isNew() && $entity->organisation_type_id === 7) {
+ $organisations = $this->find()->where(['organisation_type_id' => 7])->count();
+ if ($organisations >= 1) {
+ return false;
+ }
+ }
+ return true;
+ }, 'validateOrganisationType', [
+ 'errorField' => 'organisation_type_id',
+ "message" => __("L'organizzazione non può essere di tipo Cittadini in quanto ne esiste già una.")
+ ]);
+
+ $rules->addUpdate(function ($entity, $options) {
+ if ($entity->getOriginal('organisation_type_id') === 7 && $entity->organisation_type_id !== 7) {
+ return false;
+ }
+ return true;
+ }, 'validateOrganisationType', [
+ 'errorField' => 'organisation_type_id',
+ "message" => __("L'organizzazione è di tipo Cittadini e non è consentito modificarne il tipo.")
+ ]);
+ return $rules;
+ }
+
+ /**
+ * can_index
+ *
+ * @param User $user
+ * @param Array $options
+ * @return Bool
+ */
+ public function can_index(User $user, Array &$options): Bool
+ {
+ if (!$user->hasCapability(['configuration.organisations.read', 'voluntary_organisation']))
+ {
+ $options['error']['capabilities'] = ['configuration.organisations.read', 'voluntary_organisation'];
+ return false;
+ }
+
+ $options['finder'] = 'all';
+ $type = $options['type'];
+ if($type == "voluntary" || ($user->hasCapability(['voluntary_organisation']) && !$user->hasCapability(['configuration.organisations.read'])))
+ {
+ $options['finder'] = 'onlyType567';
+ }
+ return true;
+ }
+
+ /**
+ * findOnlyType567
+ *
+ * @param SelectQuery $query
+ * @param Array $options
+ * @return SelectQuery
+ */
+ public function findOnlyType567(SelectQuery $query, Array $params): SelectQuery
+ {
+ return $query->where(['Organisations.organisation_type_id IN' => [5, 6, 7]]);
+ }
+
+ /**
+ * applySearchParams
+ *
+ * @param SelectQuery $query
+ * @param Array $params
+ * @return SelectQuery
+ */
+ public function applySearchParams(SelectQuery $query, Array $params): SelectQuery
+ {
+ $search_params = [
+ 'id' => 'Organisations.id',
+ 'organisation_description' => 'Actors.description',
+ 'acronym' => 'Organisations.acronym',
+ 'organisation_type_id' => 'Organisations.organisation_type_id',
+ 'district' => 'Organisations.district',
+ 'province' => 'Organisations.province',
+ ];
+
+ $searck_keys = array_keys($search_params);
+
+ $search_conditions = collection($params)
+ ->filter(function ($paramValue, $paramKey) use ($searck_keys) {
+ return in_array($paramKey, $searck_keys);
+ })
+ ->map(function ($paramValue, $paramKey) use ($search_params) {
+ return [$search_params[$paramKey] => $paramValue];
+ })
+ ->reduce(function ($acc, $search_condition) {
+ $acc[] = $search_condition;
+ return $acc;
+ }, []);
+
+ if (!empty($search_conditions)) {
+ $query->where($search_conditions);
+ }
+ return $query;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PecDescriptionsTable.php b/idrocap_wa/src/Model/Table/PecDescriptionsTable.php
new file mode 100644
index 0000000..8f628b6
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PecDescriptionsTable.php
@@ -0,0 +1,74 @@
+setTable('pec_descriptions');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Pecs', [
+ 'foreignKey' => 'pec_description_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PecsTable.php b/idrocap_wa/src/Model/Table/PecsTable.php
new file mode 100644
index 0000000..578021a
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PecsTable.php
@@ -0,0 +1,111 @@
+setTable('pecs');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('PecDescriptions', [
+ 'foreignKey' => 'pec_description_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->requirePresence('value', 'create')
+ ->notEmptyString('value')
+ ->email('value', true);
+
+ $validator
+ ->boolean('is_system')
+ ->notEmptyString('is_system');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->notEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->notEmptyString('delivery_id');
+
+ $validator
+ ->integer('pec_description_id')
+ ->requirePresence('pec_description_id', 'create')
+ ->allowEmptyString('pec_description_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->add($rules->existsIn('pec_description_id', 'PecDescriptions'), ['errorField' => 'pec_description_id']);
+ $rules->add($rules->isUnique(['value'], __('Indirizzo PEC già presente a sistema!')));
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PermissionsTable.php b/idrocap_wa/src/Model/Table/PermissionsTable.php
new file mode 100644
index 0000000..2a174b0
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PermissionsTable.php
@@ -0,0 +1,85 @@
+setTable('permissions');
+ $this->setDisplayField(['capability_id', 'group_id']);
+ $this->setPrimaryKey(['capability_id', 'group_id']);
+
+ $this->belongsTo('Capabilities', [
+ 'foreignKey' => 'capability_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Groups', [
+ 'foreignKey' => 'group_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('capability_id', 'Capabilities'), ['errorField' => 'capability_id']);
+ $rules->add($rules->existsIn('group_id', 'Groups'), ['errorField' => 'group_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PhoneDescriptionsTable.php b/idrocap_wa/src/Model/Table/PhoneDescriptionsTable.php
new file mode 100644
index 0000000..412021b
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PhoneDescriptionsTable.php
@@ -0,0 +1,73 @@
+setTable('phone_descriptions');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('Phones', [
+ 'foreignKey' => 'phone_description_id',
+ ]);
+
+ $this->addBehavior('Translate', [
+ 'allowEmptyTranslations' => false,
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PhonesTable.php b/idrocap_wa/src/Model/Table/PhonesTable.php
new file mode 100644
index 0000000..6736469
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PhonesTable.php
@@ -0,0 +1,103 @@
+setTable('phones');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('PhoneDescriptions', [
+ 'foreignKey' => 'phone_description_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->requirePresence('value', 'create')
+ ->notEmptyString('value')
+ ->regex('value', '/^[0-9]*$/i');
+
+ $validator
+ ->integer('delivery_id')
+ ->notEmptyString('delivery_id');
+
+ $validator
+ ->integer('phone_description_id')
+ ->requirePresence('phone_description_id', 'create')
+ ->allowEmptyString('phone_description_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->add($rules->existsIn('phone_description_id', 'PhoneDescriptions'), ['errorField' => 'phone_description_id']);
+ $rules->add($rules->isUnique(['value'], __('Telefono già presente a sistema!')));
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PrivacyTable.php b/idrocap_wa/src/Model/Table/PrivacyTable.php
new file mode 100644
index 0000000..1bc5120
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PrivacyTable.php
@@ -0,0 +1,90 @@
+ newEntities(array $data, array $options = [])
+ * @method \App\Model\Entity\Privacy get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
+ * @method \App\Model\Entity\Privacy findOrCreate($search, ?callable $callback = null, array $options = [])
+ * @method \App\Model\Entity\Privacy patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
+ * @method array<\App\Model\Entity\Privacy> patchEntities(iterable $entities, array $data, array $options = [])
+ * @method \App\Model\Entity\Privacy|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method \App\Model\Entity\Privacy saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method iterable<\App\Model\Entity\Privacy>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Privacy>|false saveMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\Privacy>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Privacy> saveManyOrFail(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\Privacy>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Privacy>|false deleteMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\Privacy>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Privacy> deleteManyOrFail(iterable $entities, array $options = [])
+ *
+ * @mixin \Cake\ORM\Behavior\TimestampBehavior
+ */
+class PrivacyTable extends Table
+{
+ /**
+ * Initialize method
+ *
+ * @param array $config The configuration for the Table.
+ * @return void
+ */
+ public function initialize(array $config): void
+ {
+ parent::initialize($config);
+
+ $this->setTable('privacy');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->hasMany('PrivacyUsers', [
+ 'foreignKey' => 'privacy_id',
+ ]);
+
+ $this->belongsToMany('Users', [
+ 'foreignKey' => 'privacy_id',
+ 'targetForeignKey' => 'user_id',
+ 'joinTable' => 'privacy_users',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 4294967295)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+
+ /**
+ * @return Privacy
+ */
+ public function findPrivacy(): Privacy
+ {
+ $latestPrivacy = $this->find()
+ ->orderBy(['created' => 'DESC'])
+ ->first();
+
+ return $latestPrivacy ?? $this->newEmptyEntity();
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PrivacyUsersTable.php b/idrocap_wa/src/Model/Table/PrivacyUsersTable.php
new file mode 100644
index 0000000..3f6f5bb
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PrivacyUsersTable.php
@@ -0,0 +1,123 @@
+ newEntities(array $data, array $options = [])
+ * @method \App\Model\Entity\PrivacyUser get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
+ * @method \App\Model\Entity\PrivacyUser findOrCreate($search, ?callable $callback = null, array $options = [])
+ * @method \App\Model\Entity\PrivacyUser patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
+ * @method array<\App\Model\Entity\PrivacyUser> patchEntities(iterable $entities, array $data, array $options = [])
+ * @method \App\Model\Entity\PrivacyUser|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method \App\Model\Entity\PrivacyUser saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method iterable<\App\Model\Entity\PrivacyUser>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\PrivacyUser>|false saveMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\PrivacyUser>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\PrivacyUser> saveManyOrFail(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\PrivacyUser>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\PrivacyUser>|false deleteMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\PrivacyUser>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\PrivacyUser> deleteManyOrFail(iterable $entities, array $options = [])
+ *
+ * @mixin \Cake\ORM\Behavior\TimestampBehavior
+ */
+class PrivacyUsersTable extends Table
+{
+ /**
+ * Initialize method
+ *
+ * @param array $config The configuration for the Table.
+ * @return void
+ */
+ public function initialize(array $config): void
+ {
+ parent::initialize($config);
+
+ $this->setTable('privacy_users');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Privacy', [
+ 'foreignKey' => 'privacy_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('privacy_id')
+ ->notEmptyString('privacy_id');
+
+ $validator
+ ->integer('user_id')
+ ->notEmptyString('user_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn(['privacy_id'], 'Privacy'), ['errorField' => 'privacy_id']);
+ $rules->add($rules->existsIn(['user_id'], 'Users'), ['errorField' => 'user_id']);
+
+ return $rules;
+ }
+
+ public function saveConsent(int $userId, int $privacyId): bool
+ {
+ $acceptPrivacy = $this->newEmptyEntity();
+ $acceptedPrivacy = $this->patchEntity($acceptPrivacy, [
+ 'user_id' => $userId,
+ 'privacy_id' => $privacyId
+ ]);
+
+ if ($this->save($acceptedPrivacy)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function hasConsent(int $userId): bool
+ {
+ $userConsent = $this->find()
+ ->where(['user_id' => $userId])
+ ->first();
+
+ if (isset($userConsent)) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/PushNotificationsTable.php b/idrocap_wa/src/Model/Table/PushNotificationsTable.php
new file mode 100644
index 0000000..6c083dd
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/PushNotificationsTable.php
@@ -0,0 +1,101 @@
+setTable('push_notifications');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->allowEmptyString('value');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->allowEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->allowEmptyString('delivery_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->addCreate(function ($entity, $options) {
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user) return false;
+ return $this->find()->matching('Deliveries')->where(['PushNotifications.value' => $entity->value, 'Deliveries.actor_id' => $user->actor_id])->first() === null;
+ }, 'value', [
+ 'errorField' => 'value',
+ 'message' => __('Non puoi associare nuovamente questo token allo stesso utente')
+ ]);
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/SnapshotsTable.php b/idrocap_wa/src/Model/Table/SnapshotsTable.php
new file mode 100644
index 0000000..b77a390
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/SnapshotsTable.php
@@ -0,0 +1,118 @@
+setTable('snapshots');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ ]);
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('ControllableObjectTypes', [
+ 'foreignKey' => 'controllable_object_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('controllable_object_type_id')
+ ->allowEmptyString('controllable_object_type_id');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ $validator
+ ->scalar('object_snapshot')
+ ->maxLength('object_snapshot', 4294967295)
+ ->requirePresence('object_snapshot', 'create')
+ ->notEmptyString('object_snapshot');
+
+ $validator
+ ->dateTime('date')
+ ->requirePresence('date', 'create')
+ ->notEmptyDateTime('date');
+
+ $validator
+ ->integer('user_id')
+ ->allowEmptyString('user_id');
+
+ $validator
+ ->scalar('controller_action')
+ ->requirePresence('controller_action', 'create')
+ ->notEmptyString('controller_action');
+
+ $validator
+ ->integer('unpacked_with_version')
+ ->allowEmptyString('unpacked_with_version');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ $rules->add($rules->existsIn('controllable_object_type_id', 'ControllableObjectTypes'), ['errorField' => 'controllable_object_type_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/TagsTable.php b/idrocap_wa/src/Model/Table/TagsTable.php
new file mode 100644
index 0000000..1c6e1a3
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/TagsTable.php
@@ -0,0 +1,94 @@
+setTable('tags');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsToMany('Attachments', [
+ 'foreignKey' => 'tag_id',
+ 'targetForeignKey' => 'attachment_id',
+ 'joinTable' => 'attachments_tags',
+ ]);
+
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'LEFT',
+ ]);
+
+ $this->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.pdf']]]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->allowEmptyString('description');
+
+ $validator
+ ->scalar('code')
+ ->maxLength('code', 255)
+ ->allowEmptyString('code');
+
+ $validator
+ ->scalar('class')
+ ->maxLength('class', 255)
+ ->allowEmptyString('class');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ return $validator;
+ }
+
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['controllable_object']['controllable_object_type_id'] = 12;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/TelegramChatsTable.php b/idrocap_wa/src/Model/Table/TelegramChatsTable.php
new file mode 100644
index 0000000..f6e5d36
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/TelegramChatsTable.php
@@ -0,0 +1,99 @@
+setTable('telegram_chats');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('value')
+ ->maxLength('value', 255)
+ ->allowEmptyString('value');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->allowEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->allowEmptyString('delivery_id');
+
+ $validator
+ ->integer('telegram_chat_description_id')
+ ->allowEmptyString('telegram_chat_description_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+ $rules->add($rules->isUnique(['value'], __('ID Chat Telegram già presente a sistema!')));
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/TelegramContactsTable.php b/idrocap_wa/src/Model/Table/TelegramContactsTable.php
new file mode 100644
index 0000000..4827105
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/TelegramContactsTable.php
@@ -0,0 +1,116 @@
+setTable('telegram_contacts');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Deliveries', [
+ 'foreignKey' => 'delivery_id',
+ 'joinType' => 'INNER',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('phone_number')
+ ->maxLength('phone_number', 255)
+ ->requirePresence('phone_number', 'create')
+ ->notEmptyString('phone_number');
+
+ $validator
+ ->scalar('telegram_user_id')
+ ->maxLength('telegram_user_id', 255)
+ ->allowEmptyString('telegram_user_id');
+
+ $validator
+ ->boolean('enable_notifications')
+ ->allowEmptyString('enable_notifications');
+
+ $validator
+ ->integer('delivery_id')
+ ->requirePresence('delivery_id', 'create')
+ ->notEmptyString('delivery_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ $validator
+ ->integer('telegram_contact_status_id')
+ ->requirePresence('telegram_contact_status_id', 'create')
+ ->notEmptyString('telegram_contact_status_id');
+
+ $validator
+ ->scalar('error_message')
+ ->maxLength('error_message', 255)
+ ->allowEmptyString('error_message');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('delivery_id', 'Deliveries'), ['errorField' => 'delivery_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/UnpackedWaterDrawingPaperworkSnapshotsTable.php b/idrocap_wa/src/Model/Table/UnpackedWaterDrawingPaperworkSnapshotsTable.php
new file mode 100644
index 0000000..0f35afd
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/UnpackedWaterDrawingPaperworkSnapshotsTable.php
@@ -0,0 +1,137 @@
+setTable('unpacked_water_drawing_paperwork_snapshots');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Snapshots', [
+ 'foreignKey' => 'snapshot_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('snapshot_id')
+ ->notEmptyString('snapshot_id');
+
+ $validator
+ ->integer('unpacking_version')
+ ->requirePresence('unpacking_version', 'create')
+ ->notEmptyString('unpacking_version');
+
+ $validator
+ ->scalar('who')
+ ->maxLength('who', 255)
+ ->allowEmptyString('who');
+
+ $validator
+ ->dateTime('when')
+ ->allowEmptyDateTime('when');
+
+ $validator
+ ->scalar('what')
+ ->maxLength('what', 255)
+ ->allowEmptyString('what');
+
+ $validator
+ ->scalar('creator')
+ ->maxLength('creator', 255)
+ ->allowEmptyString('creator');
+
+ $validator
+ ->scalar('modifier')
+ ->maxLength('modifier', 255)
+ ->allowEmptyString('modifier');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ $validator
+ ->scalar('water_drawing_paperwork_status')
+ ->maxLength('water_drawing_paperwork_status', 255)
+ ->allowEmptyString('water_drawing_paperwork_status');
+
+ $validator
+ ->scalar('gc_user')
+ ->maxLength('gc_user', 255)
+ ->allowEmptyString('gc_user');
+
+ $validator
+ ->scalar('drar_user')
+ ->maxLength('drar_user', 255)
+ ->allowEmptyString('drar_user');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('snapshot_id', 'Snapshots'), ['errorField' => 'snapshot_id']);
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/UsersTable.php b/idrocap_wa/src/Model/Table/UsersTable.php
new file mode 100644
index 0000000..509e662
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/UsersTable.php
@@ -0,0 +1,476 @@
+setTable('users');
+ $this->setDisplayField('actor.description');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('Organisations', [
+ 'foreignKey' => 'organisation_id',
+ ]);
+ $this->belongsTo('Languages', [
+ 'foreignKey' => 'language_id',
+ ]);
+ $this->belongsTo('Actors', [
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('UserActors', [
+ 'className' => 'Actors',
+ 'foreignKey' => 'actor_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('PrivacyUsers', [
+ 'foreignKey' => 'user_id',
+ ]);
+ $this->hasMany('Memberships', [
+ 'foreignKey' => 'user_id',
+ ]);
+ $this->belongsToMany('Groups', [
+ 'foreignKey' => 'user_id',
+ 'targetForeignKey' => 'group_id',
+ 'joinTable' => 'memberships',
+ ]);
+ $this->hasMany('WaterDrawingPaperworkHistories', [
+ 'foreignKey' => 'user_id',
+ ]);
+ $this->hasMany('WaterDrawingAntimafiaCertificationRequests', [
+ 'foreignKey' => 'user_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('organisation_id')
+ ->requirePresence('organisation_id', true)
+ ->notEmptyString('organisation_id');
+
+ $validator
+ ->scalar('username')
+ ->maxLength('username', 255)
+ ->requirePresence('username', 'create')
+ ->notEmptyString('username');
+
+ $validator
+ ->scalar('password')
+ ->maxLength('password', 255)
+ ->requirePresence('password', 'create')
+ ->notEmptyString('password')
+ ->minLength('password', Configure::read('App.minPasswordLength'), __('La password deve contenere almeno {0} caratteri', Configure::read('App.minPasswordLength')))
+ ->add('password', 'min_capital_letters', [
+ 'rule' => function ($value){
+ return strlen(preg_replace('![^A-Z]+!', '', $value)) >= Configure::read('App.minPasswordCapitalCharacters');
+ },
+ 'message' => __('La password deve contenere almeno {0} carattere/i maiuscolo/i', Configure::read('App.minPasswordCapitalCharacters'))
+ ])
+ ->add('password', 'min_numbers', [
+ 'rule' => function ($value) {
+ return strlen(preg_replace('![^0-9]+!', '', $value)) >= Configure::read('App.minPasswordNumberCharacters');
+ },
+ 'message' => __('La password deve contenere almeno {0} numero/i', Configure::read('App.minPasswordNumberCharacters'))
+ ])
+ ->add('password', 'min_special_characters', [
+ 'rule' => function ($value, $context) {
+ $chars = str_split(Configure::read('App.passwordSpecialCharacters'));
+ $count = 0;
+
+ foreach($chars as $char)
+ {
+ $count+=substr_count($value, $char);
+ }
+
+ return $count >= Configure::read('App.minPasswordSpecialCharacters');
+ },
+ 'message' => __('La password deve contenere almeno {1} carattere/i speciale/i tra "{0}"', Configure::read('App.passwordSpecialCharacters'), Configure::read('App.minPasswordSpecialCharacters'))
+ ]);
+
+ $validator
+ ->scalar('surname')
+ ->maxLength('surname', 255)
+ ->requirePresence('surname', 'create')
+ ->notEmptyString('surname');
+
+ $validator
+ ->scalar('name')
+ ->maxLength('name', 255)
+ ->requirePresence('name', 'create')
+ ->notEmptyString('name');
+
+ $validator
+ ->scalar('address')
+ ->maxLength('address', 255)
+ ->allowEmptyString('address');
+
+ $validator
+ ->scalar('city')
+ ->maxLength('city', 255)
+ ->allowEmptyString('city');
+
+ $validator
+ ->scalar('cap')
+ ->maxLength('cap', 255)
+ ->allowEmptyString('cap');
+
+ $validator
+ ->scalar('tax_code')
+ ->maxLength('tax_code', 255)
+ ->allowEmptyString('tax_code')
+ ->regex('tax_code', '/^[A-Z]{6}[0-9LMNPQRSTUV]{2}[A-EHLMPR-T]{1}[0-9LMNPQRSTUV]{2}[A-Z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1}$/', 'Il formato del codice fiscale è errato.');
+
+ $validator
+ ->scalar('photo')
+ ->maxLength('photo', 255)
+ ->allowEmptyString('photo');
+
+ $validator
+ ->scalar('birthplace')
+ ->maxLength('birthplace', 255)
+ ->allowEmptyString('birthplace');
+
+ $validator
+ ->dateTime('birthday')
+ ->allowEmptyDateTime('birthday');
+
+ $validator
+ ->scalar('gender')
+ ->maxLength('gender', 1)
+ ->allowEmptyString('gender');
+
+ $validator
+ ->integer('language_id')
+ ->allowEmptyString('language_id');
+
+ $validator
+ ->scalar('password_recovery_token')
+ ->maxLength('password_recovery_token', 255)
+ ->allowEmptyString('password_recovery_token');
+
+ $validator
+ ->integer('password_recovery_counter')
+ ->allowEmptyString('password_recovery_counter');
+
+ $validator
+ ->integer('actor_id')
+ ->notEmptyString('actor_id')
+ ->add('actor_id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ return $validator;
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ if (!empty($data['birthday'])) {
+ $data['birthday'] = $data['birthday'] . ' 12:00:00';
+ }
+ $isDefaultCitizen = $options['skipCitizenOrg'] ?? false;
+ $data['actor']['actor_type_id'] = 5;
+ if (isset($data['name']) && isset($data['surname'])) {
+ $data['actor']['description'] = $data['name'] . ' ' . $data['surname'];
+ }
+ if (!empty($data['organisation_id']) && !$isDefaultCitizen) {
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user) $data['organisation_id'] = null;
+ if ($user && !$user->hasCapability('configuration.users.add')) $data['organisation_id'] = $user->organisation_id;
+ }
+
+ if (isset($data['groups']['_ids']) && !empty($data['groups']['_ids']) && is_array($data['groups']['_ids'])) {
+ $user = Router::getRequest()->getAttribute('identity');
+ if ($user && !$user->sys_admin && !$user->hasCapability(['configuration.users.profiles'])) {
+ $associable_user_groups_ids = array_keys($this->getAssociableUserGroups(as_list: true)->toArray());
+ $data['groups']['_ids'] = array_values(array_intersect($data['groups']['_ids'], $associable_user_groups_ids));
+ }
+ }
+
+ if (isset($data['tax_code'])) {
+ $data['tax_code'] = strtoupper($data['tax_code']);
+ }
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->isUnique(['username']), ['errorField' => 'username']);
+ $rules->add($rules->isUnique(['email']), ['errorField' => 'email']);
+ $rules->add($rules->isUnique(['tax_code']), ['errorField' => 'tax_code']);
+ $rules->add($rules->existsIn('organisation_id', 'Organisations'), ['errorField' => 'organisation_id']);
+ $rules->add($rules->existsIn('language_id', 'Languages'), ['errorField' => 'language_id']);
+ $rules->add($rules->existsIn('actor_id', 'Actors'), ['errorField' => 'actor_id']);
+ $rules->add(function ($entity, $options) {
+ $attachment = $entity['user_photo'] ?? null;
+ if ($attachment) $attachment = AttachmentConverter::convertUploadedFileObj2AssociativeArray($attachment);
+ if (empty($attachment['tmp_name']) || !isset($attachment['error']) || $attachment['error'] !== 0) return true;
+ $attributes = getimagesize($attachment['tmp_name']);
+ $width = (String)($attributes['0'] ?? 0);
+ $height = (String)($attributes['1'] ?? 0);
+ if ($width !== '160' || $height !== '160') return false;
+ $file_name = (String)($entity->id ?? 0) . '_' . time() . '.jpg';
+ try
+ {
+ $res = \App\WGS\FileStorage\FileStorageFactory::create()->saveFile(Configure::read('App.userPhotoPath') . "/" . $file_name, $attachment['tmp_name']);
+ $entity->photo = $file_name;
+ return true;
+ }
+ catch(\Exception $we)
+ {
+ return false;
+ }
+ }, 'user_photo_check', [
+ 'errorField' => 'user_photo',
+ 'message' => __('Errore durante il salvataggio della foto utente. Assicurarsi che sia nel formato corretto (jpeg 160x160)'),
+ ]);
+ return $rules;
+ }
+
+ /**
+ * can_index
+ *
+ * @param User $user
+ * @param Array $options
+ * @return Bool
+ */
+ public function can_index(User $user, Array &$options): Bool
+ {
+ if (!$user->hasCapability(['configuration.users.read', 'configuration.users.read_foo'])) {
+ $options['error']['capabilities'] = ['configuration.users.read', 'configuration.users.read_foo'];
+ return false;
+ }
+ $options['finder'] = 'all';
+ if (!$user->hasCapability(['configuration.users.read'])) {
+ $options['finder'] = 'foo';
+ $options['user'] = $user;
+ }
+ return true;
+ }
+
+ /**
+ * findFoo
+ *
+ * @param SelectQuery $query
+ * @param Array $options
+ * @return SelectQuery
+ */
+ public function findFoo(SelectQuery $query, Array $params): SelectQuery
+ {
+ return $query->where(['Users.organisation_id is not null', 'Users.organisation_id' => $params['user']->organisation_id]);
+ }
+
+ /**
+ * applySearchParams
+ *
+ * @param SelectQuery $query
+ * @param Array $params
+ * @return SelectQuery
+ */
+ public function applySearchParams(SelectQuery $query, Array $params): SelectQuery
+ {
+ $search_params = [
+ 'id' => 'Users.id',
+ 'name' => 'Users.name',
+ 'surname' => 'Users.surname',
+ 'organisation_description' => 'Actors.description',
+ ];
+
+ $searck_keys = array_keys($search_params);
+
+ $search_conditions = collection($params)
+ ->filter(function ($paramValue, $paramKey) use ($searck_keys) {
+ return in_array($paramKey, $searck_keys);
+ })
+ ->map(function ($paramValue, $paramKey) use ($search_params) {
+ return [$search_params[$paramKey] => $paramValue];
+ })
+ ->reduce(function ($acc, $search_condition) {
+ $acc[] = $search_condition;
+ return $acc;
+ }, []);
+
+ if (!empty($search_conditions)) {
+ $query->where($search_conditions);
+ }
+ return $query;
+ }
+
+ /**
+ * getAssociableUserGroups
+ *
+ * returns the groups that the user can associate to himself or to others
+ *
+ * @param Bool $as_list
+ * @return SelectQuery
+ */
+ public function getAssociableUserGroups(Bool $as_list = false): SelectQuery
+ {
+ $finder = $as_list ? 'list' : 'all';
+ $groups = TableRegistry::getTableLocator()->get('Groups')->find($finder)->contain(['Actors']);
+
+ $user = Router::getRequest()->getAttribute('identity');
+ if (!$user) return $groups->where(['Groups.id < 0']);
+
+ // se posso associare agli utenti qualunque profilo, restituisco la lista completa dei profili:
+ if ($user->sys_admin || $user->hasCapability(['configuration.users.profiles'])) return $groups;
+
+ $associable_user_groups_ids = TableRegistry::getTableLocator()->get('Groups')->find()
+ ->contain(['Actors'])
+ ->select(['id'])
+ ->matching('ParentGroups.Users')
+ ->where(['Users.id' => $user->id]);
+
+ return $groups->where(['Groups.id IN' => $associable_user_groups_ids]);
+ }
+
+
+ /**
+ * @param array $data
+ * @return User|false
+ */
+ public function createCitizen(User $user, array $data): User|false
+ {
+ $this->getConnection()->begin();
+ try {
+ $default_profile = $this->Groups->find()
+ ->contain(['Actors'])
+ // prendiamo il profilo con group_code 1 (valore univoco per il profilo cittadini)
+ ->where(['Groups.group_code' => 'citizen_group'])
+ ->first();
+ $user['groups'] = [$default_profile];
+ // Prendo l'organizzazione di default per i cittadini
+ $defaultCitizenOrg = $this->Organisations->find()->where(['organisation_type_id' => 7])->first();
+ if (!isset($defaultCitizenOrg)) {
+ throw new InvalidArgumentException('Organizzazione di default per cittadini non trovata');
+ }
+
+ $data['is_verified'] = 0;
+ $data['is_citizen'] = 1;
+ $data['organisation_id'] = $defaultCitizenOrg->id;
+ $password = $data['password'];
+ $confirmPassword = $data['confirmPassword'];
+
+ // inserisco controllo su password e confirmPassword;
+ if ($password !== $confirmPassword) {
+ $user->setError('password', __('Le password non corrispondono'));
+ $user->setError('confirmPassword', __('Le password non corrispondono'));
+ throw new InvalidArgumentException('Le password non corrispondono');
+ }
+
+ $user = $this->patchEntity($user, $data, ['skipCitizenOrg' => true]);
+ // genro un random_bytes in formato stringa da 32char cosi da garantirne l'univocità.
+ $user->email_verification_code = bin2hex(random_bytes(16));
+
+ if (!$this->save($user)) {
+ throw new RuntimeException('Errore durante il salvataggio di User: ' . json_encode($user->getErrors()));
+ }
+
+ $emailData = [
+ 'value' => $data['email'],
+ 'email_description_id' => '2',
+ 'enable_notifications' => '1',
+ 'delivery' => [
+ 'actor_id' => $user->actor_id,
+ 'delivery_type_id' => 3,
+ ]
+ ];
+ $email = $this->Actors->Deliveries->Emails->newEntity($emailData);
+ if (!$this->Actors->Deliveries->Emails->save($email)) {
+ if ($email->hasErrors() && isset($email->getErrors()['value']['_isUnique'])) {
+ $user->setError('email', __('Questo indirizzo email è già in uso.'));
+ }
+ throw new RuntimeException('Errore durante il salvataggio di Emails: ' . json_encode($email->getErrors()));
+ }
+ $this->getConnection()->commit();
+ return $user;
+ } catch (InvalidArgumentException $e) {
+ $this->getConnection()->rollback();
+ Log::error("Argument error: " . $e->getMessage());
+ return false;
+ } catch (RuntimeException $e) {
+ $this->getConnection()->rollback();
+ Log::error("Runtime error: " . $e->getMessage());
+ return false;
+ }
+ }
+
+ /**
+ * @param string $emailVerificationCode
+ * @return User|bool
+ */
+ public function verifyCitizen(string $emailVerificationCode): User|bool
+ {
+ $user = $this->find(contain: ['Actors'])->where(['email_verification_code' => $emailVerificationCode, 'is_verified' => 0])->first();
+ if (!$user) {
+ return false;
+ }
+ $user = $this->patchEntity($user, ['is_verified' => 1, 'email_verification_code' => null], ['validate' => false, 'skipCitizenOrg' => true]);
+ return $this->save($user);
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestStatusesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestStatusesTable.php
new file mode 100644
index 0000000..48f7c41
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestStatusesTable.php
@@ -0,0 +1,67 @@
+setTable('water_drawing_antimafia_certification_request_statuses');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingAntimafiaCertificationRequests', [
+ 'foreignKey' => 'water_drawing_antimafia_certification_request_status_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestsTable.php
new file mode 100644
index 0000000..fb5900d
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingAntimafiaCertificationRequestsTable.php
@@ -0,0 +1,107 @@
+setTable('water_drawing_antimafia_certification_requests');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingAntimafiaCertificationRequestStatuses', [
+ 'foreignKey' => 'water_drawing_antimafia_certification_request_status_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->requirePresence('water_drawing_paperwork_id', 'create')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ $validator
+ ->integer('user_id')
+ ->requirePresence('user_id', 'create')
+ ->notEmptyString('user_id');
+
+ $validator
+ ->integer('water_drawing_antimafia_certification_request_status_id')
+ ->requirePresence('water_drawing_antimafia_certification_request_status_id', 'create')
+ ->notEmptyString('water_drawing_antimafia_certification_request_status_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add($rules->existsIn('water_drawing_antimafia_certification_request_status_id', 'WaterDrawingAntimafiaCertificationRequestStatuses'), ['errorField' => 'water_drawing_antimafia_certification_request_status_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingArticlesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingArticlesTable.php
new file mode 100644
index 0000000..e14b579
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingArticlesTable.php
@@ -0,0 +1,76 @@
+setTable('water_drawing_articles');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_articles_id',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ $validator
+ ->scalar('long_description')
+ ->maxLength('long_description', 255)
+ ->allowEmptyString('long_description');
+
+ $validator
+ ->boolean('disable')
+ ->allowEmptyString('disable');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingDerivationTypesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingDerivationTypesTable.php
new file mode 100644
index 0000000..fa5d615
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingDerivationTypesTable.php
@@ -0,0 +1,66 @@
+setTable('water_drawing_derivation_types');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingDerivations', [
+ 'foreignKey' => 'water_drawing_derivation_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('description')
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingDerivationsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingDerivationsTable.php
new file mode 100644
index 0000000..c153d3f
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingDerivationsTable.php
@@ -0,0 +1,206 @@
+setTable('water_drawing_derivations');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingDerivationTypes', [
+ 'foreignKey' => 'water_drawing_derivation_type_id',
+ ]);
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->allowEmptyString('description');
+
+ $validator
+ ->scalar('water_body')
+ ->maxLength('water_body', 255)
+ ->allowEmptyString('water_body');
+
+ $validator
+ ->scalar('feature_collection')
+ ->maxLength('feature_collection', 4294967295)
+ ->allowEmptyString('feature_collection');
+
+ $validator
+ ->scalar('district')
+ ->maxLength('district', 255)
+ ->allowEmptyString('district');
+
+ $validator
+ ->scalar('cadastral_code')
+ ->maxLength('cadastral_code', 255)
+ ->allowEmptyString('cadastral_code');
+
+ $validator
+ ->scalar('location')
+ ->maxLength('location', 255)
+ ->allowEmptyString('location');
+
+ $validator
+ ->integer('cadastral_sheet')
+ ->allowEmptyString('cadastral_sheet');
+
+ $validator
+ ->integer('cadastral_parcel')
+ ->allowEmptyString('cadastral_parcel');
+
+ $validator
+ ->scalar('latitude')
+ ->maxLength('latitude', 255)
+ ->allowEmptyString('latitude');
+
+ $validator
+ ->scalar('longitude')
+ ->maxLength('longitude', 255)
+ ->allowEmptyString('longitude');
+
+ $validator
+ ->scalar('istat')
+ ->maxLength('istat', 255)
+ ->allowEmptyString('istat');
+
+ $validator
+ ->scalar('derivation_status')
+ ->maxLength('derivation_status', 255)
+ ->allowEmptyString('derivation_status');
+
+ $validator
+ ->integer('withdrawals_amount')
+ ->allowEmptyString('withdrawals_amount');
+
+ $validator
+ ->numeric('annual_volume')
+ ->allowEmptyString('annual_volume');
+
+ $validator
+ ->numeric('average_flow_rate')
+ ->allowEmptyString('average_flow_rate');
+
+ $validator
+ ->integer('water_drawing_derivation_use_id')
+ ->allowEmptyString('water_drawing_derivation_use_id');
+
+ $validator
+ ->integer('water_drawing_derivation_type_id')
+ ->allowEmptyString('water_drawing_derivation_type_id');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_derivation_type_id', 'WaterDrawingDerivationTypes'), ['errorField' => 'water_drawing_derivation_type_id']);
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add(function ($entity, $options){
+ if(isset($entity->cadastral_code, $entity->cadastral_sheet, $entity->cadastral_parcel) && !(empty($entity->latitude) && empty($entity->longitude))){
+ $coordinates = CadastralUtils::getParcelCentroidCoordinates(strtolower($entity->cadastral_code), (string) $entity->cadastral_sheet, (string) $entity->cadastral_parcel);
+ if(isset($coordinates)){
+ return GeoValidation::checkCadastralCoordinates($entity->latitude, $entity->longitude, strtolower($entity->cadastral_code), (string) $entity->cadastral_sheet, (string) $entity->cadastral_parcel);
+ }
+ }
+ return true;
+ }, ['errorField' => 'latitude', 'message' => __('Le coordinate non ricadono all\'interno della particella selezionata.')]);
+ $rules->add(function ($entity, $options){
+ if(isset($entity->cadastral_code, $entity->cadastral_sheet, $entity->cadastral_parcel) && !(empty($entity->latitude) && empty($entity->longitude))){
+ $coordinates = CadastralUtils::getParcelCentroidCoordinates(strtolower($entity->cadastral_code), (string) $entity->cadastral_sheet, (string) $entity->cadastral_parcel);
+ if(isset($coordinates)){
+ return GeoValidation::checkCadastralCoordinates($entity->latitude, $entity->longitude, strtolower($entity->cadastral_code), (string) $entity->cadastral_sheet, (string) $entity->cadastral_parcel);
+ }
+ }
+ return true;
+ }, ['errorField' => 'longitude', 'message' => __('Le coordinate non ricadono all\'interno della particella selezionata.')]);
+
+ return $rules;
+ }
+
+ public function beforeSave(EventInterface $event, EntityInterface $entity, \ArrayObject $options){
+ if(isset($entity->cadastral_code, $entity->cadastral_sheet, $entity->cadastral_parcel) && (empty($entity->latitude) && empty($entity->longitude))){
+ $coordinates = CadastralUtils::getParcelCentroidCoordinates(strtolower($entity->cadastral_code), (string) $entity->cadastral_sheet, (string) $entity->cadastral_parcel);
+ if(isset($coordinates)){
+ $entity->latitude = $coordinates->latitude;
+ $entity->longitude = $coordinates->longitude;
+ $entity->feature_collection = '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":['. $coordinates->longitude .','. $coordinates->latitude .']},"properties":null}]}';
+ }
+ }
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ if (isset($data['feature_collection']) && json_decode($data['feature_collection']) !== null) {
+ if (!GeoValidation::isValidGeometry(json_decode($data['feature_collection']))) {
+ throw new BadRequestException(__('Le geometrie inserite per georeferenziare il punto di prelievo/derivazione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell\'area di competenza della piattaforma.'));
+ }
+ $data['geom'] = $data['feature_collection'];
+ }
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingFeesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingFeesTable.php
new file mode 100644
index 0000000..bf7fa0a
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingFeesTable.php
@@ -0,0 +1,124 @@
+setTable('water_drawing_fees');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('WaterDrawingPayments', [
+ 'foreignKey' => 'water_drawing_fee_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->numeric('amount')
+ ->allowEmptyString('amount');
+
+ $validator
+ ->integer('year')
+ ->requirePresence('year', 'create')
+ ->notEmptyString('year');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->requirePresence('water_drawing_paperwork_id', 'create')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add($rules->isUnique(['year', 'water_drawing_paperwork_id'], 'WaterDrawingPaperworks'), ['errorField' => 'year', 'message' => 'Il canone per l\'anno scelto è già impostato.']);
+ $rules->add(function($entity, $options) {
+ $waterDrawingPaperworks = $this->WaterDrawingPaperworks->find()->where(["id" => $entity->water_drawing_paperwork_id])->first();
+ $releaseDate = $waterDrawingPaperworks?->release_date?->year;
+ $expirationDate = $waterDrawingPaperworks?->expiration_date?->year;
+
+ // se non ho entrambe le date skippo i controlli.
+ if(!isset($releaseDate) && !isset($expirationDate)){
+ return true;
+ }
+
+ // se ho solo la data di scadenza ma non ho la data di rilascio controllo solo la data di scadenza rispetto al canone.
+ if(!isset($releaseDate) && isset($expirationDate)) {
+ return $entity->year <= $expirationDate;
+ }
+
+ // se ho solo la data di rilascio ma non ho la data di scadenza, controllo solo la data di rilascio rispetto al canone.
+ if(isset($releaseDate) && !isset($expirationDate)) {
+ return $entity->year >= $releaseDate;
+ }
+
+ // in questo caso sono sicuro che ho sia la data di rilascio che di scadenza
+ // in questo caso specifico controllo che le date siano comprese tra la data di rilascio e la data di scadenza.
+ return ($entity->year >= $releaseDate) && ($entity->year <= $expirationDate);
+ }, "yearValidation", ['errorField' => 'year', 'message' => 'Il canone annuale deve essere compreso tra la data di rilascio del provvedimento e la data di scadenza del provvedimento.']);
+
+ return $rules;
+ }
+
+ public function beforeFind($event, $query, $options, $primary){
+ $query->order(['WaterDrawingFees.year' => 'DESC']);
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingIntendedUseTypesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingIntendedUseTypesTable.php
new file mode 100644
index 0000000..f024129
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingIntendedUseTypesTable.php
@@ -0,0 +1,67 @@
+setTable('water_drawing_intended_use_types');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingIntendedUses', [
+ 'foreignKey' => 'water_drawing_intended_use_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingIntendedUsesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingIntendedUsesTable.php
new file mode 100644
index 0000000..d78d20e
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingIntendedUsesTable.php
@@ -0,0 +1,147 @@
+ newEntities(array $data, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingIntendedUse get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
+ * @method \App\Model\Entity\WaterDrawingIntendedUse findOrCreate($search, ?callable $callback = null, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingIntendedUse patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
+ * @method array<\App\Model\Entity\WaterDrawingIntendedUse> patchEntities(iterable $entities, array $data, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingIntendedUse|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingIntendedUse saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingIntendedUse>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingIntendedUse>|false saveMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingIntendedUse>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingIntendedUse> saveManyOrFail(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingIntendedUse>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingIntendedUse>|false deleteMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingIntendedUse>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingIntendedUse> deleteManyOrFail(iterable $entities, array $options = [])
+ */
+class WaterDrawingIntendedUsesTable extends Table
+{
+ /**
+ * Initialize method
+ *
+ * @param array $config The configuration for the Table.
+ * @return void
+ */
+ public function initialize(array $config): void
+ {
+ parent::initialize($config);
+
+ $this->setTable('water_drawing_intended_uses');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingIntendedUseTypes', [
+ 'foreignKey' => 'water_drawing_intended_use_type_id',
+ ]);
+ $this->belongsTo('WaterDrawingWateringSystems', [
+ 'foreignKey' => 'water_drawing_watering_system_id',
+ ]);
+ $this->belongsToMany('CadastralCropTypes', [
+ 'foreignKey' => 'water_drawing_intended_use_id',
+ 'targetForeignKey' => 'cadastral_crop_type_id',
+ 'joinTable' => 'cadastral_crop_types_water_drawing_intended_uses',
+ ]);
+ $this->hasMany('WaterDrawingMeters', [
+ 'foreignKey' => 'water_drawing_intended_use_id',
+ ]);
+
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('area')
+ ->maxLength('area', 255)
+ ->allowEmptyString('area');
+
+ $validator
+ ->scalar('cadastral_code')
+ ->maxLength('cadastral_code', 255)
+ ->allowEmptyString('cadastral_code');
+
+ $validator
+ ->scalar('cadastral_sheet')
+ ->maxLength('cadastral_sheet', 255)
+ ->allowEmptyString('cadastral_sheet');
+
+ $validator
+ ->scalar('cadastral_parcel')
+ ->maxLength('cadastral_parcel', 255)
+ ->allowEmptyString('cadastral_parcel');
+
+ $validator
+ ->scalar('consortium_area')
+ ->maxLength('consortium_area', 255)
+ ->allowEmptyString('consortium_area');
+
+ $validator
+ ->scalar('rated_power_produced')
+ ->maxLength('rated_power_produced', 255)
+ ->allowEmptyString('rated_power_produced');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ $validator
+ ->integer('water_drawing_intended_use_type_id')
+ ->allowEmptyString('water_drawing_intended_use_type_id');
+
+ $validator
+ ->integer('vegetation_match_status')
+ ->notEmptyString('vegetation_match_status');
+
+ $validator
+ ->integer('water_drawing_watering_system_id')
+ ->allowEmptyString('water_drawing_watering_system_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn(['water_drawing_paperwork_id'], 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add($rules->existsIn(['water_drawing_intended_use_type_id'], 'WaterDrawingIntendedUseTypes'), ['errorField' => 'water_drawing_intended_use_type_id']);
+ $rules->add($rules->existsIn(['water_drawing_watering_system_id'], 'WaterDrawingWateringSystems'), ['errorField' => 'water_drawing_watering_system_id']);
+
+ return $rules;
+ }
+
+ public function beforeSave(EventInterface $event, EntityInterface $entity, \ArrayObject $options)
+ {
+ if (empty($options["skipResetIsMismatch"]) || !$options["skipResetIsMismatch"]) $entity->vegetation_match_status = 0;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingMeasurementsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingMeasurementsTable.php
new file mode 100644
index 0000000..5eb5b1a
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingMeasurementsTable.php
@@ -0,0 +1,108 @@
+setTable('water_drawing_measurements');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingMeters', [
+ 'foreignKey' => 'water_drawing_meter_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->numeric('volume')
+ ->requirePresence('volume', 'create')
+ ->notEmptyString('volume');
+
+ $validator
+ ->date('date')
+ ->requirePresence('date', 'create')
+ ->notEmptyDate('date');
+
+ $validator
+ ->integer('water_drawing_meter_id')
+ ->requirePresence('water_drawing_meter_id', 'create')
+ ->notEmptyString('water_drawing_meter_id');
+
+ $validator
+ ->integer('user_id')
+ ->requirePresence('user_id', 'create')
+ ->notEmptyString('user_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_meter_id', 'WaterDrawingMeters'), ['errorField' => 'water_drawing_meter_id']);
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+
+ $rules->add(function($entity, $option) {
+ $waterDrawingMeeter = $this->WaterDrawingMeters->find()->where(['id' => $entity->water_drawing_meter_id])->first();
+ // controlliamo che la data di misurazione sia successiva o uguale alla data di installazione dello strumento di misurazione
+ return $entity->date->greaterThanOrEquals($waterDrawingMeeter?->installation_date);
+ }, "checkMeasurementDate", ["errorField" => "date", "message" => "La data di misurazione non può essere antecedente all'installazione dello strumento di misurazione."]);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingMetersTable.php b/idrocap_wa/src/Model/Table/WaterDrawingMetersTable.php
new file mode 100644
index 0000000..d6a2252
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingMetersTable.php
@@ -0,0 +1,118 @@
+setTable('water_drawing_meters');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingToolTypes', [
+ 'foreignKey' => 'water_drawing_tool_type_id',
+ 'joinType' => 'INNER',
+ ]);
+
+ $this->belongsTo('WaterDrawingIntendedUses', [
+ 'foreignKey' => 'water_drawing_intended_use_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->hasMany('WaterDrawingMeasurements', [
+ 'foreignKey' => 'water_drawing_meter_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('water_drawing_tool_type_id')
+ ->requirePresence('water_drawing_tool_type_id', 'create')
+ ->notEmptyString('water_drawing_tool_type_id');
+
+ $validator
+ ->integer('water_drawing_intended_use_id')
+ ->requirePresence('water_drawing_intended_use_id', 'create')
+ ->notEmptyString('water_drawing_intended_use_id');
+
+ $validator
+ ->scalar('manufacturer')
+ ->maxLength('manufacturer', 255)
+ ->requirePresence('manufacturer', 'create')
+ ->allowEmptyString('manufacturer');
+
+ $validator
+ ->scalar('part_number')
+ ->maxLength('part_number', 255)
+ ->requirePresence('part_number', 'create')
+ ->notEmptyString('part_number');
+
+ $validator
+ ->date('installation_date')
+ ->requirePresence('installation_date', 'create')
+ ->allowEmptyDate('installation_date');
+
+ $validator
+ ->date('removal_date')
+ ->allowEmptyDate('removal_date', null, 'update');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_tool_type_id', 'WaterDrawingToolTypes'), ['errorField' => 'water_drawing_tool_type_id']);
+ $rules->add($rules->existsIn('water_drawing_intended_use_id', 'WaterDrawingIntendedUses'), ['errorField' => 'water_drawing_intended_use_id']);
+
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingPaperworkHistoriesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingPaperworkHistoriesTable.php
new file mode 100644
index 0000000..511977a
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingPaperworkHistoriesTable.php
@@ -0,0 +1,170 @@
+setTable('water_drawing_paperwork_histories');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingPaperworkStatuses', [
+ 'foreignKey' => 'water_drawing_paperwork_status_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ $this->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.pdf']]]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->boolean('result')
+ ->requirePresence('result', 'create')
+ ->notEmptyString('result');
+
+ $validator
+ ->scalar('note')
+ ->maxLength('note', 255)
+ ->allowEmptyString('note');
+
+ $validator
+ ->integer('user_id')
+ ->notEmptyString('user_id');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ $validator
+ ->dateTime('deleted')
+ ->allowEmptyDateTime('deleted');
+
+ $validator
+ ->integer('water_drawing_paperwork_status_id')
+ ->requirePresence('water_drawing_paperwork_status_id', 'create')
+ ->notEmptyString('water_drawing_paperwork_status_id');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add($rules->existsIn('water_drawing_paperwork_status_id', 'WaterDrawingPaperworkStatuses'), ['errorField' => 'water_drawing_paperwork_status_id']);
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ $rules->add(function ($entity){
+ if($entity->result == 0) return ($entity->note != "");
+ return true;
+ }, ['errorField' => 'note', 'message' => ' In caso di rifiuto bisogna inserire una nota.']);
+ return $rules;
+ }
+
+
+ public function beforeSave(EventInterface $event, WaterDrawingPaperworkHistory $entity, ArrayObject $options){
+ $user = Router::getRequest()->getAttribute('identity');
+ $entity->user_id = $user->id;
+ }
+
+ public function afterSave(EventInterface $event, WaterDrawingPaperworkHistory $entity, ArrayObject $options){
+ $waterDrawingPaperwork = $this->WaterDrawingPaperworks->find()->where(['WaterDrawingPaperworks.id' => $entity->water_drawing_paperwork_id])->first();
+ if($waterDrawingPaperwork->scanned){
+ if($entity->result == 1){
+ $waterDrawingPaperwork->water_drawing_paperwork_status_id = $entity->water_drawing_paperwork_status_id == 3 ? 4 : 6;
+ }else{
+ $waterDrawingPaperwork->water_drawing_paperwork_status_id = $entity->water_drawing_paperwork_status_id == 3 ? 2 : 4;
+ }
+ }else{
+ if($entity->result == 1){
+ $waterDrawingPaperwork->water_drawing_paperwork_status_id = $waterDrawingPaperwork->water_drawing_paperwork_status_id == 10 ? -1 : -4;
+ }else{
+ $waterDrawingPaperwork->water_drawing_paperwork_status_id = $waterDrawingPaperwork->water_drawing_paperwork_status_id == 10 ? 11 : -1;
+ }
+ }
+ if(! $this->WaterDrawingPaperworks->save($waterDrawingPaperwork)){
+ \Cake\Log\Log::write('debug', 'Errore durante il salvataggio della pratica. ' . json_encode($waterDrawingPaperwork->getErrors()));
+ }
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['controllable_object']['controllable_object_type_id'] = 10;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingPaperworkPecsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingPaperworkPecsTable.php
new file mode 100644
index 0000000..34eb10b
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingPaperworkPecsTable.php
@@ -0,0 +1,136 @@
+setTable('water_drawing_paperwork_pecs');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+
+ $this->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.pdf']]]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->notEmptyString('water_drawing_paperwork_id');
+
+ $validator
+ ->integer('user_id')
+ ->notEmptyString('user_id');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ $validator
+ ->scalar('document')
+ ->maxLength('document', 255)
+ ->requirePresence('document', 'create')
+ ->notEmptyString('document');
+
+ $validator
+ ->scalar('protocol_number')
+ ->maxLength('protocol_number', 255)
+ ->requirePresence('protocol_number', 'create')
+ ->notEmptyString('protocol_number');
+
+ $validator
+ ->date('protocol_date')
+ ->requirePresence('protocol_date', 'create')
+ ->notEmptyDate('protocol_date');
+
+ $validator
+ ->scalar('recipient')
+ ->maxLength('recipient', 255)
+ ->requirePresence('recipient', 'create')
+ ->notEmptyString('recipient');
+
+ $validator
+ ->scalar('sender')
+ ->maxLength('sender', 255)
+ ->requirePresence('sender', 'create')
+ ->notEmptyString('sender');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+
+ return $rules;
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['controllable_object']['controllable_object_type_id'] = 11;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingPaperworkStatusesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingPaperworkStatusesTable.php
new file mode 100644
index 0000000..00c5a0d
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingPaperworkStatusesTable.php
@@ -0,0 +1,70 @@
+setTable('water_drawing_paperwork_statuses');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_status_id',
+ ]);
+ $this->hasMany('WaterDrawingPaperworkHistories', [
+ 'foreignKey' => 'water_drawing_paperwork_status_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingPaperworksTable.php b/idrocap_wa/src/Model/Table/WaterDrawingPaperworksTable.php
new file mode 100644
index 0000000..4ae8cb2
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingPaperworksTable.php
@@ -0,0 +1,383 @@
+setTable('water_drawing_paperworks');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingPaperworkStatuses', [
+ 'foreignKey' => 'water_drawing_paperwork_status_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingArticles', [
+ 'foreignKey' => 'water_drawing_article_id',
+ 'joinType' => 'LEFT',
+ ]);
+ $this->belongsTo('ControllableObjects', [
+ 'foreignKey' => 'controllable_object_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('DrarUsers', [
+ 'className' => 'Users',
+ 'foreignKey' => 'drar_user_id',
+ 'joinType' => 'LEFT',
+ ]);
+ $this->belongsTo('GcUsers', [
+ 'className' => 'Users',
+ 'foreignKey' => 'gc_user_id',
+ 'joinType' => 'LEFT',
+ ]);
+ $this->hasMany('ApplicantsWaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->hasMany('WaterDrawingAntimafiaCertificationRequests', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->hasMany('WaterDrawingFees', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->hasMany('WaterDrawingPaperworkHistories', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ ]);
+ $this->hasMany('WaterDrawingDerivations', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->hasMany('WaterDrawingReturnPoints', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->hasMany('WaterDrawingIntendedUses', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->hasMany('WaterDrawingPaperworkPecs', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ $this->belongsToMany('Applicants', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ 'targetForeignKey' => 'applicant_id',
+ 'joinTable' => 'applicants_water_drawing_paperworks',
+ 'dependent' => true,
+ 'cascadeCallbacks' => true,
+ 'sort' => ['is_primary_applicant' => 'DESC'],
+ ]);
+
+ $this->addBehavior('Muffin/Trash.Trash');
+ $this->addBehavior('Attachments', ['attachment' => ['required' => false, 'one_public' => false, 'protected' => false, 'accept_only' => ['.pdf']]]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('water_drawing_paperwork_status_id')
+ ->requirePresence('water_drawing_paperwork_status_id', 'create')
+ ->notEmptyString('water_drawing_paperwork_status_id');
+
+ $validator
+ ->date('from_date')
+ ->allowEmptyDate('from_date');
+
+ $validator
+ ->date('to_date')
+ ->allowEmptyDate('to_date');
+
+ $validator
+ ->scalar('gurs_reference')
+ ->maxLength('gurs_reference', 255)
+ ->allowEmptyString('gurs_reference');
+
+ $validator
+ ->scalar('authorisation_type')
+ ->maxLength('authorisation_type', 255)
+ ->allowEmptyString('authorisation_type');
+
+ $validator
+ ->scalar('concession_decree_number')
+ ->maxLength('concession_decree_number', 255)
+ ->allowEmptyString('concession_decree_number');
+
+ $validator
+ ->date('release_date')
+ ->allowEmptyDate('release_date');
+
+ $validator
+ ->integer('concession_duration')
+ ->allowEmptyString('concession_duration');
+
+ $validator
+ ->date('expiration_date')
+ ->allowEmptyDate('expiration_date');
+
+ $validator
+ ->scalar('first_istance')
+ ->maxLength('first_istance', 255)
+ ->allowEmptyString('first_istance');
+
+ $validator
+ ->scalar('takeover')
+ ->maxLength('takeover', 255)
+ ->allowEmptyString('takeover');
+
+ $validator
+ ->integer('year')
+ ->allowEmptyString('year');
+
+ $validator
+ ->scalar('fee_payment_certificate')
+ ->maxLength('fee_payment_certificate', 255)
+ ->allowEmptyString('fee_payment_certificate');
+
+ $validator
+ ->integer('initial_static_level_water')
+ ->allowEmptyString('initial_static_level_water');
+
+ $validator
+ ->date('initial_static_level_water_date')
+ ->allowEmptyDate('initial_static_level_water_date');
+
+ $validator
+ ->integer('static_level_water')
+ ->allowEmptyString('static_level_water');
+
+ $validator
+ ->date('static_level_water_date')
+ ->allowEmptyDate('static_level_water_date');
+
+ $validator
+ ->scalar('authority_province')
+ ->maxLength('authority_province', 255)
+ ->allowEmptyString('authority_province');
+
+ $validator
+ ->scalar('authority_identification_code_civil_engineering_office')
+ ->maxLength('authority_identification_code_civil_engineering_office', 255)
+ ->allowEmptyString('authority_identification_code_civil_engineering_office');
+
+ $validator
+ ->scalar('authority_identification_code_derivation_department_water_waste')
+ ->maxLength('authority_identification_code_derivation_department_water_waste', 255)
+ ->allowEmptyString('authority_identification_code_derivation_department_water_waste');
+
+ $validator
+ ->integer('controllable_object_id')
+ ->notEmptyString('controllable_object_id');
+
+ $validator
+ ->scalar('feature_collection')
+ ->maxLength('feature_collection', 4294967295)
+ ->allowEmptyString('feature_collection');
+
+ $validator
+ ->scalar('protocol_number')
+ ->maxLength('protocol_number', 255)
+ ->allowEmptyString('protocol_number');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_paperwork_status_id', 'WaterDrawingPaperworkStatuses'), ['errorField' => 'water_drawing_paperwork_status_id']);
+ $rules->add($rules->existsIn('controllable_object_id', 'ControllableObjects'), ['errorField' => 'controllable_object_id']);
+ $rules->add($rules->existsIn('drar_user_id', 'DrarUsers'), ['errorField' => 'drar_user_id']);
+ $rules->add($rules->existsIn('gc_user_id', 'GcUsers'), ['errorField' => 'gc_user_id']);
+ $rules->add($rules->isUnique(['authority_identification_code_civil_engineering_office', 'deleted']), ['errorField' => 'authority_identification_code_civil_engineering_office', 'message' => __('Codice identificativo Concessione Ufficio Genio civile esistente.')]);
+ //controllo sul codice identificativo della pratica GC
+ /*$rules->add(function ($entity, $options){
+ if($entity->authority_identification_code_civil_engineering_office == ''){
+ return true;
+ }
+ return preg_match("/^[a-zA-Z]{2}[0-9]{4}$/", $entity->authority_identification_code_civil_engineering_office) == 1;
+ },
+ 'authority_identification_code_civil_engineering_office',
+ [
+ 'errorField' => 'authority_identification_code_civil_engineering_office',
+ 'message' => __('Formato del codice errato. Rispettare il seguente formato AA0000.')
+ ]);*/
+ $rules->add(function ($entity, $options){
+ if($entity->authority_identification_code_derivation_department_water_waste == ''){
+ return true;
+ }
+ return (preg_match("/^[a-zA-Z]{2}[0-9]{4}$/", $entity->authority_identification_code_derivation_department_water_waste) == 1);
+ },
+ 'authority_identification_code_derivation_department_water_waste',
+ [
+ 'errorField' => 'authority_identification_code_derivation_department_water_waste',
+ 'message' => __('Formato del codice errato. Rispettare il seguente formato AA0000.')
+ ]);
+
+ $rules->add(function ($entity, $options) {
+ $countiesTable = $this->fetchTable("Counties");
+ if (!empty($entity->authority_province)) {
+ $provinceField = strlen($entity->authority_province) === 2 ? 'sigla' : 'den_uts';
+ $exists = $countiesTable->exists([$provinceField => $entity->authority_province]);
+ if (!$exists) {
+ return false;
+ }
+ }
+
+ return true;
+ }, 'validProvince', [
+ 'errorField' => 'authority_province',
+ 'message' => 'La provincia selezionata non è valida.'
+ ]);
+
+ return $rules;
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ $data['controllable_object']['controllable_object_type_id'] = 9;
+
+ if (isset($data['feature_collection']) && json_decode($data['feature_collection']) !== null) {
+ if (!GeoValidation::isValidGeometry(json_decode($data['feature_collection']))) {
+ throw new BadRequestException(__('Le geometrie inserite per georeferenziare il punto di prelievo/derivazione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell\'area di competenza della piattaforma.'));
+ }
+ $data['geom'] = $data['feature_collection'];
+ }
+ }
+
+ public function afterSave(EventInterface $event, EntityInterface $entity, \ArrayObject $options){
+ $data = (object)[];
+ $data->water_drawing_paperwork_id = $entity->id;
+ $logged_user = Router::getRequest()->getAttribute('identity');
+ if ($logged_user) $data->notification_user_id = $logged_user->id;
+ IntendedUseVegetationCheckCommandSender::sendMessage($data);
+ }
+
+ /**
+ * checkAttachments
+ *
+ * @param Array $attachments_data
+ * @return Array
+ */
+ public function checkAttachments($data) {
+ $files = 0;
+ $error_message = [];
+ if(!isset($data['authority_identification_code_civil_engineering_office']) || $data['authority_identification_code_civil_engineering_office'] == '') return [ __('Il codice della pratica da parte del genio civile non è impostato.')];
+ foreach($data['attachments'] as $key => $attachments){
+ foreach($attachments as $attachment_obj){
+ $attachment = AttachmentConverter::convertUploadedFileObj2AssociativeArray($attachment_obj);
+ if($attachment['error'] == 0){
+ $files++;
+ switch($key){
+ case 'DV':
+ $supposedFileName = $data['authority_identification_code_civil_engineering_office'] . '.pdf';
+ break;
+ case 'DUEA':
+ $supposedFileName = $data['authority_identification_code_civil_engineering_office'] . '_2A.pdf';
+ break;
+ default:
+ $supposedFileName = $data['authority_identification_code_civil_engineering_office'] . '_' . $key . '.pdf';
+ }
+
+ if(strtoupper($supposedFileName) != strtoupper($attachment['name'])) $error_message[] = __('Il file "{0}", nella sezione {1}, non ha il nome del file corretto. Il nome corretto dell\'allegato è "{2}". ', $attachment['name'], $key, $supposedFileName);
+ }
+ }
+ }
+ if($files == 0) $error_message[] = __('Non hai inserito il numero di file necessari.');
+ return $error_message;
+ }
+
+ public function can_index(User $user, Array &$options): Bool
+ {
+ if (!$user->hasCapability(['documentation.water_drawing_paperworks.view', 'documentation.water_drawing_paperworks.view_own_province'])) {
+ $options['error']['capabilities'] = ['documentation.water_drawing_paperworks.view'];
+ return false;
+ }
+ return true;
+ }
+
+ public function applySearchParams(Query $query, Array $params): Query
+ {
+ $search_params = [
+ 'cod' => 'WaterDrawingPaperworks.authority_identification_code_civil_engineering_office',
+ 'cod_drar' => 'WaterDrawingPaperworks.authority_identification_code_derivation_department_water_waste',
+ 'province' => 'WaterDrawingPaperworks.authority_province',
+ 'surname' => 'Applicants.surname'
+ ];
+
+ $searck_keys = array_keys($search_params);
+
+ $search_conditions = collection($params)
+ ->filter(function ($paramValue, $paramKey) use ($searck_keys) {
+ return in_array($paramKey, $searck_keys);
+ })
+ ->map(function ($paramValue, $paramKey) use ($search_params) {
+ return [$search_params[$paramKey] => $paramValue];
+ })
+ ->reduce(function ($acc, $search_condition) {
+ $acc[] = $search_condition;
+ return $acc;
+ }, []);
+
+ if (!empty($search_conditions)) {
+ $query->where($search_conditions);
+ }
+ return $query;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingPaymentTypesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingPaymentTypesTable.php
new file mode 100644
index 0000000..2d48ca4
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingPaymentTypesTable.php
@@ -0,0 +1,67 @@
+setTable('water_drawing_payment_types');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingPayments', [
+ 'foreignKey' => 'water_drawing_payment_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingPaymentsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingPaymentsTable.php
new file mode 100644
index 0000000..0645ea6
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingPaymentsTable.php
@@ -0,0 +1,149 @@
+setTable('water_drawing_payments');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->addBehavior('Timestamp');
+
+ $this->belongsTo('WaterDrawingFees', [
+ 'foreignKey' => 'water_drawing_fee_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('WaterDrawingPaymentTypes', [
+ 'foreignKey' => 'water_drawing_payment_type_id',
+ 'joinType' => 'INNER',
+ ]);
+ $this->belongsTo('Users', [
+ 'foreignKey' => 'user_id',
+ 'joinType' => 'INNER',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->integer('water_drawing_fee_id')
+ ->requirePresence('water_drawing_fee_id', 'create')
+ ->notEmptyString('water_drawing_fee_id');
+
+ $validator
+ ->integer('water_drawing_payment_type_id')
+ ->requirePresence('water_drawing_payment_type_id', 'create')
+ ->notEmptyString('water_drawing_payment_type_id');
+
+ $validator
+ ->integer('user_id')
+ ->requirePresence('user_id', 'create')
+ ->notEmptyString('user_id');
+
+ $validator
+ ->numeric('amount')
+ ->requirePresence('amount', 'create')
+ ->notEmptyString('amount');
+
+ $validator
+ ->date('payment_date')
+ ->requirePresence('payment_date', 'create')
+ ->notEmptyString('payment_date');
+
+ $validator
+ ->scalar('payment_number')
+ ->maxLength('payment_number', 255)
+ ->requirePresence('payment_number', 'create')
+ ->notEmptyString('payment_number');
+
+ $validator
+ ->scalar('notes')
+ ->maxLength('notes', 4294967295)
+ ->allowEmptyString('notes');
+
+ $validator
+ ->numeric('receipt_amount')
+ ->allowEmptyString('receipt_amount');
+
+ $validator
+ ->date('receipt_date')
+ ->allowEmptyString('receipt_date');
+
+ $validator
+ ->scalar('receipt_number')
+ ->maxLength('receipt_number', 255)
+ ->allowEmptyString('receipt_number');
+
+ $validator
+ ->scalar('applicant_tax_code')
+ ->maxLength('applicant_tax_code', 4294967295)
+ ->allowEmptyString('applicant_tax_code');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_fee_id', 'WaterDrawingFees'), ['errorField' => 'water_drawing_fee_id']);
+ $rules->add($rules->existsIn('water_drawing_payment_type_id', 'WaterDrawingPaymentTypes'), ['errorField' => 'water_drawing_payment_type_id']);
+ $rules->add($rules->existsIn('user_id', 'Users'), ['errorField' => 'user_id']);
+ $rules->add(function ($entity, $options){
+ if(!isset($entity->receipt_date)) return true;
+ return ($entity->payment_date <= $entity->receipt_date);
+ }, ['errorField' => 'receipt_date', 'message' => __('La data di quietanza non può essere antecedente alla data di pagamento.')]);
+ return $rules;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingReturnPointsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingReturnPointsTable.php
new file mode 100644
index 0000000..680bdd7
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingReturnPointsTable.php
@@ -0,0 +1,120 @@
+setTable('water_drawing_return_points');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->belongsTo('WaterDrawingPaperworks', [
+ 'foreignKey' => 'water_drawing_paperwork_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('latitude')
+ ->maxLength('latitude', 255)
+ ->allowEmptyString('latitude');
+
+ $validator
+ ->scalar('longitude')
+ ->maxLength('longitude', 255)
+ ->allowEmptyString('longitude');
+
+ $validator
+ ->scalar('feature_collection')
+ ->maxLength('feature_collection', 4294967295)
+ ->allowEmptyString('feature_collection');
+
+ $validator
+ ->scalar('district')
+ ->maxLength('district', 255)
+ ->allowEmptyString('district');
+
+ $validator
+ ->integer('cadastral_sheet')
+ ->allowEmptyString('cadastral_sheet');
+
+ $validator
+ ->integer('cadastral_parcel')
+ ->allowEmptyString('cadastral_parcel');
+
+ $validator
+ ->integer('water_drawing_paperwork_id')
+ ->allowEmptyString('water_drawing_paperwork_id');
+
+ return $validator;
+ }
+
+ /**
+ * Returns a rules checker object that will be used for validating
+ * application integrity.
+ *
+ * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
+ * @return \Cake\ORM\RulesChecker
+ */
+ public function buildRules(RulesChecker $rules): RulesChecker
+ {
+ $rules->add($rules->existsIn('water_drawing_paperwork_id', 'WaterDrawingPaperworks'), ['errorField' => 'water_drawing_paperwork_id']);
+
+ return $rules;
+ }
+
+ public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options)
+ {
+ if (isset($data['feature_collection']) && json_decode($data['feature_collection']) !== null) {
+ if (!GeoValidation::isValidGeometry(json_decode($data['feature_collection']))) {
+ throw new BadRequestException(__('Le geometrie inserite per georeferenziare il punto di restituzione, non risultano valide. Controllare che siano espresse nel corretto formato (WGS84) e che rientrano nell\'area di competenza della piattaforma.'));
+ }
+ $data['geom'] = $data['feature_collection'];
+ }
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingToolTypesTable.php b/idrocap_wa/src/Model/Table/WaterDrawingToolTypesTable.php
new file mode 100644
index 0000000..0a11497
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingToolTypesTable.php
@@ -0,0 +1,67 @@
+setTable('water_drawing_tool_types');
+ $this->setDisplayField('id');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingMeters', [
+ 'foreignKey' => 'water_drawing_tool_type_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/Model/Table/WaterDrawingWateringSystemsTable.php b/idrocap_wa/src/Model/Table/WaterDrawingWateringSystemsTable.php
new file mode 100644
index 0000000..b51d036
--- /dev/null
+++ b/idrocap_wa/src/Model/Table/WaterDrawingWateringSystemsTable.php
@@ -0,0 +1,67 @@
+ newEntities(array $data, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingWateringSystem get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
+ * @method \App\Model\Entity\WaterDrawingWateringSystem findOrCreate($search, ?callable $callback = null, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingWateringSystem patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
+ * @method array<\App\Model\Entity\WaterDrawingWateringSystem> patchEntities(iterable $entities, array $data, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingWateringSystem|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method \App\Model\Entity\WaterDrawingWateringSystem saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingWateringSystem>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingWateringSystem>|false saveMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingWateringSystem>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingWateringSystem> saveManyOrFail(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingWateringSystem>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingWateringSystem>|false deleteMany(iterable $entities, array $options = [])
+ * @method iterable<\App\Model\Entity\WaterDrawingWateringSystem>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\WaterDrawingWateringSystem> deleteManyOrFail(iterable $entities, array $options = [])
+ */
+class WaterDrawingWateringSystemsTable extends Table
+{
+ /**
+ * Initialize method
+ *
+ * @param array $config The configuration for the Table.
+ * @return void
+ */
+ public function initialize(array $config): void
+ {
+ parent::initialize($config);
+
+ $this->setTable('water_drawing_watering_systems');
+ $this->setDisplayField('description');
+ $this->setPrimaryKey('id');
+
+ $this->hasMany('WaterDrawingIntendedUses', [
+ 'foreignKey' => 'water_drawing_watering_system_id',
+ ]);
+ }
+
+ /**
+ * Default validation rules.
+ *
+ * @param \Cake\Validation\Validator $validator Validator instance.
+ * @return \Cake\Validation\Validator
+ */
+ public function validationDefault(Validator $validator): Validator
+ {
+ $validator
+ ->scalar('description')
+ ->maxLength('description', 255)
+ ->requirePresence('description', 'create')
+ ->notEmptyString('description');
+
+ return $validator;
+ }
+}
diff --git a/idrocap_wa/src/View/AjaxView.php b/idrocap_wa/src/View/AjaxView.php
new file mode 100644
index 0000000..dd9d7d9
--- /dev/null
+++ b/idrocap_wa/src/View/AjaxView.php
@@ -0,0 +1,46 @@
+response = $this->response->withType('ajax');
+ }
+}
diff --git a/idrocap_wa/src/View/AppView.php b/idrocap_wa/src/View/AppView.php
new file mode 100644
index 0000000..a4e335a
--- /dev/null
+++ b/idrocap_wa/src/View/AppView.php
@@ -0,0 +1,52 @@
+addHelper('Html');`
+ *
+ * @return void
+ */
+ public function initialize(): void
+ {
+ parent::initialize();
+ $this->initializeCakeLte();
+ $this->addHelper('Sections');
+ $this->addHelper('Menu');
+ $this->addHelper('Breadcrumb');
+ $this->addHelper('Notifications');
+ }
+}
diff --git a/idrocap_wa/src/View/Cell/.gitkeep b/idrocap_wa/src/View/Cell/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/src/View/Cell/DistrictProvinceCell.php b/idrocap_wa/src/View/Cell/DistrictProvinceCell.php
new file mode 100644
index 0000000..9061ec6
--- /dev/null
+++ b/idrocap_wa/src/View/Cell/DistrictProvinceCell.php
@@ -0,0 +1,68 @@
+autoFillTargetEnabled) && $provinceCellConfig->autoFillTargetEnabled && empty($provinceCellConfig?->autoFillTargetId);
+ if ($autoFillIsMisconfigured) {
+ throw new Exception("autoFillTargetId must be set when autoFillTargetEnabled is true");
+ }
+
+ $viewVars = [];
+
+ /**
+ * Controllo che in mapConfig abbiamo un array di codeReg e che la specifica region
+ * sia effettivamente presente.
+ */
+ $codeReg = ProvinceDistrictFieldHelper::getCodeRegByRegion(Regions::SICILY);
+ $viewVars["codReg"] = $codeReg;
+
+ if ($provinceCellConfig) {
+ $viewVars["provinces"] = $this->fetchTable('Counties')->getCountiesByRegion($codeReg, $provinceCellConfig);
+ $viewVars["provinceCellConfig"] = $provinceCellConfig;
+ }
+
+ if ($districtCellConfig) {
+ $viewVars["codReg"] = $codeReg;
+ $viewVars["districtCellConfig"] = $districtCellConfig;
+ }
+
+ $this->set($viewVars);
+ }
+}
diff --git a/idrocap_wa/src/View/Cell/FilterInputCell.php b/idrocap_wa/src/View/Cell/FilterInputCell.php
new file mode 100644
index 0000000..d662de2
--- /dev/null
+++ b/idrocap_wa/src/View/Cell/FilterInputCell.php
@@ -0,0 +1,51 @@
+Cell('FilterInput', [
+ * filter_id, // Int -> id fel filtro da recuperare in table filters
+ * value, // ?Any -> il valore impostato dall'utente per il tipo di filtro
+ * ]);
+ */
+class FilterInputCell extends Cell
+{
+ protected array $_validCellOptions = [];
+
+ /**
+ * display
+ *
+ * @param Int $filter_id
+ * @param ?String $value
+ * @return void
+ */
+ public function display(Int $filter_id, ?String $value = null)
+ {
+ $filter = $this->fetchTable('Filters')->get($filter_id);
+
+ if ($filter->filter_type == 'class') {
+ $table_name = $this->fetchTable($filter->class_name)->getAlias();
+ $display_field = $this->fetchTable($filter->class_name)->getDisplayField();
+ $order_clause = json_decode($filter->order_clause ?? '', true) ?? ["$table_name.$display_field" => 'ASC'];
+ $options = $this->fetchTable($filter->class_name)->find('list')->order($order_clause);
+ }
+
+ if ($filter->filter_type == 'bool') {
+ $options = [0 => __('NO'), 1 => __('SI')];
+ }
+
+ $this->set('label', $filter->description);
+ $this->set('name', 'filter_id_' . $filter->id);
+ $this->set('type', in_array($filter->filter_type, ['class', 'bool']) ? 'select' : 'text');
+ $this->set('additional_classes', $filter->filter_type == 'date' ? ' jixeldaterangepicker' : '');
+ $this->set('options', $options ?? null);
+ $this->set('value', $value ?? null);
+ }
+}
diff --git a/idrocap_wa/src/View/Cell/FiltersCell.php b/idrocap_wa/src/View/Cell/FiltersCell.php
new file mode 100755
index 0000000..d225eb9
--- /dev/null
+++ b/idrocap_wa/src/View/Cell/FiltersCell.php
@@ -0,0 +1,50 @@
+Cell('Filters', [
+ * header_title, // String -> titolo da visualizzare nell'header del collapsable
+ * ]);
+ *
+ */
+class FiltersCell extends Cell
+{
+ protected array $_validCellOptions = [];
+
+ /**
+ * display
+ *
+ * @param String $header_title
+ * @return void
+ */
+ public function display(String $header_title)
+ {
+ $logged_user = Router::getRequest()->getAttribute('identity');
+ $logged_user_id = $logged_user->id ?? 0;
+ $controller = Router::getRequest()->getParam('controller');
+ $action = Router::getRequest()->getParam('action');
+ $controller_action_category = "$controller-$action";
+ $filter_session_key = "filters-$logged_user_id-$controller-$action";
+ $filters = Router::getRequest()->getSession()->read($filter_session_key);
+
+ $available_filters = $this->fetchTable('Filters')->find('list')
+ ->where(['Filters.controller_action_category' => $controller_action_category])
+ ->order(['Filters.order_number' => 'ASC']);
+
+ if (!$logged_user->sys_admin) {
+ $available_filters = $available_filters->where(['Filters.sys_admin_only' => false]);
+ }
+
+ $this->set('filters', $filters ?? []);
+ $this->set('available_filters', $available_filters);
+ $this->set('header_title', $header_title);
+ }
+}
diff --git a/idrocap_wa/src/View/Cell/IntendedUsesCell.php b/idrocap_wa/src/View/Cell/IntendedUsesCell.php
new file mode 100644
index 0000000..5569264
--- /dev/null
+++ b/idrocap_wa/src/View/Cell/IntendedUsesCell.php
@@ -0,0 +1,33 @@
+getTableLocator()->get('WaterDrawingIntendedUseTypes')->find()->all()->combine('id', 'description')->toArray();
+ $cadastralCropTypes = $this->getTableLocator()->get('CadastralCropTypes')->find()->all()->combine('id', 'description')->toArray();
+ $wateringSystems = $this->getTableLocator()->get('WaterDrawingWateringSystems')->find()->all()->combine('id', 'description')->toArray();
+ $this->set(compact('intended_use_item_block', 'intendedUseTypes', 'cadastralCropTypes', 'wateringSystems'));
+ }
+}
diff --git a/idrocap_wa/src/View/Cell/MapCell.php b/idrocap_wa/src/View/Cell/MapCell.php
new file mode 100755
index 0000000..aa629ee
--- /dev/null
+++ b/idrocap_wa/src/View/Cell/MapCell.php
@@ -0,0 +1,234 @@
+Cell('Map', [
+ [-1], // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Evento'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => true, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => true, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => true, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => true, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'feature_collection' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'feature-collection-custom1',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'feature_collection_custom1',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Collezione di geometrie'),
+ ],
+ 'longitude' => [ // Array = null -> null/[] = il campo longitude non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude-custom2',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude_custom2',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Longitudine'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo latitude non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude-custom3',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude_custom3',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Latitudine'),
+ ],
+ 'coordinates' => [ // Array = null -> null/[] = il campo coordinates non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'coordinates-custom4',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'coordinates_custom4',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinate (Longitudine Latitudine)'),
+ ],
+ 'cap' => [ // Array = null -> null/[] = il campo cap non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'cap',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'cap',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Cap'),
+ ],
+ 'province' => [ // Array = null -> null/[] = il campo province non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'province',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'province',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Provincia'),
+ ],
+ 'district_code' => [ // Array = null -> null/[] = il campo district_code non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district-code',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district_code',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Codice ISTAT'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo district non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ 'address' => [ // Array = null -> null/[] = il campo address non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'address',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'address',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Indirizzo'),
+ ],
+ 'description' => [ // Array = null -> null/[] = il campo description non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'description',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'description',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Descrizione luogo'),
+ ],
+ ],
+ 'geo_resources' => [ // Array = null -> null/[] = geo_resources serve a specificare delle geo-risorse dalle quali vogliamo estrarre degli attributi. per ogni geo-risorsa, tra le altre cose, bisogna specificare il mapping dei campi nella forma "attributo_geo_risorsa":"id-campo-nel-form"
+ [
+ 'table_name' => 'geo.rw_watersheds', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'id' => 'ws-id',
+ 'swbcode' => 'swbcode'
+ ],
+ ],
+ [
+ 'external' => true, // se la geo-risorsa è un servizio esterno, bisogna specificare 'external' => true!
+ 'url' // se la geo-risorsa è esterna va specificata la 'url' per chiamare il servizio
+ => 'https://wms.cartografia.agenziaentrate.gov.it/inspire/ajax/ajax.php?op=getDatiOggetto',
+ 'lon_parameter_name' => 'lon', // lon_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lon'
+ 'lat_parameter_name' => 'lat', // lat_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lat'
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'COD_COMUNE' => 'cadastral-code',
+ 'FOGLIO' => 'cadastral-sheet',
+ 'NUM_PART' => 'cadastral-parcel',
+ ],
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]);
+ */
+
+ /**
+ * display
+ *
+ * @param ?Array $layer_ids
+ * @param Bool $get_current_position
+ * @param ?Array $tools
+ * @param ?Int $zoom_to_layer_with_id
+ * @return void
+ */
+ public function display(?Array $layer_ids = null, Bool $get_current_position = false, ?Array $tools = null, ?Int $zoom_to_layer_with_id = null)
+ {
+ $layers = [];
+
+ if (is_array($layer_ids)) {
+ $layers = $this->fetchTable('Maps')->find();
+
+ if (isset($layer_ids) && is_array($layer_ids) && count($layer_ids) > 0) {
+ $layers->where(['Maps.id IN' => $layer_ids]);
+ }
+
+ $layers = $layers->all();
+
+ $layers = $layers->map(function ($value, $key) use ($zoom_to_layer_with_id) {
+ $value->style = json_decode($value->style ?? '');
+ $value->zoom_to_layer = isset($zoom_to_layer_with_id) && $value->id == $zoom_to_layer_with_id;
+ return $value;
+ });
+
+ $found_layers = $layers->reduce(function ($acc, $layer) {
+ $acc[$layer->id][$layer->language_code] = $layer;
+ return $acc;
+ }, []);
+
+ $locale = I18n::getLocale();
+
+ $layers = collection($found_layers)
+ ->reduce(function ($acc, $found_layer) use ($locale) {
+ $acc[] = isset($found_layer[$locale]) ? $found_layer[$locale] : $found_layer['it'];
+ return $acc;
+ }, []);
+ }
+
+ $this->set('layers', $layers);
+ $this->set('get_current_position', (isset($get_current_position) && $get_current_position));
+ $this->set('tools', is_array($tools) && !empty($tools));
+ $this->set('drawing_layer_name', !empty($tools['drawing_layer_name']) ? $tools['drawing_layer_name'] : __('Geometrie disegnate'));
+ $this->set('geocoding', isset($tools['geocoding']) && $tools['geocoding']);
+ $this->set('point', isset($tools['point']) && $tools['point']);
+ $this->set('multiple_points', !(isset($tools['geocoding']) && $tools['geocoding']) && isset($tools['multiple_points']) && $tools['multiple_points']);
+ $this->set('polygon', isset($tools['polygon']) && $tools['polygon']);
+ $this->set('circle', isset($tools['circle']) && $tools['circle']);
+ $this->set('delete_geometry', isset($tools['delete_geometry']) && $tools['delete_geometry']);
+ $this->set('feature_collection', $tools['fields']['feature_collection'] ?? false);
+ $this->set('longitude', $tools['fields']['longitude'] ?? false);
+ $this->set('latitude', $tools['fields']['latitude'] ?? false);
+ $this->set('coordinates', $tools['fields']['coordinates'] ?? false);
+ $this->set('cap', $tools['fields']['cap'] ?? false);
+ $this->set('province', $tools['fields']['province'] ?? false);
+ $this->set('district_code', $tools['fields']['district_code'] ?? false);
+ $this->set('district', $tools['fields']['district'] ?? false);
+ $this->set('address', $tools['fields']['address'] ?? false);
+ $this->set('description', $tools['fields']['description'] ?? false);
+ $this->set('geo_resources', $tools['geo_resources'] ?? false);
+ }
+}
diff --git a/idrocap_wa/src/View/CustomCsvView.php b/idrocap_wa/src/View/CustomCsvView.php
new file mode 100644
index 0000000..fd65f46
--- /dev/null
+++ b/idrocap_wa/src/View/CustomCsvView.php
@@ -0,0 +1,100 @@
+getConfig('setSeparator');
+ if ($setSeparator) {
+ fwrite($fp, 'sep=' . $setSeparator . "\n");
+ }
+ } else {
+ ftruncate($fp, 0);
+ }
+
+ $null = $this->getConfig('null');
+ if ($null) {
+ foreach ($row as &$field) {
+ if ($field === null) {
+ $field = $null;
+ }
+ }
+ }
+
+ $delimiter = $this->getConfig('delimiter');
+ $enclosure = $this->getConfig('enclosure');
+ $newline = $this->getConfig('newline');
+
+ $row = str_replace(["\r\n", "\n", "\r"], $newline, $row);
+ if ($enclosure === '') {
+ // fputcsv does not supports empty enclosure
+ if (fputs($fp, implode($delimiter, $row) . "\n") === false) {
+ return false;
+ }
+ } else {
+ if (fputcsv($fp, $row, $delimiter, $enclosure, "\\") === false) {
+ return false;
+ }
+ }
+
+ rewind($fp);
+
+ $csv = '';
+ while (($buffer = fgets($fp, 4096)) !== false) {
+ $csv .= $buffer;
+ }
+
+ $eol = $this->getConfig('eol');
+ if ($eol !== "\n") {
+ $csv = str_replace("\n", $eol, $csv);
+ }
+
+ $dataEncoding = $this->getConfig('dataEncoding');
+ $csvEncoding = $this->getConfig('csvEncoding');
+ if ($dataEncoding !== $csvEncoding) {
+ $extension = $this->getConfig('transcodingExtension');
+ if ($extension === static::EXTENSION_ICONV) {
+ $csv = iconv($dataEncoding, $csvEncoding, $csv);
+ } elseif ($extension === static::EXTENSION_MBSTRING) {
+ $csv = mb_convert_encoding($csv, $csvEncoding, $dataEncoding);
+ }
+ }
+
+ // BOM must be added after encoding
+ $bom = $this->getConfig('bom');
+ if ($bom && $this->isFirstBom) {
+ $csv = $this->getBom($csvEncoding) . $csv;
+ $this->isFirstBom = false;
+ }
+
+ return $csv;
+ }
+}
diff --git a/idrocap_wa/src/View/Helper/BreadcrumbHelper.php b/idrocap_wa/src/View/Helper/BreadcrumbHelper.php
new file mode 100644
index 0000000..a0124ea
--- /dev/null
+++ b/idrocap_wa/src/View/Helper/BreadcrumbHelper.php
@@ -0,0 +1,67 @@
+
+ */
+ protected array $_defaultConfig = [];
+
+ public array $helpers = ['Breadcrumbs'];
+
+ /**
+ * output
+ *
+ * @param String $breadcrumb
+ * @return String
+ */
+ private function output(String $breadcrumb)
+ {
+ return <<
+
+ $breadcrumb
+
+
+ EOD;
+ }
+
+ /**
+ * render
+ *
+ * @param Array $items
+ * @return String
+ */
+ public function render(Array $items): String
+ {
+ $this->Breadcrumbs->setTemplates([
+ 'wrapper' => '{{content}} ',
+ 'item' => ' {{title}} {{separator}}',
+ 'itemWithoutLink' => ' {{title}} {{separator}}',
+ 'separator' => '{{separator}} ',
+ ]);
+
+ $items = collection($items)
+ ->map(function ($item) {
+ return ['title' => $item['title'], 'url' => $item['url'] ?? null, 'options' => ['innerAttrs' => ['class' => $item['icon'] ?? '']]];
+ })
+ ->toArray();
+
+ $this->Breadcrumbs->add($items);
+
+ $breadcrumb = $this->Breadcrumbs->render(['class' => 'float-sm-right']);
+
+ return $this->output($breadcrumb);
+ }
+}
diff --git a/idrocap_wa/src/View/Helper/MenuHelper.php b/idrocap_wa/src/View/Helper/MenuHelper.php
new file mode 100644
index 0000000..87fb82d
--- /dev/null
+++ b/idrocap_wa/src/View/Helper/MenuHelper.php
@@ -0,0 +1,108 @@
+
+ */
+ protected array $_defaultConfig = [];
+
+ public array $helpers = ['Form', 'Html'];
+
+ /**
+ * makeSingleItem
+ *
+ * @param String $title
+ * @param ?String $icon
+ * @param String $link
+ * @param ?String $confirm
+ * @param String $method
+ * @return String
+ */
+ private function makeSingleItem(String $title, String|Null $icon, String $link, ?String $confirm = null, String $method = 'GET'): String
+ {
+ $fa_icon = !empty($icon) ? " fa fa-$icon" : "";
+
+ if (!empty($confirm) || $method == 'POST') {
+ $form_title = <<
+ $title
+ EOD;
+
+ $form_link = $method == 'POST' ? $this->Form->postLink($form_title, $link, ['confirm' => $confirm, 'escape' => false, 'class' => 'nav-link']) : $this->Html->link($form_title, $link, ['confirm' => $confirm, 'escape' => false, 'class' => 'nav-link']);
+ } else {
+ $form_link = <<
+
+ $title
+
+ EOD;
+ }
+
+ return <<
+ $form_link
+
+ EOD;
+ }
+
+ /**
+ * makeItemWithSubItems
+ *
+ * @param String $title
+ * @param ?String $icon
+ * @param Array $items
+ * @return String
+ */
+ private function makeItemWithSubItems(String $title, String|Null $icon, Array $items): String
+ {
+ $menu_items = implode("", collection($items)->map(function ($item) { return isset($item['link']) ? $this->makeSingleItem($item['title'], $item['icon'], $item['link'], $item['confirm'] ?? null, $item['method'] ?? 'GET') : $this->makeItemWithSubItems($item['title'], $item['icon'], $item['menu_items']); })->toArray());
+
+ $fa_icon = !empty($icon) ? " fa fa-$icon" : "";
+
+ return <<
+
+
+
+ $title
+
+
+
+
+
+ EOD;
+ }
+
+ /**
+ * create
+ *
+ * @param Array $menu_items
+ * @return String
+ */
+ public function create(Array $menu_items): String
+ {
+ $output = '';
+
+ foreach ($menu_items as $menu_item) {
+ if (isset($menu_item['link'])) {
+ $output.= $this->makeSingleItem($menu_item['title'], $menu_item['icon'], $menu_item['link'], $menu_item['confirm'] ?? null, $menu_item['method'] ?? 'GET');
+ } else {
+ $output.= $this->makeItemWithSubItems($menu_item['title'], $menu_item['icon'], $menu_item['menu_items']);
+ }
+ }
+ return $output;
+ }
+}
diff --git a/idrocap_wa/src/View/Helper/NotificationsHelper.php b/idrocap_wa/src/View/Helper/NotificationsHelper.php
new file mode 100644
index 0000000..a457c2d
--- /dev/null
+++ b/idrocap_wa/src/View/Helper/NotificationsHelper.php
@@ -0,0 +1,87 @@
+
+ */
+ protected array $_defaultConfig = [];
+
+ /**
+ * makeNotification
+ *
+ * @param String $id
+ * @param String $icon
+ * @param String $title
+ * @param String $time_ago
+ * @param String $body
+ * @return String
+ */
+ private function makeNotification(String $id, String $icon, String $title, String $time_ago, String $body): String
+ {
+ $title = strlen($title) > 35 ? substr($title, 0, 32) . '...' : $title;
+ return <<
+
+ $title
+ $time_ago
+ $body
+
+ EOD;
+ }
+
+ /**
+ * makeNotificationList
+ *
+ * @param String $user_notifications_count
+ * @param String $notification_items
+ * @return String
+ */
+ private function makeNotificationList(String $user_notifications_count, String $notification_items): String
+ {
+ $user_notifications_count_badge = $user_notifications_count > 0 ? '' . $user_notifications_count . ' ' : '';
+ $notifications_header = '';
+ $notifications_footer = $user_notifications_count > 0 ? '
' : '';
+
+ return <<
+
+
+ $user_notifications_count_badge
+
+
+
+ EOD;
+ }
+
+ /**
+ * create
+ *
+ * @param Array $menu_sections
+ * @return String
+ */
+ public function create(Array $notifications): String
+ {
+ $notification_items = '';
+ foreach ($notifications as $notification) {
+ $notification_items.= $this->makeNotification((String)$notification['id'], $notification['icon'], $notification['title'], $notification['time_ago'], $notification['body']);
+ }
+ return $this->makeNotificationList((String)count($notifications), $notification_items);
+ }
+}
diff --git a/idrocap_wa/src/View/Helper/SectionsHelper.php b/idrocap_wa/src/View/Helper/SectionsHelper.php
new file mode 100644
index 0000000..d99a80d
--- /dev/null
+++ b/idrocap_wa/src/View/Helper/SectionsHelper.php
@@ -0,0 +1,55 @@
+
+ */
+ protected array $_defaultConfig = [];
+
+ /**
+ * makeSection
+ *
+ * @param String $title
+ * @param ?String $icon
+ * @param Int $id
+ * @return String
+ */
+ private function makeSection(String $title, String|Null $icon, Int $id): String
+ {
+ $url = Router::getRequest()->getPath();
+ return <<
+
+
+
+
+ EOD;
+ }
+
+ /**
+ * create
+ *
+ * @param Array $menu_sections
+ * @return String
+ */
+ public function create(Array $menu_sections): String
+ {
+ $output = '';
+ foreach ($menu_sections as $menu_section) {
+ $output.= $this->makeSection($menu_section['title'], $menu_section['icon'], $menu_section['id']);
+ }
+ return $output;
+ }
+}
diff --git a/idrocap_wa/src/WGS/Auth/OpenIdConnectClient.php b/idrocap_wa/src/WGS/Auth/OpenIdConnectClient.php
new file mode 100644
index 0000000..10ac5af
--- /dev/null
+++ b/idrocap_wa/src/WGS/Auth/OpenIdConnectClient.php
@@ -0,0 +1,163 @@
+getSession()->write("oidc.oidc_state", $state);
+
+ // Construct the authorization URL
+ $params = [
+ 'state' => $state,
+ 'response_type' => 'code',
+ 'client_id' => $clientId,
+ 'scope' => $scopes,
+ 'redirect_uri' => $redirectUri,
+ ];
+
+ $authRequestUrl = $authUrl . '?' . http_build_query($params);
+ // Redirect the user to the OpenID Provider's authorization page
+ header("Location: $authRequestUrl");
+ exit();
+ }
+
+ /**
+ * get_access_token
+ *
+ * This method performs a POST request to the IdP tokenUrl endpoint in order to obtain both id and access tokens
+ *
+ * @param String $tokenUrl
+ * @param String $issuer
+ * @param String $clientId
+ * @param Null|String $clientSecret
+ * @param String $redirectUri
+ * @throws Exception
+ * @return String
+ */
+ public static function get_access_token(String $tokenUrl, String $issuer, String $clientId, Null|String $clientSecret, String $redirectUri): String
+ {
+ // Check if the state parameter matches the stored one to prevent CSRF
+ if (Router::getRequest()->getSession()->read("oidc.oidc_state") !== Router::getRequest()->getQuery('state')) {
+ throw new \Exception("oidc_state mismatch!");
+ }
+
+ // Retrieve the authorization code from the callback
+ $code = Router::getRequest()->getQuery('code');
+ Router::getRequest()->getSession()->write('oidc.auth_code', $code);
+
+ // Exchange the authorization code for tokens
+ $data = [
+ 'grant_type' => 'authorization_code',
+ 'code' => $code,
+ 'client_id' => $clientId,
+ 'redirect_uri' => $redirectUri,
+ ];
+
+ if (!empty($clientSecret)) $data['client_secret'] = $clientSecret;
+
+ // Use cURL to send the POST request to the token endpoint
+ $ch = curl_init($tokenUrl);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
+ curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
+ $response = curl_exec($ch);
+ $errno = curl_errno($ch);
+ if($errno) {
+ $error_message = curl_strerror($errno);
+ throw new \Exception("Error retrieving access token from $tokenUrl: $errno - $error_message");
+ }
+ curl_close($ch);
+
+ // Decode the response, which contains the ID token and Access Token
+ $responseData = is_string($response) && strlen($response) > 0 ? json_decode($response, true) : '';
+ if (empty($responseData)) throw new \Exception("Unexpected or malformed Issuer response");
+ Router::getRequest()->getSession()->write("oidc.id_token", $responseData['id_token'] ?? '');
+ Router::getRequest()->getSession()->write("oidc.access_token", $responseData['access_token'] ?? '');
+
+ $id_token_array = explode('.', $responseData['id_token'] ?? '');
+ $decodedPayload = !empty($id_token_array[1]) && is_string($id_token_array[1]) && strlen($id_token_array[1]) > 0 ? json_decode(base64_decode($id_token_array[1]), true) : '';
+ if (empty($decodedPayload)) throw new \Exception("Error decoding ID Token");
+ if (empty($decodedPayload['iss'])) throw new \Exception("Issuer data is missing");
+ if ($decodedPayload['iss'] !== $issuer) throw new \Exception("Invalid Issuer");
+ if (empty($decodedPayload['aud'])) throw new \Exception("Audience data is missing");
+ $audience_array = is_array($decodedPayload['aud']) ? $decodedPayload['aud'] : [$decodedPayload['aud']];
+ if (!in_array($clientId, $audience_array)) throw new \Exception("Invalid Audience");
+ if (empty($decodedPayload['exp'])) throw new \Exception("ID Token expiration information is missing");
+ if ($decodedPayload['exp'] < time()) throw new \Exception("ID token has expired");
+ return $responseData['access_token'] ?? '';
+ }
+
+ /**
+ * get_user_info
+ *
+ * This method performs a GET request to the IdP userInfoUrl endpoint using previously retrieved access token
+ *
+ * @param String $userInfoUrl
+ * @param String $access_token
+ * @throws Exception
+ * @return String
+ */
+ public static function get_user_info(String $userInfoUrl, String $userinfo_claim_key, String $access_token): array
+ {
+ $ch = curl_init($userInfoUrl);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ 'Authorization: Bearer ' . $access_token,
+ ]);
+ $userInfoResponse = curl_exec($ch);
+ $errno = curl_errno($ch);
+ if($errno) {
+ $error_message = curl_strerror($errno);
+ throw new \Exception("Error retrieving user info from $userInfoUrl: $errno - $error_message");
+ }
+ curl_close($ch);
+
+ // Decode the response, which contains all user info
+ $decodedUserInfoResponse = is_string($userInfoResponse) && strlen($userInfoResponse) > 0 ? json_decode($userInfoResponse, true) : '';
+ if (empty($decodedUserInfoResponse)) throw new \Exception("Unexpected or malformed User info response");
+ if (empty($decodedUserInfoResponse[$userinfo_claim_key])) throw new \Exception("User info '$userinfo_claim_key' attribute is missing");
+ return $decodedUserInfoResponse;
+ }
+
+ /**
+ * logout
+ *
+ * @param String $endSessionUrl
+ * @param String $clientId
+ * @param String $postLogoutRedirectUri
+ * @return void
+ */
+ public static function logout(String $endSessionUrl, String $clientId, String $postLogoutRedirectUri)
+ {
+ $params = [
+ 'client_id' => $clientId,
+ 'state' => Router::getRequest()->getSession()->read("oidc.oidc_state"),
+ 'post_logout_redirect_uri' => $postLogoutRedirectUri, // Where to redirect after logout
+ ];
+
+ // Construct the logout URL with query parameters
+ $logoutUrl = $endSessionUrl . '?' . http_build_query($params);
+
+ Router::getRequest()->getSession()->destroy();
+ // Redirect to the OpenID Provider's logout page
+ header('Location: ' . $logoutUrl);
+ exit();
+ }
+}
diff --git a/idrocap_wa/src/WGS/FileStorage/FileStorage.php b/idrocap_wa/src/WGS/FileStorage/FileStorage.php
new file mode 100755
index 0000000..e002896
--- /dev/null
+++ b/idrocap_wa/src/WGS/FileStorage/FileStorage.php
@@ -0,0 +1,14 @@
+namenodeHost = $namenodeHost;
+ $this->namenodePort = $namenodePort;
+ $this->namenodeUser = $namenodeUser;
+ $this->namenodeRpcHost = $namenodeRpcHost;
+ $this->namenodeRpcPort = $namenodeRpcPort;
+ $this->hdfs = new \org\apache\hadoop\WebHDFS($this->namenodeHost, $this->namenodePort, $this->namenodeUser, $this->namenodeRpcHost, $this->namenodeRpcPort, true);
+ }
+
+ /**
+ * getFile
+ *
+ * @param String $path
+ * @return mixed
+ */
+ public function getFile(String $path)
+ {
+ return $this->hdfs->open($path);
+ }
+
+ /**
+ * deleteFile
+ *
+ * @param String $path
+ * @return mixed
+ */
+ public function deleteFile(String $path)
+ {
+ $this->hdfs->delete($path);
+ }
+
+ /**
+ * saveFile
+ *
+ * @param String $path
+ * @param String $tmpPath
+ * @throws \Exception
+ * @return mixed
+ */
+ public function saveFile(String $path, String $tmpPath)
+ {
+ try
+ {
+ $result = $this->hdfs->create($path, $tmpPath);
+ return $result;
+ }
+ catch(\org\apache\hadoop\WebHDFS_Exception $we)
+ {
+ throw new \Exception('Unable to save file on HadoopFileStorage: ' . $we->getMessage());
+ }
+ }
+
+ /**
+ * savePassedFile
+ *
+ * @param String $path
+ * @param String $file
+ * @return mixed
+ */
+ public function savePassedFile(String $path, String $file)
+ {
+ return $this->hdfs->createWithData($path, $file);
+ }
+
+ /**
+ * copyFile
+ *
+ * @param String $path1
+ * @param String $path2
+ * @return mixed
+ */
+ public function copyFile(String $path1, String $path2)
+ {
+ $file = $this->getFile($path1);
+ $this->savePassedFile($path2, $file);
+ }
+
+ /**
+ * checkIfExists
+ *
+ * @param String $path
+ * @return mixed
+ */
+ public function checkIfExists(String $path)
+ {
+ $response = $this->hdfs->getFileStatus($path);
+ $jsonResponse = json_decode($response);
+ return !isset($jsonResponse->RemoteException->exception);
+ }
+}
diff --git a/idrocap_wa/src/WGS/FileStorage/S3MinioFileStorage.php b/idrocap_wa/src/WGS/FileStorage/S3MinioFileStorage.php
new file mode 100755
index 0000000..1d41137
--- /dev/null
+++ b/idrocap_wa/src/WGS/FileStorage/S3MinioFileStorage.php
@@ -0,0 +1,180 @@
+config = [
+ 'version' => 'latest',
+ 'region' => $region,
+ 'use_path_style_endpoint' => true,
+ 'credentials' => [
+ 'key' => $accessKey,
+ 'secret' => $secretKey,
+ ],
+ ];
+
+ if($endpoint != null)
+ {
+ $this->config['endpoint'] = $endpoint;
+ }
+
+ $this->bucket = $bucket;
+ $this->client = new S3Client($this->config);
+
+ if(!$this->client->doesBucketExist($bucket)) $this->client->createBucket(['Bucket' => $bucket]);
+ }
+
+ /**
+ * adaptPath
+ *
+ * @param String $path
+ * @return String
+ */
+ protected function adaptPath($path)
+ {
+ return substr(str_replace('/', '_', $path),1);
+ }
+
+ /**
+ * getFile
+ *
+ * @param String $path
+ * @return mixed
+ */
+ public function getFile(String $path)
+ {
+ $path = $this->adaptPath($path);
+ $retrive = $this->client->getObject([
+ 'Bucket' => $this->bucket,
+ 'Key' => $path,
+ ]);
+
+ return $retrive['Body']->__toString();
+ }
+
+ /**
+ * deleteFile
+ *
+ * @param String $path
+ * @return mixed
+ */
+ public function deleteFile(String $path)
+ {
+ $path = $this->adaptPath($path);
+ $this->client->deleteObject([
+ 'Bucket' => $this->bucket,
+ 'Key' => $path,
+ ]);
+ }
+
+ /**
+ * saveFile
+ *
+ * @param String $path
+ * @param String $tmpPath
+ * @throws \Exception
+ * @return mixed
+ */
+ public function saveFile(String $path, String $tmpPath)
+ {
+ $path = $this->adaptPath($path);
+ try
+ {
+ $insert = $this->client->putObject([
+ 'Bucket' => $this->bucket,
+ 'Key' => $path,
+ 'SourceFile' => $tmpPath
+ ]);
+
+ return $insert;
+ }
+ catch(\Exception $we)
+ {
+ throw new \Exception('Unable to save file on S3MinioFileStorage: ' . $we->getMessage());
+ }
+ }
+
+ /**
+ * savePassedFile
+ *
+ * @param String $path
+ * @param String $file
+ * @throws \Exception
+ * @return mixed
+ */
+ public function savePassedFile(String $path, String $file)
+ {
+ $path = $this->adaptPath($path);
+ try
+ {
+ $insert = $this->client->putObject([
+ 'Bucket' => $this->bucket,
+ 'Key' => $path,
+ 'Body' => $file,
+ ]);
+
+ return $insert;
+ }
+ catch(\Exception $we)
+ {
+ throw new \Exception('Unable to save file on S3MinioFileStorage: ' . $we->getMessage());
+ }
+ }
+
+ /**
+ * copyFile
+ *
+ * @param String $path1
+ * @param String $path2
+ * @return mixed
+ */
+ public function copyFile(String $path1, String $path2)
+ {
+ $path1 = $this->adaptPath($path1);
+ $path2 = $this->adaptPath($path2);
+ $sourceBucket = $this->bucket;
+ $sourceKeyname = $path1;
+
+ $copy = $this->client->copyObject([
+ 'Bucket' => $this->bucket,
+ 'Key' => $path2,
+ 'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
+ ]);
+
+ return $copy;
+ }
+
+ /**
+ * checkIfExists
+ *
+ * @param String $path
+ * @return Bool
+ */
+ public function checkIfExists(String $path)
+ {
+ $path = $this->adaptPath($path);
+ return $this->client->doesObjectExist($this->bucket, $path);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/Geo/CadastralUtils.php b/idrocap_wa/src/WGS/Geo/CadastralUtils.php
new file mode 100644
index 0000000..736a7d6
--- /dev/null
+++ b/idrocap_wa/src/WGS/Geo/CadastralUtils.php
@@ -0,0 +1,61 @@
+execute($sql_statement)->fetchAll('assoc');
+ if (!isset($result[0]['result']) || json_decode($result[0]['result'], true) === null || !isset(json_decode($result[0]['result'], true)['coordinates'])) return null;
+ $result_object = json_decode($result[0]['result'], true)['coordinates'];
+ $coordinates = (object)[];
+ $coordinates->latitude = $result_object[0];
+ $coordinates->longitude = $result_object[1];
+ return $coordinates;
+ }
+ catch(\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * isParcelWithinVegetationArea
+ *
+ * controlla se la particella specificata, del foglio specificato del comune specificato si interseca o meno con un'area di vegetazione
+ *
+ * @param String $cadastral_code
+ * @param String $sheet
+ * @param String $parcel
+ * @return Bool
+ */
+ public static function isParcelWithinVegetationArea(String $cadastral_code, String $sheet, String $parcel): Bool
+ {
+ $sql_statement = "select count(*) as result from full_vegetations where st_intersects(SHAPE, (select SHAPE from cadastral_{$cadastral_code}_parcels where nationalcadastralreference = concat((select nationalcadastralzoningreference from cadastral_{$cadastral_code}_sheets where label = '{$sheet}'), '.', '{$parcel}')));";
+
+ $connection = ConnectionManager::get('geo');
+ try {
+ $result = $connection->execute($sql_statement)->fetchAll('assoc');
+ return isset($result[0]['result']) && $result[0]['result'] > 0;
+ }
+ catch(\Exception $e) {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/Geo/ExtGeoResourceAttributesRetriever.php b/idrocap_wa/src/WGS/Geo/ExtGeoResourceAttributesRetriever.php
new file mode 100644
index 0000000..865521e
--- /dev/null
+++ b/idrocap_wa/src/WGS/Geo/ExtGeoResourceAttributesRetriever.php
@@ -0,0 +1,40 @@
+url = $url;
+ $this->lon_parameter_name = $lon_parameter_name;
+ $this->lat_parameter_name = $lat_parameter_name;
+ }
+
+ /**
+ * retrieve
+ *
+ * @param String $lat
+ * @param String $lon
+ * @return Array
+ */
+ public function retrieve(String $lon, String $lat)
+ {
+ $http = new Client();
+ $response = $http->get($this->url, [$this->lon_parameter_name => $lon, $this->lat_parameter_name => $lat]);
+ return json_decode($response->getStringBody(), true);
+ }
+}
diff --git a/idrocap_wa/src/WGS/Geo/GeoValidation.php b/idrocap_wa/src/WGS/Geo/GeoValidation.php
new file mode 100644
index 0000000..698a79b
--- /dev/null
+++ b/idrocap_wa/src/WGS/Geo/GeoValidation.php
@@ -0,0 +1,61 @@
+execute('SELECT st_intersects(st_geomFromGeojson(\''.$testGeometry.'\'),st_geomFromGeojson(\''.json_encode($geometry).'\')) as result')
+ ->fetchAll('assoc');
+ return isset($result[0]['result']) && $result[0]['result'];
+ }
+ catch(\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * checkCadastralCoordinates
+ *
+ * chiede a mysql GEO se le coordinate passate costituiscono un punto all'interno del comune, foglio e particella passate
+ *
+ * @param String $latitude
+ * @param String $longitude
+ * @param String $cadastral_code
+ * @param String $sheet
+ * @param String $parcel
+ * @return Bool
+ */
+ public static function checkCadastralCoordinates(String $latitude, String $longitude, String $cadastral_code, String $sheet, String $parcel): Bool
+ {
+ $sql_statement = "select count(*) as result from cadastral_{$cadastral_code}_parcels where nationalcadastralreference = concat((select nationalcadastralzoningreference from cadastral_{$cadastral_code}_sheets where label = '{$sheet}'),'.', '{$parcel}') and st_intersects(SHAPE, st_geomfromtext('POINT({$latitude} {$longitude})',4326));";
+ $connection = ConnectionManager::get('geo');
+ try {
+ $result = $connection->execute($sql_statement)->fetchAll('assoc');
+ return isset($result[0]['result']) && $result[0]['result'] === 1;
+ }
+ catch(\Exception $e) {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/Geo/Geocoding.php b/idrocap_wa/src/WGS/Geo/Geocoding.php
new file mode 100644
index 0000000..c9a60e5
--- /dev/null
+++ b/idrocap_wa/src/WGS/Geo/Geocoding.php
@@ -0,0 +1,84 @@
+get(
+ $url,
+ ['type' => 'json'], ['ssl_verify_peer' => false, 'ssl_verify_peer_name' => false]
+ );
+ $http_code = $result->getStatusCode();
+ if ($http_code == 200 && $result->getJson() !== null) {
+ $result = $result->getJson();
+ } else {
+ $result = [];
+ }
+ return ['http_code' => $http_code, 'result' => $result];
+ }
+
+ /**
+ * performGeocoding
+ *
+ * @param ?String $parameters
+ * @param ?Array $queryParameters
+ * @return Array
+ */
+ public static function performGeocoding(?String $parameters = null, ?Array $queryParameters = null)
+ {
+ $language_code = substr(I18n::getLocale(), 0, 2);
+ $status = 'online';
+
+ $map_config = Configure::read('App.mapConfig');
+ $upperLeftBoundLon = $map_config['upperLeftBoundLon'];
+ $upperLeftBoundLat = $map_config['upperLeftBoundLat'];
+ $lowerRightBoundLon = $map_config['lowerRightBoundLon'];
+ $lowerRightBoundLat = $map_config['lowerRightBoundLat'];
+
+ $url = Configure::read('App.urlGeocodingOnline') . "$parameters?accept-language=$language_code&viewbox=$upperLeftBoundLon,$upperLeftBoundLat,$lowerRightBoundLon,$lowerRightBoundLat&bounded=1";
+
+ foreach ($queryParameters as $key => $value)
+ {
+ $url .= "&$key=" . urlencode($value);
+ }
+
+ if(!Configure::read('App.enableGeocodingOffline') || !Cache::read('geocoding_offline') || (time() - Cache::read('geocoding_offline') > Configure::read('App.offlineTimeout')))
+ {
+ Cache::delete('geocoding_offline');
+ $json_result = Geocoding::getJson($url);
+ }
+
+ if (Configure::read('App.enableGeocodingOffline') && (!isset($json_result) || $json_result['http_code'] != 200 || is_string($json_result['result'])))
+ {
+ if(!Cache::read('geocoding_offline'))
+ {
+ Cache::write('geocoding_offline', time());
+ }
+ $url = Configure::read('App.urlGeocodingOffline') . "$parameters?accept-language=$language_code&viewbox=$upperLeftBoundLon,$upperLeftBoundLat,$lowerRightBoundLon,$lowerRightBoundLat&bounded=1";
+
+ foreach($queryParameters as $key => $value)
+ {
+ $url .= "&$key=" . urlencode($value);
+ }
+ $status = 'offline';
+ $json_result = Geocoding::getJson($url);
+ }
+
+ $result = ['url' => $url, 'status' => $status, 'contents' => $json_result['result'], 'status_code' => ['http_code' => $json_result['http_code']]];
+ return $result;
+ }
+}
diff --git a/idrocap_wa/src/WGS/Geo/IntGeoResourceAttributesRetriever.php b/idrocap_wa/src/WGS/Geo/IntGeoResourceAttributesRetriever.php
new file mode 100644
index 0000000..702cb5a
--- /dev/null
+++ b/idrocap_wa/src/WGS/Geo/IntGeoResourceAttributesRetriever.php
@@ -0,0 +1,57 @@
+connection_name = count($geo_resource_path_array ) > 1 ? $geo_resource_path_array[0] : 'default';
+ $this->db_name = count($geo_resource_path_array ) > 1 ? $geo_resource_path_array[0] : 'jixel';
+ $this->table_name = $geo_resource_path_array[count($geo_resource_path_array) - 1];
+ $this->geometry_name = $geometry_name;
+ $field_prefix = $this->db_name . '.' . $this->table_name;
+ $this->select_fields = implode(",", collection($attributes)->map(function ($attribute) use ($field_prefix) { return "$field_prefix.$attribute"; })->toArray());
+ }
+
+ /**
+ * retrieve
+ *
+ * @return Array
+ */
+ public function retrieve($feature_collection)
+ {
+ $select_fields = $this->select_fields;
+ $connection_name = $this->connection_name;
+ $db_name = $this->db_name;
+ $table_name = $this->table_name;
+ $geometry_name = $this->geometry_name;
+ $connection = ConnectionManager::get("$connection_name");
+ $sql_statement = "select $select_fields from $db_name.$table_name where st_intersects($db_name.$table_name.$geometry_name, st_geomfromgeojson('$feature_collection'))";
+ try {
+ $result = $connection->execute($sql_statement)->fetchAll('assoc');
+ return $result;
+ }
+ catch(\Exception $e) {
+ return ['error' => true, 'code' => $e->getCode(), 'message' => $e->getMessage()];
+ }
+ }
+}
diff --git a/idrocap_wa/src/WGS/Geo/LocationAttributesRetriever.php b/idrocap_wa/src/WGS/Geo/LocationAttributesRetriever.php
new file mode 100644
index 0000000..24eda59
--- /dev/null
+++ b/idrocap_wa/src/WGS/Geo/LocationAttributesRetriever.php
@@ -0,0 +1,65 @@
+setLocation($location);
+ }
+
+ /**
+ * setLocation
+ *
+ * @param ?Location $location
+ * @return LocationAttributesRetriever
+ */
+ public function setLocation(?Location $location = null): LocationAttributesRetriever
+ {
+ if (empty($location) || get_class($location) != 'App\Model\Entity\Location') {
+ throw new \Exception('LocationAttributesRetriever/setLocation: Invalid location entity passed!');
+ }
+
+ $geometry_collection = json_decode('{"type": "FeatureCollection","features": []}');
+ if (isset($location->feature_collection) && json_decode($location->feature_collection) != null) {
+ $geometry_collection = json_decode($location->feature_collection);
+ }
+ if (isset($location->coordinates) && $location->coordinates != '' && json_decode($location->coordinates) == null) {
+ $geometry_collection->features[] = json_decode('{"type": "Feature", "properties": {}, "geometry": {"type": "Point", "coordinates": ['.str_replace(" ", ",", $location->coordinates).']}}');
+ }
+ $this->geometry_collection = json_encode($geometry_collection);
+
+ return $this;
+ }
+
+ /**
+ * retrieve
+ *
+ * @return Array
+ */
+ public function retrieve()
+ {
+ $sql_statement = "select pro_com_t as district_code, comune as district_name, sigla as county_code, den_uts as county_name, den_reg as region, den_rip as area from geo.districts join geo.counties on geo.counties.cod_prov = geo.districts.cod_prov join geo.regions on geo.regions.cod_reg = geo.counties.cod_reg join geo.areas on geo.areas.cod_rip = geo.regions.cod_rip where st_intersects(geo.areas.SHAPE, st_geomfromgeojson('$this->geometry_collection')) and st_intersects(geo.regions.SHAPE, st_geomfromgeojson('$this->geometry_collection')) and st_intersects(geo.counties.SHAPE, st_geomfromgeojson('$this->geometry_collection')) and st_intersects(geo.districts.SHAPE, st_geomfromgeojson('$this->geometry_collection'))";
+ $connection = ConnectionManager::get('geo');
+ try {
+ $result = $connection->execute($sql_statement)->fetchAll('assoc');
+ return $result;
+ }
+ catch(\Exception $e) {
+ return ['error' => true, 'code' => $e->getCode(), 'message' => $e->getMessage()];
+ }
+ }
+}
diff --git a/idrocap_wa/src/WGS/NotificationsHandler/MessagingHandler.php b/idrocap_wa/src/WGS/NotificationsHandler/MessagingHandler.php
new file mode 100644
index 0000000..d6b8de7
--- /dev/null
+++ b/idrocap_wa/src/WGS/NotificationsHandler/MessagingHandler.php
@@ -0,0 +1,631 @@
+<è+òàù,.-';
+ }
+
+ $charactersLength = strlen($characters);
+ $randomString = '';
+ for ($i = 0; $i < $length; $i++) {
+ $randomString .= $characters[rand(0, $charactersLength - 1)];
+ }
+ return $randomString;
+ }
+
+ /**
+ * generateOneTimePassword
+ *
+ * @return String
+ */
+ private static function generateOneTimePassword(): String
+ {
+ return time().md5(MessagingHandler::generateRandomString(50));
+ }
+
+ /**
+ * getEventID
+ *
+ * @param ?String $co_id
+ * @param ?String $user_id
+ * @return String
+ */
+ private static function getEventID(?String $co_id = null, ?String $user_id = null): String
+ {
+ $datetime = new \DateTime();
+
+ if($co_id && $user_id)
+ {
+ return $datetime->format('ymdhi') . 'UID' . $user_id . 'COID' . $co_id . 'TS' . substr((string)microtime(), 2, 8);
+ }
+ return $datetime->format('ymdhi') . 'LID' . MessagingHandler::generateRandomString(5, true) . 'RID' . MessagingHandler::generateRandomString(5, true) . 'TS' . substr((string)microtime(), 2, 8);
+ }
+
+ /**
+ * trimMessage
+ *
+ * @param String $header
+ * @param String $link
+ * @param String $body
+ * @param Int $length
+ * @return String
+ */
+ private static function trimMessage(String $header, String $link, String $body, Int $length): String
+ {
+ if(strlen($header . $link) > $length)
+ {
+ return substr($header . $link, 0, $length);
+ }
+ $trimmed_body = substr($body, 0, $length - strlen($header . $link) - 4) . "... ";
+ return $header . $trimmed_body . $link;
+ }
+
+ /**
+ * createPushNotificationFromNotification
+ *
+ * @param Int $recipientId
+ * @param Array $notification
+ * @param String $token
+ * @return Array
+ */
+ private static function createPushNotificationFromNotification(Int $recipientId, Array $notification, String $token): Array
+ {
+ $eventID = MessagingHandler::getEventID((String)$notification['co_id'], (String)$recipientId);
+ $webURL = Configure::read('App.weburl');
+ $link = $webURL . $notification['link'];
+ $event_string = (Configure::read('App.messaging_config.event_id_prefix') != '' ? Configure::read('App.messaging_config.event_id_prefix') . '_' : '') . "PUSHNOTIFICATION" . $eventID;
+ $notificationEntity = TableRegistry::getTableLocator()->get('Notifications')->find()->where(['Notifications.user_id' => $recipientId])->order(['Notifications.created' => 'DESC'])->first();
+ $message = [
+ "EVENT_ID" => $event_string,
+ "MESSAGE" => [
+ 'token' => $token,
+ 'notification' => [
+ 'title' => $notification['title'],
+ 'body' => $notification['body'],
+ ],
+ 'data' => [
+ 'id' => !empty($notificationEntity->id) ? (string)$notificationEntity->id : '',
+ 'delay' => '',
+ 'start' => !empty($notification['start']) ? $notification['start'] : '',
+ 'datetime' => !empty($notification['datetime']) ? $notification['datetime'] : '',
+ 'before_link' => !empty($notification['before_link']) ? $notification['before_link'] : '',
+ 'link' => !empty($link) ? $link : '',
+ 'end' => !empty($notification['end']) ? $notification['end'] : '',
+ ],
+ ],
+ "RECIPIENTS" => [$token],
+ ];
+ return $message;
+ }
+
+ /**
+ * createSmsFromNotification
+ *
+ * @param String $recipientId
+ * @param Array $notification
+ * @param String $number
+ * @return Array
+ */
+ private static function createSmsFromNotification(String $recipientId, Array $notification, String $number): Array
+ {
+ $eventID = MessagingHandler::getEventID((String)$notification['co_id'], (String)$recipientId);
+ $event_string = (Configure::read('App.messaging_config.event_id_prefix') != '' ? Configure::read('App.messaging_config.event_id_prefix') . '_' : '') . "SMS" . $eventID . $number;
+ $webURL = Configure::read('App.weburl');
+ $link = $notification['use_otp'] ? $webURL . "/users/oneTimePassword/" . $notification['otp'] : $webURL . $notification['link'];
+ $notification_title = $notification['sms_skip_title'] ? '' : $notification['title'] . ': ';
+ $body = MessagingHandler::trimMessage($notification['start'] . $notification['datetime'] . ' ' . $notification_title, $notification['before_link'] . $link.$notification['end'], $notification['body'], 640);
+ $message = [
+ "EVENT_ID" => $event_string,
+ "MESSAGE" => substr($body, 0, 640),
+ "RECIPIENTS" => [$number],
+ "TYPE" => "INFOTIM",
+ "OSDC" => "DRPCSORIS",
+ "TOKEN" => "",
+ "CALLBACK" => Configure::read('App.messageCallbackUrl') . '/' . 'messages/post_report.json',
+ ];
+ return $message;
+ }
+
+ /**
+ * createFaxFromNotification
+ *
+ * @param String $recipientId
+ * @param Array $notification
+ * @param String $number
+ * @return Array
+ */
+ private static function createFaxFromNotification(String $recipientId, Array $notification, String $number): Array
+ {
+ $eventID = MessagingHandler::getEventID((String)$notification['co_id'], (String)$recipientId);
+ $subject = $notification['title'];
+ $webURL = Configure::read('App.weburl');
+ $link = $notification['use_otp'] ? $webURL . "/users/oneTimePassword/" . $notification['otp'] : $webURL . $notification['link'];
+ $body = $notification['start'] . $notification['datetime'] . ' ' . $notification['title'] . ': ' . $notification['body'] . ' ' . $notification['before_link'] . $link . $notification['end'];
+ $event_string = (Configure::read('App.messaging_config.event_id_prefix') != '' ? Configure::read('App.messaging_config.event_id_prefix') . '_' : '') . "FAX" . $eventID;
+ $message = [
+ "EVENT_ID" => $event_string,
+ "MESSAGE" => substr($body, 0, 640),
+ "SUBJECT" => $subject,
+ "RECIPIENTS" => [$number],
+ "TOKEN" => "",
+ "CALLBACK" => Configure::read('App.messageCallbackUrl') . '/' . 'messages/post_report.json',
+ ];
+ return $message;
+ }
+
+ /**
+ * createEmailFromNotification
+ *
+ * @param String $recipientId
+ * @param Array $notification
+ * @param String $email
+ * @return Array
+ */
+ private static function createEmailFromNotification(String $recipientId, Array $notification, String $email): Array
+ {
+ $eventID = MessagingHandler::getEventID((String)$notification['co_id'], (String)$recipientId);
+ $subject = $notification['datetime'] . ' ' . $notification['title'];
+ $webURL = Configure::read('App.weburl');
+ $link = $notification['use_otp'] ? $webURL . "/users/oneTimePassword/" . $notification['otp'] : $webURL . $notification['link'];
+ $body = $notification['start'] . $notification['datetime'] . ' ' . $notification['title'] . ': ' . $notification['body'] . '.' . chr(0x0D) . $notification['before_link'] . $link.$notification['end'] . chr(0x0D) . chr(0x0D) . chr(0x0D) . '---' . chr(0x0D) . $notification['disclaimer'];
+ $event_string = (Configure::read('App.messaging_config.event_id_prefix') != '' ? Configure::read('App.messaging_config.event_id_prefix') . '_' : '') . "EMAIL" . $eventID;
+ $message = [
+ "EVENT_ID" => $event_string,
+ "MESSAGE" => $body,
+ "SUBJECT" => $subject,
+ "RECIPIENTS" => [$email],
+ "TOKEN" => "",
+ "CALLBACK" => Configure::read('App.messageCallbackUrl') . '/' . 'messages/post_report.json',
+ ];
+ return $message;
+ }
+
+ /**
+ * createTelegramChatMessageFromNotification
+ *
+ * @param String $recipientId
+ * @param Array $notification
+ * @param String $telegram_chat_id
+ * @return Array
+ */
+ private static function createTelegramChatMessageFromNotification(String $recipientId, Array $notification, String $telegram_chat_id): Array
+ {
+ $eventID = MessagingHandler::getEventID((String)$notification['co_id'], (String)$recipientId);
+ $webURL = Configure::read('App.weburl');
+ $link = $notification['use_otp'] ? $webURL . "/users/oneTimePassword/" . $notification['otp'] : $webURL . $notification['link'];
+ $body = '🔔' . $notification['start'] . $notification['datetime'] . ' ' . $notification['title'] . ' \n\n' . $notification['body'] . '. ' . $notification['before_link'] . '\n\n' . $link . " " . $notification['end'];
+ $event_string = (Configure::read('App.messaging_config.event_id_prefix') != '' ? Configure::read('App.messaging_config.event_id_prefix') . '_' : '') . "TELEGRAM" . $eventID;
+ $message = [
+ "EVENT_ID" => $event_string,
+ "MESSAGE" => $body,
+ "RECIPIENTS" => [$telegram_chat_id],
+ ];
+ return $message;
+ }
+
+ /**
+ * createPecFromNotification
+ *
+ * @param String $recipientId
+ * @param Array $notification
+ * @param String $pec
+ * @return Array
+ */
+ private static function createPecFromNotification(String $recipientId, Array $notification, String $pec): Array
+ {
+ $eventID = MessagingHandler::getEventID((String)$notification['co_id'], (String)$recipientId);
+ $subject = $notification['datetime'] . ' ' . $notification['title'];
+ $webURL = Configure::read('App.weburl');
+ $link = $notification['use_otp'] ? $webURL . "/users/oneTimePassword/" . $notification['otp'] : $webURL . $notification['link'];
+ $body = $notification['start'] . $notification['datetime'] . ' ' . $notification['title'] . ': ' . $notification['body'] . '.' . chr(0x0D) . $notification['before_link'] . $link.$notification['end'] . chr(0x0D) . chr(0x0D) . chr(0x0D) . '---' . chr(0x0D) . $notification['disclaimer'];
+ $event_string = (Configure::read('App.messaging_config.event_id_prefix') != '' ? Configure::read('App.messaging_config.event_id_prefix') . '_' : '') . "PEC" . $eventID;
+ $message = [
+ "EVENT_ID" => $event_string,
+ "MESSAGE" => $body,
+ "SUBJECT" => $subject,
+ "RECIPIENTS" => [$pec],
+ "TOKEN" => "",
+ "CALLBACK" => Configure::read('App.messageCallbackUrl') . '/' . 'messages/post_report.json',
+ ];
+ return $message;
+ }
+
+ /**
+ * sendMessageToQueue
+ *
+ * @param Array $m
+ * @param String $queue
+ * @return void
+ */
+ private static function sendMessageToQueue(Array $m, String $queue)
+ {
+ Log::write('debug', 'MessagingHandler::sendMessageToQueue publishing queue: ' . $queue);
+ Log::write('debug', 'MessagingHandler::sendMessageToQueue publishing message: ' . json_encode($m));
+ $connection = new AMQPStreamConnection(Configure::read('App.rabbitMQhost'), Configure::read('App.rabbitMQport'), Configure::read('App.rabbitMQusername'), Configure::read('App.rabbitMQpassword'));
+ $channel = $connection->channel();
+ $channel->queue_declare($queue, false, true, false, false);
+ $msg = new AMQPMessage(json_encode($m), ['delivery_mode' => 2]);
+ $channel->basic_publish($msg, '', $queue);
+ $channel->close();
+ $connection->close();
+ }
+
+ /**
+ * sendMessageOfTypeToConfiguredProvider
+ *
+ * @param Array $message
+ * @param String $type
+ * @throws \Exception
+ * @return void
+ */
+ private static function sendMessageOfTypeToConfiguredProvider(Array $message, String $type)
+ {
+ $dispatching_provider = Configure::read('App.messaging_config.' . $type);
+ Log::write('debug', "MessagingHandler::sendMessageToConfiguredProvider: $dispatching_provider");
+ $queue = '';
+ $m = [];
+
+ switch ($dispatching_provider) {
+ case 'tim':
+ if ($type != 'sms') throw new \Exception("messaging: dispatching_provider '$dispatching_provider' doesn't support '$type'!");
+ $queue = Configure::read('App.messaging_broker_config.tim.sms.queue');
+ $m["infotim"] = Configure::read('App.messaging_broker_config.tim.sms.infotim');
+ $m["dispatching_method"] = 'tim';
+ $m["message"] = $message;
+ $m["type"] = $type;
+ break;
+
+ case 'firebase':
+ if ($type != 'push_notification') throw new \Exception("messaging: dispatching_provider '$dispatching_provider' doesn't support '$type'!");
+ $queue = Configure::read('App.messaging_broker_config.firebase.push_notification.queue');
+ $m["dispatching_method"] = 'firebase';
+ $m["message"] = $message;
+ $m["type"] = $type;
+ break;
+
+ case 'amazon':
+ switch ($type)
+ {
+ case 'email':
+ $awsCredentials = [
+ 'ses_aws_access_key_id' => Configure::read('App.messaging_broker_config.amazon.email.ses_aws_access_key_id'),
+ 'ses_aws_secret_access_key' => Configure::read('App.messaging_broker_config.amazon.email.ses_aws_secret_access_key'),
+ ];
+ $queue = Configure::read('App.messaging_broker_config.amazon.email.queue');
+ break;
+
+ case 'sms':
+ $awsCredentials = [
+ 'sns_aws_access_key_id' => Configure::read('App.messaging_broker_config.amazon.sms.sns_aws_access_key_id'),
+ 'sns_aws_secret_access_key' => Configure::read('App.messaging_broker_config.amazon.sms.sns_aws_secret_access_key'),
+ ];
+ $queue = Configure::read('App.messaging_broker_config.amazon.sms.queue');
+ break;
+
+ default:
+ throw new \Exception("messaging: dispatching_provider '$dispatching_provider' doesn't support '$type'!");
+ }
+ $m["awsCredentials"] = $awsCredentials;
+ $m["dispatching_method"] = 'amazon';
+ $m["messageChannel"] = '';
+ $m["message"] = $message;
+ $m["type"] = $type;
+ break;
+
+ case 'ies':
+ switch ($type)
+ {
+ case 'email':
+ $queue = Configure::read('App.messaging_broker_config.ies.email.queue');
+ $m["smtp_username"] = Configure::read('App.messaging_broker_config.ies.email.smtp_username');
+ $m["smtp_password"] = Configure::read('App.messaging_broker_config.ies.email.smtp_password');
+ $m["default_sender"] = Configure::read('App.messaging_broker_config.ies.email.default_sender');
+ $m["reply-to"] = Configure::read('App.messaging_broker_config.ies.email.reply-to');
+ $m["list-unsubscribe"] = Configure::read('App.messaging_broker_config.ies.email.list-unsubscribe');
+ $m["domain"] = Configure::read('App.messaging_broker_config.ies.email.domain');
+ $m["messageChannel"] = Configure::read('App.messaging_broker_config.ies.email.messageChannel');
+ break;
+
+ case 'telegram':
+ $queue = Configure::read('App.messaging_broker_config.ies.telegram.queue');
+ $m["telegram_bot_token"] = Configure::read('App.messaging_broker_config.ies.telegram.bot_token');
+ break;
+
+ case 'pec':
+ $queue = Configure::read('App.messaging_broker_config.ies.pec.queue');
+ $m["smtp_username"] = Configure::read('App.messaging_broker_config.ies.pec.smtp_username');
+ $m["smtp_password"] = Configure::read('App.messaging_broker_config.ies.pec.smtp_password');
+ $m["default_sender"] = Configure::read('App.messaging_broker_config.ies.pec.default_sender');
+ $m["reply-to"] = Configure::read('App.messaging_broker_config.ies.pec.reply-to');
+ $m["list-unsubscribe"] = Configure::read('App.messaging_broker_config.ies.pec.list-unsubscribe');
+ $m["domain"] = Configure::read('App.messaging_broker_config.ies.pec.domain');
+ $m["messageChannel"] = Configure::read('App.messaging_broker_config.ies.pec.messageChannel');
+ break;
+
+ default:
+ throw new \Exception("messaging: dispatching_provider '$dispatching_provider' doesn't support '$type'!");
+ }
+ $m["dispatching_method"] = 'ies';
+ $m["message"] = $message;
+ $m["type"] = $type;
+ break;
+
+ case 'log':
+ switch ($type)
+ {
+ case 'fax':
+ $queue = Configure::read('App.messaging_broker_config.log.fax.queue');
+ break;
+
+ case 'email':
+ $queue = Configure::read('App.messaging_broker_config.log.email.queue');
+ break;
+
+ case 'sms':
+ $queue = Configure::read('App.messaging_broker_config.log.sms.queue');
+ break;
+
+ case 'telegram':
+ $queue = Configure::read('App.messaging_broker_config.log.telegram.queue');
+ break;
+
+ case 'push_notification':
+ $queue = Configure::read('App.messaging_broker_config.log.push_notification.queue');
+ break;
+
+ case 'pec':
+ $queue = Configure::read('App.messaging_broker_config.log.pec.queue');
+ break;
+
+ default:
+ throw new \Exception("messaging: dispatching_provider '$dispatching_provider' doesn't support '$type'!");
+ }
+ $m["dispatching_method"] = 'log';
+ $m["messageChannel"] = 'log';
+ $m["message"] = $message;
+ $m["type"] = $type;
+ break;
+
+ default:
+ throw new \Exception("messaging: dispatching_provider '$dispatching_provider' not handled!");
+ }
+ MessagingHandler::sendMessageToQueue($m, $queue);
+ }
+
+ /**
+ * saveMessage
+ *
+ * @param Array $orig_message
+ * @param ?Int $user_id
+ * @param String $group
+ * @param Int $type_id
+ * @param ?Int $co_id
+ * @param ?Int $org_id
+ * @param String $contact
+ * @return void
+ */
+ private static function saveMessage(Array $orig_message, ?Int $user_id, String $group, Int $type_id, ?Int $co_id, ?Int $org_id, String $contact)
+ {
+ $message = TableRegistry::getTableLocator()->get('Messages')->newEntity([
+ 'controllable_object_id' => $co_id,
+ 'user_id' => $user_id,
+ 'organisation_id' => $org_id,
+ 'mgroup' => $group,
+ 'message_status_id' => 0,
+ 'content' => $orig_message['MESSAGE'],
+ 'event_string' => $orig_message['EVENT_ID'],
+ 'message_type_id' => $type_id,
+ 'last_update' => new DateTime(),
+ 'contact' => $contact,
+ ]);
+
+ Log::write('debug', 'MessagingHandler::saveMessage saving messaage: ' . json_encode($message));
+ if (!TableRegistry::getTableLocator()->get('Messages')->save($message)) {
+ Log::write('debug', 'MessagingHandler::saveMessage error:');
+ Log::write('debug', json_encode($message->getErrors()));
+ }
+ }
+
+ /**
+ * dispatch
+ *
+ * @param Array $recipients
+ * @param Array $notification
+ * @param String $group
+ * @param ?Int $co_id
+ * @param Int $dispatching_task_id
+ * @throws \Exception
+ * @return void
+ */
+ public static function dispatch(Array $recipients, Array $notification, String $group, ?Int $co_id, Int $dispatching_task_id)
+ {
+ Log::write('debug', 'MessagingHandler::dispatch START');
+ foreach($recipients as $recipient)
+ {
+ // inserisco nella notifica il datetime in base al timezone dello user. Se lo user non ha timezone
+ // o se si tratta di una organizzazione, usiamo il defaultUserTimezone:
+ $notification['datetime'] = (new DateTime())->i18nFormat(Configure::read('App.notification_datetime_format'), $recipient->timezone ?? Configure::read('App.defaultUserTimezone'));
+
+ // recupero l'actor del recipient (che sia user o organisation):
+ $recipient_actor = $recipient->getActor();
+
+ // se l'actor non è ne USER ne ORGANISATION -> skip:
+ if (!in_array($recipient_actor->actor_type_id, [1, 5])) continue;
+
+ // se il recipient è uno user e va usato otp per il tipo di notifica,
+ // genero otp, lo ingetto nella notifica, lo salvo nello user insieme a redirect url ed expires:
+ if ($recipient_actor->actor_type_id == 5 && $notification['use_otp']) {
+ $notification['otp'] = MessagingHandler::generateOneTimePassword();
+ $recipient->otp = $notification['otp'];
+ $recipient->otp_redirect_url = empty($notification['link']) ? '/' : $notification['link'];
+ $hours = Configure::read('App.oneTimePasswordExpirationHours', 1);
+ $recipient->otp_expires = new DateTime("+$hours hours");
+ TableRegistry::getTableLocator()->get('Users')->save($recipient);
+ }
+
+ // stabilisco il prefix da inviare a createSmsFromNotification e createEmailFromNotification:
+ $recipientIdPrefix = $recipient_actor->actor_type_id == 1 ? 'O' : 'U';
+
+ // recupero il dispatching_task_item per l'actor specifico:
+ $dispatching_task_item = TableRegistry::getTableLocator()->get('DispatchingTaskItems')->find()->contain(['DispatchingTasks'])->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task_id, 'DispatchingTaskItems.actor_id' => $recipient->actor_id])->first();
+ if (!$dispatching_task_item) continue;
+
+ if ($recipient_actor->actor_type_id == 5) {
+ // SOLO PER UTENTE - gestione invio PUSH NOTIFICATION:
+ $push_notification_bit = TableRegistry::getTableLocator()->get('MessageTypes')->get(0)->dispatching_bitmask_weight;
+ if (($dispatching_task_item->not_performed_dispatching_bitmask & $push_notification_bit))
+ {
+ foreach($recipient->getPushNotificationsWithNotifications() as $pushNotificationObj)
+ {
+ $pushNotification = $pushNotificationObj->value;
+ Log::write('debug', 'MessagingHandler::dispatch Creating PUSH NOTIFICATION for ' . $recipient->name . " " . $recipient->surname . " with token " . $pushNotification);
+ $message = MessagingHandler::createPushNotificationFromNotification($recipient->id, $notification, $pushNotification);
+ MessagingHandler::sendMessageOfTypeToConfiguredProvider($message, 'push_notification');
+ $message['MESSAGE'] = $message['MESSAGE']['notification']['title'] . ' - ' . $message['MESSAGE']['notification']['body'];
+ MessagingHandler::saveMessage($message, $recipient->id, $group, 0, $co_id, null, $pushNotification);
+ }
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->performed_dispatching_bitmask += $push_notification_bit;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ }
+
+ // gestione invio SMS:
+ $sms_bit = TableRegistry::getTableLocator()->get('MessageTypes')->get(1)->dispatching_bitmask_weight;
+ if (($dispatching_task_item->not_performed_dispatching_bitmask & $sms_bit))
+ {
+ foreach($recipient->getMobilePhonesWithNotifications() as $mobileObj)
+ {
+ $mobile = $mobileObj->value;
+ Log::write('debug', 'MessagingHandler::dispatch Creating SMS for ' . $recipient_actor->description . " with number " . $mobile);
+ $message = MessagingHandler::createSmsFromNotification($recipientIdPrefix . $recipient->id . 'D' . $mobileObj->delivery_id, $notification, $mobile);
+ MessagingHandler::sendMessageOfTypeToConfiguredProvider($message, 'sms');
+ MessagingHandler::saveMessage($message, $recipient_actor->actor_type_id == 1 ? null : $recipient->id, $group, 1, $co_id, $recipient_actor->actor_type_id == 1 ? $recipient->id : null, $mobile);
+ }
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->performed_dispatching_bitmask += $sms_bit;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+
+ if ($recipient_actor->actor_type_id == 5) {
+ // SOLO PER UTENTE - gestione invio FAX:
+ $fax_bit = TableRegistry::getTableLocator()->get('MessageTypes')->get(2)->dispatching_bitmask_weight;
+ if (($dispatching_task_item->not_performed_dispatching_bitmask & $fax_bit))
+ {
+ foreach($recipient->getFaxesWithNotifications() as $faxObj)
+ {
+ $fax = $faxObj->value;
+ Log::write('debug', 'MessagingHandler::dispatch Creating FAX for ' . $recipient->name . " " . $recipient->surname . " with number " . $fax);
+ $message = MessagingHandler::createFaxFromNotification('U' . $recipient->id . 'D' . $faxObj->delivery_id, $notification, $fax);
+ MessagingHandler::sendMessageOfTypeToConfiguredProvider($message, 'fax');
+ MessagingHandler::saveMessage($message, $recipient->id, $group, 2, $co_id, null, $fax);
+ }
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->performed_dispatching_bitmask += $fax_bit;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ }
+
+ // gestione invio EMAIL:
+ $email_bit = TableRegistry::getTableLocator()->get('MessageTypes')->get(3)->dispatching_bitmask_weight;
+ if (($dispatching_task_item->not_performed_dispatching_bitmask & $email_bit))
+ {
+ foreach($recipient->getEmailsWithNotifications() as $emailObj)
+ {
+ $email = $emailObj->value;
+ Log::write('debug', 'MessagingHandler::dispatch Creating EMAIL for ' . $recipient_actor->description . " with email " . $email);
+ $message = MessagingHandler::createEmailFromNotification($recipientIdPrefix . $recipient->id . 'D' . $emailObj->delivery_id, $notification, $email);
+ MessagingHandler::sendMessageOfTypeToConfiguredProvider($message, 'email');
+ MessagingHandler::saveMessage($message, $recipient_actor->actor_type_id == 1 ? null : $recipient->id, $group, 3, $co_id, $recipient_actor->actor_type_id == 1 ? $recipient->id : null, $email);
+ }
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->performed_dispatching_bitmask += $email_bit;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+
+ if ($recipient_actor->actor_type_id == 5) {
+ // SOLO PER UTENTE - gestione invio TELEGRAM CHAT (BOT):
+ $telegram_bit = TableRegistry::getTableLocator()->get('MessageTypes')->get(4)->dispatching_bitmask_weight;
+ if (($dispatching_task_item->not_performed_dispatching_bitmask & $telegram_bit))
+ {
+ foreach($recipient->getTelegramChatsWithNotifications() as $telegramChatObj)
+ {
+ $telegramChat = $telegramChatObj->value;
+ Log::write('debug', 'MessagingHandler::dispatch Creating TELEGRAM CHAT for ' . $recipient->name . " " . $recipient->surname . " with telegram_chat_id " . $telegramChat);
+ $message = MessagingHandler::createTelegramChatMessageFromNotification('U' . $recipient->id . 'D' . $telegramChatObj->delivery_id, $notification, $telegramChat);
+ MessagingHandler::sendMessageOfTypeToConfiguredProvider($message, 'telegram');
+ MessagingHandler::saveMessage($message, $recipient->id, $group, 4, $co_id, null, $telegramChat);
+ }
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->performed_dispatching_bitmask += $telegram_bit;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ }
+
+ // gestione invio PEC:
+ $pec_bit = TableRegistry::getTableLocator()->get('MessageTypes')->get(5)->dispatching_bitmask_weight;
+ if (($dispatching_task_item->not_performed_dispatching_bitmask & $pec_bit))
+ {
+ foreach($recipient->getPecsWithNotifications() as $pecObj)
+ {
+ $pec = $pecObj->value;
+ Log::write('debug', 'MessagingHandler::dispatch Creating PEC for ' . $recipient_actor->description . " with PEC " . $pec);
+ $message = MessagingHandler::createPecFromNotification($recipientIdPrefix . $recipient->id . 'D' . $pecObj->delivery_id, $notification, $pec);
+ MessagingHandler::sendMessageOfTypeToConfiguredProvider($message, 'pec');
+ MessagingHandler::saveMessage($message, $recipient_actor->actor_type_id == 1 ? null : $recipient->id, $group, 5, $co_id, $recipient_actor->actor_type_id == 1 ? $recipient->id : null, $pec);
+ }
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->performed_dispatching_bitmask += $pec_bit;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ }
+ Log::write('debug', 'MessagingHandler::dispatch END');
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/NotificationsHandler/NotificationGenerator.php b/idrocap_wa/src/WGS/NotificationsHandler/NotificationGenerator.php
new file mode 100644
index 0000000..fb49144
--- /dev/null
+++ b/idrocap_wa/src/WGS/NotificationsHandler/NotificationGenerator.php
@@ -0,0 +1,169 @@
+get('NotificationTypes')->find()->where(['NotificationTypes.description' => $notification['type']])->first();
+ $notification['type_id'] = $notificationType->id ?? '';
+ }
+
+ return $notification;
+ }
+}
diff --git a/idrocap_wa/src/WGS/NotificationsHandler/NotificationsHandler.php b/idrocap_wa/src/WGS/NotificationsHandler/NotificationsHandler.php
new file mode 100644
index 0000000..90f6ac0
--- /dev/null
+++ b/idrocap_wa/src/WGS/NotificationsHandler/NotificationsHandler.php
@@ -0,0 +1,243 @@
+channel();
+ $channel->queue_declare(Configure::read('App.background_tasks.notifications.channel'), false, true, false, false);
+ $msg = new AMQPMessage(json_encode($m), ['delivery_mode' => 2]);
+ $channel->basic_publish($msg, '', Configure::read('App.background_tasks.notifications.channel'));
+ $channel->close();
+ $connection->close();
+ }
+
+ /**
+ * dispatch
+ *
+ * @param Int|Null $co_id
+ * @param String $notification_code
+ * @param Array $options
+ * @param Int|String $group
+ * @param Int|Null $user_logged
+ * @return void
+ */
+ public static function dispatch(Int|Null $co_id, String $notification_code, Array $options, String|Null $group = null, Int|Null $user_logged = null)
+ {
+ $group = !empty($group) ? $group : (new \DateTime())->format('ymdhi').substr((string)microtime(), 2, 8);
+
+ $bt = TableRegistry::getTableLocator()->get('BackgroundTasks')->newEntity([
+ 'command' => 'notifications_handler',
+ 'data' => json_encode(['co_id' => $co_id, 'notification_code' => $notification_code, 'options' => $options, 'group' => $group, 'user_logged' => $user_logged]),
+ 'dgroup' => $group,
+ ]);
+ if (TableRegistry::getTableLocator()->get('BackgroundTasks')->save($bt)) NotificationsHandler::sendDispatchingBackgroundTask(['command' => 'notifications_handler', 'data' => json_encode(['background_task_id' => $bt->id])]);
+ }
+
+ /**
+ * executeDispatch
+ *
+ * @param Int|Null $co_id
+ * @param String $notification_code
+ * @param Array $options
+ * @param String $group
+ * @param Int|Null $user_logged
+ * @throws \Exception
+ * @return void
+ */
+ public static function executeDispatch(Int|Null $co_id, String $notification_code, Array $options, String $group, Int|Null $user_logged)
+ {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - DISPATCH FOR CODE: "' . $notification_code . '" AND GROUP: "' . $group . '" START!!!');
+
+ $dispatch_step = 0;
+
+ // Fase 0 (eseguita sempre) - creazione/aggiornamento task:
+ $background_task = TableRegistry::getTableLocator()->get('BackgroundTasks')->find()->where(['BackgroundTasks.dgroup' => $group])->first();
+ if ($background_task) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - linked background_task id: ' . $background_task->id);
+ $dispatching_task = TableRegistry::getTableLocator()->get('DispatchingTasks')->find()->where(['DispatchingTasks.background_task_id' => $background_task->id])->first();
+ if (!$dispatching_task) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - Creating new dispatching_task');
+ $dispatching_task = TableRegistry::getTableLocator()->get('DispatchingTasks')->newEntity([
+ 'dispatching_task_group' => $group,
+ 'dispatching_task_status_id' => 1,
+ 'retries' => 0,
+ 'failed' => false,
+ 'background_task_id' => $background_task->id,
+ ]);
+ } else {
+ if ($dispatching_task->dispatching_task_status_id != 5 && !$dispatching_task->failed) $dispatching_task->retries++;
+ }
+ if ($dispatching_task->dispatching_task_status_id != 5 && !$dispatching_task->failed) {
+ if ($dispatching_task->retries >= Configure::read('App.dispatching_task_max_retries')) $dispatching_task->failed = true;
+ Log::write('debug', 'NotificationsHandler::executeDispatch - Saving dispatching_task:' . json_encode($dispatching_task));
+ if (!TableRegistry::getTableLocator()->get('DispatchingTasks')->save($dispatching_task)) {
+ throw new \Exception(json_encode($dispatching_task->getErrors()));
+ }
+ $dispatch_step = $dispatching_task->failed ? 0 : $dispatching_task->dispatching_task_status_id;
+ }
+ }
+
+ // Fase 1 - Retrieving - se lo stato è "recipients_detection":
+ if ($dispatch_step == 1) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - RECIPIENTS_DETECTION START!!!');
+ $recipients = RecipientsDetector::getRecipients($notification_code, $options);
+
+ // in questo foreach prendo un utente e verifico se ha almeno un recapito valido:
+ // si: rimuovo l'organizzazione da recipients, almeno c'è un destinatario in grado di ricevere, quindi l'org va rimossa.
+ // no: vado avanti (l'organizzazione rimane dentro recipients e quindi verrà lasciata, se poi dopo si trova un utente che ha recapiti in caso viene rimossa)
+ if (count($recipients['users']) > 0) Log::write('debug', 'NotificationsHandler::executeDispatch - checking users to be notified (if they have notification enabled push notifications, mobile phones, faxes, emails, telegram chats or PECs):');
+ foreach ($recipients['users'] as $recipient) {
+ // creo (se non esiste il task item per l'utente specifico):
+ $dispatching_task_item = TableRegistry::getTableLocator()->get('DispatchingTaskItems')->find()->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task->id, 'DispatchingTaskItems.actor_id' => $recipient->actor_id])->first();
+ if (!$dispatching_task_item) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - creating dispatching_task_item for user recipient with id: ' . $recipient->id);
+ $dispatching_task_item = TableRegistry::getTableLocator()->get('DispatchingTaskItems')->newEntity([
+ 'dispatching_task_id' => $dispatching_task->id,
+ 'actor_id' => $recipient->actor_id,
+ 'system_dispatched' => false,
+ 'actor_dispatching_bitmask' => $recipient->getDispatchingBitmask($notification_code),
+ 'performed_dispatching_bitmask' => 0,
+ ]);
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ if($notification_code != 'test_all' && isset($recipient->organisation_id) && $recipient->getDispatchingBitmask($notification_code) > 0)
+ {
+ if (($key = array_search($recipient->organisation_id, $recipients['organisations'])) !== false) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - Removing organisation with ID: ' . $recipients['organisations'][$key] . ' from notifiable organisations because there is at least 1 belonging user that will be notified!');
+ unset($recipients['organisations'][$key]);
+ }
+ }
+ }
+
+ if (count($recipients['organisations']) > 0) Log::write('debug', 'NotificationsHandler::executeDispatch - checking organisations to be notified (if they have notification enabled mobile phones, emails or PECs):');
+ foreach($recipients['organisations'] as $organisation_id)
+ {
+ $recipient = TableRegistry::getTableLocator()->get('Organisations')->find()->where(['Organisations.id' => $organisation_id])->first();
+ if (!$recipient) continue;
+
+ // creo (se non esiste il task item per l'org specifica):
+ $dispatching_task_item = TableRegistry::getTableLocator()->get('DispatchingTaskItems')->find()->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task->id, 'DispatchingTaskItems.actor_id' => $recipient->actor_id])->first();
+ if (!$dispatching_task_item && $recipient->getDispatchingBitmask()) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - creating dispatching_task_item for organisation recipient with id: ' . $recipient->id);
+ $dispatching_task_item = TableRegistry::getTableLocator()->get('DispatchingTaskItems')->newEntity([
+ 'dispatching_task_id' => $dispatching_task->id,
+ 'actor_id' => $recipient->actor_id,
+ 'system_dispatched' => null,
+ 'actor_dispatching_bitmask' => $recipient->getDispatchingBitmask(),
+ 'performed_dispatching_bitmask' => 0,
+ ]);
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ }
+ $dispatching_task->dispatching_task_status_id++;
+ if (!TableRegistry::getTableLocator()->get('DispatchingTasks')->save($dispatching_task)) {
+ throw new \Exception(json_encode($dispatching_task->getErrors()));
+ }
+ $dispatch_step = $dispatching_task->dispatching_task_status_id;
+ Log::write('debug', 'NotificationsHandler::executeDispatch - RECIPIENTS_DETECTION END!!!');
+ }
+
+ $notification = null;
+ if (in_array($dispatch_step, [2,3,4])) {
+ $notification = NotificationGenerator::getNotification($co_id, $notification_code, $options);
+ $notification['user_logged'] = $user_logged;
+ Log::write('debug', 'NotificationsHandler::executeDispatch - GENERATED NOTIFICATION: ' . json_encode($notification));
+ }
+
+ // Fase 2 - se lo stato è "system_dispatching":
+ if ($dispatch_step == 2) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - SYSTEM_DISPATCHING START!!!');
+
+ $actor_ids_query = TableRegistry::getTableLocator()->get('DispatchingTaskItems')
+ ->find()
+ ->select(['DispatchingTaskItems.actor_id'])
+ ->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task->id, 'DispatchingTaskItems.system_dispatched' => false]);
+
+ $users = TableRegistry::getTableLocator()->get('Users')
+ ->find()
+ ->where(['Users.actor_id IN' => $actor_ids_query])
+ ->toArray();
+
+ if($notification_code != "password_recovery" && $notification_code != "verify-citizen-registration")
+ {
+ SystemNotificationsDispatcher::dispatch($users, $notification, $group, $co_id, $dispatching_task->id);
+ }
+ $dispatching_task->dispatching_task_status_id++;
+ if (!TableRegistry::getTableLocator()->get('DispatchingTasks')->save($dispatching_task)) {
+ throw new \Exception(json_encode($dispatching_task->getErrors()));
+ }
+ $dispatch_step = $dispatching_task->dispatching_task_status_id;
+ Log::write('debug', 'NotificationsHandler::executeDispatch - SYSTEM_DISPATCHING END!!!');
+ }
+
+ // Fase 3 - se lo stato è "users_message_dispatching":
+ if ($dispatch_step == 3) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - USERS_MESSAGE_DISPATCHING START!!!');
+
+ $actor_ids_query = TableRegistry::getTableLocator()->get('DispatchingTaskItems')
+ ->find()
+ ->select(['DispatchingTaskItems.actor_id'])
+ ->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task->id, 'DispatchingTaskItems.system_dispatched IS NOT NULL', 'DispatchingTaskItems.not_performed_dispatching_bitmask > 0']);
+
+ $users = TableRegistry::getTableLocator()->get('Users')
+ ->find()
+ ->where(['Users.actor_id IN' => $actor_ids_query])
+ ->toArray();
+
+ MessagingHandler::dispatch($users, $notification, $group, $co_id, $dispatching_task->id);
+
+ $dispatching_task->dispatching_task_status_id++;
+ if (!TableRegistry::getTableLocator()->get('DispatchingTasks')->save($dispatching_task)) {
+ throw new \Exception(json_encode($dispatching_task->getErrors()));
+ }
+ $dispatch_step = $dispatching_task->dispatching_task_status_id;
+ Log::write('debug', 'NotificationsHandler::executeDispatch - USERS_MESSAGE_DISPATCHING END!!!');
+ }
+
+ // Fase 4 - se lo stato è "organisations_message_dispatching":
+ if ($dispatch_step == 4) {
+ Log::write('debug', 'NotificationsHandler::executeDispatch - ORGANISATIONS_MESSAGE_DISPATCHING START!!!');
+
+ $actor_ids_query = TableRegistry::getTableLocator()->get('DispatchingTaskItems')
+ ->find()
+ ->select(['DispatchingTaskItems.actor_id'])
+ ->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task->id, 'DispatchingTaskItems.system_dispatched IS NULL', 'DispatchingTaskItems.not_performed_dispatching_bitmask > 0']);
+
+ $organisations = TableRegistry::getTableLocator()->get('Organisations')
+ ->find()
+ ->where(['Organisations.actor_id IN' => $actor_ids_query])
+ ->toArray();
+
+ MessagingHandler::dispatch($organisations, $notification, $group, $co_id, $dispatching_task->id);
+
+ $dispatching_task->dispatching_task_status_id++;
+ if (!TableRegistry::getTableLocator()->get('DispatchingTasks')->save($dispatching_task)) {
+ throw new \Exception(json_encode($dispatching_task->getErrors()));
+ }
+ $dispatch_step = $dispatching_task->dispatching_task_status_id;
+ Log::write('debug', 'NotificationsHandler::executeDispatch - ORGANISATIONS_MESSAGE_DISPATCHING END!!!');
+ }
+ Log::write('debug', 'NotificationsHandler::executeDispatch - DISPATCH FOR CODE: "' . $notification_code . '" AND GROUP: "' . $group . '" END!!!');
+ }
+}
diff --git a/idrocap_wa/src/WGS/NotificationsHandler/RecipientsDetector.php b/idrocap_wa/src/WGS/NotificationsHandler/RecipientsDetector.php
new file mode 100644
index 0000000..94ed81f
--- /dev/null
+++ b/idrocap_wa/src/WGS/NotificationsHandler/RecipientsDetector.php
@@ -0,0 +1,119 @@
+ [], 'organisations' => []];
+
+ switch($notification_code)
+ {
+ case "test_all":
+ $recipients['users'] = TableRegistry::getTableLocator()->get('Users')->find()->toArray();
+ $recipients['organisations'] = TableRegistry::getTableLocator()->get('Organisations')->find()->all()->extract('id')->toArray();
+ break;
+ case "verify-citizen-registration":
+ case "password_recovery":
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['user_id']);
+ break;
+
+ case "send_to_drar_admin":
+ // recupero gli utenti appartenenti all'organizzazione di tipo DRAR (id 6)
+ // che hanno la capability "documentation.water_drawing_paperworks.assign":
+ $user_ids_query = TableRegistry::getTableLocator()->get('Users')
+ ->find()
+ ->matching('Groups.Capabilities')
+ ->matching('Organisations')
+ ->select(['Users.id'])
+ ->where(['Organisations.organisation_type_id' => 6, 'Capabilities.value' => 'documentation.water_drawing_paperworks.assign']);
+
+ $recipients['users'] = TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.id IN' => $user_ids_query])->toArray();
+ break;
+ case "send_to_drar_anac_user":
+ // recupero gli utenti appartenenti all'organizzazione di tipo DRAR (id 6)
+ // che hanno la capability "documentation.water_drawing_paperworks.antimafia_request":
+ $user_ids_query = TableRegistry::getTableLocator()->get('Users')
+ ->find()
+ ->matching('Groups.Capabilities')
+ ->matching('Organisations')
+ ->select(['Users.id'])
+ ->where(['Organisations.organisation_type_id' => 6, 'Capabilities.value' => 'documentation.water_drawing_paperworks.antimafia_request']);
+
+ $recipients['users'] = TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.id IN' => $user_ids_query])->toArray();
+ break;
+ case "send_to_drar_user_antimafia_uploaded":
+ // recupero l'utente DRAR a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['drar_user_id']);
+ break;
+ case "send_to_drar_user_antimafia_request_expired":
+ // recupero l'utente DRAR a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['drar_user_id']);
+ break;
+ case "send_to_drar_user":
+ // recupero l'utente DRAR a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['drar_user_id']);
+ break;
+ case "send_to_gc_user":
+ // recupero l'utente GC a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['gc_user_id']);
+ break;
+ case "send_to_gc_user_paperwork_verified":
+ // recupero l'utente GC a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['gc_user_id']);
+ break;
+ case "send_to_gc_user_request_self_certification":
+ // recupero l'utente GC a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['gc_user_id']);
+ break;
+ case "send_to_gc_user_paperwork_completed":
+ // recupero l'utente GC a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['gc_user_id']);
+ break;
+ case "send_to_gc_assign_paperwork":
+ // recupero gli utenti appartenenti all'organizzazione di tipo GC (id 0)
+ // che hanno la capability "documentation.water_drawing_paperworks.assign":
+ $user_ids_query = TableRegistry::getTableLocator()->get('Users')
+ ->find()
+ ->matching('Groups.Capabilities')
+ ->matching('Organisations')
+ ->select(['Users.id'])
+ ->where(['Organisations.province' => $options['water_drawing_paperwork_province'], 'Organisations.organisation_type_id' => 0, 'Capabilities.value' => 'documentation.water_drawing_paperworks.assign']);
+
+ $recipients['users'] = TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.id IN' => $user_ids_query])->toArray();
+
+ // recupero l'organizzazione di tipo GC (id 0) per la provincia di competenza:
+ $recipients['organisations'] = TableRegistry::getTableLocator()->get('Organisations')->find()->where(['Organisations.organisation_type_id' => 0, 'Organisations.province' => $options['water_drawing_paperwork_province']])->all()->extract('id')->toArray();
+ break;
+ case "send_to_gc_validate_paperwork":
+ // recupero l'utente GC a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['gc_user_id']);
+ break;
+ case "send_to_citizen_paperwork_verified":
+ // recupero l'utente Cittadino a cui la pratica risulta intestata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.tax_code' => $options['citizen_user_tax_code']])->first();
+ break;
+ case "send_result_of_validation_to_operator":
+ // recupero l'utente Cittadino a cui la pratica risulta intestata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->find()->where(['Users.id' => $options['user_id']])->first();
+ break;
+ case "send_to_last_edit_user_intended_use_check_completed":
+ // recupero l'utente DRAR a cui la pratica risulta già assegnata:
+ $recipients['users'][] = TableRegistry::getTableLocator()->get('Users')->get($options['last_edit_user_id']);
+ break;
+ default:
+ break;
+ }
+ return $recipients;
+ }
+}
diff --git a/idrocap_wa/src/WGS/NotificationsHandler/SystemNotificationsDispatcher.php b/idrocap_wa/src/WGS/NotificationsHandler/SystemNotificationsDispatcher.php
new file mode 100644
index 0000000..ab1c948
--- /dev/null
+++ b/idrocap_wa/src/WGS/NotificationsHandler/SystemNotificationsDispatcher.php
@@ -0,0 +1,122 @@
+get('Notifications')->newEntity([
+ 'user_id' => $user_id,
+ 'notification_type_id' => $orig_notification['type_id'],
+ 'thread' => substr($type_string, 0, 45 - strlen($co_id_string) - 1) . '-' . $co_id_string,
+ 'info' => json_encode($orig_notification),
+ 'ngroup' => $group,
+ 'controllable_object_id' => $co_id,
+ ]);
+
+ Log::write('debug', 'SystemNotificationsDispatcher::saveNotification saving notification: ' . json_encode($notification));
+ if (!TableRegistry::getTableLocator()->get('Notifications')->save($notification)) {
+ Log::write('debug', 'SystemNotificationsDispatcher::saveNotification error:');
+ Log::write('debug', json_encode($notification->getErrors()));
+ return null;
+ }
+ return $notification->id;
+ }
+
+ /**
+ * createSystemNotificationFromNotification
+ *
+ * @param Int $user_id
+ * @param Array $orig_notification
+ * @param Int $saved_notification_id
+ * @return Object
+ */
+ private static function createSystemNotificationFromNotification(Int $user_id, Array $orig_notification, Int $saved_notification_id): Object
+ {
+ $system_notification = (object)[];
+ $system_notification->type = "notification";
+ $system_notification->user_ids = [$user_id];
+ $system_notification->notification_ids = [$user_id => $saved_notification_id];
+ $system_notification->msg = (object)[];
+ $system_notification->msg->title = $orig_notification['title'];
+ $system_notification->msg->body = $orig_notification['body'];
+ $system_notification->msg->type = TableRegistry::getTableLocator()->get('NotificationTypes')->find()->where(['NotificationTypes.id' => $orig_notification['type_id'] ?? 0])->first()->description ?? 'unknown';
+ $system_notification->msg->sound = 'notification';
+ return $system_notification;
+ }
+
+ /**
+ * sendNotification
+ *
+ * @param Object $system_notification
+ * @return void
+ */
+ private static function sendNotification(Object $system_notification)
+ {
+ Log::write('debug', 'SystemNotificationsDispatcher::sendNotificationRequests publishing exchange: ' . Configure::read('App.notificatorExchange'));
+ Log::write('debug', 'SystemNotificationsDispatcher::sendNotificationRequests publishing system_notification: ' . json_encode($system_notification));
+ $connection = new AMQPStreamConnection(Configure::read('App.rabbitMQhost'), Configure::read('App.rabbitMQport'), Configure::read('App.rabbitMQusername'), Configure::read('App.rabbitMQpassword'));
+ $channel = $connection->channel();
+ $exchange = Configure::read('App.notificatorExchange');
+ $channel->exchange_declare($exchange, 'fanout', false, true, false);
+ $msg = new AMQPMessage(json_encode($system_notification), ['expiration' => '600000']);
+ $channel->basic_publish($msg, $exchange);
+ $channel->close();
+ $connection->close();
+ }
+
+ /**
+ * dispatch
+ *
+ * @param Array $recipients
+ * @param Array $orig_notification
+ * @param String $group
+ * @param ?Int $co_id
+ * @param Int $dispatching_task_id
+ * @throws \Exception
+ * @return void
+ */
+ public static function dispatch(Array $recipients, Array $orig_notification, String $group, ?Int $co_id, Int $dispatching_task_id)
+ {
+ Log::write('debug', 'SystemNotificationsDispatcher::dispatch START');
+ foreach($recipients as $recipient)
+ {
+ // recupero il dispatching_task_item per l'actor specifico:
+ $dispatching_task_item = TableRegistry::getTableLocator()->get('DispatchingTaskItems')->find()->contain(['DispatchingTasks'])->where(['DispatchingTaskItems.dispatching_task_id' => $dispatching_task_id, 'DispatchingTaskItems.actor_id' => $recipient->actor_id])->first();
+ if (!$dispatching_task_item) continue;
+
+ $saved_notification_id = SystemNotificationsDispatcher::saveNotification($orig_notification, $recipient->id, $group, $co_id);
+ if (!is_int($saved_notification_id)) continue;
+ $system_notification = SystemNotificationsDispatcher::createSystemNotificationFromNotification($recipient->id, $orig_notification, $saved_notification_id);
+ SystemNotificationsDispatcher::sendNotification($system_notification);
+
+ // aggiorno il task item per l'utente specifico):
+ $dispatching_task_item->system_dispatched = true;
+ $dispatching_task_item->dispatching_task->dispatching_task_group = $dispatching_task_item->dispatching_task->dispatching_task_group;
+ $dispatching_task_item->setDirty('dispatching_task');
+ if (!TableRegistry::getTableLocator()->get('DispatchingTaskItems')->save($dispatching_task_item)) {
+ throw new \Exception(json_encode($dispatching_task_item->getErrors()));
+ }
+ }
+ Log::write('debug', 'SystemNotificationsDispatcher::dispatch END');
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/SnapshotsHandler/SnapshotsHandler.php b/idrocap_wa/src/WGS/SnapshotsHandler/SnapshotsHandler.php
new file mode 100644
index 0000000..c12ae88
--- /dev/null
+++ b/idrocap_wa/src/WGS/SnapshotsHandler/SnapshotsHandler.php
@@ -0,0 +1,304 @@
+get('ControllableObjects')->find()->contain(['ControllableObjectTypes'])->where(['ControllableObjects.id' => $controllable_object_id])->first();
+ if (!isset($controllable_object->controllable_object_type->description)) return false;
+
+ switch($controllable_object->controllable_object_type->description)
+ {
+ case "water_drawing_paperwork":
+ $snapshot = SnapshotsHandler::createSnapshotForWaterDrawingPaperworks($controllable_object_id);
+ break;
+ }
+
+ if (!isset($snapshot)) return false;
+
+ $user_id = Router::getRequest()?->getAttribute('identity')?->id;
+ $controller = Router::getRequest()?->getParam('controller');
+ $action = Router::getRequest()?->getParam('action');
+
+ if (!isset($user_id) || !isset($controller) || !isset($action)) return false;
+
+ $snapshotsTable = TableRegistry::getTableLocator()->get('Snapshots');
+ $snapshotEntity = $snapshotsTable->newEntity([
+ 'controllable_object_type_id' => $controllable_object->controllable_object_type_id,
+ 'controllable_object_id' => $controllable_object_id,
+ 'object_snapshot' => $snapshot,
+ 'date' => new DateTime(),
+ 'user_id' => $user_id,
+ 'controller_action' => "$controller-$action",
+ ]);
+ if (!$snapshotsTable->save($snapshotEntity)) return false;
+
+ // all good!
+ return true;
+ }
+
+ /**
+ * createSnapshotForWaterDrawingPaperworks
+ *
+ * @param Int $controllable_object_id
+ * @return String
+ */
+ private static function createSnapshotForWaterDrawingPaperworks(Int $controllable_object_id): String
+ {
+ $controllableObjectsTable = TableRegistry::getTableLocator()->get('ControllableObjects');
+ $contain = [
+ 'Organisations' => [
+ 'Actors',
+ ],
+ 'Locations',
+ 'ChildAttachments' => [
+ 'Tags',
+ 'ControllableObjects' => [
+ 'Locations',
+ 'Creator' => [
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ]
+ ]
+ ],
+ 'Creator' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ 'Modifier' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ 'WaterDrawingPaperworks' => [
+ 'WaterDrawingPaperworkPecs' => [
+ 'Users' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ ],
+ 'WaterDrawingPaperworkStatuses',
+ 'WaterDrawingArticles',
+ 'DrarUsers' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ 'GcUsers' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ 'Applicants',
+ 'WaterDrawingAntimafiaCertificationRequests' => [
+ 'WaterDrawingAntimafiaCertificationRequestStatuses',
+ 'Users' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ ],
+ 'WaterDrawingFees' => [
+ 'WaterDrawingPayments' => [
+ 'WaterDrawingPaymentTypes',
+ 'Users' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ ],
+ ],
+ 'WaterDrawingPaperworkHistories' => [
+ 'Users' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ ],
+ 'WaterDrawingDerivations' => [
+ 'WaterDrawingDerivationTypes',
+ ],
+ 'WaterDrawingReturnPoints',
+ 'WaterDrawingIntendedUses' => [
+ 'WaterDrawingIntendedUseTypes',
+ 'CadastralCropTypes',
+ 'WaterDrawingMeters' => [
+ 'WaterDrawingToolTypes',
+ 'WaterDrawingMeasurements' => [
+ 'Users' => [
+ 'Actors',
+ 'Organisations' => [
+ 'Actors'
+ ]
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+
+ $logged_user = Router::getRequest()?->getAttribute('identity');
+
+ // disabilitiamo temporaneamente lo UserTimezoneDatetimeEntityTrait altrimenti la serializzazione
+ // verrà eseguita con tutte le date nel timezone dello user loggato e non in UTC!!!!!>
+ if ($logged_user) $logged_user->disableUserTimezoneDatetimeEntityTrait = true;
+
+ $waterDrawingPaperwork = $controllableObjectsTable->find()->contain($contain)->where(['ControllableObjects.id' => $controllable_object_id])->first();
+
+ // riabilitiamo lo UserTimezoneDatetimeEntityTrait post serializzazione
+ if ($logged_user) $logged_user->disableUserTimezoneDatetimeEntityTrait = false;
+
+ return base64_encode(serialize($waterDrawingPaperwork));
+ }
+
+ /**
+ * getControllableObjectFromSnapshotWithId
+ *
+ * @param Int $snapshot_id
+ * @return ControllableObject|Null
+ */
+ public static function getControllableObjectFromSnapshotWithId(Int $snapshot_id): ?ControllableObject
+ {
+ $snapshotsTable = TableRegistry::getTableLocator()->get('Snapshots');
+ $snapshot = $snapshotsTable->find()->where(['Snapshots.id' => $snapshot_id])->first();
+ if (!$snapshot) return null;
+ return unserialize(base64_decode($snapshot->object_snapshot));
+ }
+
+ /**
+ * getLastWaterDrawingPaperworkUnpackingVersion
+ *
+ * @return Int
+ */
+ public static function getLastWaterDrawingPaperworkUnpackingVersion(): Int
+ {
+ // ogni volta che si modifica il codice del metodo seguente getUnpackedWaterDrawingPaperworkSnapshot(),
+ // incrementare il numero int da restituire. Questo permetterà al cron job di rieseguire l'unpacking
+ // secondo la nuova versione.
+ return 1;
+ }
+
+ /**
+ * getSnapshotControllerActionDescription
+ *
+ * @param String $controller_action
+ * @return String
+ */
+ public static function getSnapshotControllerActionDescription($controller_action): String
+ {
+ $controller_action_descriptions = [
+ 'WaterDrawingPaperworks-add' => __('ha creato una nuova Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-add_scan' => __('ha inserito una nuova Pratica di Attingimento scansionata'),
+ 'WaterDrawingPaperworks-edit' => __('ha modificato la Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-edit_scan' => __('ha modificato la Pratica di Attingimento scansionata'),
+ 'WaterDrawingPaperworks-delete' => __('ha eliminato la Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-validate_scan' => __('ha verificato la Pratica di Attingimento scansionata'),
+ 'WaterDrawingPaperworks-upload_attachment' => __('ha inserito un allegato sulla Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-upload_attachment_scan' => __('ha inserito un allegato sulla Pratica di Attingimento scansionata'),
+ 'WaterDrawingPaperworks-send_to_validation' => __('ha inviato in validazione la Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-assign' => __('ha assegnato la Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-validate' => __('ha verificato la Pratica di Attingimento'),
+ 'WaterDrawingPaperworks-send_to_drar' => __('ha inviato la Pratica di Attingimento al DRAR'),
+ 'WaterDrawingPaperworks-send_to_gc' => __('ha inviato la Pratica di Attingimento al Genio Civile'),
+ 'WaterDrawingPaperworks-submit_antimafia_request' => __('ha creato la richiesta Antimafia'),
+ 'WaterDrawingPaperworks-antimafia_request_to_anac' => __('ha inviato la richiesta Antimafia all\'ANAC'),
+ 'WaterDrawingPaperworks-request_self_certification' => __('ha richiesto l\'autocertificazione Antimafia'),
+ 'WaterDrawingPaperworks-upload_antimafia_attachment' => __('ha inserito l\'allegato Antimafia'),
+ 'WaterDrawingPayments-add' => __('ha inserito un pagamento sulla Pratica di Attingimento'),
+ 'WaterDrawingPayments-edit' => __('ha aggiornato un pagamento sulla Pratica di Attingimento'),
+ 'WaterDrawingPayments-delete' => __('ha cancellato un pagamento sulla Pratica di Attingimento'),
+ 'WaterDrawingPaperworkPecs-add' => __('ha inserito un documento PEC sulla Pratica di Attingimento'),
+ 'WaterDrawingPaperworkPecs-edit' => __('ha aggiornato un documento PEC sulla Pratica di Attingimento'),
+ 'WaterDrawingPaperworkPecs-delete' => __('ha cancellato un documento PEC sulla Pratica di Attingimento'),
+ 'WaterDrawingDerivations-add' => __('ha inserito un punto di prelievo alla Pratica di Attingimento'),
+ 'WaterDrawingDerivations-edit' => __('ha aggiornato un punto di prelievo alla Pratica di Attingimento'),
+ 'WaterDrawingDerivations-delete' => __('ha cancellato un punto di prelievo alla Pratica di Attingimento'),
+ 'WaterDrawingDerivations-update_location' => __('ha aggiornato la località di un punto di prelievo alla Pratica di Attingimento'),
+ 'WaterDrawingDerivations-update_data' => __('ha aggiornato la portata e il volume di un punto di prelievo alla Pratica di Attingimento'),
+ 'WaterDrawingFees-add' => __('ha inserito un canone alla Pratica di Attingimento'),
+ 'WaterDrawingFees-edit' => __('ha aggiornato un canone alla Pratica di Attingimento'),
+ 'WaterDrawingFees-delete' => __('ha cancellato un canone alla Pratica di Attingimento'),
+ 'WaterDrawingMeters-add' => __('ha inserito uno strumento di misura alla Pratica di Attingimento'),
+ 'WaterDrawingMeters-edit' => __('ha aggiornato un strumento di misura alla Pratica di Attingimento'),
+ 'WaterDrawingMeters-delete' => __('ha cancellato un strumento di misura alla Pratica di Attingimento'),
+ 'WaterDrawingMeasurements-add' => __('ha inserito una misurazione alla Pratica di Attingimento'),
+ 'WaterDrawingMeasurements-delete' => __('ha cancellato una misurazione alla Pratica di Attingimento'),
+ 'WaterDrawingReturnPoints-add' => __('ha inserito un punto di restituzione alla Pratica di Attingimento'),
+ 'WaterDrawingReturnPoints-edit' => __('ha aggiornato un punto di restituzione alla Pratica di Attingimento'),
+ 'WaterDrawingReturnPoints-delete' => __('ha cancellato un punto di restituzione alla Pratica di Attingimento'),
+ ];
+ return $controller_action_descriptions[$controller_action] ?? '';
+ }
+
+ /**
+ * getUnpackedWaterDrawingPaperworkSnapshot
+ *
+ * @param Int $snapshot_id
+ * @return UnpackedWaterDrawingPaperworkSnapshot!Null
+ */
+ public static function getUnpackedWaterDrawingPaperworkSnapshot(Int $snapshot_id): ?UnpackedWaterDrawingPaperworkSnapshot
+ {
+ $co = SnapshotsHandler::getControllableObjectFromSnapshotWithId($snapshot_id);
+ if (!$co) return null;
+
+ $snapshot = TableRegistry::getTableLocator()->get('Snapshots')
+ ->find()
+ ->contain(['Users' => ['Actors', 'Organisations' => ['Actors']]])
+ ->where(['Snapshots.id' => $snapshot_id])
+ ->first();
+
+ if (!$snapshot) return null;
+
+ $unpacked_water_drawing_paperwork_snapshot = [];
+
+ // Inizializzazione valori di base:
+ $unpacked_water_drawing_paperwork_snapshot['snapshot_id'] = $snapshot_id;
+ $unpacked_water_drawing_paperwork_snapshot['unpacking_version'] = SnapshotsHandler::getLastWaterDrawingPaperworkUnpackingVersion();
+ $unpacked_water_drawing_paperwork_snapshot['who'] = $snapshot->user?->name. ' ' . $snapshot->user?->surname;
+ $unpacked_water_drawing_paperwork_snapshot['when'] = isset($snapshot->date) ? new DateTime($snapshot->date->format("Y-m-d H:i:s")) : null;
+ $unpacked_water_drawing_paperwork_snapshot['what'] = SnapshotsHandler::getSnapshotControllerActionDescription($snapshot->controller_action);
+
+ // Inizializzazione valori presi da oggetto 'root' (controllable_object):
+ $creator_organisation = isset($co->creator->organisation->actor->description) ? " (" . $co->creator->organisation->actor->description . ")" : "";
+ $unpacked_water_drawing_paperwork_snapshot['creator'] = $co->creator->name . ' ' . $co->creator->surname . $creator_organisation;
+ $unpacked_water_drawing_paperwork_snapshot['created'] = isset($co->created) ? new DateTime($co->created->format("Y-m-d H:i:s")) : null;
+ $modifier_organisation = isset($co->modifier->organisation->actor->description) ? " (" . $co->modifier->organisation->actor->description . ")" : "";
+ $unpacked_water_drawing_paperwork_snapshot['modifier'] = $co->modifier->name . ' ' . $co->modifier->surname . $modifier_organisation;
+ $unpacked_water_drawing_paperwork_snapshot['modified'] = isset($co->modified) ? new DateTime($co->modified->format("Y-m-d H:i:s")) : null;
+
+ // Inizializzazione valori presi da specializzazione oggetto (water_drawing_paperwork):
+ $unpacked_water_drawing_paperwork_snapshot['water_drawing_paperwork_id'] = $co->water_drawing_paperwork->id;
+ $unpacked_water_drawing_paperwork_snapshot['water_drawing_paperwork_status'] = $co->water_drawing_paperwork->water_drawing_paperwork_status->description;
+ $gc_user_organisation = isset($co->water_drawing_paperwork->gc_user->organisation->actor->description) ? " (" . $co->water_drawing_paperwork->gc_user->organisation->actor->description . ")" : "";
+ $unpacked_water_drawing_paperwork_snapshot['gc_user'] = $co->water_drawing_paperwork->gc_user?->name . ' ' . $co->water_drawing_paperwork->gc_user?->surname . $gc_user_organisation;
+ $drar_user_organisation = isset($co->water_drawing_paperwork->drar_user->organisation->actor->description) ? " (" . $co->water_drawing_paperwork->drar_user->organisation->actor->description . ")" : "";
+ $unpacked_water_drawing_paperwork_snapshot['drar_user'] = $co->water_drawing_paperwork->drar_user?->name . ' ' . $co->water_drawing_paperwork->drar_user?->surname . $drar_user_organisation;
+
+ return TableRegistry::getTableLocator()->get('UnpackedWaterDrawingPaperworkSnapshots')->newEntity($unpacked_water_drawing_paperwork_snapshot);
+ }
+}
diff --git a/idrocap_wa/src/WGS/Utils/Attachments/AttachmentChecker.php b/idrocap_wa/src/WGS/Utils/Attachments/AttachmentChecker.php
new file mode 100644
index 0000000..6efd1d8
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/Attachments/AttachmentChecker.php
@@ -0,0 +1,27 @@
+ 1 ? strtolower($file_name_parts[count($file_name_parts) - 1]) : '';
+ // if (!in_array($file_name_extension, ["txt", "pdf", "jpg", "png"])) throw new \Exception(__('Allegato "{0}" non valido! Estensione file "{1}" non ammessa!', $attachment['name'], $file_name_extension));
+ // if (!in_array(mime_content_type($attachment['tmp_name']), ["text/plain", "application/pdf", "image/jpeg", "image/png"])) throw new \Exception(__('Allegato "{0}" non ammesso! Tipo dichiarato: "{1}", tipo realmente riscontrato: "{2}". Dimensioni: "{3} bytes"', $attachment['name'], $attachment['type'], mime_content_type($attachment['tmp_name']), $attachment['size']));
+ } else {
+ if (!$skip_form_check) throw new \Exception(__('L\'allegato "{0}" non risulta caricato correttamente tramite apposita funzione nel form!', $attachment['name']));
+ }
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/Utils/Attachments/AttachmentConverter.php b/idrocap_wa/src/WGS/Utils/Attachments/AttachmentConverter.php
new file mode 100644
index 0000000..5553c13
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/Attachments/AttachmentConverter.php
@@ -0,0 +1,39 @@
+getError() === 0) {
+ return [
+ 'name' => $attachment->getClientFilename(),
+ 'size' => $attachment->getSize(),
+ 'tmp_name' => $attachment->getStream()->getMetadata('uri'),
+ 'type' => $attachment->getClientMediaType(),
+ 'error' => $attachment->getError(),
+ ];
+ } else {
+ return [
+ 'name' => '',
+ 'size' => '',
+ 'tmp_name' => '',
+ 'type' => '',
+ 'error' => $attachment->getError(),
+ ];
+ }
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/src/WGS/Utils/Attachments/SignedAttachmentChecker.php b/idrocap_wa/src/WGS/Utils/Attachments/SignedAttachmentChecker.php
new file mode 100644
index 0000000..4d03d42
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/Attachments/SignedAttachmentChecker.php
@@ -0,0 +1,133 @@
+ il path del file firmato da controllare
+ * $signer_fiscal_code -----------------------------------> il CF che dovrebbe essere presente nella firma (dentro il certificato)
+ * $signer_description -----------------------------------> descrizione del firmatario in base al contesto
+ * $certificate_expired_if_expires_within_seconds -> il lasso di tempo espresso in secondi entro il quale
+ * il certificato DEVE essere ancora valido per non considerarlo SCADUTO
+ * valore di default 1 ora (86400 seconds)
+ *
+ * @param String $signed_attachment
+ * @param String $signer_fiscal_code
+ * @param String $signer_description
+ * @param String $certificate_expired_if_expires_within_seconds
+ * @return Bool|String
+ */
+ public static function check_cades(String $signed_attachment, String $signer_fiscal_code, String $signer_description, String $certificate_expired_if_expires_within_seconds = '86400'): Bool|String
+ {
+ $command = null;
+ $output = null;
+ $result_code = null;
+
+ // Verifica formale firma:
+ $tmpfname = tempnam(sys_get_temp_dir(), 'signed_file_content_');
+ $command = "openssl cms -verify -noverify -in $signed_attachment -inform DER -out $tmpfname";
+ exec($command, $output, $result_code);
+ unlink($tmpfname);
+ unset($output);
+ if ($result_code) return __('Verifica formale della firma fallita!');
+
+ // Estrazione del certificato PEM allegato al file firmato:
+ $signed_file_certificate = tempnam(sys_get_temp_dir(), 'signed_file_certificate_');
+ $command = "openssl pkcs7 -inform DER -in $signed_attachment -print_certs -out $signed_file_certificate";
+ exec($command, $output, $result_code);
+ unset($output);
+ if ($result_code) {
+ unlink($signed_file_certificate);
+ return __('Impossibile estrarre il certificato dal file firmato!');
+ }
+
+ // Verifica formale del certificato PEM estratto:
+ $command = "openssl x509 -in $signed_file_certificate -noout";
+ exec($command, $output, $result_code);
+ unset($output);
+ if ($result_code) {
+ unlink($signed_file_certificate);
+ return __('Certificato formalmente non valido!');
+ }
+
+ // Verifica se il certificato PEM estratto scadrà entro i prossimi "$certificate_expired_if_expires_within_seconds" secondi:
+ $command = "openssl x509 -in $signed_file_certificate -noout -checkend $certificate_expired_if_expires_within_seconds";
+ exec($command, $output, $result_code);
+ unset($output);
+ if ($result_code) {
+ unlink($signed_file_certificate);
+ $hours = $certificate_expired_if_expires_within_seconds / 3600;
+ return __("Certificato scaduto o in scadenza nelle prossime $hours ore!");
+ }
+
+ // Verifica formale del certificato PEM estratto ed estrazione attributi del firmatario (ultimo subject nella chain!):
+ $command = "awk 'BEGIN {c=0; out=\"\"} /BEGIN CERTIFICATE/ {c++; out=\"\";} {out = out \$0 ORS} /END CERTIFICATE/ {last=out;} END {print last}' $signed_file_certificate | openssl x509 -noout -subject";
+ exec($command, $output, $result_code);
+ if ($result_code) {
+ unlink($signed_file_certificate);
+ return __('Errore durante l\'estrazione delle informazioni del soggetto firmatario dal certificato!');
+ }
+
+ // Estrazione del CODICE FISCALE dal certificato PEM estratto:
+ $certificate_fiscal_code = self::extract_fiscal_code_from_certificate_subject_row($output[0]);
+ if (!$certificate_fiscal_code) {
+ unlink($signed_file_certificate);
+ return __('Errore durante l\'estrazione del Codice Fiscale dal certificato!');
+ }
+
+ // Controlliamo se il CODICE FISCALE preso dal certificato PEM estratto coincide con quello passato:
+ if ($certificate_fiscal_code != $signer_fiscal_code) {
+ unlink($signed_file_certificate);
+ return __("Il Codice Fiscale del firmatario del documento non corrisponde a quello del $signer_description!");
+ }
+
+ // Tutto OK!
+ unlink($signed_file_certificate);
+ return true;
+ }
+
+ /**
+ * extract_certificate_subject_fiscal_code
+ *
+ * @param String $certificate_attributes
+ * @return ?String
+ */
+ private static function extract_fiscal_code_from_certificate_subject_row(String $certificate_subject_row): ?String {
+ // estrazione CF con subject preceduto da "TINIT-":
+ $serial_number_start_index = strpos($certificate_subject_row, "TINIT-");
+ if ($serial_number_start_index !== false) return substr($certificate_subject_row, $serial_number_start_index + 6, 16);
+ // estrazione CF con subject preceduto da "CN=":
+ $serial_number_start_index = strpos($certificate_subject_row, "CN=");
+ if ($serial_number_start_index !== false) return substr($certificate_subject_row, $serial_number_start_index + 3, 16);
+ return null;
+ }
+
+ /**
+ * check_pades
+ *
+ * controlla la firma di un file in formato PAdES
+ *
+ * $signed_attachment -----------------------------> il path del file firmato da controllare
+ * $signer_fiscal_code -----------------------------------> il CF che dovrebbe essere presente nella firma (dentro il certificato)
+ * $signer_description -----------------------------------> descrizione del firmatario in base al contesto
+ * $certificate_expired_if_expires_within_seconds -> il lasso di tempo espresso in secondi entro il quale
+ * il certificato DEVE essere ancora valido per non considerarlo SCADUTO
+ * valore di default 1 ora (86400 seconds)
+ *
+ * @param mixed $signed_attachment
+ * @param mixed $signer_fiscal_code
+ * @param String $signer_description
+ * @param mixed $certificate_expired_if_expires_within_seconds
+ * @return Bool|String
+ */
+ public static function check_pades(String $signed_attachment, String $signer_fiscal_code, String $signer_description, String $certificate_expired_if_expires_within_seconds = '86400'): Bool|String
+ {
+ return true;
+ }
+}
diff --git a/idrocap_wa/src/WGS/Utils/Dto/ProvinceDistrictCellDto/DistrictCellDto.php b/idrocap_wa/src/WGS/Utils/Dto/ProvinceDistrictCellDto/DistrictCellDto.php
new file mode 100644
index 0000000..7c6c5f5
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/Dto/ProvinceDistrictCellDto/DistrictCellDto.php
@@ -0,0 +1,25 @@
+showAlert;
+ }
+
+ public function setShowAlert(bool $showAlert): CitizenRegistrationDTO
+ {
+ $this->showAlert = $showAlert;
+ return $this;
+ }
+
+ public function getFiscalCode(): string
+ {
+ return $this->fiscalCode;
+ }
+
+ public function setFiscalCode(string $fiscalCode): CitizenRegistrationDTO
+ {
+ $this->fiscalCode = $fiscalCode;
+ return $this;
+ }
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ public function setName(string $name): CitizenRegistrationDTO
+ {
+ $this->name = $name;
+ return $this;
+ }
+
+ public function getSurname(): string
+ {
+ return $this->surname;
+ }
+
+ public function setSurname(string $surname): CitizenRegistrationDTO
+ {
+ $this->surname = $surname;
+ return $this;
+ }
+
+ public function getGender(): string
+ {
+ return $this->gender;
+ }
+
+ public function setGender(string $gender): CitizenRegistrationDTO
+ {
+ $this->gender = $gender;
+ return $this;
+ }
+
+ public function getBirthdate(): string
+ {
+ return !empty($this->birthdate) ? new DateTime($this->birthdate)->format('Y-m-d') : '';
+ }
+
+ public function setBirthdate(string $birthdate): CitizenRegistrationDTO
+ {
+ $this->birthdate = $birthdate;
+ return $this;
+ }
+}
diff --git a/idrocap_wa/src/WGS/Utils/Enum/InputFieldType.php b/idrocap_wa/src/WGS/Utils/Enum/InputFieldType.php
new file mode 100644
index 0000000..865db54
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/Enum/InputFieldType.php
@@ -0,0 +1,8 @@
+name, $fullName) === 0) {
+ return "GC " . $case->value;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/idrocap_wa/src/WGS/Utils/Helper/ProvinceDistrictFieldHelper.php b/idrocap_wa/src/WGS/Utils/Helper/ProvinceDistrictFieldHelper.php
new file mode 100644
index 0000000..4239838
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/Helper/ProvinceDistrictFieldHelper.php
@@ -0,0 +1,44 @@
+value;
+ }
+
+ public static function withAlias(string $alias, ProvinceDistrictFields $field): string
+ {
+ return "{$alias}.{$field->value}";
+ }
+
+ public static function forDistricts(ProvinceDistrictFields $field): string
+ {
+ return self::withAlias('Districts', $field);
+ }
+
+ public static function forCounties(ProvinceDistrictFields $field): string
+ {
+ return self::withAlias('Counties', $field);
+ }
+
+ public static function getCodeRegByRegion(Regions $region): int
+ {
+ $regionKey = $region->value;
+ $configMap = Configure::read("App.mapConfig.cod_reg", []);
+
+ if (!isset($configMap[$regionKey])) {
+ throw new Exception("Region '{$regionKey}' not found in AppConfig.");
+ }
+
+ return $configMap[$regionKey];
+ }
+}
diff --git a/idrocap_wa/src/WGS/Utils/RabbitMQSenders/IntendedUseVegetationCheckCommandSender.php b/idrocap_wa/src/WGS/Utils/RabbitMQSenders/IntendedUseVegetationCheckCommandSender.php
new file mode 100644
index 0000000..c1a8a31
--- /dev/null
+++ b/idrocap_wa/src/WGS/Utils/RabbitMQSenders/IntendedUseVegetationCheckCommandSender.php
@@ -0,0 +1,28 @@
+channel();
+ $channel->queue_declare($queue, false, true, false, false);
+ $msg = new AMQPMessage(json_encode($m), ['delivery_mode' => 2]);
+ $channel->basic_publish($msg, '', $queue);
+ $channel->close();
+ $connection->close();
+ }
+}
\ No newline at end of file
diff --git a/idrocap_wa/templates/Applicants/citizen_add.php b/idrocap_wa/templates/Applicants/citizen_add.php
new file mode 100644
index 0000000..ab25410
--- /dev/null
+++ b/idrocap_wa/templates/Applicants/citizen_add.php
@@ -0,0 +1,49 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Creazione Concessionario'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($applicant, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('name', ['label' => __('Nome'), 'type' => 'text', 'disabled' => true, 'value' => $user->name]);
+ echo $this->Form->control('surname', ['label' => __('Cognome'), 'type' => 'text', 'disabled' => true, 'value' => $user->surname]);
+ echo $this->Form->control('tax_code', ['label' => __('Codice fiscale'), 'type' => 'text', 'disabled' => true, 'value' => $user->tax_code]);
+ echo $this->Form->control('company_name', ['label' => __('Ragione sociale'), 'type' => 'text']);
+ echo $this->Form->control('vat_number', ['label' => __('Partita IVA'), 'type' => 'text']);
+ echo $this->Form->control('address', ['label' => __('Indirizzo'), 'type' => 'text', 'required' => true, 'value' => $user->address]);
+ echo $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'required' => true, 'value' => $user->city]);
+ echo $this->Form->control('province', ['label' => __('Provincia'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('pec_address', ['label' => __('Indirizzo PEC'), 'type' => 'text']);
+ echo $this->Form->control('email_address', ['label' => __('Indirizzo email'), 'type' => 'text']);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Applicants/citizen_edit.php b/idrocap_wa/templates/Applicants/citizen_edit.php
new file mode 100644
index 0000000..f63b258
--- /dev/null
+++ b/idrocap_wa/templates/Applicants/citizen_edit.php
@@ -0,0 +1,49 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Creazione Concessionario'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($applicant, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('name', ['label' => __('Nome'), 'type' => 'text', 'disabled' => true]);
+ echo $this->Form->control('surname', ['label' => __('Cognome'), 'type' => 'text', 'disabled' => true]);
+ echo $this->Form->control('tax_code', ['label' => __('Codice fiscale'), 'type' => 'text', 'disabled' => true]);
+ echo $this->Form->control('company_name', ['label' => __('Ragione sociale'), 'type' => 'text']);
+ echo $this->Form->control('vat_number', ['label' => __('Partita IVA'), 'type' => 'text']);
+ echo $this->Form->control('address', ['label' => __('Indirizzo'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('province', ['label' => __('Provincia'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('pec_address', ['label' => __('Indirizzo PEC'), 'type' => 'text']);
+ echo $this->Form->control('email_address', ['label' => __('Indirizzo email'), 'type' => 'text']);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Applicants/citizen_view.php b/idrocap_wa/templates/Applicants/citizen_view.php
new file mode 100644
index 0000000..6376615
--- /dev/null
+++ b/idrocap_wa/templates/Applicants/citizen_view.php
@@ -0,0 +1,63 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Dettagli Concessionario'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($applicant, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('name', ['label' => __('Nome'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('surname', ['label' => __('Cognome'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('tax_code', ['label' => __('Codice fiscale'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('company_name', ['label' => __('Ragione sociale'), 'type' => 'text']);
+ echo $this->Form->control('vat_number', ['label' => __('Partita IVA'), 'type' => 'text']);
+ echo $this->Form->control('address', ['label' => __('Indirizzo'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('province', ['label' => __('Provincia'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('pec_address', ['label' => __('Indirizzo PEC'), 'type' => 'text']);
+ echo $this->Form->control('email_address', ['label' => __('Indirizzo email'), 'type' => 'text']);
+ ?>
+
+ Form->end();
+ ?>
+
+
+
diff --git a/idrocap_wa/templates/Applicants/edit.php b/idrocap_wa/templates/Applicants/edit.php
new file mode 100644
index 0000000..b10c9b5
--- /dev/null
+++ b/idrocap_wa/templates/Applicants/edit.php
@@ -0,0 +1,71 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Modifica Concessionario'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($applicant, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('name', ['label' => __('Nome'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('surname', ['label' => __('Cognome'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('tax_code', ['label' => __('Codice fiscale'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('company_name', ['label' => __('Ragione sociale'), 'type' => 'text']);
+ echo $this->Form->control('vat_number', ['label' => __('Partita IVA'), 'type' => 'text']);
+ echo $this->Form->control('address', ['label' => __('Indirizzo'), 'type' => 'text', 'required' => true]);
+ echo $this->Cell("DistrictProvince", [
+ new ProvinceCellDto(
+ fieldId: 'province',
+ fieldName: 'province',
+ formContext: $applicant ?? null,
+ fieldRequired: true,
+ fieldContainerClass: "mb-3",
+ fieldValue: $applicant->province ?? null,
+ ),
+ new DistrictCellDto(
+ fieldId: 'district',
+ fieldName: 'district',
+ provinceFieldId: "province",
+ fieldRequired: true,
+ fieldContainerClass: "mb-3",
+ fieldValue: $applicant->district ?? null,
+ entity: $applicant ?? null,
+ )
+ ]
+ );
+ echo $this->Form->control('pec_address', ['label' => __('Indirizzo PEC'), 'type' => 'text']);
+ echo $this->Form->control('email_address', ['label' => __('Indirizzo email'), 'type' => 'text']);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Applicants/view.php b/idrocap_wa/templates/Applicants/view.php
new file mode 100644
index 0000000..60a8863
--- /dev/null
+++ b/idrocap_wa/templates/Applicants/view.php
@@ -0,0 +1,72 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Concessionario'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($applicant, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('name', ['label' => __('Nome'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('surname', ['label' => __('Cognome'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('tax_code', ['label' => __('Codice fiscale'), 'type' => 'text', 'required' => true]);
+ echo $this->Form->control('company_name', ['label' => __('Ragione sociale'), 'type' => 'text']);
+ echo $this->Form->control('vat_number', ['label' => __('Partita IVA'), 'type' => 'text']);
+ echo $this->Form->control('address', ['label' => __('Indirizzo'), 'type' => 'text', 'required' => true]);
+ echo $this->Cell("DistrictProvince", [
+ new ProvinceCellDto(
+ fieldId: 'province',
+ fieldName: 'province',
+ formContext: $applicant ?? null,
+ fieldRequired: true,
+ disabled: true,
+ fieldContainerClass: "mb-3",
+ fieldValue: $applicant->province ?? null,
+ ),
+ new DistrictCellDto(
+ fieldId: 'district',
+ fieldName: 'district',
+ fieldRequired: true,
+ disabled: true,
+ fieldContainerClass: "mb-3",
+ fieldValue: $applicant->district ?? null,
+ )
+ ]
+ );
+ echo $this->Form->control('pec_address', ['label' => __('Indirizzo PEC'), 'type' => 'text']);
+ echo $this->Form->control('email_address', ['label' => __('Indirizzo email'), 'type' => 'text']);
+ ?>
+
+ Form->end();
+ ?>
+
+
diff --git a/idrocap_wa/templates/Capabilities/index.php b/idrocap_wa/templates/Capabilities/index.php
new file mode 100644
index 0000000..def20e9
--- /dev/null
+++ b/idrocap_wa/templates/Capabilities/index.php
@@ -0,0 +1,85 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Gestione competenze'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+
+ = $this->Paginator->sort('description',__('Descrizione')) ?>
+ = $this->Paginator->sort('value', __('Codice')) ?>
+ = $this->Paginator->sort('priority', __('Priorità')) ?>
+ = $this->Paginator->sort('CapabilityGroups.description', __('Gruppo')) ?>
+ = __('Azioni') ?>
+
+
+
+
+ is_configurable ? $style .= 'background-color:#bfbddc;' : '';
+ isset($capability->deleted) ? $style .= 'color:red; text-decoration:line-through;' : '';
+ $style .= '"';
+
+ $title = 'title="';
+ !$capability->is_configurable ? $title .= __('Competenza non visibile e non configurabile dai non SYSADMIN') . ' ' : '';
+ isset($capability->deleted) ? $title .= __('Competenza eliminata dal sistema') : '';
+ $title .= '"';
+ ?>
+ = $title ?>>
+ = h($capability->description) ?>
+ = h($capability->value) ?>
+ = h($capability->priority) ?>
+ = h($capability->capability_group->description) ?>
+
+ = $this->Form->postLink($capability->is_configurable ? __('Nascondi') : __('Mostra'), ['action' => $capability->is_configurable ? 'hide' : 'show', $capability->id, '?' => $this->request->getQueryParams()], ['class'=>'btn btn-warning btn-xs']) ?>
+ = $this->Form->postLink(isset($capability->deleted) ? __('Ripristina') : __('Cancella'), ['action' => isset($capability->deleted) ? 'restore' : 'delete', $capability->id, '?' => $this->request->getQueryParams()], ['class'=>'btn btn-danger btn-xs']) ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/ControllableObjects/get_attachments.php b/idrocap_wa/templates/ControllableObjects/get_attachments.php
new file mode 100755
index 0000000..6eb1eb3
--- /dev/null
+++ b/idrocap_wa/templates/ControllableObjects/get_attachments.php
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Paginator->sort('Attachments.private', ' ', ['escape' => false]) ?> = ' ';?>
+
+ = $this->Paginator->sort('Attachments.original_file_name', __('Nome')) ?>
+ = $this->Paginator->sort('Attachments.relevant', ' ', ['escape' => false]) ?>
+ = $this->Paginator->sort('Attachments.original_file_size', __('Dimensione')) ?>
+ = $this->Paginator->sort('Attachments.mimetype', __('Tipo')) ?>
+ = $this->Paginator->sort('Attachments.upload_date', __('Caricato il')) ?>
+ = $this->Paginator->sort('Creator.surname', __('Da')) ?>
+ = __('Azioni') ?>
+
+
+
+ controllable_object->modified))->wasWithinLast('5 minutes') ? "font-weight: bold;background-color:#f8d716" : "";
+ ?>
+
+ ';
+ if($attachment->private)
+ {
+ $htmlCode = ' ';
+ }
+ ?>
+ = $htmlCode ?> = $htmlCode;?>
+
+ = h($attachment->original_file_name) ?>
+ = $attachment->relevant ? ' ' : '' ?>
+ = h($attachment->human_original_file_size) ?>
+ = h($attachment->mimetype) ?>
+ = h($attachment->upload_date) ?>
+ = h($attachment->controllable_object->creator) ?>
+
+ Html->link(__('Visualizza'), ['controller' => 'attachments', 'action' => 'view', $attachment->file_name], ['target' => '_blank', 'class' => 'btn btn-info btn-xs', 'style' => 'margin-right: 5px;', 'data-mimetype' => $attachment->mimetype]);
+ if (isset($removecurrentfiles) && $removecurrentfiles == "true") {
+ echo $this->Html->link(__('Segna da eliminare'), ['controller' => 'attachments', 'action' => 'markAsDeleted', $attachment->controllable_object_id], ['target' => '_blank', 'class' => 'btn btn-danger btn-xs', 'style' => 'margin-right: 5px;']);
+ } else {
+ echo $this->Html->link($attachment->relevant ? __('Segna come non rilevante') : __('Segna come rilevante'), ['controller' => 'attachments', 'action' => 'markAsRelevant', $attachment->file_name], ['id' => $attachment->controllable_object_id, 'target' => '_blank', 'class' => 'btn btn-warning btn-xs', 'style' => 'margin-right: 5px;']);
+ }
+ ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/Dashboard/index.php b/idrocap_wa/templates/Dashboard/index.php
new file mode 100644
index 0000000..6b392db
--- /dev/null
+++ b/idrocap_wa/templates/Dashboard/index.php
@@ -0,0 +1,32 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ ],
+ ]);
+?>
+
+
+
+ Cell('Map', [
+ [-1, -5], // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ null, // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]);
+ ?>
+
+
+
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/Deliveries/index.php b/idrocap_wa/templates/Deliveries/index.php
new file mode 100644
index 0000000..7a45ddb
--- /dev/null
+++ b/idrocap_wa/templates/Deliveries/index.php
@@ -0,0 +1,284 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+
+
+
+ = __('Descrizione') ?>
+ = __('Cellulare') ?>
+ = __('Ricevi notifiche a questo recapito') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($mobile_phone->mobile_phone_description->description) ?>
+ = h($mobile_phone->value) ?>
+ = $mobile_phone->enable_notifications ? __('SI') : __('NO') ?>
+
+ = $can_edit_mobile_phone ? $this->Html->link(__('Modifica'), ['controller' => 'MobilePhones', 'action' => 'edit', $mobile_phone->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $can_delete_mobile_phone ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $mobile_phone->delivery_id], ['confirm' => __('Sei sicuro che vuoi cancellare il Cellulare "{0}" ?', $mobile_phone->value), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Descrizione') ?>
+ = __('Fax') ?>
+ = __('Ricevi notifiche a questo recapito') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($fax->fax_description->description) ?>
+ = h($fax->value) ?>
+ = $fax->enable_notifications ? __('SI') : __('NO') ?>
+
+ = $can_edit_fax ? $this->Html->link(__('Modifica'), ['controller' => 'Faxes', 'action' => 'edit', $fax->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $can_delete_fax ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $fax->delivery_id], ['confirm' => __('Sei sicuro che vuoi cancellare il Fax "{0}" ?', $fax->value), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Descrizione') ?>
+ = __('Email') ?>
+ = __('Ricevi notifiche a questo recapito') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($email->email_description->description) ?>
+ = h($email->value) ?>
+ = $email->enable_notifications ? __('SI') : __('NO') ?>
+
+ = $can_edit_email ? $this->Html->link(__('Modifica'), ['controller' => 'Emails', 'action' => 'edit', $email->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $can_delete_email ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $email->delivery_id], ['confirm' => __('Sei sicuro che vuoi cancellare l\'Email "{0}" ?', $email->value), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Descrizione') ?>
+ = __('Telefono') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($phone->phone_description->description) ?>
+ = h($phone->value) ?>
+
+ = $can_edit_phone ? $this->Html->link(__('Modifica'), ['controller' => 'Phones', 'action' => 'edit', $phone->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $can_delete_phone ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $phone->delivery_id], ['confirm' => __('Sei sicuro che vuoi cancellare il Telefono "{0}" ?', $phone->value), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('ID') ?>
+ = __('Ricevi notifiche a questo recapito') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($telegram_chat->value) ?>
+ = $telegram_chat->enable_notifications ? __('SI') : __('NO') ?>
+
+ = $can_edit_telegram_chat ? $this->Html->link(__('Modifica'), ['controller' => 'TelegramChats', 'action' => 'edit', $telegram_chat->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $can_delete_telegram_chat ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $telegram_chat->delivery_id], ['confirm' => __('Sei sicuro che vuoi cancellare la Chat Telegram con ID "{0}" ?', $telegram_chat->value), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Descrizione') ?>
+ = __('PEC') ?>
+ = __('Ricevi notifiche a questo recapito') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($pec->pec_description->description) ?>
+ = h($pec->value) ?>
+ = $pec->enable_notifications ? __('SI') : __('NO') ?>
+
+ = $can_edit_pec ? $this->Html->link(__('Modifica'), ['controller' => 'Pecs', 'action' => 'edit', $pec->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $can_delete_pec ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $pec->delivery_id], ['confirm' => __('Sei sicuro che vuoi cancellare la PEC "{0}" ?', $pec->value), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/Emails/add.php b/idrocap_wa/templates/Emails/add.php
new file mode 100644
index 0000000..a0c6040
--- /dev/null
+++ b/idrocap_wa/templates/Emails/add.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Aggiungi Email'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($email, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Email')]);
+ echo $this->Form->control('email_description_id', ['label' => __('Descrizione'), 'options' => $emailDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Emails/edit.php b/idrocap_wa/templates/Emails/edit.php
new file mode 100644
index 0000000..a3cc434
--- /dev/null
+++ b/idrocap_wa/templates/Emails/edit.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Modifica Email'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($email, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Email')]);
+ echo $this->Form->control('email_description_id', ['label' => __('Descrizione'), 'options' => $emailDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Error/error400.php b/idrocap_wa/templates/Error/error400.php
new file mode 100644
index 0000000..eeaa6f9
--- /dev/null
+++ b/idrocap_wa/templates/Error/error400.php
@@ -0,0 +1,49 @@
+layout = 'default';
+
+if (Configure::read('debug')) :
+ $this->layout = 'dev_error';
+
+ $this->assign('title', $message);
+ $this->assign('templateName', 'error400.php');
+
+ $this->start('file');
+?>
+queryString)) : ?>
+
+ SQL Query:
+ = h($error->queryString) ?>
+
+
+params)) : ?>
+ SQL Query Params:
+ params) ?>
+
+= $this->element('auto_table_warning') ?>
+end();
+endif;
+?>
+
+
+
+
+
+
+
+
+= Configure::read('Theme.title') ?>
+= __('L\'indirizzo o la risorsa associata a {0} ha generato il seguente errore:', "'{$url}' ") ?>
+= h($message) ?>
+
+= $this->Html->link(__('Torna indietro'), 'javascript:history.back()') ?>
diff --git a/idrocap_wa/templates/Error/error500.php b/idrocap_wa/templates/Error/error500.php
new file mode 100644
index 0000000..8f52f47
--- /dev/null
+++ b/idrocap_wa/templates/Error/error500.php
@@ -0,0 +1,53 @@
+layout = 'default';
+
+if (Configure::read('debug')) :
+ $this->layout = 'dev_error';
+
+ $this->assign('title', $message);
+ $this->assign('templateName', 'error500.php');
+
+ $this->start('file');
+?>
+queryString)) : ?>
+
+ SQL Query:
+ = h($error->queryString) ?>
+
+
+params)) : ?>
+ SQL Query Params:
+ params) ?>
+
+
+ Error in:
+ = sprintf('%s, line %s', str_replace(ROOT, 'ROOT', $error->getFile()), $error->getLine()) ?>
+
+element('auto_table_warning');
+
+ $this->end();
+endif;
+?>
+
+
+
+
+
+
+
+
+= Configure::read('Theme.title') ?>
+= __('Si è verificato un errore interno alla richiesta con url: {0}. Per favore riprovare.', "'{$url}' ") ?>
+= __('Se l\'errore persiste, per favore contattare l\'assistenza via mail all\'indirizzo "{0}" o chiamando il numero "{1}"', Configure::read('App.manufacturer_email'), Configure::read('App.manufacturer_number')) ?>
+
+= $this->Html->link(__('Torna indietro'), 'javascript:history.back()') ?>
diff --git a/idrocap_wa/templates/Faxes/add.php b/idrocap_wa/templates/Faxes/add.php
new file mode 100644
index 0000000..cb3250e
--- /dev/null
+++ b/idrocap_wa/templates/Faxes/add.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Aggiungi Fax'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($fax, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Fax')]);
+ echo $this->Form->control('fax_description_id', ['label' => __('Descrizione'), 'options' => $faxDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Faxes/edit.php b/idrocap_wa/templates/Faxes/edit.php
new file mode 100644
index 0000000..8a37561
--- /dev/null
+++ b/idrocap_wa/templates/Faxes/edit.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Modifica Fax'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($fax, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Fax')]);
+ echo $this->Form->control('fax_description_id', ['label' => __('Descrizione'), 'options' => $faxDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Filters/get_filter_input.php b/idrocap_wa/templates/Filters/get_filter_input.php
new file mode 100644
index 0000000..b159ed8
--- /dev/null
+++ b/idrocap_wa/templates/Filters/get_filter_input.php
@@ -0,0 +1 @@
+= $this->Cell('FilterInput', [$filter_id]) ?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/Groups/add.php b/idrocap_wa/templates/Groups/add.php
new file mode 100644
index 0000000..c385218
--- /dev/null
+++ b/idrocap_wa/templates/Groups/add.php
@@ -0,0 +1,61 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei Profili Utente'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'groups', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Nuovo Profilo Utente'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($group, ['role' => 'form']); ?>
+
+ Form->control('description', ['label' => __('Descrizione')]);
+ echo $this->Form->control('is_default', ['label' => __('Profilo Default')]);
+ echo $this->Form->control('child_groups._ids', ['label' => __('Profili associati'), 'options' => $child_groups, 'multiple' => true, 'style="width: 100%']);
+ ?>
+
+
+ Form->end(); ?>
+
+
+
+
diff --git a/idrocap_wa/templates/Groups/edit.php b/idrocap_wa/templates/Groups/edit.php
new file mode 100644
index 0000000..a3fe706
--- /dev/null
+++ b/idrocap_wa/templates/Groups/edit.php
@@ -0,0 +1,66 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei Profili Utente'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'groups', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Profilo Utente'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'groups', 'action' => 'view', $group->id],
+ ],
+ [
+ 'title' => __('Modifica Profilo Utente'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($group, ['role' => 'form']); ?>
+
+ Form->control('description', ['label' => __('Descrizione')]);
+ echo $this->Form->control('is_default', ['label' => __('Profilo Default')]);
+ echo $this->Form->control('child_groups._ids', ['label' => __('Profili associati'), 'options' => $child_groups, 'multiple' => true, 'style="width: 100%']);
+ ?>
+
+
+ Form->end(); ?>
+
+
+
+
diff --git a/idrocap_wa/templates/Groups/handle_capabilities.php b/idrocap_wa/templates/Groups/handle_capabilities.php
new file mode 100644
index 0000000..9f87622
--- /dev/null
+++ b/idrocap_wa/templates/Groups/handle_capabilities.php
@@ -0,0 +1,75 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei Profili Utente'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'groups', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Profilo Utente'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'groups', 'action' => 'view', $group->id],
+ ],
+ [
+ 'title' => __('Gestione competenze'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+
+ Form->create($group, ['role' => 'form']); ?>
+
+ Form->control('description', ['type' => 'hidden']);
+ ?>
+
+
+ capabilities) > 0): ?>
+
+
description); ?>
+
+
+ capabilities as $capability): ?>
+ id; ?>
+
+ is_configurable ? 'style="background-color:#bfbddc;" title="' . __('Competenza non visibile e non configurabile dai non SYSADMIN') . '"' : '' ?>>= $capability->priority == 1 ? $this->Form->control('capabilities._ids[]', ['id' => "capability-id-$capability_id", 'value' => $capability->id, 'label' => $capability->description . (isset($capability->longdescription) ? ' (' . $capability->longdescription . ')' : ''), 'type' => 'checkbox', 'required' => false, 'checked' => in_array($capability->id, $group_capability_ids)]) : '' ?>
+ is_configurable ? 'style="background-color:#bfbddc;" title="' . __('Competenza non visibile e non configurabile dai non SYSADMIN') . '"' : '' ?>>= $capability->priority == 2 ? $this->Form->control('capabilities._ids[]', ['id' => "capability-id-$capability_id", 'value' => $capability->id, 'label' => $capability->description . (isset($capability->longdescription) ? ' (' . $capability->longdescription . ')' : ''), 'type' => 'checkbox', 'required' => false, 'checked' => in_array($capability->id, $group_capability_ids)]) : '' ?>
+ is_configurable ? 'style="background-color:#bfbddc;" title="' . __('Competenza non visibile e non configurabile dai non SYSADMIN') . '"' : '' ?>>= $capability->priority == 3 ? $this->Form->control('capabilities._ids[]', ['id' => "capability-id-$capability_id", 'value' => $capability->id, 'label' => $capability->description . (isset($capability->longdescription) ? ' (' . $capability->longdescription . ')' : ''), 'type' => 'checkbox', 'required' => false, 'checked' => in_array($capability->id, $group_capability_ids)]) : '' ?>
+
+
+
+
+
+
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Groups/index.php b/idrocap_wa/templates/Groups/index.php
new file mode 100644
index 0000000..2bc379f
--- /dev/null
+++ b/idrocap_wa/templates/Groups/index.php
@@ -0,0 +1,63 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei Profili Utente'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('description',__('Descrizione')) ?>
+ = $this->Paginator->sort('is_default', __('Profilo Default')) ?>
+ = __('Profili Associati') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($group->description) ?>
+ = $group->is_default ? __('SI') : __('NO') ?>
+ = $group->child_groups_csv ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'view', $group->id], ['class'=>'btn btn-info btn-xs']) ?>
+ = $group->can_edit ? $this->Html->link(__('Modifica'), ['action' => 'edit', $group->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $group->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $group->id], ['confirm' => __('Sei sicuro che vuoi cancellare il profilo "{0}" ?', $group->description), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/Groups/view.php b/idrocap_wa/templates/Groups/view.php
new file mode 100644
index 0000000..90a714e
--- /dev/null
+++ b/idrocap_wa/templates/Groups/view.php
@@ -0,0 +1,45 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei Profili Utente'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'groups', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Profilo Utente'),
+ 'icon' => 'fa fa-info',
+ ],
+ ]);
+?>
+
+
+
+
+
+ = __('Descrizione') ?>
+ = h($group->description) ?>
+ = __('Profilo Default') ?>
+ = $group->is_default ? __('SI') : __('NO') ?>
+ = __('Profili Associati') ?>
+ = $group->child_groups_csv ?>
+
+
+
+
diff --git a/idrocap_wa/templates/Maps/index.php b/idrocap_wa/templates/Maps/index.php
new file mode 100644
index 0000000..3cc1f79
--- /dev/null
+++ b/idrocap_wa/templates/Maps/index.php
@@ -0,0 +1,149 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => 'Mappe',
+ 'icon' => 'fa fa-map',
+ ],
+ ]);
+?>
+
+
+
+
+ Form->control('feature_collection', ['type' => 'text', 'readonly' => true, 'label' => __('Campo esistente appartenente al form ospite'), 'id' => 'feature-collection-custom1', 'value' => '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[14.379508819839112,37.75776939310461],[15.079779119829889,37.74925139070119],[14.74580405368044,37.227801841878815],[14.379508819839112,37.75776939310461]]]},"properties":null},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[13.302169896776373,37.83438727544886],[13.33565484759548,37.8721796404016],[13.359158669099903,37.9143809499671],[13.371778122610326,37.95936327940137],[13.373028249605412,38.00539445333166],[13.362861008405815,38.0507051513184],[13.341667120388989,38.09355695996422],[13.310261054785746,38.13230874682358],[13.269849729084495,38.165478870642175],[13.221986127869002,38.19180096750125],[13.168509622491761,38.21027134460931],[13.111475285064454,38.220186354514],[13.053074913189183,38.221168496367],[12.995552800405811,38.213180384842815],[12.941119489249829,38.19652613223133],[12.89186682134241,38.17184009894592],[12.849687549090019,38.140063377845536],[12.816202598270912,38.10240878417548],[12.792698776766489,38.06031551994914],[12.780079323256066,38.01539506079607],[12.77882919626098,37.96937016275294],[12.788996437460577,37.924009190796056],[12.810190325477404,37.881058212202475],[12.841596391080646,37.84217345733417],[12.8820077167819,37.80885681076607],[12.92987131799739,37.782396943193774],[12.983347823374631,37.76381852162746],[13.040382160801938,37.75384164211793],[13.098782532677207,37.75285322445332],[13.156304645460581,37.76089160937822],[13.210737956616564,37.77764503105661],[13.259990624523983,37.80246403167463],[13.302169896776373,37.83438727544886]]]},"properties":null},{"type":"Feature","geometry":{"type":"Point","coordinates":[14.00244019676715,37.71516957586901]},"properties":null}]}']);
+
+ echo $this->Cell('Map', [
+ [-1], // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Evento'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => true, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => true, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => true, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => true, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'feature_collection' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'feature-collection-custom1',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'feature_collection_custom1',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Collezione di geometrie'),
+ ],
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude-custom2',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude_custom2',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Longitudine'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude-custom3',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude_custom3',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Latitudine'),
+ ],
+ 'coordinates' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'coordinates-custom4',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'coordinates_custom4',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinate (Longitudine Latitudine)'),
+ ],
+ 'cap' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'cap',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'cap',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Cap'),
+ ],
+ 'province' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'province',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'province',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Provincia'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ 'address' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'address',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'address',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Indirizzo'),
+ ],
+ 'description' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'description',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'description',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Descrizione luogo'),
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]);
+ ?>
+
+
+
diff --git a/idrocap_wa/templates/MobilePhones/add.php b/idrocap_wa/templates/MobilePhones/add.php
new file mode 100644
index 0000000..5bc4fb9
--- /dev/null
+++ b/idrocap_wa/templates/MobilePhones/add.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Aggiungi Cellulare'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($mobilePhone, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Cellulare')]);
+ echo $this->Form->control('mobile_phone_description_id', ['label' => __('Descrizione'), 'options' => $mobilePhoneDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/MobilePhones/edit.php b/idrocap_wa/templates/MobilePhones/edit.php
new file mode 100644
index 0000000..2496d6c
--- /dev/null
+++ b/idrocap_wa/templates/MobilePhones/edit.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Modifica Cellulare'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($mobilePhone, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Cellulare')]);
+ echo $this->Form->control('mobile_phone_description_id', ['label' => __('Descrizione'), 'options' => $mobilePhoneDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Notifications/index.php b/idrocap_wa/templates/Notifications/index.php
new file mode 100644
index 0000000..601379c
--- /dev/null
+++ b/idrocap_wa/templates/Notifications/index.php
@@ -0,0 +1,4 @@
+= $this->Notifications->create($user_notifications) ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/Notifications/read_all.php b/idrocap_wa/templates/Notifications/read_all.php
new file mode 100644
index 0000000..af458c8
--- /dev/null
+++ b/idrocap_wa/templates/Notifications/read_all.php
@@ -0,0 +1,5 @@
+= $this->Notifications->create($user_notifications) ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/Organisations/add.php b/idrocap_wa/templates/Organisations/add.php
new file mode 100644
index 0000000..55f90e8
--- /dev/null
+++ b/idrocap_wa/templates/Organisations/add.php
@@ -0,0 +1,197 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Organizzazioni'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'organisations', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Nuova Organizzazione'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($organisation, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Form->control('actor.description', ['label' => __('Nome')]); ?>
+
+
+ = $this->Form->control('acronym', ['label' => __('Acronimo')]); ?>
+
+
+ = $this->Form->control('organisation_type_id', ['label' => __('Tipo organizzazione'), 'style="width: 100%']); ?>
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Organizzazione'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => true, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => true, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => true, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'feature_collection' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => true, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => true, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'feature-collection',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'feature_collection',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => null,
+ ],
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => true, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Longitudine'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => true, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Latitudine'),
+ ],
+ 'coordinates' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'coordinates',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'coordinates',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinate (Longitudine Latitudine)'),
+ ],
+ 'cap' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'cap',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'cap',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Cap'),
+ ],
+ 'province' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'province',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'province',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Provincia'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ 'address' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'address',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'address',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Indirizzo'),
+ ],
+ 'description' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'description',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'description',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Descrizione luogo'),
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]);
+ ?>
+
+
+ = $this->Form->control('coordinates', ['label' => __('Coordinate (Longitudine Latitudine)'), 'type' => 'text', 'readonly' => true]); ?>
+
+
+ = $this->Form->control('address', ['label' => __('Indirizzo')]); ?>
+
+
+ = $this->Form->control('cap', ['label' => __('CAP')]); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune')]); ?>
+
+
+ = $this->Form->control('province', ['label' => __('Provincia')]); ?>
+
+
+ = $this->element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'accept_only' => ['.pdf'],
+ 'upload_single' => true,
+ ]); ?>
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/Organisations/edit.php b/idrocap_wa/templates/Organisations/edit.php
new file mode 100644
index 0000000..1e94bb6
--- /dev/null
+++ b/idrocap_wa/templates/Organisations/edit.php
@@ -0,0 +1,118 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Organizzazioni'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'organisations', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Organizzazione'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'organisations', 'action' => 'view', $organisation->id],
+ ],
+ [
+ 'title' => __('Modifica Organizzazione'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ = $this->Form->create($organisation, ['role' => 'form', 'type' => 'file']) ?>
+
+
+
+ = $this->Form->control('actor.description', ['label' => __('Nome')]); ?>
+
+
+ = $this->Form->control('acronym', ['label' => __('Acronimo')]); ?>
+
+
+ = $this->Form->control('organisation_type_id', ['label' => __('Tipo organizzazione'), 'style="width: 100%']); ?>
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Organizzazione'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => true, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => true, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => true, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]);
+ ?>
+
+
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('coordinates', ['label' => __('Coordinate (Longitudine Latitudine)'), 'type' => 'text', 'readonly' => true]); ?>
+
+
+ = $this->Form->control('address', ['label' => __('Indirizzo')]); ?>
+
+
+ = $this->Form->control('cap', ['label' => __('CAP')]); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune')]); ?>
+
+
+ = $this->Form->control('province', ['label' => __('Provincia')]); ?>
+
+
+
+ controllable_object_interface)) {
+ $attachment_options = [
+ 'filepicker' => true,
+ 'coId' => $organisation->controllable_object_interface->controllable_object_id,
+ 'viewer' => true,
+ 'currentFilesRemovable' => true,
+ 'view_in_frame_with_id' => false,
+ 'accept_only' => ['.pdf'],
+ 'upload_single' => true,
+ ];
+ } else {
+ $attachment_options = [
+ 'filepicker' => true,
+ 'accept_only' => ['.pdf'],
+ 'upload_single' => true,
+ ];
+ }
+ echo $this->element('attachments', $attachment_options);
+ ?>
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/Organisations/index.php b/idrocap_wa/templates/Organisations/index.php
new file mode 100644
index 0000000..bdd562c
--- /dev/null
+++ b/idrocap_wa/templates/Organisations/index.php
@@ -0,0 +1,75 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Organizzazioni'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('Actors.description', __('Descrizione')) ?>
+ = $this->Paginator->sort('acronym', __('Acronimo')) ?>
+ = $this->Paginator->sort('OrganisationTypes.description', __('Tipologia')) ?>
+ = $this->Paginator->sort('address', __('Indirizzo')) ?>
+ = $this->Paginator->sort('cap', __('CAP')) ?>
+ = $this->Paginator->sort('district', __('Comune')) ?>
+ = $this->Paginator->sort('province', __('Provincia')) ?>
+ = __('Recapiti') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($organisation->actor->description) ?>
+ = h($organisation->acronym) ?>
+ = h($organisation->organisation_type->description) ?>
+ = h($organisation->address) ?>
+ = h($organisation->cap) ?>
+ = h($organisation->district) ?>
+ = h($organisation->province) ?>
+ = h($organisation->actor->contacts) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'view', $organisation->id], ['class'=>'btn btn-info btn-xs']) ?>
+ = $organisation->can_edit ? $this->Html->link(__('Modifica'), ['action' => 'edit', $organisation->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $organisation->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $organisation->id], ['confirm' => __('Sei sicuro che vuoi cancellare l\'organizzazione "{0}" ?', $organisation->actor->description), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/Organisations/view.php b/idrocap_wa/templates/Organisations/view.php
new file mode 100644
index 0000000..badad7b
--- /dev/null
+++ b/idrocap_wa/templates/Organisations/view.php
@@ -0,0 +1,99 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Organizzazioni'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'organisations', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Organizzazione'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ = $this->Form->create($organisation, ['role' => 'form', 'type' => 'file']) ?>
+
+
+
+ = $this->Form->control('actor.description', ['label' => __('Nome')]); ?>
+
+
+ = $this->Form->control('acronym', ['label' => __('Acronimo')]); ?>
+
+
+ = $this->Form->control('organisation_type_id', ['label' => __('Tipo organizzazione'), 'style="width: 100%', 'disabled' => true]); ?>
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Organizzazione'),
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+
+
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('coordinates', ['label' => __('Coordinate (Longitudine Latitudine)'), 'type' => 'text']); ?>
+
+
+ = $this->Form->control('address', ['label' => __('Indirizzo')]); ?>
+
+
+ = $this->Form->control('cap', ['label' => __('CAP')]); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune')]); ?>
+
+
+ = $this->Form->control('province', ['label' => __('Provincia')]); ?>
+
+
+ = $this->Form->control('deliveries', ['label' => __('Recapiti'), 'type' => 'text', 'value' => $organisation->actor->contacts]); ?>
+
+
+ controllable_object_interface)) {
+ echo $this->element('attachments', [
+ 'coId' => $organisation->controllable_object_interface->controllable_object_id,
+ 'viewer' => true
+ ]);
+ }
+ ?>
+
+
+ Form->end(); ?>
+
+
+
+
+
diff --git a/idrocap_wa/templates/Pecs/add.php b/idrocap_wa/templates/Pecs/add.php
new file mode 100644
index 0000000..d6c8b45
--- /dev/null
+++ b/idrocap_wa/templates/Pecs/add.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Aggiungi PEC'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($pec, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('PEC')]);
+ echo $this->Form->control('pec_description_id', ['label' => __('Descrizione'), 'options' => $pecDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Pecs/edit.php b/idrocap_wa/templates/Pecs/edit.php
new file mode 100644
index 0000000..3bac119
--- /dev/null
+++ b/idrocap_wa/templates/Pecs/edit.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Modifica PEC'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($pec, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('PEC')]);
+ echo $this->Form->control('pec_description_id', ['label' => __('Descrizione'), 'options' => $pecDescriptions, 'empty' => false]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Phones/add.php b/idrocap_wa/templates/Phones/add.php
new file mode 100644
index 0000000..d5c6e02
--- /dev/null
+++ b/idrocap_wa/templates/Phones/add.php
@@ -0,0 +1,53 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Aggiungi Telefono'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($phone, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Telefono')]);
+ echo $this->Form->control('phone_description_id', ['label' => __('Descrizione'), 'options' => $phoneDescriptions, 'empty' => false]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Phones/edit.php b/idrocap_wa/templates/Phones/edit.php
new file mode 100644
index 0000000..b346733
--- /dev/null
+++ b/idrocap_wa/templates/Phones/edit.php
@@ -0,0 +1,53 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Modifica Telefono'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($phone, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Telefono')]);
+ echo $this->Form->control('phone_description_id', ['label' => __('Descrizione'), 'options' => $phoneDescriptions, 'empty' => false]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Privacy/accept_privacy.php b/idrocap_wa/templates/Privacy/accept_privacy.php
new file mode 100644
index 0000000..c1ba8d1
--- /dev/null
+++ b/idrocap_wa/templates/Privacy/accept_privacy.php
@@ -0,0 +1,29 @@
+= $this->Breadcrumb->render($breadcrumbs); ?>
+
+
+
+ = $this->Form->create($privacy, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->input('description', ['type' => 'textarea', 'id' => 'description']); ?>
+
+
+
+
+ = $this->Form->end(); ?>
+
+
+= $this->Html->script(['/js/tinymce/tinymce.min.js']) ?>
+= $this->Html->script(['/js/init_tiny_mce.js']) ?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/Privacy/edit.php b/idrocap_wa/templates/Privacy/edit.php
new file mode 100644
index 0000000..8ff3081
--- /dev/null
+++ b/idrocap_wa/templates/Privacy/edit.php
@@ -0,0 +1,24 @@
+= $this->Breadcrumb->render($breadcrumbs); ?>
+
+
+
+ = $this->Form->create($privacy, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->input('description', ['type' => 'textarea', 'id' => 'description']); ?>
+
+
+
+
+ = $this->Form->end(); ?>
+
+
+= $this->Html->script(['/js/tinymce/tinymce.min.js']) ?>
+= $this->Html->script(['/js/init_tiny_mce.js']) ?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/Privacy/view.php b/idrocap_wa/templates/Privacy/view.php
new file mode 100644
index 0000000..7b723a7
--- /dev/null
+++ b/idrocap_wa/templates/Privacy/view.php
@@ -0,0 +1,19 @@
+= $this->Breadcrumb->render($breadcrumbs); ?>
+
+
+
+ = $this->Form->create($privacy, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->input('description', ['type' => 'textarea', 'id' => 'description']); ?>
+
+
+
+ = $this->Form->end(); ?>
+
+
+= $this->Html->script(['/js/tinymce/tinymce.min.js']) ?>
+= $this->Html->script(['/js/init_tiny_mce.js']) ?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/Privacy/view_public.php b/idrocap_wa/templates/Privacy/view_public.php
new file mode 100644
index 0000000..bc7b4c0
--- /dev/null
+++ b/idrocap_wa/templates/Privacy/view_public.php
@@ -0,0 +1,10 @@
+= $this->Form->create($privacy, ['role' => 'form']); ?>
+
+
+ = isset($privacy->description) ? $this->Form->input('description', ['type' => 'textarea', 'id' => 'description']) : ''; ?>
+
+
+= $this->Form->end(); ?>
+
+= $this->Html->script(['/js/tinymce/tinymce.min.js']) ?>
+= $this->Html->script(['/js/init_tiny_mce.js']) ?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/Tags/add.php b/idrocap_wa/templates/Tags/add.php
new file mode 100644
index 0000000..87514ef
--- /dev/null
+++ b/idrocap_wa/templates/Tags/add.php
@@ -0,0 +1,54 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei tags'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['action' => 'index'],
+ ],
+ [
+ 'title' => __('Crea tag'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($tag, ['role' => 'form', 'type' => 'file', 'id' => 'editTag']); ?>
+
+
+
+ = $this->Form->control('description', ['label' => __('Descrizione')]); ?>
+
+
+ = $this->Form->control('code', ['label' => __('Codice')]); ?>
+
+
+ = $this->element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'required' => true,
+ 'upload_single' => true,
+ ]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Tags/edit.php b/idrocap_wa/templates/Tags/edit.php
new file mode 100644
index 0000000..73f5144
--- /dev/null
+++ b/idrocap_wa/templates/Tags/edit.php
@@ -0,0 +1,55 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei tags'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['action' => 'index'],
+ ],
+ [
+ 'title' => __('Modifica tag'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($tag, ['role' => 'form', 'type' => 'file', 'id' => 'editTag']); ?>
+
+
+
+ = $this->Form->control('description', ['label' => __('Descrizione')]); ?>
+
+
+ = $this->Form->control('code', ['label' => __('Codice')]); ?>
+
+
+ = $this->element('attachments', [
+ 'coId' => isset($tag->controllable_object_id) ? $tag->controllable_object_id : null,
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'required' => false,
+ 'upload_single' => true,
+ ]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Tags/index.php b/idrocap_wa/templates/Tags/index.php
new file mode 100644
index 0000000..cd61756
--- /dev/null
+++ b/idrocap_wa/templates/Tags/index.php
@@ -0,0 +1,63 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista degli tags'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('id',__('Id')) ?>
+ = $this->Paginator->sort('description', __('Descrizione')) ?>
+ = $this->Paginator->sort('code', __('Codice')) ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($tag->id) ?>
+ = h($tag->description) ?>
+ = h($tag->code) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'view', $tag->id], ['class'=>'btn btn-info btn-xs']) ?>
+ = $tag->can_edit ? $this->Html->link(__('Modifica'), ['action' => 'edit', $tag->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/Tags/view.php b/idrocap_wa/templates/Tags/view.php
new file mode 100644
index 0000000..23b79de
--- /dev/null
+++ b/idrocap_wa/templates/Tags/view.php
@@ -0,0 +1,52 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista dei tags'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio tag'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($tag, ['role' => 'form', 'type' => 'file', 'id' => 'editTag']); ?>
+
+
+
+ = $this->Form->control('description', ['label' => __('Descrizione'), 'disabled' => true]); ?>
+
+
+ = $this->Form->control('code', ['label' => __('Codice'), 'disabled' => true]); ?>
+
+
+ = $this->element('attachments', [
+ 'coId' => $tag->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ ]); ?>
+
+
+
+ Form->end(); ?>
+
+
diff --git a/idrocap_wa/templates/TelegramChats/add.php b/idrocap_wa/templates/TelegramChats/add.php
new file mode 100644
index 0000000..6ebc23d
--- /dev/null
+++ b/idrocap_wa/templates/TelegramChats/add.php
@@ -0,0 +1,53 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Aggiungi Chat Telegram'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($telegram_chat, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Chat Telegram ID')]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/TelegramChats/edit.php b/idrocap_wa/templates/TelegramChats/edit.php
new file mode 100644
index 0000000..f5bdb3d
--- /dev/null
+++ b/idrocap_wa/templates/TelegramChats/edit.php
@@ -0,0 +1,53 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista {0}', $actor->hasValue('organisation') ? __('Organizzazioni') : __('Utenti')),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio {0}', $actor->hasValue('organisation') ? __('Organizzazione') : __('Utente')),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => $actor->hasValue('organisation') ? 'organisations' : 'users', 'action' => 'view', $actor->organisation->id ?? $actor->user->id],
+ ],
+ [
+ 'title' => __('Gestione recapiti'),
+ 'icon' => 'fa fa-phone',
+ 'url' => ['controller' => 'deliveries', 'action' => 'index', $actor->id],
+ ],
+ [
+ 'title' => __('Modifica Chat Telegram'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($telegram_chat, ['role' => 'form']); ?>
+
+ Form->control('value', ['label' => __('Chat Telegram ID')]);
+ echo $this->Form->control('enable_notifications', ['label' => __('Ricevi notifiche a questo recapito')]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/Users/add.php b/idrocap_wa/templates/Users/add.php
new file mode 100644
index 0000000..453d8eb
--- /dev/null
+++ b/idrocap_wa/templates/Users/add.php
@@ -0,0 +1,108 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Utenti'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Nuovo Utente'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ = $this->Form->create($user, ['role' => 'form', 'type' => 'file']) ?>
+
+
+
+ = $this->Form->control('username', ['label' => __('Nome utente')]); ?>
+
+
+ = $this->Form->control('name', ['label' => __('Nome')]); ?>
+
+
+ = $this->Form->control('surname', ['label' => __('Cognome')]); ?>
+
+
+ = $this->Form->control('tax_code', ['label' => __('Codice Fiscale')]); ?>
+
+
+ = $this->Form->control('password', ['label' => __('Password')]); ?>
+
+
+ = $this->Form->control('birthday', ['type' => 'date', 'label' => __('Data di nascita'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+ = $this->Form->control('birthplace', ['label' => __('Luogo di nascita')]); ?>
+
+
+ = $this->Form->control('gender', ['label' => __('Sesso'), 'type' => 'select', 'options' => ['M' => 'M', 'F' => 'F'], 'empty' => false, 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('address', ['label' => __('Indirizzo')]); ?>
+
+
+ = $this->Form->control('city', ['label' => __('Città')]); ?>
+
+
+ = $this->Form->control('cap', ['label' => __('CAP')]); ?>
+
+
+ = $this->Form->control('language_id', ['label' => __('Lingua preferita'), 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('organisation_id', ['label' => __('Organizzazione'), 'empty' => true, 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('user_photo', ['label' => __('Foto del profilo (solo jpeg di dimensioni 160x160!)'), 'type' => 'file', 'accept' => '.jpeg']); ?>
+
+
+
+ = $this->Form->control('groups._ids', ['label' => __('Profili'), 'options' => $groups, 'multiple' => true, 'disabled' => !$can_handle_profiles, 'style="width: 100%']); ?>
+
+
+
+
+
+ Form->end(); ?>
+
+
+
+
diff --git a/idrocap_wa/templates/Users/add_citizen.php b/idrocap_wa/templates/Users/add_citizen.php
new file mode 100644
index 0000000..5429e85
--- /dev/null
+++ b/idrocap_wa/templates/Users/add_citizen.php
@@ -0,0 +1,256 @@
+
+Html->css('/bower_components/select2/dist/css/select2.min'); ?>
+
+
+ = $this->Form->create($user, ['role' => 'form', 'type' => 'file', 'id' => 'add-citizen-js']) ?>
+
+
+
+ = $this->Form->control('username', ['label' => __('Nome utente')]); ?>
+
+
+ getName() ?? ''): ?>
+ = $this->Form->control('name', ['label' => __('Nome'),
+ 'value' => $citizenRegistrationData?->getName() ?? '',
+ 'readonly' => $citizenRegistrationData?->getName() ? true : false
+ ]); ?>
+
+ = $this->Form->control('name', ['label' => __('Nome'), 'required' => true]); ?>
+
+
+
+ getSurname() ?? ''): ?>
+ = $this->Form->control('surname', ['label' => __('Cognome'),
+ 'value' => $citizenRegistrationData?->getSurname() ?? '',
+ 'readonly' => $citizenRegistrationData?->getSurname() ? true : false
+ ]); ?>
+
+ = $this->Form->control('surname', ['label' => __('Cognome'), 'required' => true]); ?>
+
+
+
+ getFiscalCode() ?? ''): ?>
+ = $this->Form->control('tax_code', ['label' => __('Codice Fiscale'),
+ 'value' => $citizenRegistrationData?->getFiscalCode() ?? '',
+ 'readonly' => $citizenRegistrationData?->getFiscalCode() ? true : false
+ ]); ?>
+
+ = $this->Form->control('tax_code', ['label' => __('Codice Fiscale'), 'required' => true]); ?>
+
+
+
+
+ = $this->Form->control('email', ['label' => __('Email'), 'required' => true, 'type' => 'email']); ?>
+
+
+
+ = $this->Form->control('password', ['label' => __('Password')]); ?>
+
+
+
+ = $this->Form->control('confirmPassword', ['label' => __('Conferma password'), 'type' => 'password', 'required' => true]); ?>
+
+
+
+ getBirthdate() ?? ''): ?>
+ = $this->Form->control('birthday', ['label' => __('Data di nascita'),
+ 'type' => 'date',
+ 'value' => $citizenRegistrationData?->getBirthdate() ?? '',
+ 'readonly' => $citizenRegistrationData?->getBirthdate() ? true : false
+ ]); ?>
+
+ = $this->Form->control('birthday', ['type' => 'date', 'label' => __('Data di nascita'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+
+ = $this->Form->control('birthplace', ['label' => __('Luogo di nascita')]); ?>
+
+
+ getGender() ?? ''): ?>
+ = $this->Form->control('gender', ['label' => __('Sesso'),
+ 'value' => $citizenRegistrationData?->getGender() ?? '',
+ 'readonly' => $citizenRegistrationData?->getGender() ? true : false
+ ]); ?>
+
+ = $this->Form->control('gender', ['label' => __('Sesso'), 'type' => 'select', 'options' => ['M' => 'M', 'F' => 'F'], 'empty' => false, 'style="width: 100%']); ?>
+
+
+
+
+ = $this->Form->control('address', ['label' => __('Indirizzo')]); ?>
+
+
+ = $this->Form->control('city', ['label' => __('Città')]); ?>
+
+
+ = $this->Form->control('cap', ['label' => __('CAP')]); ?>
+
+
+ = $this->Form->control('language_id', ['label' => __('Lingua preferita'), 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('user_photo', ['label' => __('Foto del profilo (solo jpeg di dimensioni 160x160!)'), 'type' => 'file', 'accept' => '.jpeg']); ?>
+
+
+
+
+ Form->end(); ?>
+
+
+= $this->Html->script('/adminlte/plugins/jquery/jquery.min.js') ?>
+
+Html->script('/bower_components/select2/dist/js/select2.min'); ?>
+
+
+
+
diff --git a/idrocap_wa/templates/Users/choose_new_password.php b/idrocap_wa/templates/Users/choose_new_password.php
new file mode 100644
index 0000000..89aa06c
--- /dev/null
+++ b/idrocap_wa/templates/Users/choose_new_password.php
@@ -0,0 +1,10 @@
+
+ = $this->Form->create() ?>
+
+ = __('Imposta una nuova password') ?>
+ = $this->Form->control('new_password', ['label' => __('Digita la nuova password'), 'type' => 'password']) ?>
+ = $this->Form->control('confirm_new_password', ['label' => __('Ridigita la nuova password'), 'type' => 'password']) ?>
+
+ = $this->Form->button(__('Salva'), ['class' => 'btn btn-success']); ?>
+ = $this->Form->end() ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/Users/edit.php b/idrocap_wa/templates/Users/edit.php
new file mode 100644
index 0000000..d3c93cd
--- /dev/null
+++ b/idrocap_wa/templates/Users/edit.php
@@ -0,0 +1,112 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Utenti'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Utente'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'users', 'action' => 'view', $user->id],
+ ],
+ [
+ 'title' => __('Modifica Utente'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ = $this->Form->create($user, ['role' => 'form', 'type' => 'file']) ?>
+
+
+
+ = $this->Form->control('username', ['label' => __('Nome utente')]); ?>
+
+
+ = $this->Form->control('name', ['label' => __('Nome')]); ?>
+
+
+ = $this->Form->control('surname', ['label' => __('Cognome')]); ?>
+
+
+ = $this->Form->control('tax_code', ['label' => __('Codice Fiscale')]); ?>
+
+
+ = $this->Form->control('password', ['label' => __('Password')]); ?>
+
+
+ = $this->Form->control('birthday', ['type' => 'date', 'label' => __('Data di nascita'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+ = $this->Form->control('birthplace', ['label' => __('Luogo di nascita')]); ?>
+
+
+ = $this->Form->control('gender', ['label' => __('Sesso'), 'type' => 'select', 'options' => ['M' => 'M', 'F' => 'F'], 'empty' => false, 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('address', ['label' => __('Indirizzo')]); ?>
+
+
+ = $this->Form->control('city', ['label' => __('Città')]); ?>
+
+
+ = $this->Form->control('cap', ['label' => __('CAP')]); ?>
+
+
+ = $this->Form->control('language_id', ['label' => __('Lingua preferita'), 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('organisation_id', ['label' => __('Organizzazione'), 'style="width: 100%']); ?>
+
+
+ = $this->Form->control('user_photo', ['label' => __('Foto del profilo (solo jpeg di dimensioni 160x160!)'), 'type' => 'file', 'accept' => '.jpeg']); ?>
+
+
+
+ = $this->Form->control('groups._ids', ['label' => __('Profili'), 'options' => $groups, 'multiple' => true, 'disabled' => !$can_handle_profiles, 'style="width: 100%']); ?>
+
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/Users/index.php b/idrocap_wa/templates/Users/index.php
new file mode 100644
index 0000000..0cdd4c0
--- /dev/null
+++ b/idrocap_wa/templates/Users/index.php
@@ -0,0 +1,71 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Utenti'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('surname',__('Cognome')) ?>
+ = $this->Paginator->sort('name', __('Nome')) ?>
+ = $this->Paginator->sort('username', __('Username')) ?>
+ = __('Recapiti') ?>
+ = __('Profili') ?>
+ = $this->Paginator->sort('OrganisationActors.description', __('Organizzazione')) ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($user->surname) ?>
+ = h($user->name) ?>
+ = h($user->username) ?>
+ = h($user->actor->contacts) ?>
+ = h($user->profiles) ?>
+ = h($user->organisation->actor->description) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'view', $user->id], ['class'=>'btn btn-info btn-xs']) ?>
+ = $user->can_edit ? $this->Html->link(__('Modifica'), ['action' => 'edit', $user->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $user->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $user->id], ['confirm' => __('Sei sicuro che vuoi cancellare l\'utente "{0}" ?', $user->actor->description), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/Users/login.php b/idrocap_wa/templates/Users/login.php
new file mode 100644
index 0000000..4f02e58
--- /dev/null
+++ b/idrocap_wa/templates/Users/login.php
@@ -0,0 +1,27 @@
+
+
+ = $this->Form->create() ?>
+
+ = __('Accedi') ?>
+ = $this->Form->control('user_timezone', ['type' => 'hidden']) ?>
+ = $this->Form->control('username') ?>
+ = $this->Form->control('password') ?>
+ = $this->Form->control('remember_me', ['label' => __(' Rimani connesso'), 'type' => 'checkbox', 'checked' => true]) ?>
+
+
+
+ = $this->Form->button(__('Login'), ['class' => 'btn btn-success']); ?>
+
+
+ = Configure::read('App.oidc') ? $this->Html->link(__('Accedi con {0}', Configure::read('App.oidc.idp_name', 'OpenID Connect')), ['controller' => 'Users', 'action' => 'login_oidc'], ['class'=>'btn btn-info']) : ''?>
+
+
+ = $this->Form->end() ?>
+
+
diff --git a/idrocap_wa/templates/Users/one_time_password.php b/idrocap_wa/templates/Users/one_time_password.php
new file mode 100644
index 0000000..fded58c
--- /dev/null
+++ b/idrocap_wa/templates/Users/one_time_password.php
@@ -0,0 +1,8 @@
+
+ = $this->Form->create() ?>
+
+ = __('Premendo il pulsante sottostante, si verrà reindirizzati alla risorsa richiesta') ?>
+
+ = $this->Form->button(__('Procedi'), ['class' => 'btn btn-success']); ?>
+ = $this->Form->end() ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/Users/password_recovery.php b/idrocap_wa/templates/Users/password_recovery.php
new file mode 100644
index 0000000..079cbd2
--- /dev/null
+++ b/idrocap_wa/templates/Users/password_recovery.php
@@ -0,0 +1,9 @@
+
+ = $this->Form->create() ?>
+
+ = __('Inserisci un indirizzo email associato alla tua utenza') ?>
+ = $this->Form->control('email') ?>
+
+ = $this->Form->button(__('Richiedi reset password'), ['class' => 'btn btn-success']); ?>
+ = $this->Form->end() ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/Users/view.php b/idrocap_wa/templates/Users/view.php
new file mode 100644
index 0000000..1ebab21
--- /dev/null
+++ b/idrocap_wa/templates/Users/view.php
@@ -0,0 +1,72 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista Utenti'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'users', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Utente'),
+ 'icon' => 'fa fa-info',
+ ],
+ ]);
+?>
+
+
+ photo): ?>
+
+
+
+
+ = __('Nome utente') ?>
+ = h($user->username) ?>
+ = __('Nome') ?>
+ = h($user->name) ?>
+ = __('Cognome') ?>
+ = h($user->surname) ?>
+ = __('Codice Fiscale') ?>
+ = h($user->tax_code) ?>
+ = __('Data di nascita') ?>
+ = h(isset($user->birthday) ? $user->birthday->format('d/m/Y') : '') ?>
+ = __('Luogo di nascita') ?>
+ = h($user->birthplace) ?>
+ = __('Sesso') ?>
+ = h($user->gender) ?>
+ = __('Indirizzo') ?>
+ = h($user->address) ?>
+ = __('Città') ?>
+ = h($user->city) ?>
+ = __('CAP') ?>
+ = h($user->cap) ?>
+ = __('Lingua preferita') ?>
+ = h(isset($user->language->description) ? $user->language->description : __('Non specificata')) ?>
+ = __('Organizzazione') ?>
+ = h(!empty($user->organisation->actor->description) ? $user->organisation->actor->description : '') ?>
+ = __('Profili') ?>
+ = h($user->profiles) ?>
+ = __('Recapiti:') ?>
+ = h($user->actor->contacts) ?>
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingArticles/add.php b/idrocap_wa/templates/WaterDrawingArticles/add.php
new file mode 100644
index 0000000..2a66599
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingArticles/add.php
@@ -0,0 +1,45 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista degli Articoli di legge delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingArticles', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Nuovo Articolo di legge delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingArticle, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('description', ['label' => __('Articolo')]); ?>
+
+
+ = $this->Form->control('long_description', ['label' => __('Descrizione')]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingArticles/edit.php b/idrocap_wa/templates/WaterDrawingArticles/edit.php
new file mode 100644
index 0000000..9434199
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingArticles/edit.php
@@ -0,0 +1,45 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista degli Articoli di legge delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingArticles', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Modifica Articolo di legge delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingArticle, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('description', ['label' => __('Articolo')]); ?>
+
+
+ = $this->Form->control('long_description', ['label' => __('Descrizione')]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingArticles/index.php b/idrocap_wa/templates/WaterDrawingArticles/index.php
new file mode 100644
index 0000000..39d6d9c
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingArticles/index.php
@@ -0,0 +1,65 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista degli Articoli delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('description',__('Articolo')) ?>
+ = $this->Paginator->sort('long_description', __('Descrizione')) ?>
+ = $this->Paginator->sort('disabled', __('Abilitato')) ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingArticle->description) ?>
+ = h($waterDrawingArticle->long_description) ?>
+ = $waterDrawingArticle->disable ? __('No') : __('Si') ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'view', $waterDrawingArticle->id], ['class'=>'btn btn-info btn-xs']) ?>
+ = $waterDrawingArticle->can_edit ? $this->Html->link(__('Modifica'), ['action' => 'edit', $waterDrawingArticle->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingArticle->can_delete ? $this->Form->postLink(($waterDrawingArticle->disable ? __('Abilita') : __('Disabilita')), ['action' => 'change_status', $waterDrawingArticle->id], ['confirm' => ($waterDrawingArticle->disable ? __('Sei sicuro che vuoi abilitare l\'articolo "{0}" ?', $waterDrawingArticle->description) : __('Sei sicuro che vuoi disabilitare l\'articolo "{0}" ?', $waterDrawingArticle->description)), 'class'=>'btn btn-info btn-xs']) : null ?>
+ = $waterDrawingArticle->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $waterDrawingArticle->id], ['confirm' => __('Sei sicuro che vuoi cancellare l\'articolo "{0}" ?', $waterDrawingArticle->description), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingArticles/view.php b/idrocap_wa/templates/WaterDrawingArticles/view.php
new file mode 100644
index 0000000..86f6eb7
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingArticles/view.php
@@ -0,0 +1,55 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Lista degli Articoli di legge delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingArticles', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Articolo di legge delle pratiche d\'attingimento'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingArticle, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('description', ['label' => __('Articolo')]); ?>
+
+
+ = $this->Form->control('long_description', ['label' => __('Descrizione')]); ?>
+
+
+ = $this->Form->control('disabled', ['label' => __('Abilitato'), 'value' => ($waterDrawingArticle->disable ? __('No') : __('Si')), 'disabled' => true]); ?>
+
+
+
+
+ Form->end(); ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingDerivations/add.php b/idrocap_wa/templates/WaterDrawingDerivations/add.php
new file mode 100644
index 0000000..3da6bad
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingDerivations/add.php
@@ -0,0 +1,250 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Aggiungi Punto di prelievo/derivazione'),
+ 'icon' => 'fa fa-add',
+ ],
+]);
+?>
+
+
+ Form->create($waterDrawingDerivation, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+
+ = $this->Cell('Map', [
+ [-2, -3, -4], // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Punto di prelievo/derivazione'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => false, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => false, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => false, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lon'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lat'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ 'address' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'location',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'location',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Contrada/Località'),
+ ],
+ 'district_code' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'istat',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'istat',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('ISTAT'),
+ ],
+ ],
+ 'geo_resources' => [ // Array = null -> null/[] = geo_resources serve a specificare delle geo-risorse dalle quali vogliamo estrarre degli attributi. per ogni geo-risorsa, tra le altre cose, bisogna specificare il mapping dei campi nella forma "attributo_geo_risorsa":"id-campo-nel-form"
+ [
+ 'table_name' => 'geo.rw_watersheds', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'swbcode' => 'swbcode'
+ ],
+ ],
+ [
+ 'table_name' => 'geo.cw_draining_areas', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'cw_wise_co' => 'cw-wise-co'
+ ],
+ ],
+ [
+ 'table_name' => 'geo.gwbs', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'wbcod' => 'wbcod',
+ ],
+ ],
+ [
+ 'external' => true, // se la geo-risorsa è un servizio esterno, bisogna specificare 'external' => true!
+ 'url' // se la geo-risorsa è esterna va specificata la 'url' per chiamare il servizio
+ => 'https://wms.cartografia.agenziaentrate.gov.it/inspire/ajax/ajax.php?op=getDatiOggetto',
+ 'lon_parameter_name' => 'lon', // lon_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lon'
+ 'lat_parameter_name' => 'lat', // lat_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lat'
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'COD_COMUNE' => 'cadastral-code',
+ 'FOGLIO' => 'cadastral-sheet',
+ 'NUM_PART' => 'cadastral-parcel',
+ ],
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'requred' => true]) ?>
+
+
+ = $this->Form->control('cadastral_code', ['label' => __('Codice catastale (Belfiore)'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('location', ['label' => __('Contrada/Località'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('cadastral_sheet', ['label' => __('Foglio di Mappa'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('cadastral_parcel', ['label' => __('Particella'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('longitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lon'), 'readonly' => true, 'requred' => true,]) ?>
+
+
+ = $this->Form->control('latitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lat'), 'readonly' => true, 'requred' => true,]) ?>
+
+
+ = $this->Form->hidden('water_drawing_paperwork_id', ['value' => $water_drawing_paperwork_id]) ?>
+ = $this->Form->control('water_drawing_derivation_type_id', ['label' => __('Tipo di derivazione'), 'options' => $waterDrawingDerivationTypes, 'onChange' => 'setWaterBody()']) ?>
+
+
+ = $this->Form->control('water_body', ['label' => __('Corpo idrico'), 'type' => 'text']) ?>
+
+
+
+
+ = $this->Form->control('description', ['label' => __('Descrizione'), 'type' => 'text']) ?>
+
+
+
+ = $this->Form->control('wbcod', ['label' => __('Codice corpo idrico sotterraneo'), 'type' => 'text', 'readonly' => true]) ?>
+
+
+ Usa come corpo idrico
+
+
+
+ = $this->Form->control('cw_wise_co', ['label' => __('Codice area afferente al corpo idrico marino costiero'), 'type' => 'text', 'readonly' => true]) ?>
+
+
+ Usa come corpo idrico
+
+
+
+ = $this->Form->control('swbcode', ['label' => __('Codice corpo idrico superficiale'), 'type' => 'text', 'readonly' => true]) ?>
+
+
+ Usa come corpo idrico
+
+
+
+ = $this->Form->control('istat', ['label' => __('Codice ISTAT'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('derivation_status', ['label' => __('Status della derivazione'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('withdrawals_amount', ['label' => __('N. prelievi'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('annual_volume', ['label' => __('Volume annuo (m^3)'), 'type' => 'number', 'min' => 0]) ?>
+
+
+ = $this->Form->control('average_flow_rate', ['label' => __('Portata media (l/s)'), 'type' => 'number', 'min' => 0]) ?>
+
+
+
+ Form->submit(__('Salva'), ['id' => 'submitForm']); ?>
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingDerivations/edit.php b/idrocap_wa/templates/WaterDrawingDerivations/edit.php
new file mode 100644
index 0000000..d1fb035
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingDerivations/edit.php
@@ -0,0 +1,235 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingDerivation->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Modifica Punto di prelievo/derivazione'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingDerivation, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Form->control('water_drawing_derivation_type_id', ['label' => __('Tipo di derivazione'), 'options' => $waterDrawingDerivationTypes]) ?>
+
+
+ = $this->Form->control('water_body', ['label' => __('Corpo idrico'), 'type' => 'text']) ?>
+
+
+
+
+ = $this->Form->control('description', ['label' => __('Descrizione'), 'type' => 'text']) ?>
+
+
+
+ = $this->Form->control('wbcod', ['label' => __('Codice corpo idrico sotterraneo'), 'type' => 'text', 'readonly' => true]) ?>
+
+
+ Usa come corpo idrico
+
+
+
+ = $this->Form->control('cw_wise_co', ['label' => __('Codice area afferente al corpo idrico marino costiero'), 'type' => 'text', 'readonly' => true]) ?>
+
+
+ Usa come corpo idrico
+
+
+
+ = $this->Form->control('swbcode', ['label' => __('Codice corpo idrico superficiale'), 'type' => 'text', 'readonly' => true]) ?>
+
+
+ Usa come corpo idrico
+
+
+
+ = $this->Cell('Map', [
+ [-2, -3, -4], // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Punto di prelievo/derivazione'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => false, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => false, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => false, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lon'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lat'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ 'address' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'location',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'location',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Contrada/Località'),
+ ],
+ 'district_code' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'istat',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'istat',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('ISTAT'),
+ ],
+ ],
+ 'geo_resources' => [ // Array = null -> null/[] = geo_resources serve a specificare delle geo-risorse dalle quali vogliamo estrarre degli attributi. per ogni geo-risorsa, tra le altre cose, bisogna specificare il mapping dei campi nella forma "attributo_geo_risorsa":"id-campo-nel-form"
+ [
+ 'table_name' => 'geo.rw_watersheds', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'swbcode' => 'swbcode'
+ ],
+ ],
+ [
+ 'table_name' => 'geo.cw_draining_areas', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'cw_wise_co' => 'cw-wise-co'
+ ],
+ ],
+ [
+ 'table_name' => 'geo.gwbs', // Nome della tabella dove risiede la geo-risorsa. Specificare il prefisso (esempio 'geo') qualora la risorsa si trovi al di fuori del datasource 'default' di Jixel
+ 'geometry_name' => 'SHAPE', // specifica il nome del campo di tipo GEOMETRY della geo-risorsa (se si omette, verrà preso il nome di default 'SHAPE')
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'wbcod' => 'wbcod',
+ ],
+ ],
+ [
+ 'external' => true, // se la geo-risorsa è un servizio esterno, bisogna specificare 'external' => true!
+ 'url' // se la geo-risorsa è esterna va specificata la 'url' per chiamare il servizio
+ => 'https://wms.cartografia.agenziaentrate.gov.it/inspire/ajax/ajax.php?op=getDatiOggetto',
+ 'lon_parameter_name' => 'lon', // lon_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lon'
+ 'lat_parameter_name' => 'lat', // lat_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lat'
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'COD_COMUNE' => 'cadastral-code',
+ 'FOGLIO' => 'cadastral-sheet',
+ 'NUM_PART' => 'cadastral-parcel',
+ ],
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'requred' => true]) ?>
+
+
+ = $this->Form->control('cadastral_code', ['label' => __('Codice catastale (Belfiore)'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('location', ['label' => __('Contrada/Località'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('cadastral_sheet', ['label' => __('Foglio di Mappa'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('cadastral_parcel', ['label' => __('Particella'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('longitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lon'), 'readonly' => true, 'requred' => true,]) ?>
+
+
+ = $this->Form->control('latitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lat'), 'readonly' => true, 'requred' => true,]) ?>
+
+
+ = $this->Form->control('istat', ['label' => __('Codice ISTAT'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('derivation_status', ['label' => __('Status della derivazione'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('withdrawals_amount', ['label' => __('N. prelievi'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('annual_volume', ['label' => __('Volume annuo (m^3)'), 'type' => 'number', 'min' => 0]) ?>
+
+
+ = $this->Form->control('average_flow_rate', ['label' => __('Portata media (l/s)'), 'type' => 'number', 'min' => 0]) ?>
+
+
+
+ Form->submit(__('Salva'), ['id' => 'submitForm']); ?>
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingDerivations/index.php b/idrocap_wa/templates/WaterDrawingDerivations/index.php
new file mode 100644
index 0000000..f333f78
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingDerivations/index.php
@@ -0,0 +1,72 @@
+ $waterDrawingDerivations
+ */
+?>
+
+ = $this->Html->link(__('New Water Drawing Derivation'), ['action' => 'add'], ['class' => 'button float-right']) ?>
+
= __('Water Drawing Derivations') ?>
+
+
+
+
+ = $this->Paginator->sort('id') ?>
+ = $this->Paginator->sort('water_body') ?>
+ = $this->Paginator->sort('district') ?>
+ = $this->Paginator->sort('cadastral_code') ?>
+ = $this->Paginator->sort('location') ?>
+ = $this->Paginator->sort('cadastral_sheet') ?>
+ = $this->Paginator->sort('cadastral_parcel') ?>
+ = $this->Paginator->sort('latitude') ?>
+ = $this->Paginator->sort('longitude') ?>
+ = $this->Paginator->sort('istat') ?>
+ = $this->Paginator->sort('derivation_status') ?>
+ = $this->Paginator->sort('withdrawals_amount') ?>
+ = $this->Paginator->sort('annual_volume') ?>
+ = $this->Paginator->sort('average_flow_rate') ?>
+ = $this->Paginator->sort('water_drawing_derivation_type_id') ?>
+ = $this->Paginator->sort('water_drawing_paperwork_id') ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = $this->Number->format($waterDrawingDerivation->id) ?>
+ = h($waterDrawingDerivation->water_body) ?>
+ = h($waterDrawingDerivation->district) ?>
+ = h($waterDrawingDerivation->cadastral_code) ?>
+ = h($waterDrawingDerivation->location) ?>
+ = $waterDrawingDerivation->cadastral_sheet === null ? '' : $this->Number->format($waterDrawingDerivation->cadastral_sheet) ?>
+ = $waterDrawingDerivation->cadastral_parcel === null ? '' : $this->Number->format($waterDrawingDerivation->cadastral_parcel) ?>
+ = h($waterDrawingDerivation->latitude) ?>
+ = h($waterDrawingDerivation->longitude) ?>
+ = h($waterDrawingDerivation->istat) ?>
+ = h($waterDrawingDerivation->derivation_status) ?>
+ = $waterDrawingDerivation->withdrawals_amount === null ? '' : $this->Number->format($waterDrawingDerivation->withdrawals_amount) ?>
+ = $waterDrawingDerivation->annual_volume === null ? '' : $this->Number->format($waterDrawingDerivation->annual_volume) ?>
+ = $waterDrawingDerivation->average_flow_rate === null ? '' : $this->Number->format($waterDrawingDerivation->average_flow_rate) ?>
+ = $waterDrawingDerivation->hasValue('water_drawing_derivation_type') ? $this->Html->link($waterDrawingDerivation->water_drawing_derivation_type->id, ['controller' => 'WaterDrawingDerivationTypes', 'action' => 'view', $waterDrawingDerivation->water_drawing_derivation_type->id]) : '' ?>
+ = $waterDrawingDerivation->hasValue('water_drawing_paperwork') ? $this->Html->link($waterDrawingDerivation->water_drawing_paperwork->id, ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingDerivation->water_drawing_paperwork->id]) : '' ?>
+
+ = $this->Html->link(__('View'), ['action' => 'view', $waterDrawingDerivation->id]) ?>
+ = $this->Html->link(__('Edit'), ['action' => 'edit', $waterDrawingDerivation->id]) ?>
+ = $this->Form->postLink(__('Delete'), ['action' => 'delete', $waterDrawingDerivation->id], ['confirm' => __('Are you sure you want to delete # {0}?', $waterDrawingDerivation->id)]) ?>
+
+
+
+
+
+
+
+
+
= $this->Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingDerivations/view.php b/idrocap_wa/templates/WaterDrawingDerivations/view.php
new file mode 100644
index 0000000..021f894
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingDerivations/view.php
@@ -0,0 +1,104 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingDerivation->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dettagli Punto di prelievo/derivazione'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingDerivation, ['id' => 'myForm', 'role' => 'form']); ?>
+
+
+
+ = $this->Form->control('water_drawing_derivation_type.description', ['label' => __('Tipo di derivazione'), 'type' => 'text', 'required' => false, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('water_body', ['label' => __('Corpo idrico'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('description', ['label' => __('Descrizione'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Punto di prelievo/derivazione'),
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'requred' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('cadastral_code', ['label' => __('Codice catastale (Belfiore)'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('location', ['label' => __('Contrada/Località'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('cadastral_sheet', ['label' => __('Foglio di Mappa'), 'requred' => true, 'min' => 0, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('cadastral_parcel', ['label' => __('Particella'), 'requred' => true, 'min' => 0, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('longitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lon'), 'readonly' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('latitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lat'), 'readonly' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('istat', ['label' => __('Codice ISTAT'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('derivation_status', ['label' => __('Status della derivazione'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('withdrawals_amount', ['label' => __('N. prelievi'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('annual_volume', ['label' => __('Volume annuo (m^3)'), 'type' => 'number', 'min' => 0, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('average_flow_rate', ['label' => __('Portata media (l/s)'), 'type' => 'number', 'min' => 0, 'disabled' => true]) ?>
+
+
+
+ Form->end(); ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingFees/add.php b/idrocap_wa/templates/WaterDrawingFees/add.php
new file mode 100644
index 0000000..9b91c12
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingFees/add.php
@@ -0,0 +1,46 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Dettagli pratica d\'attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Aggiungi Canone annuale'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingFee, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('amount', ['label' => __('Canone'), 'required' => true, 'min' => 0]); ?>
+
+
+ = $this->Form->control('year', ['label' => __('Anno'), 'type' => 'number', 'min' => 1900, 'max' => ((new \DateTime())->format("Y") + 1)]); ?>
+ = $this->Form->hidden('water_drawing_paperwork_id', ['value' => $water_drawing_paperwork_id]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingFees/edit.php b/idrocap_wa/templates/WaterDrawingFees/edit.php
new file mode 100644
index 0000000..f7eeb8d
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingFees/edit.php
@@ -0,0 +1,46 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Dettagli pratica d\'attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingFee->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Modifica Canone annuale'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingFee, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('amount', ['label' => __('Canone'), 'required' => true, 'min' => 0]); ?>
+
+
+ = $this->Form->control('year', ['label' => __('Anno'), 'type' => 'number', 'min' => 1900, 'max' => ((new \DateTime())->format("Y") + 1)]); ?>
+ = $this->Form->hidden('water_drawing_paperwork_id', ['value' => $waterDrawingFee->water_drawing_paperwork_id]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingFees/index.php b/idrocap_wa/templates/WaterDrawingFees/index.php
new file mode 100644
index 0000000..e044f94
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingFees/index.php
@@ -0,0 +1,76 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Lista canoni annuali'),
+ 'icon' => 'fa fa-list',
+ ],
+]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = __('Anno') ?>
+ = __('Canone') ?>
+ = __('Dovuto') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingFee->year) ?>
+ = h($waterDrawingFee->amount . ' €') ?>
+ = h($waterDrawingFee->to_pay . ' €') ?>
+
+ = $waterDrawingFee->can_edit ? $this->Html->link(__('Modifica'), ['controller' => 'waterDrawingFees', 'action' => 'edit', $waterDrawingFee->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $this->Html->link(__('Dettagli'), ['controller' => 'waterDrawingFees', 'action' => 'view', $waterDrawingFee->id], ['class' => 'btn btn-info btn-xs'])?>
+ = $waterDrawingFee->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $waterDrawingFee->id], ['confirm' => __('Sei sicuro che vuoi cancellare il canone annuale "{0}" ?', $waterDrawingFee->year), 'class' => 'btn btn-danger btn-xs']) : null; ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingFees/view.php b/idrocap_wa/templates/WaterDrawingFees/view.php
new file mode 100644
index 0000000..35fc10e
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingFees/view.php
@@ -0,0 +1,91 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Configurazioni'),
+ 'icon' => 'fa fa-wrench',
+ ],
+ [
+ 'title' => __('Dettagli pratica d\'attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingFee->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dettagli Canone annuale'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingFee, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('amount', ['label' => __('Canone'), 'required' => true, 'disabled' => true]); ?>
+
+
+ = $this->Form->control('year', ['label' => __('Anno'), 'disabled' => true]); ?>
+ = $this->Form->hidden('water_drawing_paperwork_id', ['value' => $waterDrawingFee->water_drawing_paperwork_id]); ?>
+
+
+ = $this->Form->end(); ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Data inserimento') ?>
+ = __('Utente') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee->year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->created) ?>
+ = h($waterDrawingPayment->user) ?>
+
+ = $waterDrawingPayment->can_edit ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPayments', 'action' => 'edit', $waterDrawingPayment->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPayment->can_view ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingPayments', 'action' => 'view', $waterDrawingPayment->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+ = $waterDrawingPayment->can_delete ? $this->Form->postLink(__('Cancella'), ['controller' => 'WaterDrawingPayments', 'action' => 'delete', $waterDrawingPayment->id], ['confirm' => __('Sei sicuro che vuoi cancellare il pagamento n° "{0}" ?', $waterDrawingPayment->payment_number), 'class' => 'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingIntendedUses/add.php b/idrocap_wa/templates/WaterDrawingIntendedUses/add.php
new file mode 100644
index 0000000..26ccb03
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingIntendedUses/add.php
@@ -0,0 +1,37 @@
+
+
+
+
+
= __('Actions') ?>
+ = $this->Html->link(__('List Water Drawing Intended Uses'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
+
+
+
+
+ = $this->Form->create($waterDrawingIntendedUse) ?>
+
+ = __('Add Water Drawing Intended Use') ?>
+ Form->control('area');
+ echo $this->Form->control('cadastral_code');
+ echo $this->Form->control('cadastral_sheet');
+ echo $this->Form->control('cadastral_parcel');
+ echo $this->Form->control('watering_system');
+ echo $this->Form->control('consortium_area');
+ echo $this->Form->control('rated_power_produced');
+ echo $this->Form->control('water_drawing_paperwork_id', ['options' => $waterDrawingPaperworks]);
+ echo $this->Form->control('water_drawing_intended_use_type_id', ['options' => $waterDrawingIntendedUseTypes, 'empty' => true]);
+ ?>
+
+ = $this->Form->button(__('Submit')) ?>
+ = $this->Form->end() ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingIntendedUses/edit.php b/idrocap_wa/templates/WaterDrawingIntendedUses/edit.php
new file mode 100644
index 0000000..abbd62c
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingIntendedUses/edit.php
@@ -0,0 +1,42 @@
+
+
+
+
+
= __('Actions') ?>
+ = $this->Form->postLink(
+ __('Delete'),
+ ['action' => 'delete', $waterDrawingIntendedUse->id],
+ ['confirm' => __('Are you sure you want to delete # {0}?', $waterDrawingIntendedUse->id), 'class' => 'side-nav-item']
+ ) ?>
+ = $this->Html->link(__('List Water Drawing Intended Uses'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
+
+
+
+
+ = $this->Form->create($waterDrawingIntendedUse) ?>
+
+ = __('Edit Water Drawing Intended Use') ?>
+ Form->control('area');
+ echo $this->Form->control('cadastral_code');
+ echo $this->Form->control('cadastral_sheet');
+ echo $this->Form->control('cadastral_parcel');
+ echo $this->Form->control('watering_system');
+ echo $this->Form->control('consortium_area');
+ echo $this->Form->control('rated_power_produced');
+ echo $this->Form->control('water_drawing_paperwork_id', ['options' => $waterDrawingPaperworks]);
+ echo $this->Form->control('water_drawing_intended_use_type_id', ['options' => $waterDrawingIntendedUseTypes, 'empty' => true]);
+ ?>
+
+ = $this->Form->button(__('Submit')) ?>
+ = $this->Form->end() ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingIntendedUses/index.php b/idrocap_wa/templates/WaterDrawingIntendedUses/index.php
new file mode 100644
index 0000000..09b9ca4
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingIntendedUses/index.php
@@ -0,0 +1,60 @@
+ $waterDrawingIntendedUses
+ */
+?>
+
+ = $this->Html->link(__('New Water Drawing Intended Use'), ['action' => 'add'], ['class' => 'button float-right']) ?>
+
= __('Water Drawing Intended Uses') ?>
+
+
+
+
+ = $this->Paginator->sort('id') ?>
+ = $this->Paginator->sort('area') ?>
+ = $this->Paginator->sort('cadastral_code') ?>
+ = $this->Paginator->sort('cadastral_sheet') ?>
+ = $this->Paginator->sort('cadastral_parcel') ?>
+ = $this->Paginator->sort('watering_system') ?>
+ = $this->Paginator->sort('consortium_area') ?>
+ = $this->Paginator->sort('rated_power_produced') ?>
+ = $this->Paginator->sort('water_drawing_paperwork_id') ?>
+ = $this->Paginator->sort('water_drawing_intended_use_type_id') ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = $this->Number->format($waterDrawingIntendedUse->id) ?>
+ = h($waterDrawingIntendedUse->area) ?>
+ = h($waterDrawingIntendedUse->cadastral_code) ?>
+ = h($waterDrawingIntendedUse->cadastral_sheet) ?>
+ = h($waterDrawingIntendedUse->cadastral_parcel) ?>
+ = h($waterDrawingIntendedUse->watering_system) ?>
+ = h($waterDrawingIntendedUse->consortium_area) ?>
+ = h($waterDrawingIntendedUse->rated_power_produced) ?>
+ = $waterDrawingIntendedUse->hasValue('water_drawing_paperwork') ? $this->Html->link($waterDrawingIntendedUse->water_drawing_paperwork->id, ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_paperwork->id]) : '' ?>
+ = $waterDrawingIntendedUse->hasValue('water_drawing_intended_use_type') ? $this->Html->link($waterDrawingIntendedUse->water_drawing_intended_use_type->id, ['controller' => 'WaterDrawingIntendedUseTypes', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_intended_use_type->id]) : '' ?>
+
+ = $this->Html->link(__('View'), ['action' => 'view', $waterDrawingIntendedUse->id]) ?>
+ = $this->Html->link(__('Edit'), ['action' => 'edit', $waterDrawingIntendedUse->id]) ?>
+ = $this->Form->postLink(__('Delete'), ['action' => 'delete', $waterDrawingIntendedUse->id], ['confirm' => __('Are you sure you want to delete # {0}?', $waterDrawingIntendedUse->id)]) ?>
+
+
+
+
+
+
+
+
+
= $this->Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingIntendedUses/view.php b/idrocap_wa/templates/WaterDrawingIntendedUses/view.php
new file mode 100644
index 0000000..85d1f7c
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingIntendedUses/view.php
@@ -0,0 +1,64 @@
+
+
+
+
+
= __('Actions') ?>
+ = $this->Html->link(__('Edit Water Drawing Intended Use'), ['action' => 'edit', $waterDrawingIntendedUse->id], ['class' => 'side-nav-item']) ?>
+ = $this->Form->postLink(__('Delete Water Drawing Intended Use'), ['action' => 'delete', $waterDrawingIntendedUse->id], ['confirm' => __('Are you sure you want to delete # {0}?', $waterDrawingIntendedUse->id), 'class' => 'side-nav-item']) ?>
+ = $this->Html->link(__('List Water Drawing Intended Uses'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
+ = $this->Html->link(__('New Water Drawing Intended Use'), ['action' => 'add'], ['class' => 'side-nav-item']) ?>
+
+
+
+
+
= h($waterDrawingIntendedUse->id) ?>
+
+
+ = __('Area') ?>
+ = h($waterDrawingIntendedUse->area) ?>
+
+
+ = __('Cadastral Code') ?>
+ = h($waterDrawingIntendedUse->cadastral_code) ?>
+
+
+ = __('Cadastral Sheet') ?>
+ = h($waterDrawingIntendedUse->cadastral_sheet) ?>
+
+
+ = __('Cadastral Parcel') ?>
+ = h($waterDrawingIntendedUse->cadastral_parcel) ?>
+
+
+ = __('Watering System') ?>
+ = h($waterDrawingIntendedUse->watering_system) ?>
+
+
+ = __('Consortium Area') ?>
+ = h($waterDrawingIntendedUse->consortium_area) ?>
+
+
+ = __('Rated Power Produced') ?>
+ = h($waterDrawingIntendedUse->rated_power_produced) ?>
+
+
+ = __('Water Drawing Paperwork') ?>
+ = $waterDrawingIntendedUse->hasValue('water_drawing_paperwork') ? $this->Html->link($waterDrawingIntendedUse->water_drawing_paperwork->id, ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_paperwork->id]) : '' ?>
+
+
+ = __('Water Drawing Intended Use Type') ?>
+ = $waterDrawingIntendedUse->hasValue('water_drawing_intended_use_type') ? $this->Html->link($waterDrawingIntendedUse->water_drawing_intended_use_type->id, ['controller' => 'WaterDrawingIntendedUseTypes', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_intended_use_type->id]) : '' ?>
+
+
+ = __('Id') ?>
+ = $this->Number->format($waterDrawingIntendedUse->id) ?>
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingMeasurements/add.php b/idrocap_wa/templates/WaterDrawingMeasurements/add.php
new file mode 100644
index 0000000..e0f8a27
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingMeasurements/add.php
@@ -0,0 +1,51 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index']
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view_scan', $water_drawing_paperwork_id]
+ ],
+ [
+ 'title' => __('Nuova lettura dello strumento'),
+ 'icon' => 'fa fa-plus',
+ ]
+]);
+?>
+
+
+
+ Form->create($waterDrawingMeasurement, ['role' => 'form', 'type' => 'file']); ?>
+
+
+ = $this->Form->control('water_drawing_meter_id', ['type' => 'hidden', 'value' => $water_drawing_meter_id]); ?>
+
+ = $this->Form->control('volume', ['label' => __('Lettura volume (m^3)'), 'type' => 'number', 'required' => true, 'min' => 0]); ?>
+
+
+ = $this->Form->control('date', ['label' => __('Data del rilievo'), 'style' => 'margin-left: 5px;', 'type' => 'date', 'max' => $today->format('Y-m-d')]); ?>
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingMeasurements/index.php b/idrocap_wa/templates/WaterDrawingMeasurements/index.php
new file mode 100644
index 0000000..5586106
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingMeasurements/index.php
@@ -0,0 +1,73 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index']
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id]
+ ],
+ [
+ 'title' => __('Lista misurazioni relativi alla pratica'),
+ 'icon' => 'fa fa-list',
+ ],
+
+]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('water_drawing_meter_id', __('N° matricola strumento di misura')) ?>
+ = $this->Paginator->sort('volume', __('Lettura volume (m^3)')) ?>
+ = $this->Paginator->sort('date', __('Data lettura')) ?>
+ = $this->Paginator->sort('volume', __('Utente')) ?>
+
+
+
+
+
+ = h($waterDrawingMeasurement->water_drawing_meter->part_number) ?>
+ = h($waterDrawingMeasurement->volume) ?>
+ = h($waterDrawingMeasurement->date) ?>
+ = h($waterDrawingMeasurement->user) ?>
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingMeters/add.php b/idrocap_wa/templates/WaterDrawingMeters/add.php
new file mode 100644
index 0000000..8315bd0
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingMeters/add.php
@@ -0,0 +1,66 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Aggiungi lo strumento di misura'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingMeter, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('water_drawing_tool_type_id', ['label' => __('Tipo'), 'type' => 'select', 'options' => $waterDrawingToolTypes, 'empty' => true]) ?>
+
+
+ = $this->Form->control('installation_date', ['label' => __('Data installazione'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'max' => $today->format('Y-m-d')]) ?>
+
+
+
+
+ = $this->Form->control('manufacturer', ['label' => __('Marca'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('part_number', ['label' => __('Matricola'), 'type' => 'text']) ?>
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingMeters/dismiss.php b/idrocap_wa/templates/WaterDrawingMeters/dismiss.php
new file mode 100644
index 0000000..c7057cb
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingMeters/dismiss.php
@@ -0,0 +1,67 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dismetti lo strumento di misura'),
+ 'icon' => 'fa fa-times-circle',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingMeter, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('water_drawing_tool_type.description', ['label' => __('Tipo'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('installation_date', ['label' => __('Data installazione'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+
+
+
+
+ = $this->Form->control('manufacturer', ['label' => __('Marca'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('part_number', ['label' => __('Matricola'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+ installation_date)):?>
+ = $this->Form->control('removal_date', ['label' => __('Data dismissione'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'min' => $waterDrawingMeter->installation_date->format('Y-m-d'), 'max' => $today->format('Y-m-d')]) ?>
+
+ = $this->Form->control('removal_date', ['label' => __('Data dismissione'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'max' => $today->format('Y-m-d')]) ?>
+
+
+
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingMeters/edit.php b/idrocap_wa/templates/WaterDrawingMeters/edit.php
new file mode 100644
index 0000000..14302c9
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingMeters/edit.php
@@ -0,0 +1,66 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Modifica lo strumento di misura'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingMeter, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('water_drawing_tool_type_id', ['label' => __('Tipo'), 'type' => 'select', 'options' => $waterDrawingToolTypes, 'empty' => true]) ?>
+
+
+ = $this->Form->control('installation_date', ['label' => __('Data installazione'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'max' => $today->format('Y-m-d')]) ?>
+
+
+
+
+ = $this->Form->control('manufacturer', ['label' => __('Marca'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('part_number', ['label' => __('Matricola'), 'type' => 'text']) ?>
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingMeters/view.php b/idrocap_wa/templates/WaterDrawingMeters/view.php
new file mode 100644
index 0000000..5aaf288
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingMeters/view.php
@@ -0,0 +1,103 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingMeter->water_drawing_intended_use->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dettaglio dello strumento di misura'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingMeter, ['role' => 'form']); ?>
+
+
+
+ = $this->Form->control('water_drawing_tool_type_id', ['label' => __('Tipo'), 'type' => 'select', 'options' => $waterDrawingToolTypes, 'empty' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('installation_date', ['label' => __('Data installazione'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+
+
+
+
+ = $this->Form->control('manufacturer', ['label' => __('Marca'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('part_number', ['label' => __('Matricola'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ Form->end(); ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Utente') ?>
+ = __('Lettura') ?>
+ = __('Data') ?>
+
+
+
+ water_drawing_measurements as $waterDrawingMeasurement) : ?>
+
+ = h($waterDrawingMeasurement->user) ?>
+ = h($waterDrawingMeasurement->volume) ?>
+ = h($waterDrawingMeasurement->date->format("d/m/Y")) ?>
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworkPecs/add.php b/idrocap_wa/templates/WaterDrawingPaperworkPecs/add.php
new file mode 100644
index 0000000..684edc2
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworkPecs/add.php
@@ -0,0 +1,62 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Aggiungi il documento PEC'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPaperworkPec, ['role' => 'form', 'type' => 'file']); ?>
+
+ = $this->Form->hidden('water_drawing_paperwork_id', ['value' => $water_drawing_paperwork_id]) ?>
+ = $this->Form->control('document', ['label' => __('Documento'), 'type' => 'text']) ?>
+ = $this->Form->control('protocol_number', ['label' => __('Numero di protocollo'), 'type' => 'text']) ?>
+ = $this->Form->control('recipient', ['label' => __('Destinatario'), 'type' => 'text']) ?>
+ = $this->Form->control('sender', ['label' => __('Inviato da'), 'type' => 'text']) ?>
+ = $this->Form->control('protocol_date', ['label' => __('Data'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'max' => $today->format('Y-m-d')]) ?>
+ element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tags,
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.pdf']
+ ]);
+ ?>
+ Form->control('note', ['label' => 'Note:', 'type' => 'textarea']);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworkPecs/edit.php b/idrocap_wa/templates/WaterDrawingPaperworkPecs/edit.php
new file mode 100644
index 0000000..6cdf4b4
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworkPecs/edit.php
@@ -0,0 +1,62 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ //'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Modifica il documento PEC'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPaperworkPec, ['role' => 'form', 'type' => 'file']); ?>
+
+ = $this->Form->control('document', ['label' => __('Documento'), 'type' => 'text']) ?>
+ = $this->Form->control('protocol_number', ['label' => __('Numero di protocollo'), 'type' => 'text']) ?>
+ = $this->Form->control('recipient', ['label' => __('Destinatario'), 'type' => 'text']) ?>
+ = $this->Form->control('sender', ['label' => __('Inviato da'), 'type' => 'text']) ?>
+ = $this->Form->control('protocol_date', ['label' => __('Data'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'max' => $today->format('Y-m-d')]) ?>
+ element('attachments', [
+ 'coId' => $waterDrawingPaperworkPec->controllable_object_id,
+ 'filepicker' => true,
+ 'viewer' => true,
+ 'currentFilesRemovable' => true,
+ 'tags' => $tags,
+ 'required' => false,
+ 'view_in_frame_with_id' => false,
+ 'accept_only' => ['.pdf']
+ ]);
+ ?>
+ Form->control('note', ['label' => 'Note:', 'type' => 'textarea']);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworkPecs/index.php b/idrocap_wa/templates/WaterDrawingPaperworkPecs/index.php
new file mode 100644
index 0000000..7acbe21
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworkPecs/index.php
@@ -0,0 +1,81 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index']
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id]
+ ],
+ [
+ 'title' => __('Lista misurazioni relativi alla pratica'),
+ 'icon' => 'fa fa-list',
+ ],
+
+]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('document', __('Documento')) ?>
+ = $this->Paginator->sort('protocol_number', __('Numero protocollo')) ?>
+ = $this->Paginator->sort('protocol_date', __('Data')) ?>
+ = $this->Paginator->sort('user_id', __('Utente')) ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPaperworkPec->document) ?>
+ = h($waterDrawingPaperworkPec->protocol_number) ?>
+ = h($waterDrawingPaperworkPec->protocol_date) ?>
+ = h($waterDrawingPaperworkPec->user) ?>
+
+ = $waterDrawingPaperworkPec->can_edit_pec ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'edit', $waterDrawingPaperworkPec->id], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem']) : null; ?>
+ = $this->Html->link(__('Visualizza'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'view', $waterDrawingPaperworkPec->id], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']); ?>
+ = $waterDrawingPaperworkPec->can_delete_pec ? $this->Form->postLink(__('Cancella'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'delete', $waterDrawingPaperworkPec->id], ['confirm' => __('Sei sicuro che vuoi cancellare la documentazione PEC "{0}" ?', $waterDrawingPaperworkPec->id), 'class' => 'btn btn-danger btn-xs', 'style' => 'margin-right:1rem']) : null; ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworkPecs/view.php b/idrocap_wa/templates/WaterDrawingPaperworkPecs/view.php
new file mode 100644
index 0000000..17c80dc
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworkPecs/view.php
@@ -0,0 +1,61 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettaglio Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ //'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dettagli documento PEC'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPaperworkPec, ['role' => 'form', 'type' => 'file']); ?>
+
+ = $this->Form->control('document', ['label' => __('Documento'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('protocol_number', ['label' => __('Numero di protocollo'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('recipient', ['label' => __('Destinatario'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('sender', ['label' => __('Inviato da'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('protocol_date', ['label' => __('Data'), 'type' => 'date', 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+ element('attachments', [
+ 'coId' => $waterDrawingPaperworkPec->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'tags' => $tags,
+ 'currentFilesRemovable' => false,
+ 'view_in_frame_with_id' => false,
+ ]);
+ ?>
+ Form->control('note', ['label' => 'Note:', 'type' => 'textarea', 'disabled' => true]);
+ ?>
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/add.php b/idrocap_wa/templates/WaterDrawingPaperworks/add.php
new file mode 100644
index 0000000..f27d3aa
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/add.php
@@ -0,0 +1,632 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Gestione Pratica di attingimento'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file', 'id' => 'editWaterDrawingPaperwork']); ?>
+
+
+
+
+
+ element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tags,
+ 'required' => false,
+ 'accept_only' => ['.pdf'],
+ 'upload_single' => true,
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), "style" => "cursor: not-allowed", 'type' => 'text', "disabled" => true, 'value' => (isset($hide_authority_province) && $hide_authority_province) ? ($authority_civil_engineer_code ?? null) : null]) ?>
+
+
+ = $this->Cell("DistrictProvince", [new ProvinceCellDto(fieldId: "authority-province", fieldName: "authority_province", formContext: $waterDrawingPaperwork, autoFillTargetId: "authority-civil-engineer-code", autoFillTargetEnabled: true, fieldRequired: true, showProvinceFullName: true)]) ?>
+
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true]) ?>
+
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}']) ?>
+
+
+ = $this->Form->control('protocol_number', ['label' => __('Numero di protocollo della pratica'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'empty' => true, 'options' => $WaterDrawingArticles]) ?>
+
+
+
+
+
+
+
+
+
+ element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, "formContext" => $waterDrawingPaperwork]);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+ Cell('IntendedUses', ['intended_use_item_block' => 0]);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date']) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date']) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)')]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'max' => $today->format('Y-m-d')]) ?>
+
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)')]) ?>
+
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => 'text']) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date']) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date']) ?>
+
+
+
+
+
+
+
+ Form->end(); ?>
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/add_scan.php b/idrocap_wa/templates/WaterDrawingPaperworks/add_scan.php
new file mode 100644
index 0000000..1c9660a
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/add_scan.php
@@ -0,0 +1,49 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Nuova Pratica di attingimento Scansionata'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('water_drawing_paperwork_status_id', ['type' => 'hidden', 'value' => 1]);
+ echo $this->element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tags,
+ 'required' => false,
+ 'accept_only' => ['.pdf']
+ ]);
+ echo $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'required' => true]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/antimafia_request_to_anac.php b/idrocap_wa/templates/WaterDrawingPaperworks/antimafia_request_to_anac.php
new file mode 100644
index 0000000..867f848
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/antimafia_request_to_anac.php
@@ -0,0 +1,49 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Carica ricevuta della richiesta antimafia alla Pratica di attingimento'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tag,
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.pdf']
+ ]);
+ echo $this->Form->hidden('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/applicants_water_drawing_paperworks_item_block.php b/idrocap_wa/templates/WaterDrawingPaperworks/applicants_water_drawing_paperworks_item_block.php
new file mode 100644
index 0000000..093a6fe
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/applicants_water_drawing_paperworks_item_block.php
@@ -0,0 +1,5 @@
+= $this->element('WaterDrawingPaperworks/applicants', [
+ 'applicant_item_block' => $applicant_item_block,
+ 'water_drawing_paperwork_status_id' => isset($waterDrawingPaperwork) ? $waterDrawingPaperwork->water_drawing_paperwork_status_id : null,
+ 'water_drawing_paperwork_id' => isset($waterDrawingPaperwork) ? $waterDrawingPaperwork->id : null
+]);?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/assign.php b/idrocap_wa/templates/WaterDrawingPaperworks/assign.php
new file mode 100644
index 0000000..8d89319
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/assign.php
@@ -0,0 +1,48 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Assegna Pratica di attingimento'),
+ 'icon' => 'fa fa-user',
+ ],
+]);
+?>
+
+
+
+ = $this->Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Form->control(($organisation_type_id == 6 ? 'drar_user_id' : 'gc_user_id'), ['id' => 'select2user-id', 'label' => __('Ricerca utente'), 'type' => 'select', 'options' => $users, 'empty' => true, 'required' => true]); ?>
+
+
+
+
+ = $this->Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_index.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_index.php
new file mode 100644
index 0000000..65fd6c5
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_index.php
@@ -0,0 +1,115 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Lista documenti della richiesta di attingimento'),
+ 'icon' => 'fa fa-list',
+ ],
+]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('original_file_name', __('Nome del file')) ?>
+ = $this->Paginator->sort('mimetype', __('Tipologia file')) ?>
+ = $this->Paginator->sort('description', __('Tipologia documento')) ?>
+ = $this->Paginator->sort('upload_date', __('Caricato il')) ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = h($attachment->original_file_name) ?>
+ = h($attachment->mimetype) ?>
+ = h($attachment->tags[0]->description) ?>
+ = h($attachment->upload_date) ?>
+
+ = $this->Html->link(__('Visualizza'), ['controller' => 'Attachments', 'action' => 'view', $attachment->file_name], ['class' => 'btn btn-info btn-xs', 'target' => '_blank']) ?>
+ = ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 8 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == 11) ? $this->Html->link(__('Elimina'), ['action' => 'delete_attachment', $waterDrawingPaperwork->id, $attachment->id], ['class' => 'btn btn-warning btn-xs', 'confirm' => __('Sei sicuro di voler cancellare questo documento?')]) : ''?>
+
+
+
+
+
+
+
+ = $waterDrawingPaperwork->water_drawing_paperwork_status_id == 8 || $waterDrawingPaperwork->water_drawing_paperwork_status_id == 11 ? $this->Html->link(__('Aggiungi documentazione'), ['action' => 'citizen_documentation_requested', $waterDrawingPaperwork->id], ['class' => 'btn btn-success btn-xs']) : '' ?>
+ = $waterDrawingPaperwork->is_citizen_water_drawing_paperwork_ok_to_send() ? $this->Html->link(__('Invia richiesta'), ['action' => 'citizen_send_to_validation', $waterDrawingPaperwork->id], ['confirm' => __('Vuoi procedere con l\'invio ?'), 'class' => 'btn btn-info btn-xs']) : ''?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Paginator->sort('result', __('Esito della verifica')) ?>
+ = $this->Paginator->sort('note', __('Note')) ?>
+ = $this->Paginator->sort('created', __('Data e ora della verifica')) ?>
+ = __('Allegato') ?>
+
+
+
+
+
+ = h($waterDrawingPaperworkHistory->result == 1 ? 'Accettata' : 'Rifiutata') ?>
+ = h($waterDrawingPaperworkHistory->note) ?>
+ = h($waterDrawingPaperworkHistory->created) ?>
+ = !empty($waterDrawingPaperworkHistory->controllable_object->attachment_file_names) ? $this->Html->link(__('Visualizza'), ['controller' => 'Attachments', 'action' => 'view', array_keys($waterDrawingPaperworkHistory->controllable_object->attachment_file_names)[0]], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem', 'target' => '_blank']) : null ?>
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_requested.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_requested.php
new file mode 100644
index 0000000..30451d0
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_documentation_requested.php
@@ -0,0 +1,376 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Lista Documenti sottomessi della Pratica'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_documentation_index', $waterDrawingPaperwork->id],
+ ],
+ [
+ 'title' => __('Lista modulistica'),
+ 'icon' => 'fa fa-list',
+ ],
+]);
+?>
+
+
+
+
+
+
+
+
+
+ = __('Dichiarazione Piano anticorruzione (modello da allegare a tutte le istanze)') ?>
+
+
+ check_adam) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 5], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 5], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Istanza concessione acque superficiali art.7') ?>
+
+
+ check_rap) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 1], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 1], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+ = __('Istanza concessione acque sotterranee art.7') ?>
+
+
+ check_ia7) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 2], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 2], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+ = __('Istanza concessione art.56') ?>
+
+
+ check_ia56) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 3], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 3], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+ = __('Istanza Subentro art. 20') ?>
+
+
+ check_isu) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 6], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 6], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+ = __('Istanza Attingimento art. 30') ?>
+
+
+ check_ira) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 4], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 4], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+ = __('Istanza rinnovo concessione art.56') ?>
+
+
+ check_irc56) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 20], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 20], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Relazione tecnica (obbligatorio)') ?>
+
+
+ check_thc_a) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 7], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 7], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Certificato catastale ed estratto di mappa (obbligatorio)') ?>
+
+
+ check_thc_aa) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 8], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 8], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Titolo di proprietà in copia conforme all\'originale (obbligatorio)') ?>
+
+
+ check_thc_ab) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 9], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 9], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Planimetria del comprensorio (obbligatorio)') ?>
+
+
+ check_thc_ac) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 10], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 10], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Carta topografica in scala 1:25.000 edita dall\'IGM in originale (obbligatorio)') ?>
+
+
+ check_thc_ad) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 11], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 11], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Sezione quotata dell\'opera di captazione (obbligatorio)') ?>
+
+
+ check_thc_ae) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 12], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 12], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Disegni particolareggiati delle opere d\'arte principali') ?>
+
+
+ check_thc_af) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 13], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 13], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Identificazione catastale delle aree servite e comprensorio servito e planimetria catastale') ?>
+
+
+ check_thc_ag) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 14], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 14], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Relazione idrogeologica (obbligatorio)') ?>
+
+
+ check_thc_b) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 15], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 15], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Ubicazione del pozzo su tavoletta o stralcio topografico scala 1:25.000') ?>
+
+
+ check_thc_b1) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 16], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 16], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Carta idrogeologica scala 1:25.000 (obbligatorio)') ?>
+
+
+ check_thc_b2) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 17], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 17], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Schema dell\'opera di presa') ?>
+
+
+ check_thc_b3) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 18], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 18], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Sezione litostratigrafica del pozzo') ?>
+
+
+ check_thc_b4) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 19], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Compila il documento'), ['action' => 'citizen_upload_attachment', $waterDrawingPaperwork->id, 19], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+ = __('Ricevuta pagamento dei diritti di istruttoria') ?>
+
+
+ check_rpdi) { ?>
+
+ Html->link(__('Modifica'), ['action' => 'citizen_upload_payment_receipt', $waterDrawingPaperwork->id, -15], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } else {
+ echo $this->Html->link(__('Carica ricevuta'), ['action' => 'citizen_upload_payment_receipt', $waterDrawingPaperwork->id, -15], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ } ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_request_paperwork.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_request_paperwork.php
new file mode 100644
index 0000000..e183541
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_request_paperwork.php
@@ -0,0 +1,35 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Carica allegato'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+
+ Html->link(__('Per mio conto'), ['controller' => 'Applicants', 'action' => 'citizen_view'], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm']);
+ echo '
Per conto terzi
';
+ ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_submission_index.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_submission_index.php
new file mode 100644
index 0000000..b106d06
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_submission_index.php
@@ -0,0 +1,73 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ ],
+]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('id', __('ID')) ?>
+ = $this->Paginator->sort('authority_identification_code_civil_engineering_office', __('Codice identificativo')) ?>
+ = $this->Paginator->sort('WaterDrawingPaperworkStatuses.description', __('Stato')) ?>
+ = $this->Paginator->sort('authority_province', __('Provincia')) ?>
+ = $this->Paginator->sort('release_date', __('Data di rilascio')) ?>
+ = $this->Paginator->sort('expiration_date', __('Scadenza')) ?>
+ = $this->Paginator->sort('ControllableObjects.created', __('Creata il')) ?>
+ = $this->Paginator->sort('ControllableObjects.modified', __('Modificata il')) ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = $this->Number->format($waterDrawingPaperwork->id) ?>
+ = h($waterDrawingPaperwork->authority_identification_code_civil_engineering_office) ?>
+ water_drawing_paperwork_status->rgb) ? 'style="color:' . $waterDrawingPaperwork->water_drawing_paperwork_status->rgb . '"' : '' ?>>= h($waterDrawingPaperwork->water_drawing_paperwork_status->description) ?>
+ = h($waterDrawingPaperwork->authority_province) ?>
+ = h($waterDrawingPaperwork->release_date) ?>
+ = h($waterDrawingPaperwork->expiration_date) ?>
+ = h($waterDrawingPaperwork->controllable_object->created) ?>
+ = h($waterDrawingPaperwork->controllable_object->modified) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'citizen_documentation_index', $waterDrawingPaperwork->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_submit_paperwork.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_submit_paperwork.php
new file mode 100644
index 0000000..154293e
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_submit_paperwork.php
@@ -0,0 +1,46 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Selezione della provincia di competenza'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($applicant, ['role' => 'form', 'type' => 'file']); ?>
+
+ = $this->Cell("DistrictProvince", [new ProvinceCellDto(fieldId: "authority-province", fieldName: "authority_province", formContext: $applicant, autoFillTargetEnabled: false, fieldRequired: true, showProvinceFullName: true)]) ?>
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_attachment.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_attachment.php
new file mode 100644
index 0000000..ce7febd
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_attachment.php
@@ -0,0 +1,60 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Lista documenti della richiesta di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_documentation_index', $waterDrawingPaperwork->id],
+ ],
+ [
+ 'title' => __('Carica allegato'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ link != '') {
+ echo $this->Html->link($tag->description, ['controller' => 'Attachments', 'action' => 'view', $tag->link], ['target' => '_blank']);
+ echo $this->Html->link(__('Scarica'), ['controller' => 'Attachments', 'action' => 'view', $tag->link], ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm', 'target' => '_blank']);
+ }
+ echo $this->element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => [
+ $tag->code => $tag->description,
+ ],
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.p7m']
+ ]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_payment_receipt.php b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_payment_receipt.php
new file mode 100644
index 0000000..a73695f
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/citizen_upload_payment_receipt.php
@@ -0,0 +1,58 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Richieste di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_submission_index'],
+ ],
+ [
+ 'title' => __('Lista documenti della richiesta di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'citizen_documentation_index', $waterDrawingPaperwork->id],
+ ],
+ [
+ 'title' => __('Carica allegato'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ Html->link(__('Portale pagamenti - Regione Siciliana'), 'https://pagamenti.regione.sicilia.it/static/', ['target' => '_blank']);
+ echo $this->Html->link(__('Accedi al portale'), 'https://pagamenti.regione.sicilia.it/static/', ['style="margin-left:1rem;"', 'class' => 'btn btn-default btn-sm', 'target' => '_blank']);
+ echo $this->element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => [
+ $tag->code => $tag->description,
+ ],
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.pdf']
+ ]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/edit.php b/idrocap_wa/templates/WaterDrawingPaperworks/edit.php
new file mode 100644
index 0000000..119f9dd
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/edit.php
@@ -0,0 +1,641 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Modifica Pratica di attingimento'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+
+
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file', 'id' => 'editWaterDrawingPaperwork']); ?>
+
+
+
+
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => true,
+ 'tags' => $tags_picker,
+ 'required' => false,
+ 'accept_only' => ['.pdf'],
+ 'upload_single' => true,
+ ]);
+
+ echo $this->element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => true,
+ 'view_in_frame_with_id' => 'previewiframe',
+ 'tags' => $tags_viewer,
+ 'required' => false
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), "style" => "cursor: not-allowed", 'type' => 'text', "disabled" => true, 'value' => (isset($hide_authority_province) && $hide_authority_province) ? ($authority_civil_engineer_code ?? null) : null]) ?>
+
+
+ = $this->Cell("DistrictProvince", [new ProvinceCellDto(fieldId: "authority-province", fieldName: "authority_province", formContext: $waterDrawingPaperwork, autoFillTargetId: "authority-civil-engineer-code", autoFillTargetEnabled: true, fieldRequired: true, showProvinceFullName: true)]) ?>
+
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true]) ?>
+
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}']) ?>
+
+
+ = $this->Form->control('protocol_number', ['label' => __('Numero di protocollo della pratica'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'empty' => true, 'options' => $waterDrawingArticles]) ?>
+
+
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, "formContext" => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'applicant' => $applicant, "formContext" => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+ water_drawing_intended_uses) == 0) echo $this->Cell('IntendedUses', ['intended_use_item_block' => 0]);
+ foreach ($waterDrawingPaperwork->water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes, 'wateringSystems' => $wateringSystems]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date']) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date']) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)')]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'max' => $today->format('Y-m-d')]) ?>
+
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)')]) ?>
+
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => 'text']) ?>
+
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => 'text']) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date']) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date']) ?>
+
+
+
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/edit_scan.php b/idrocap_wa/templates/WaterDrawingPaperworks/edit_scan.php
new file mode 100644
index 0000000..9eff8e2
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/edit_scan.php
@@ -0,0 +1,667 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Modifica Pratica di attingimento scansionata'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+
+
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file', 'id' => 'editWaterDrawingPaperwork']); ?>
+
+
+
+
+
+ Form->control('water_drawing_paperwork_status_id', ['type' => 'hidden', 'value' => $waterDrawingPaperwork->water_drawing_paperwork_status_id >= 6 ? $waterDrawingPaperwork->water_drawing_paperwork_status_id : ($waterDrawingPaperwork->water_drawing_paperwork_status_id == 4 ? 5 : 3)]);
+ echo $this->element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => true,
+ 'tags' => $tags_picker,
+ 'required' => false,
+ 'accept_only' => ['.pdf'],
+ 'upload_single' => true,
+ ]);
+
+ echo $this->element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => true,
+ 'view_in_frame_with_id' => 'previewiframe',
+ 'tags' => $tags_viewer,
+ 'required' => false
+ ]);
+ ?>
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), "style" => "cursor: not-allowed", 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), "disabled" => true]) ?>
+
+ = $this->Cell(
+ "DistrictProvince",
+ [
+ new ProvinceCellDto(
+ fieldId: "authority-province",
+ fieldName: "authority_province",
+ formContext: $waterDrawingPaperwork,
+ autoFillTargetId: "authority-civil-engineer-code",
+ autoFillTargetEnabled: true,
+ fieldRequired: true,
+ fieldType: ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? InputFieldType::SELECT : InputFieldType::HIDDEN),
+ showProvinceFullName: true
+ )
+ ]
+ ) ?>
+
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text']) ?>
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden')]) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'select' : 'hidden'), 'options' => $waterDrawingArticles]) ?>
+
+
+
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, 'water_drawing_paperwork_status_id' => $waterDrawingPaperwork->water_drawing_paperwork_status_id, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'water_drawing_paperwork_status_id' => $waterDrawingPaperwork->water_drawing_paperwork_status_id, 'applicant' => $applicant, 'water_drawing_paperwork_id' => $waterDrawingPaperwork->id, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+
+ water_drawing_paperwork_status_id > 3) : ?>
+
+
+
+
+ water_drawing_intended_uses) == 0) echo $this->Cell('IntendedUses', ['intended_use_item_block' => 0]);
+ foreach ($waterDrawingPaperwork->water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes, 'wateringSystems' => $wateringSystems]);
+ }
+ ?>
+
+
+
+
+
+
+ water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date']) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date']) ?>
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden')]) ?>
+
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden')]) ?>
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)')]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'style' => 'margin-left: 5px;']) ?>
+
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'number' : 'hidden'), 'pattern' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? '[0-9]*' : '')]) ?>
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)'), 'style' => 'margin-left: 5px;']) ?>
+
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden')]) ?>
+
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden')]) ?>
+
+
+
+
+
+ water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date']) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'min' => 0]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id === 1): ?>
+
+ = $this->Html->script('ia-form-filler/dist/entrypoints/content.js', ['type' => 'module']) ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/index.php b/idrocap_wa/templates/WaterDrawingPaperworks/index.php
new file mode 100644
index 0000000..d0a942c
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/index.php
@@ -0,0 +1,81 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('id', __('ID')) ?>
+ = $this->Paginator->sort('authority_identification_code_civil_engineering_office', __('Codice identificativo')) ?>
+ = $this->Paginator->sort('WaterDrawingPaperworkStatuses.description', __('Stato')) ?>
+ = $this->Paginator->sort('authority_province', __('Provincia')) ?>
+ = $this->Paginator->sort('release_date', __('Data di rilascio')) ?>
+ = $this->Paginator->sort('expiration_date', __('Scadenza')) ?>
+ = __('% avanzamento') ?>
+ = $this->Paginator->sort('ControllableObjects.created', __('Creata il')) ?>
+ = $this->Paginator->sort('ControllableObjects.modified', __('Modificata il')) ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = $this->Number->format($waterDrawingPaperwork->id) ?>
+ = h($waterDrawingPaperwork->authority_identification_code_civil_engineering_office) ?>
+ water_drawing_paperwork_status->rgb) ? 'style="color:'. $waterDrawingPaperwork->water_drawing_paperwork_status->rgb . '"' : '' ?>>= h($waterDrawingPaperwork->water_drawing_paperwork_status->description) ?>
+ = h($waterDrawingPaperwork->authority_province) ?>
+ = h($waterDrawingPaperwork->release_date) ?>
+ = h($waterDrawingPaperwork->expiration_date) ?>
+ = h($waterDrawingPaperwork->percentage) ?>
+ = h($waterDrawingPaperwork->controllable_object->created) ?>
+ = h($waterDrawingPaperwork->controllable_object->modified) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => ($waterDrawingPaperwork->scanned ? 'view_scan' : 'view'), $waterDrawingPaperwork->id], ['class'=>'btn btn-info btn-xs']) ?>
+ = $waterDrawingPaperwork->can_edit ? $this->Html->link(__('Modifica'), ['action' => ($waterDrawingPaperwork->scanned ? 'edit_scan' : 'edit'), $waterDrawingPaperwork->id], ['class'=>'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $waterDrawingPaperwork->id], ['confirm' => __('Sei sicuro che vuoi cancellare la pratica di attingimento con ID:"{0}" ?', $waterDrawingPaperwork->id), 'class'=>'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots.php b/idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots.php
new file mode 100644
index 0000000..ee61e92
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots.php
@@ -0,0 +1,80 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Storico Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('when', __('Data')) ?>
+ = $this->Paginator->sort('who', __('Da')) ?>
+ = $this->Paginator->sort('what', __('Azione')) ?>
+ = $this->Paginator->sort('water_drawing_paperwork_status', __('Stato Pratica')) ?>
+ = $this->Paginator->sort('gc_user', __('Assegnatario Genio Civile')) ?>
+ = $this->Paginator->sort('drar_user', __('Assegnatario DRAR')) ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = h(isset($unpackedWaterDrawingPaperworkSnapshot->when) ? (new DateTime($unpackedWaterDrawingPaperworkSnapshot->when))->i18nFormat('dd/MM/Y HH:mm:ss', $logged_user_timezone) : null) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->who) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->what) ?>
+ = H($unpackedWaterDrawingPaperworkSnapshot->water_drawing_paperwork_status) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->gc_user) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->drar_user) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => ($waterDrawingPaperwork->scanned ? 'view_scan_snapshot' : 'view_snapshot'), $unpackedWaterDrawingPaperworkSnapshot->snapshot_id], ['class'=>'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots_all.php b/idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots_all.php
new file mode 100644
index 0000000..deadc64
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/index_snapshots_all.php
@@ -0,0 +1,77 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Logs Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('when', __('Data')) ?>
+ = $this->Paginator->sort('who', __('Da')) ?>
+ = $this->Paginator->sort('what', __('Azione')) ?>
+ = $this->Paginator->sort('water_drawing_paperwork_id', __('ID Pratica')) ?>
+ = $this->Paginator->sort('water_drawing_paperwork_status', __('Stato Pratica')) ?>
+ = $this->Paginator->sort('gc_user', __('Assegnatario Genio Civile')) ?>
+ = $this->Paginator->sort('drar_user', __('Assegnatario DRAR')) ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = h(isset($unpackedWaterDrawingPaperworkSnapshot->when) ? (new DateTime($unpackedWaterDrawingPaperworkSnapshot->when))->i18nFormat('dd/MM/Y HH:mm:ss', $logged_user_timezone) : null) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->who) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->what) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->water_drawing_paperwork_id) ?>
+ = H($unpackedWaterDrawingPaperworkSnapshot->water_drawing_paperwork_status) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->gc_user) ?>
+ = h($unpackedWaterDrawingPaperworkSnapshot->drar_user) ?>
+
+ = $this->Html->link(__('Dettaglio'), ['action' => 'view_snapshot', $unpackedWaterDrawingPaperworkSnapshot->snapshot_id, '?' => ['origin' => 'logs']], ['class'=>'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/intended_uses_water_drawing_paperworks_item_block.php b/idrocap_wa/templates/WaterDrawingPaperworks/intended_uses_water_drawing_paperworks_item_block.php
new file mode 100644
index 0000000..316ef1b
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/intended_uses_water_drawing_paperworks_item_block.php
@@ -0,0 +1 @@
+= $this->Cell('IntendedUses', ['intended_use_item_block' => ($intended_use_item_block)]);?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/upload_antimafia_attachment.php b/idrocap_wa/templates/WaterDrawingPaperworks/upload_antimafia_attachment.php
new file mode 100644
index 0000000..fe9e69b
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/upload_antimafia_attachment.php
@@ -0,0 +1,49 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Carica antimafia alla Pratica di attingimento'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tag,
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.pdf']
+ ]);
+ echo $this->Form->hidden('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment.php b/idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment.php
new file mode 100644
index 0000000..8720542
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment.php
@@ -0,0 +1,50 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Carica allegato Pratica di attingimento'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tag,
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.pdf']
+ ]);
+ echo $this->Form->hidden('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment_scan.php b/idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment_scan.php
new file mode 100644
index 0000000..f8ee0b4
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/upload_attachment_scan.php
@@ -0,0 +1,50 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Carica allegato Pratica di attingimento scansionata'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($waterDrawingPaperwork, ['role' => 'form', 'type' => 'file']); ?>
+
+ Form->control('water_drawing_paperwork_status_id', ['type' => 'hidden', 'value' => 1]);
+ echo $this->element('attachments', [
+ 'filepicker' => true,
+ 'viewer' => false,
+ 'currentFilesRemovable' => false,
+ 'tags' => $tag,
+ 'required' => true,
+ 'upload_single' => true,
+ 'accept_only' => ['.pdf']
+ ]);
+ echo $this->Form->hidden('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true]);
+ ?>
+
+
+ Form->end(); ?>
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/validate.php b/idrocap_wa/templates/WaterDrawingPaperworks/validate.php
new file mode 100644
index 0000000..146fdae
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/validate.php
@@ -0,0 +1,713 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Validazione Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+
+ = __('Accesso rapido a:') ?>
+
+
+
+
+Form->create($waterDrawingPaperwork, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+
+ = $this->Form->control('water_drawing_paperwork_status.description', ['label' => __('Stato della pratica'), 'type' => 'text', 'disabled' => true, 'required' => false]) ?>
+ = $this->Form->control('gc_user', ['label' => __('Assegnatario Genio Civile'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('drar_user', ['label' => __('Assegnatario DRAR'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ = __('Documenti Tecnici (THC)') ?>
+ = __('Documenti Vari (DV)') ?>
+ = __('Licenza di attingimento (LIC)') ?>
+ = __('Decreto di Derivazione (DEC)') ?>
+ = __('Schema del Disciplinare (SDD)') ?>
+ = __('Disciplinare (DSC)') ?>
+ = __('Modulo 2A (2A)') ?>
+ = __('Documento antimafia (DAM)') ?>
+
+
+
+ = $waterDrawingPaperwork->check_thc ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check_dv ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check_lic ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check_dec ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check_sdd ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check_dsc ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check2a ? __('Presente') : __('Assente ')?>
+ = $waterDrawingPaperwork->check_dam ? __('Presente') : __('Assente ')?>
+
+
+
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => false,
+ 'view_in_frame_with_id' => 'previewiframe',
+ 'tags' => null
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), 'type' => 'text', 'disabled' => true]) ?>
+
+ = $this->Cell("DistrictProvince", [new ProvinceCellDto(fieldId: "authority-province", fieldName: "authority_province", formContext: $waterDrawingPaperwork, fieldRequired: true, disabled: true, showProvinceFullName: true)]) ?>
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'options' => $WaterDrawingArticles, 'empty' => true, 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, 'is_view' => true, "formContext" => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'is_view' => true, "formContext" => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Tipo derivazione') ?>
+ = __('Corpo idrico') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Stato') ?>
+ = __('Volume (m^3)') ?>
+ = __('Portata (l/s)') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_derivations as $waterDrawingDerivation) : ?>
+
+ = h($waterDrawingDerivation->latitude . ', ' . $waterDrawingDerivation->longitude) ?>
+ = h(isset($waterDrawingDerivation->water_drawing_derivation_type_id) ? $waterDrawingDerivation->water_drawing_derivation_type->description : null) ?>
+ = h($waterDrawingDerivation->water_body) ?>
+ = h($waterDrawingDerivation->district) ?>
+ = h($waterDrawingDerivation->cadastral_sheet) ?>
+ = h($waterDrawingDerivation->cadastral_parcel) ?>
+ = h($waterDrawingDerivation->derivation_status) ?>
+ = h($waterDrawingDerivation->annual_volume) ?>
+ = $waterDrawingDerivation->average_flow_rate ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'WaterDrawingDerivations', 'action' => 'view', $waterDrawingDerivation->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'is_view' => true, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_return_points as $waterDrawingReturnPoint) : ?>
+
+ = h($waterDrawingReturnPoint->latitude . ', ' . $waterDrawingReturnPoint->longitude) ?>
+ = h($waterDrawingReturnPoint->district) ?>
+ = h($waterDrawingReturnPoint->cadastral_sheet) ?>
+ = h($waterDrawingReturnPoint->cadastral_parcel) ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'waterDrawingReturnPoints', 'action' => 'view', $waterDrawingReturnPoint->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => 'number', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+ can_view_fee): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Canone') ?>
+ = __('Dovuto') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_fees as $waterDrawingFees) : ?>
+
+ = h($waterDrawingFees->year) ?>
+ = h($waterDrawingFees->amount . ' €') ?>
+ = h($waterDrawingFees->to_pay . ' €') ?>
+
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingFees', 'action' => 'view', $waterDrawingFees->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+ can_view_payment): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Data inserimento') ?>
+ = __('Utente') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee->year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->created) ?>
+ = h($waterDrawingPayment->user) ?>
+
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingPayments', 'action' => 'view', $waterDrawingPayment->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id <= -4) : ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Tipologia di uso') ?>
+ = __('Tipologia strumento di misura') ?>
+ = __('Data installazione') ?>
+ = __('Marca ') ?>
+ = __('Matricola') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_intended_uses as $waterDrawingIntendedUse) :
+ if (isset($waterDrawingIntendedUse->water_drawing_intended_use_type_id)):
+ ?>
+
+ = h($waterDrawingIntendedUse->water_drawing_intended_use_type->description) ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->water_drawing_tool_type->description : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->installation_date->format('d/m/Y') : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->manufacturer : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->part_number : '') ?>
+ water_drawing_meters[0]->id)) {
+ echo $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingMeters', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:0.5rem']);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+
+ = __('Utente') ?>
+ = __('Stato') ?>
+ = __('Data e ora') ?>
+
+
+
+ water_drawing_antimafia_certification_requests as $waterDrawinAntimafiaRequest) : ?>
+
+ = h($waterDrawinAntimafiaRequest->user) ?>
+ water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? 'style="color:red;"' : null ?>>= h($waterDrawinAntimafiaRequest->water_drawing_antimafia_certification_request_status->description) . ($waterDrawinAntimafiaRequest->water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? __(' - Richiesta scaduta') : null) ?>
+ water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? 'style="color:red;"' : null ?>>= h($waterDrawinAntimafiaRequest->created) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Documento') ?>
+ = __('Numero protocollo') ?>
+ = __('Data') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_paperwork_pecs as $waterDrawingPaperworkPec) : ?>
+
+ = h($waterDrawingPaperworkPec->document) ?>
+ = h($waterDrawingPaperworkPec->protocol_number) ?>
+ = h($waterDrawingPaperworkPec->protocol_date->format('d/m/Y')) ?>
+
+ = $this->Html->link(__('Visualizza'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'view', $waterDrawingPaperworkPec->id], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']); ?>
+
+
+
+
+
+
+
+
+= $this->Form->end() ?>
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/validate_index.php b/idrocap_wa/templates/WaterDrawingPaperworks/validate_index.php
new file mode 100644
index 0000000..0853e7b
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/validate_index.php
@@ -0,0 +1,71 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento da validare'),
+ 'icon' => 'fa fa-list',
+ ],
+ ]);
+?>
+
+
+
+
+
+
+
+ = $this->Paginator->sort('id', __('ID')) ?>
+ = $this->Paginator->sort('WaterDrawingPaperworkStatuses.description', __('Stato')) ?>
+ = $this->Paginator->sort('district', __('Comune')) ?>
+ = $this->Paginator->sort('release_date', __('Data di rilascio')) ?>
+ = $this->Paginator->sort('concession_duration', __('Durata della Derivazione (anni)')) ?>
+ = $this->Paginator->sort('expiration_date', __('Scadenza')) ?>
+ = $this->Paginator->sort('ControllableObjects.created', __('Creata il')) ?>
+ = $this->Paginator->sort('ControllableObjects.modified', __('Modificata il')) ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = $this->Number->format($waterDrawingPaperwork->id) ?>
+ = h($waterDrawingPaperwork->water_drawing_paperwork_status->description) ?>
+ = h($waterDrawingPaperwork->district) ?>
+ = h($waterDrawingPaperwork->release_date) ?>
+ = isset($waterDrawingPaperwork->concession_duration) ? $this->Number->format($waterDrawingPaperwork->concession_duration) : '' ?>
+ = h($waterDrawingPaperwork->expiration_date) ?>
+ = h($waterDrawingPaperwork->controllable_object->created) ?>
+ = h($waterDrawingPaperwork->controllable_object->modified) ?>
+
+ = $waterDrawingPaperwork->can_validate ? $this->Html->link(__('Valida'), ['controller' => 'WaterDrawingPaperworks', 'action' => ( $waterDrawingPaperwork->scanned ? 'validate_scan' : 'validate'), $waterDrawingPaperwork->id], ['class'=>'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/validate_scan.php b/idrocap_wa/templates/WaterDrawingPaperworks/validate_scan.php
new file mode 100644
index 0000000..a8764c7
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/validate_scan.php
@@ -0,0 +1,728 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento scansionata'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+
+ = __('Accesso rapido a:') ?>
+
+ Info amministrative
+
+ Richiedente/Ditta
+
+ water_drawing_paperwork_status_id > 5): ?>
+ Punto di prelievo/derivazione
+
+ water_drawing_paperwork_status_id > 3):
+ ?>
+ Impiego Risorsa
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Punto di restituzione
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Periodo richiesto di prelievo
+
+
+ Info del provvedimento
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Canone
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Strumenti di misura
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Misurazione piezometrica
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Antimafia
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Documentazione PEC
+
+
+ Scorri in
+ fondo
+
+
+
+
+
+Form->create($waterDrawingPaperwork, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+
+ = $this->Form->control('water_drawing_paperwork_status.description', ['label' => __('Stato della pratica'), 'type' => 'text', 'disabled' => true, 'required' => false]) ?>
+
+
+
+
+
+
+
+
+
+ = __('Documenti Tecnici (THC)') ?>
+ = __('Documenti Vari (DV)') ?>
+ = __('Licenza di attingimento (LIC)') ?>
+ = __('Decreto di Derivazione (DEC)') ?>
+ = __('Schema del Disciplinare (SDD)') ?>
+ = __('Disciplinare (DSC)') ?>
+ = __('Modulo 2A (2A)') ?>
+ = __('Documento antimafia (DAM)') ?>
+
+
+
+ = $waterDrawingPaperwork->check_thc ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -8], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dv ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -7], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_lic ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -6], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dec ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -5], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_sdd ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -10], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dsc ? __('Presente') : __('Assente ') . (((($logged_user_id === $waterDrawingPaperwork->gc_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < 0) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -4], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check2a ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -3], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dam ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_upload_antimafia_attachment) ? $this->Html->link(__('Carica'), ['action' => 'upload_antimafia_attachment', $waterDrawingPaperwork->id], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+
+
+
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => false,
+ 'view_in_frame_with_id' => 'previewiframe',
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+ = $this->Cell("DistrictProvince", [
+ new ProvinceCellDto(
+ fieldId: "authority-province",
+ fieldName: "authority_province",
+ formContext: $waterDrawingPaperwork,
+ fieldRequired: true,
+ disabled: true,
+ fieldType: ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? InputFieldType::SELECT : InputFieldType::HIDDEN),
+ showProvinceFullName: true
+ )
+ ]
+ ) ?>
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'select' : 'hidden'), 'options' => $waterDrawingArticles, 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, 'water_drawing_paperwork_status_id' => $waterDrawingPaperwork->water_drawing_paperwork_status_id, 'is_view' => true, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'water_drawing_paperwork_status_id' => $waterDrawingPaperwork->water_drawing_paperwork_status_id, 'is_view' => true, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+water_drawing_paperwork_status_id > 5): ?>
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Tipo derivazione') ?>
+ = __('Corpo idrico') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Stato') ?>
+ = __('Volume (m^3)') ?>
+ = __('Portata (l/s)') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_derivations as $waterDrawingDerivation) : ?>
+
+ = h($waterDrawingDerivation->latitude . ', ' . $waterDrawingDerivation->longitude) ?>
+ = h(isset($waterDrawingDerivation->water_drawing_derivation_type_id) ? $waterDrawingDerivation->water_drawing_derivation_type->description : null) ?>
+ = h($waterDrawingDerivation->water_body) ?>
+ = h($waterDrawingDerivation->district) ?>
+ = h($waterDrawingDerivation->cadastral_sheet) ?>
+ = h($waterDrawingDerivation->cadastral_parcel) ?>
+ = h($waterDrawingDerivation->derivation_status) ?>
+ = h($waterDrawingDerivation->annual_volume) ?>
+ = $waterDrawingDerivation->average_flow_rate ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'WaterDrawingDerivations', 'action' => 'view', $waterDrawingDerivation->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 3) : ?>
+
+
+
+
+ water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'is_view' => true, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes]);
+ }
+ ?>
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_return_points as $waterDrawingReturnPoint) : ?>
+
+ = h($waterDrawingReturnPoint->latitude . ', ' . $waterDrawingReturnPoint->longitude) ?>
+ = h($waterDrawingReturnPoint->district) ?>
+ = h($waterDrawingReturnPoint->cadastral_sheet) ?>
+ = h($waterDrawingReturnPoint->cadastral_parcel) ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'waterDrawingReturnPoints', 'action' => 'view', $waterDrawingReturnPoint->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'number' : 'hidden'), 'pattern' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? '[0-9]*' : ''), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)'), 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+ can_view_fee): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Canone') ?>
+ = __('Dovuto') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_fees as $waterDrawingFees) : ?>
+
+ = h($waterDrawingFees->year) ?>
+ = h($waterDrawingFees->amount . ' €') ?>
+ = h($waterDrawingFees->to_pay . ' €') ?>
+
+ = $waterDrawingPaperwork->can_add_payment ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingFees', 'action' => 'edit', $waterDrawingFees->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingFees', 'action' => 'view', $waterDrawingFees->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+ can_view_payment): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Data inserimento') ?>
+ = __('Utente') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee->year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->created) ?>
+ = h($waterDrawingPayment->user) ?>
+
+ = $waterDrawingPaperwork->can_add_payment ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPayments', 'action' => 'edit', $waterDrawingPayment->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingPayments', 'action' => 'view', $waterDrawingPayment->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id <= -4) : ?>
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+
+ = __('Tipologia di uso') ?>
+ = __('Tipologia strumento di misura') ?>
+ = __('Data installazione') ?>
+ = __('Marca ') ?>
+ = __('Matricola') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_intended_uses as $waterDrawingIntendedUse) :
+ if (isset($waterDrawingIntendedUse->water_drawing_intended_use_type_id)):
+ ?>
+
+ = h($waterDrawingIntendedUse->water_drawing_intended_use_type->description) ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->water_drawing_tool_type->description : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->installation_date->format('d/m/Y') : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->manufacturer : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->part_number : '') ?>
+ water_drawing_meters[0]->id)) {
+ echo $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingMeters', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-info btn-xs']);
+ echo $this->Html->link(__('Dismetti'), ['controller' => 'WaterDrawingMeters', 'action' => 'dismiss', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-danger btn-xs']);
+ } else {
+ echo $this->Html->link(__('Aggiungi strumento di misura'), ['controller' => 'WaterDrawingMeters', 'action' => 'add', $waterDrawingIntendedUse->id], ['class' => 'btn btn-success btn-xs']);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Paginator->sort('result', __('Esito della verifica')) ?>
+ = $this->Paginator->sort('note', __('Note')) ?>
+ = $this->Paginator->sort('user_id', __('Utente')) ?>
+ = $this->Paginator->sort('created', __('Data e ora della verifica')) ?>
+ = __('Allegato') ?>
+
+
+
+
+
+ = h($waterDrawingPaperworkHistory->result == 1 ? 'Accettata' : 'Rifiutata') ?>
+ = h($waterDrawingPaperworkHistory->note) ?>
+ = h($waterDrawingPaperworkHistory->user) ?>
+ = h($waterDrawingPaperworkHistory->created) ?>
+ = !empty($waterDrawingPaperworkHistory->controllable_object->attachment_file_names) ? $this->Html->link(__('Visualizza'), ['controller' => 'Attachments', 'action' => 'view', array_keys($waterDrawingPaperworkHistory->controllable_object->attachment_file_names)[0]], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem', 'target' => '_blank']) : null ?>
+
+
+
+
+
+
+Form->end();
+echo $this->Form->create($waterDrawingPaperworkHistory, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']);
+?>
+
+
+
+
+
+
+ = $this->Form->control('result', ['label' => __('Esito'), 'onChange' => 'checkNote()', 'type' => 'radio', 'options' => [1 => __('Accettata'), 0 => __('Respinta')]]); ?>
+
+
+ = $this->Form->control('note', ['label' => __('Note'), 'type' => 'textarea']); ?>
+
+
+
+
+
+ = $this->Form->end() ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/view.php b/idrocap_wa/templates/WaterDrawingPaperworks/view.php
new file mode 100644
index 0000000..93e5af4
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/view.php
@@ -0,0 +1,768 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+
+
+
+ = __('Accesso rapido a:') ?>
+
+
+
+
+ Info amministrative
+
+ Richiedente/Ditta
+
+ Punto di prelievo/derivazione
+
+ Impiego Risorsa
+
+ Punto di restituzione
+
+ Periodo richiesto di prelievo
+
+ Info del provvedimento
+
+ can_view_fee && $waterDrawingPaperwork->can_view_payment): ?>
+ Canone
+
+
+ Strumenti di misura
+
+ Misurazione piezometrica
+
+ Antimafia
+
+ Documentazione PEC
+
+ Scorri in
+ fondo
+
+
+
+
+
+
+Form->create($waterDrawingPaperwork, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+
+ = $this->Form->control('water_drawing_paperwork_status.description', ['label' => __('Stato della pratica'), 'type' => 'text', 'disabled' => true, 'required' => false]) ?>
+ = $this->Form->control('gc_user', ['label' => __('Assegnatario Genio Civile'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('drar_user', ['label' => __('Assegnatario DRAR'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ = __('Documenti Tecnici (THC)') ?>
+ = __('Documenti Vari (DV)') ?>
+ = __('Licenza di attingimento (LIC)') ?>
+ = __('Decreto di Derivazione (DEC)') ?>
+ = __('Schema del Disciplinare (SDD)') ?>
+ = __('Disciplinare (DSC)') ?>
+ = __('Modulo 2A (2A)') ?>
+ = __('Ricevuta richiesta antimafia (RAM)') ?>
+ = __('Documento antimafia (DAM)') ?>
+
+
+
+ = $waterDrawingPaperwork->check_thc ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -8], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dv ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -7], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_lic ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -6], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dec ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -5], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_sdd ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -10], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dsc ? __('Presente') : __('Assente ') . (((($logged_user_id === $waterDrawingPaperwork->gc_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < 0) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -4], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check2a ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -3], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_ram ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_antimafia_request_to_anac) ? $this->Html->link(__('Carica'), ['action' => 'antimafia_request_to_anac', $waterDrawingPaperwork->id], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = ($waterDrawingPaperwork->check_adam || $waterDrawingPaperwork->check_dam) ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_upload_antimafia_attachment) ? $this->Html->link(__('Carica'), ['action' => 'upload_antimafia_attachment', $waterDrawingPaperwork->id], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+
+
+
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => false,
+ 'view_in_frame_with_id' => 'previewiframe',
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), 'type' => 'text', 'disabled' => true]) ?>
+
+ = $this->Cell("DistrictProvince", [new ProvinceCellDto(fieldId: "authority-province", fieldName: "authority_province", formContext: $waterDrawingPaperwork, fieldRequired: true, disabled: true, showProvinceFullName: true)]) ?>
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('protocol_number', ['label' => __('Numero di protocollo della pratica'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'options' => $WaterDrawingArticles, 'empty' => true, 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, 'is_view' => true, "formContext" => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'is_view' => true, "formContext" => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Tipo derivazione') ?>
+ = __('Corpo idrico') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Stato') ?>
+ = __('Volume (m^3)') ?>
+ = __('Portata (l/s)') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_derivations as $waterDrawingDerivation) : ?>
+
+ = h(isset ($waterDrawingDerivation->latitude, $waterDrawingDerivation->longitude) ? (number_format((float) $waterDrawingDerivation->latitude, 4) . ', ' . number_format((float) $waterDrawingDerivation->longitude, 4)) : '')?>
+ = h(isset($waterDrawingDerivation->water_drawing_derivation_type_id) ? $waterDrawingDerivation->water_drawing_derivation_type->description : null) ?>
+ = h($waterDrawingDerivation->water_body) ?>
+ = h($waterDrawingDerivation->district) ?>
+ = h($waterDrawingDerivation->cadastral_sheet) ?>
+ = h($waterDrawingDerivation->cadastral_parcel) ?>
+ = h($waterDrawingDerivation->derivation_status) ?>
+ = h($waterDrawingDerivation->annual_volume) ?>
+ = $waterDrawingDerivation->average_flow_rate ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'WaterDrawingDerivations', 'action' => 'view', $waterDrawingDerivation->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'is_view' => true, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes, 'wateringSystems' => $wateringSystems]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_return_points as $waterDrawingReturnPoint) : ?>
+
+ = h(isset ($waterDrawingDerivation->latitude, $waterDrawingDerivation->longitude) ? (number_format((float) $waterDrawingDerivation->latitude, 4) . ', ' . number_format((float) $waterDrawingDerivation->longitude, 4)) : '')?>
+ = h($waterDrawingReturnPoint->district) ?>
+ = h($waterDrawingReturnPoint->cadastral_sheet) ?>
+ = h($waterDrawingReturnPoint->cadastral_parcel) ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'waterDrawingReturnPoints', 'action' => 'view', $waterDrawingReturnPoint->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => 'number', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+can_view_fee && $waterDrawingPaperwork->can_view_payment): ?>
+
+
+
+ can_view_fee): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Canone') ?>
+ = __('Dovuto') ?>
+ = __('Pagato') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_fees as $waterDrawingFees) : ?>
+
+ = h($waterDrawingFees->year) ?>
+ = h($waterDrawingFees->amount . ' €') ?>
+ = h($waterDrawingFees->to_pay . ' €') ?>
+ = h($waterDrawingFees->paied ? 'SI' : 'NO') ?>
+
+ = $waterDrawingPaperwork->can_add_payment ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingFees', 'action' => 'edit', $waterDrawingFees->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingFees', 'action' => 'view', $waterDrawingFees->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+ can_view_payment): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Codice fiscale concessionario') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee->year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->applicant_tax_code) ?>
+
+ = $waterDrawingPaperwork->can_add_payment ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPayments', 'action' => 'edit', $waterDrawingPayment->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingPayments', 'action' => 'view', $waterDrawingPayment->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_delete_payment ? $this->Form->postLink(__('Cancella'), ['controller' => 'WaterDrawingPayments', 'action' => 'delete', $waterDrawingPayment->id], ['confirm' => __('Sei sicuro che vuoi cancellare il pagamento n° "{0}" ?', $waterDrawingPayment->payment_number), 'class' => 'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id <= -4) : ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Tipologia di uso') ?>
+ = __('Tipologia strumento di misura') ?>
+ = __('Data installazione') ?>
+ = __('Marca ') ?>
+ = __('Matricola') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_intended_uses as $waterDrawingIntendedUse) :
+ if (isset($waterDrawingIntendedUse->water_drawing_intended_use_type_id)):
+ ?>
+
+ = h($waterDrawingIntendedUse->water_drawing_intended_use_type->description) ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->water_drawing_tool_type->description : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->installation_date?->format('d/m/Y') : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->manufacturer : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->part_number : '') ?>
+ water_drawing_meters[0]->id)) {
+ echo $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingMeters', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:0.5rem']);
+ echo $this->Html->link(__('Dismetti'), ['controller' => 'WaterDrawingMeters', 'action' => 'dismiss', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-danger btn-xs']);
+ } else {
+ echo $this->Html->link(__('Aggiungi strumento di misura'), ['controller' => 'WaterDrawingMeters', 'action' => 'add', $waterDrawingIntendedUse->id], ['class' => 'btn btn-success btn-xs', 'style' => 'margin-right:1rem']);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+
+ = __('Utente') ?>
+ = __('Stato') ?>
+ = __('Data e ora') ?>
+
+
+
+ water_drawing_antimafia_certification_requests as $waterDrawinAntimafiaRequest) : ?>
+
+ = h($waterDrawinAntimafiaRequest->user) ?>
+ water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? 'style="color:red;"' : null ?>>= h($waterDrawinAntimafiaRequest->water_drawing_antimafia_certification_request_status->description) . ($waterDrawinAntimafiaRequest->water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? __(' - Richiesta scaduta') : null) ?>
+ water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? 'style="color:red;"' : null ?>>= h($waterDrawinAntimafiaRequest->created) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Documento') ?>
+ = __('Numero protocollo') ?>
+ = __('Data') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_paperwork_pecs as $waterDrawingPaperworkPec) : ?>
+
+ = h($waterDrawingPaperworkPec->document) ?>
+ = h($waterDrawingPaperworkPec->protocol_number) ?>
+ = h($waterDrawingPaperworkPec->protocol_date->format('d/m/Y')) ?>
+
+ = $waterDrawingPaperwork->can_edit_pec ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'edit', $waterDrawingPaperworkPec->id], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem']) : null; ?>
+ = $this->Html->link(__('Visualizza'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'view', $waterDrawingPaperworkPec->id], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']); ?>
+ = $waterDrawingPaperwork->can_delete_pec ? $this->Form->postLink(__('Cancella'), ['controller' => 'WaterDrawingPaperworkPecs', 'action' => 'delete', $waterDrawingPaperworkPec->id], ['confirm' => __('Sei sicuro che vuoi cancellare la documentazione PEC "{0}" ?', $waterDrawingPaperworkPec->id), 'class' => 'btn btn-danger btn-xs', 'style' => 'margin-right:1rem']) : null; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Paginator->sort('result', __('Esito della verifica')) ?>
+ = $this->Paginator->sort('note', __('Note')) ?>
+ = $this->Paginator->sort('user_id', __('Utente')) ?>
+ = $this->Paginator->sort('created', __('Data e ora della verifica')) ?>
+ = __('Allegato') ?>
+
+
+
+
+
+ = h($waterDrawingPaperworkHistory->result == 1 ? 'Accettata' : 'Rifiutata') ?>
+ = h($waterDrawingPaperworkHistory->note) ?>
+ = h($waterDrawingPaperworkHistory->user) ?>
+ = h($waterDrawingPaperworkHistory->created) ?>
+ = !empty($waterDrawingPaperworkHistory->controllable_object->attachment_file_names) ? $this->Html->link(__('Visualizza'), ['controller' => 'Attachments', 'action' => 'view', array_keys($waterDrawingPaperworkHistory->controllable_object->attachment_file_names)[0]], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem', 'target' => '_blank']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+ can_send_to_drar ? $this->Html->link(__('Invia pratica al DRAR'), ['controller' => 'WaterDrawingPaperworks', 'action' => 'send_to_drar', $waterDrawingPaperwork->id], ['confirm' => __('Sei sicuro di inviare la pratica al DRAR?'), 'class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']) : null;
+ echo $waterDrawingPaperwork->can_send_to_gc ? $this->Html->link(__('Invia pratica al GC'), ['controller' => 'WaterDrawingPaperworks', 'action' => 'send_to_gc', $waterDrawingPaperwork->id], ['confirm' => __('Sei sicuro di inviare la pratica al Genio Civile di competenza?'), 'class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']) : null;
+ echo $waterDrawingPaperwork->can_assign_to_drar ? $this->Html->link(__('Assegna pratica DRAR'), ['controller' => 'WaterDrawingPaperworks', 'action' => 'assign', $waterDrawingPaperwork->id, 6], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']) : null;
+ echo $waterDrawingPaperwork->can_assign_to_gc ? $this->Html->link(__('Assegna pratica GC'), ['controller' => 'WaterDrawingPaperworks', 'action' => 'assign', $waterDrawingPaperwork->id, 0], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']) : null;
+ echo $waterDrawingPaperwork->can_validate ? $this->Html->link(__('Verifica'), ['controller' => 'WaterDrawingPaperworks', 'action' => 'validate', $waterDrawingPaperwork->id], ['class' => 'btn btn-info btn-xs', 'style' => 'margin-right:1rem']) : null;
+ echo $waterDrawingPaperwork->can_edit ? $this->Html->link(__('Modifica'), ['action' => 'edit', $waterDrawingPaperwork->id], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem']) : null;
+ echo $waterDrawingPaperwork->can_delete ? $this->Form->postLink(__('Cancella'), ['action' => 'delete', $waterDrawingPaperwork->id], ['confirm' => __('Sei sicuro che vuoi cancellare la pratica di attingimento "{0}" ?', $waterDrawingPaperwork->id), 'class' => 'btn btn-danger btn-xs']) : null;
+ ?>
+
+
+
+
+= $this->Form->end() ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/view_scan.php b/idrocap_wa/templates/WaterDrawingPaperworks/view_scan.php
new file mode 100644
index 0000000..f1bacb8
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/view_scan.php
@@ -0,0 +1,727 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento scansionata'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+
+ = __('Accesso rapido a:') ?>
+
+ Info amministrative
+
+ Richiedente/Ditta
+
+ water_drawing_paperwork_status_id > 5): ?>
+ Punto di prelievo/derivazione
+
+ water_drawing_paperwork_status_id > 3):
+ ?>
+ Impiego Risorsa
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Punto di restituzione
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Periodo richiesto di prelievo
+
+
+ Info del provvedimento
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Canone
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Strumenti di misura
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Misurazione piezometrica
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Antimafia
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+ Documentazione PEC
+
+
+ Scorri infondo
+
+
+
+
+Form->create($waterDrawingPaperwork, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+
+ = $this->Form->control('water_drawing_paperwork_status.description', ['label' => __('Stato della pratica'), 'type' => 'text', 'disabled' => true, 'required' => false]) ?>
+
+
+
+
+
+
+
+
+
+ = __('Documenti Tecnici (THC)') ?>
+ = __('Documenti Vari (DV)') ?>
+ = __('Licenza di attingimento (LIC)') ?>
+ = __('Decreto di Derivazione (DEC)') ?>
+ = __('Schema del Disciplinare (SDD)') ?>
+ = __('Disciplinare (DSC)') ?>
+ = __('Modulo 2A (2A)') ?>
+ = __('Documento antimafia (DAM)') ?>
+
+
+
+ = $waterDrawingPaperwork->check_thc ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -8], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dv ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -7], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_lic ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -6], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dec ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -5], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_sdd ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -10], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dsc ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -4], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check2a ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -3], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dam ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit) ? $this->Html->link(__('Carica'), ['action' => 'upload_antimafia_attachment', $waterDrawingPaperwork->id], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+
+
+
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => false,
+ 'view_in_frame_with_id' => 'previewiframe',
+ ]);
+ ?>
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+ = $this->Cell("DistrictProvince", [
+ new ProvinceCellDto(
+ fieldId: "authority-province",
+ fieldName: "authority_province",
+ formContext: $waterDrawingPaperwork,
+ fieldRequired: true,
+ disabled: true,
+ fieldType: ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? InputFieldType::SELECT : InputFieldType::HIDDEN),
+ showProvinceFullName: true
+ )
+ ]
+ ) ?>
+
+
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'disabled' => true]) ?>
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'text' : 'hidden'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'type' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? 'select' : 'hidden'), 'options' => $WaterDrawingArticles, 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, 'water_drawing_paperwork_status_id' => $waterDrawingPaperwork->water_drawing_paperwork_status_id, 'is_view' => true, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'water_drawing_paperwork_status_id' => $waterDrawingPaperwork->water_drawing_paperwork_status_id, 'is_view' => true, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+water_drawing_paperwork_status_id > 5): ?>
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Tipo derivazione') ?>
+ = __('Corpo idrico') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Stato') ?>
+ = __('Volume (m^3)') ?>
+ = __('Portata (l/s)') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_derivations as $waterDrawingDerivation) : ?>
+
+ = h(isset ($waterDrawingDerivation->latitude, $waterDrawingDerivation->longitude) ? (number_format((float) $waterDrawingDerivation->latitude, 4) . ', ' . number_format((float) $waterDrawingDerivation->longitude, 4)) : '')?>
+ = h(isset($waterDrawingDerivation->water_drawing_derivation_type_id) ? $waterDrawingDerivation->water_drawing_derivation_type->description : null) ?>
+ = h($waterDrawingDerivation->water_body) ?>
+ = h($waterDrawingDerivation->district) ?>
+ = h($waterDrawingDerivation->cadastral_sheet) ?>
+ = h($waterDrawingDerivation->cadastral_parcel) ?>
+ = h($waterDrawingDerivation->derivation_status) ?>
+ = h($waterDrawingDerivation->annual_volume) ?>
+ = $waterDrawingDerivation->average_flow_rate ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'WaterDrawingDerivations', 'action' => 'view', $waterDrawingDerivation->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 3) : ?>
+
+
+
+
+ water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'is_view' => true, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes, 'wateringSystems' => $wateringSystems]);
+ }
+ ?>
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Azione') ?>
+
+
+
+ water_drawing_return_points as $waterDrawingReturnPoint) : ?>
+
+ = h($waterDrawingReturnPoint->latitude . ', ' . $waterDrawingReturnPoint->longitude) ?>
+ = h($waterDrawingReturnPoint->district) ?>
+ = h($waterDrawingReturnPoint->cadastral_sheet) ?>
+ = h($waterDrawingReturnPoint->cadastral_parcel) ?>
+ = $this->Html->link(__('Dettaglio'), ['controller' => 'waterDrawingReturnPoints', 'action' => 'view', $waterDrawingReturnPoint->id], ['class' => 'btn btn-info btn-xs']) ?>
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => 'text', 'disabled' => true]) ?>
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)'), 'disabled' => true]) ?>
+
+
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => 'number', 'pattern' => ($waterDrawingPaperwork->water_drawing_paperwork_status_id > 5 ? '[0-9]*' : ''), 'disabled' => true]) ?>
+
+
+
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)'), 'style' => 'margin-left: 5px;', 'disabled' => true]) ?>
+
+ water_drawing_paperwork_status_id > 5): ?>
+
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => 'text', 'disabled' => true]) ?>
+
+ water_drawing_paperwork_status_id > 5):
+ ?>
+
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+ can_view_fee): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Canone') ?>
+ = __('Dovuto') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_fees as $waterDrawingFees) : ?>
+
+ = h($waterDrawingFees->year) ?>
+ = h($waterDrawingFees->amount . ' €') ?>
+ = h($waterDrawingFees->to_pay . ' €') ?>
+
+ = $waterDrawingPaperwork->can_add_payment ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingFees', 'action' => 'edit', $waterDrawingFees->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingFees', 'action' => 'view', $waterDrawingFees->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+ can_view_payment): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Data inserimento') ?>
+ = __('Utente') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee->year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->created) ?>
+ = h($waterDrawingPayment->user) ?>
+
+ = $waterDrawingPaperwork->can_add_payment ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPayments', 'action' => 'edit', $waterDrawingPayment->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $waterDrawingPaperwork->can_view_payment ? $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingPayments', 'action' => 'view', $waterDrawingPayment->id], ['class' => 'btn btn-info btn-xs']) : null ?>
+
+
+
+
+
+
+
+ water_drawing_paperwork_status_id <= 5) : ?>
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+
+ = __('Tipologia di uso') ?>
+ = __('Tipologia strumento di misura') ?>
+ = __('Data installazione') ?>
+ = __('Marca ') ?>
+ = __('Matricola') ?>
+ = __('Azioni') ?>
+
+
+
+ water_drawing_intended_uses as $waterDrawingIntendedUse) :
+ if (isset($waterDrawingIntendedUse->water_drawing_intended_use_type_id)):
+ ?>
+
+ = h($waterDrawingIntendedUse->water_drawing_intended_use_type->description) ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->water_drawing_tool_type->description : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->installation_date?->format('d/m/Y') : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->manufacturer : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->part_number : '') ?>
+ water_drawing_meters[0]->id)) {
+ echo $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingMeters', 'action' => 'view', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-info btn-xs']);
+ echo $this->Html->link(__('Dismetti'), ['controller' => 'WaterDrawingMeters', 'action' => 'dismiss', $waterDrawingIntendedUse->water_drawing_meters[0]->id], ['class' => 'btn btn-danger btn-xs']);
+ } else {
+ echo $this->Html->link(__('Aggiungi strumento di misura'), ['controller' => 'WaterDrawingMeters', 'action' => 'add', $waterDrawingIntendedUse->id], ['class' => 'btn btn-success btn-xs']);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+water_drawing_paperwork_status_id > 5) : ?>
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+
+
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Paginator->sort('result', __('Esito della verifica')) ?>
+ = $this->Paginator->sort('note', __('Note')) ?>
+ = $this->Paginator->sort('user_id', __('Utente')) ?>
+ = $this->Paginator->sort('created', __('Data e ora della verifica')) ?>
+ = __('Allegato') ?>
+
+
+
+
+
+ = h($waterDrawingPaperworkHistory->result == 1 ? 'Accettata' : 'Rifiutata') ?>
+ = h($waterDrawingPaperworkHistory->note) ?>
+ = h($waterDrawingPaperworkHistory->user) ?>
+ = h($waterDrawingPaperworkHistory->created) ?>
+ = !empty($waterDrawingPaperworkHistory->controllable_object->attachment_file_names) ? $this->Html->link(__('Visualizza'), ['controller' => 'Attachments', 'action' => 'view', array_keys($waterDrawingPaperworkHistory->controllable_object->attachment_file_names)[0]], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem', 'target' => '_blank']) : null ?>
+
+
+
+
+
+
+
+
+
+
+
+
+= $this->Form->end() ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPaperworks/view_snapshot.php b/idrocap_wa/templates/WaterDrawingPaperworks/view_snapshot.php
new file mode 100644
index 0000000..cf408dd
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPaperworks/view_snapshot.php
@@ -0,0 +1,641 @@
+
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Logs Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_snapshots_all'],
+ ],
+ [
+ 'title' => __('Dettagli Istantanea Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ ],
+ ]);
+} else {
+ echo $this->Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => ($waterDrawingPaperwork->scanned ? 'view_scan' : 'view'), $waterDrawingPaperwork->id],
+ ],
+ [
+ 'title' => __('Storico Pratica di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index_snapshots', $waterDrawingPaperwork->id],
+ ],
+ [
+ 'title' => __('Dettagli Istantanea Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ ],
+ ]);
+}
+?>
+
+
+
+
+ = __('Accesso rapido a:') ?>
+
+
+
+
+Form->create($waterDrawingPaperwork, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+
+ = $this->Form->control('water_drawing_paperwork_status.description', ['label' => __('Stato della pratica'), 'type' => 'text', 'disabled' => true, 'required' => false]) ?>
+ = $this->Form->control('gc_user', ['label' => __('Assegnatario Genio Civile'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('drar_user', ['label' => __('Assegnatario DRAR'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ = __('Documenti Tecnici (THC)') ?>
+ = __('Documenti Vari (DV)') ?>
+ = __('Licenza di attingimento (LIC)') ?>
+ = __('Decreto di Derivazione (DEC)') ?>
+ = __('Schema del Disciplinare (SDD)') ?>
+ = __('Disciplinare (DSC)') ?>
+ = __('Modulo 2A (2A)') ?>
+ = __('Documento antimafia (DAM)') ?>
+
+
+
+ = $waterDrawingPaperwork->check_thc ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -8], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dv ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -7], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_lic ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -6], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dec ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -5], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_sdd ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -10], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dsc ? __('Presente') : __('Assente ') . (((($logged_user_id === $waterDrawingPaperwork->gc_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < 0) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -4], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check2a ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_edit && (($logged_user_id === $waterDrawingPaperwork->gc_user_id) || ($logged_user_id === $waterDrawingPaperwork->drar_user_id && $waterDrawingPaperwork->water_drawing_paperwork_status_id < -2))) ? $this->Html->link(__('Carica'), ['action' => 'upload_attachment', $waterDrawingPaperwork->id, -3], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+ = $waterDrawingPaperwork->check_dam ? __('Presente') : __('Assente ') . (($waterDrawingPaperwork->can_upload_antimafia_attachment) ? $this->Html->link(__('Carica'), ['action' => 'upload_antimafia_attachment', $waterDrawingPaperwork->id], ['class' => 'btn btn-danger btn-xs']) : null) ?>
+
+
+
+
+ element('attachments', [
+ 'coId' => $waterDrawingPaperwork->controllable_object_id,
+ 'filepicker' => false,
+ 'viewer' => true,
+ 'currentFilesRemovable' => false,
+ 'view_in_frame_with_id' => 'previewiframe',
+ ]);
+ ?>
+
+
+
+
+
+
+ = $this->Form->control('authority_civil_engineer_code', ['label' => __('Codice Genio Civile'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Cell("DistrictProvince", [
+ new ProvinceCellDto(
+ fieldId: "authority-province",
+ fieldName: "authority_province",
+ formContext: $waterDrawingPaperwork,
+ fieldRequired: true,
+ disabled: true,
+ fieldContainerClass: "",
+ showProvinceFullName: true
+ )
+ ]
+ ) ?>
+ = $this->Form->control('authority_identification_code_civil_engineering_office', ['label' => __('Codice identificativo Concessione Ufficio Genio civile (es. AA0000)'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'required' => true, 'disabled' => true]) ?>
+ = $this->Form->control('authority_identification_code_derivation_department_water_waste', ['label' => __('Codice identificativo Concessione Dipartimento Acqua e rifiuti'), 'type' => 'text', 'pattern' => '[a-zA-Z]{2}[0-9]{4}', 'disabled' => true]) ?>
+ = $this->Form->control('water_drawing_article_id', ['label' => __('Articolo'), 'options' => $WaterDrawingArticles, 'empty' => true, 'disabled' => true]) ?>
+
+
+
+
+
+
+
+ applicants) == 0) echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => 0, 'is_view' => true, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $waterDrawingPaperwork->applicants]);
+ foreach ($waterDrawingPaperwork->applicants as $applicant_item_block => $applicant) {
+ echo $this->element('WaterDrawingPaperworks/applicants', ['applicant_item_block' => $applicant_item_block, 'is_view' => true, 'formContext' => $waterDrawingPaperwork, 'districtProvinceApplicant' => $applicant]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Tipo derivazione') ?>
+ = __('Corpo idrico') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+ = __('Stato') ?>
+ = __('Volume (m^3)') ?>
+ = __('Portata (l/s)') ?>
+
+
+
+ water_drawing_derivations as $waterDrawingDerivation) : ?>
+
+ = h($waterDrawingDerivation->latitude . ', ' . $waterDrawingDerivation->longitude) ?>
+ = h(isset($waterDrawingDerivation->water_drawing_derivation_type_id) ? $waterDrawingDerivation->water_drawing_derivation_type->description : null) ?>
+ = h($waterDrawingDerivation->water_body) ?>
+ = h($waterDrawingDerivation->district) ?>
+ = h($waterDrawingDerivation->cadastral_sheet) ?>
+ = h($waterDrawingDerivation->cadastral_parcel) ?>
+ = h($waterDrawingDerivation->derivation_status) ?>
+ = h($waterDrawingDerivation->annual_volume) ?>
+ = $waterDrawingDerivation->average_flow_rate ?>
+
+
+
+
+
+
+
+
+
+
+
+ water_drawing_intended_uses as $water_drawing_intended_use_item_block => $waterDrawingIntendedUse) {
+ echo $this->element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $water_drawing_intended_use_item_block, 'is_view' => true, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes, 'wateringSystems' => $wateringSystems]);
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+ = __('Coordinate Latitudine, Longitudine') ?>
+ = __('Comune') ?>
+ = __('Foglio') ?>
+ = __('Particella') ?>
+
+
+
+ water_drawing_return_points as $waterDrawingReturnPoint) : ?>
+
+ = h($waterDrawingReturnPoint->latitude . ', ' . $waterDrawingReturnPoint->longitude) ?>
+ = h($waterDrawingReturnPoint->district) ?>
+ = h($waterDrawingReturnPoint->cadastral_sheet) ?>
+ = h($waterDrawingReturnPoint->cadastral_parcel) ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('from_date', ['label' => __('Dal'), 'type' => 'date', 'disabled' => true]) ?>
+ = $this->Form->control('to_date', ['label' => __('Al'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+ = $this->Form->control('gurs_reference', ['label' => __('Estremi GURS con pubblicazione istanza'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('authorisation_type', ['label' => __('Natura del provvedimento di autorizzazione'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('concession_decree_number', ['label' => __('Decreto di Concessione n° (o di riconoscimento del diritto di derivazione)'), 'disabled' => true]) ?>
+ = $this->Form->control('release_date', ['label' => __('Data di rilascio del provvedimento'), 'disabled' => true]) ?>
+ = $this->Form->control('concession_duration', ['label' => __('Durata Concessione (in anni)'), 'type' => 'number', 'disabled' => true]) ?>
+ = $this->Form->control('expiration_date', ['label' => __('Validità fino a (scadenza del provvedimento)'), 'disabled' => true]) ?>
+ = $this->Form->control('first_istance', ['label' => __('Prima istanza'), 'type' => 'text', 'disabled' => true]) ?>
+ = $this->Form->control('takeover', ['label' => __('Subentro'), 'type' => 'text', 'disabled' => true]) ?>
+
+
+
+
+
+
+ can_view_fee): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Canone') ?>
+ = __('Dovuto') ?>
+
+
+
+ water_drawing_fees as $waterDrawingFees) : ?>
+
+ = h($waterDrawingFees->year) ?>
+ = h($waterDrawingFees->amount . ' €') ?>
+ = h($waterDrawingFees->to_pay . ' €') ?>
+
+
+
+
+
+ can_view_payment): ?>
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Data inserimento') ?>
+ = __('Utente') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee_year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->created) ?>
+ = h($waterDrawingPayment->user) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Tipologia di uso') ?>
+ = __('Tipologia strumento di misura') ?>
+ = __('Data installazione') ?>
+ = __('Marca ') ?>
+ = __('Matricola') ?>
+
+
+
+ water_drawing_intended_uses as $waterDrawingIntendedUse) :
+ ?>
+
+ = h($waterDrawingIntendedUse->water_drawing_intended_use_type->description ?? '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->water_drawing_tool_type->description : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->installation_date : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->manufacturer : '') ?>
+ = h(isset($waterDrawingIntendedUse->water_drawing_meters[0]) ? $waterDrawingIntendedUse->water_drawing_meters[0]->part_number : '') ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->Form->control('static_level_water', ['label' => __('Livello statico dal boccaforo al momento del rinvenimento dell\'acqua (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+ = $this->Form->control('static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+ = $this->Form->control('initial_static_level_water', ['label' => __('Livello statico dal boccaforo il giorno di inizio derivazione (cm)'), 'type' => 'number', 'pattern' => '[0-9]*', 'disabled' => true]) ?>
+ = $this->Form->control('initial_static_level_water_date', ['label' => __('Data del rilievo'), 'type' => 'date', 'disabled' => true]) ?>
+
+
+
+
+
+
+
+
+
+ = __('Utente') ?>
+ = __('Stato') ?>
+ = __('Data e ora') ?>
+
+
+
+ water_drawing_antimafia_certification_requests as $waterDrawinAntimafiaRequest) : ?>
+
+ = h($waterDrawinAntimafiaRequest->user) ?>
+ water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? 'style="color:red;"' : null ?>>= h($waterDrawinAntimafiaRequest->water_drawing_antimafia_certification_request_status->description) . ($waterDrawinAntimafiaRequest->water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? __(' - Richiesta scaduta') : null) ?>
+ water_drawing_antimafia_certification_request_status_id == 2 && $waterDrawingPaperwork->can_request_self_certification ? 'style="color:red;"' : null ?>>= h($waterDrawinAntimafiaRequest->created) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Documento') ?>
+ = __('Numero protocollo') ?>
+ = __('Data') ?>
+
+
+
+ water_drawing_paperwork_pecs as $waterDrawingPaperworkPec) : ?>
+
+ = h($waterDrawingPaperworkPec->document) ?>
+ = h($waterDrawingPaperworkPec->protocol_number) ?>
+ = h($waterDrawingPaperworkPec->protocol_date) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = __('Esito della verifica') ?>
+ = __('Note') ?>
+ = __('Utente') ?>
+ = __('Data e ora della verifica') ?>
+ = __('Allegato') ?>
+
+
+
+
+
+ = h($waterDrawingPaperworkHistory->result == 1 ? 'Accettata' : 'Rifiutata') ?>
+ = h($waterDrawingPaperworkHistory->note) ?>
+ = h($waterDrawingPaperworkHistory->user) ?>
+ = h($waterDrawingPaperworkHistory->created) ?>
+ = !empty($waterDrawingPaperworkHistory->controllable_object->attachment_file_names) ? $this->Html->link(__('Visualizza'), ['controller' => 'Attachments', 'action' => 'view', array_keys($waterDrawingPaperworkHistory->controllable_object->attachment_file_names)[0]], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem', 'target' => '_blank']) : null ?>
+
+
+
+
+
+
+
+= $this->Form->end() ?>
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPayments/add.php b/idrocap_wa/templates/WaterDrawingPayments/add.php
new file mode 100644
index 0000000..1bf3c60
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPayments/add.php
@@ -0,0 +1,93 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view_scan', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Nuovo pagamento'),
+ 'icon' => 'fa fa-plus',
+ ],
+ ]);
+?>
+
+
+
+ Form->create($waterDrawingPayment, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Form->control('water_drawing_fee_id', ['label' => __('Anno'), 'options' => $waterDrawingFees, 'empty' => true, 'required' => true]);?>
+
+
+ = $this->Form->control('water_drawing_payment_type_id', ['label' => __('Tipologia di pagamento'), 'empty' => true]); ?>
+
+
+ = $this->Form->control('amount', ['label' => __('Importo'), 'min' => 0]); ?>
+
+
+ = $this->Form->control('payment_number', ['label' => __('Numero del pagamento')]); ?>
+
+
+
+
+ = $this->Form->control('receipt_number', ['label' => __('Numero quietanza')]); ?>
+
+
+ = $this->Form->control('receipt_amount', ['label' => __('Importo quietanza'), 'min' => 0]); ?>
+
+
+ = $this->Form->control('applicant_tax_code', ['label' => __('Codice fiscale concessionario'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+
+
+ = $this->Form->control('payment_date', ['label' => __('Data pagamento'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+ = $this->Form->control('receipt_date', ['label' => __('Data quietanza'), 'type' => 'date', 'max' => $today->format('Y-m-d')]); ?>
+
+
+
+
+ = $this->Form->control('notes', ['label' => __('Note')]); ?>
+
+
+
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPayments/edit.php b/idrocap_wa/templates/WaterDrawingPayments/edit.php
new file mode 100644
index 0000000..250ec5e
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPayments/edit.php
@@ -0,0 +1,92 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingPayment->water_drawing_fee->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Modifica pagamento'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPayment, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Form->control('water_drawing_fee_id', ['label' => __('Anno'), 'options' => $waterDrawingFees, 'empty' => true, 'required' => true]); ?>
+
+
+ = $this->Form->control('water_drawing_payment_type_id', ['label' => __('Tipologia di pagamento'), 'empty' => true]); ?>
+
+
+ = $this->Form->control('amount', ['label' => __('Importo'), 'min' => 0]); ?>
+
+
+ = $this->Form->control('payment_number', ['label' => __('Numero del pagamento')]); ?>
+
+
+
+
+ = $this->Form->control('receipt_number', ['label' => __('Numero quietanza')]); ?>
+
+
+ = $this->Form->control('receipt_amount', ['label' => __('Importo quietanza'), 'min' => 0]); ?>
+
+
+ = $this->Form->control('applicant_tax_code', ['label' => __('Codice fiscale concessionario'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+
+
+ = $this->Form->control('payment_date', ['label' => __('Data pagamento'), 'max' => $today->format('Y-m-d')]); ?>
+
+
+ = $this->Form->control('receipt_date', ['label' => __('Data quietanza'), 'type' => 'date', 'max' => $today->format('Y-m-d')]); ?>
+
+
+
+
+ = $this->Form->control('notes', ['label' => __('Note')]); ?>
+
+
+
+
+
+Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPayments/index.php b/idrocap_wa/templates/WaterDrawingPayments/index.php
new file mode 100644
index 0000000..54e63a1
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPayments/index.php
@@ -0,0 +1,83 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Lista pagamenti'),
+ 'icon' => 'fa fa-list',
+ ],
+]);
+?>
+
+= $this->Cell('Filters', [__('Filtri')]) ?>
+
+
+
+
+
+
+
+
+ = __('Anno') ?>
+ = __('Data pagamento') ?>
+ = __('Numero del pagamento') ?>
+ = __('Importo') ?>
+ = __('Tipologia di pagamento') ?>
+ = __('Codice fiscale concessionario') ?>
+ = __('Azioni') ?>
+
+
+
+
+
+ = h($waterDrawingPayment->water_drawing_fee->year) ?>
+ = h($waterDrawingPayment->payment_date) ?>
+ = h($waterDrawingPayment->payment_number) ?>
+ = h($waterDrawingPayment->amount) ?>
+ = h($waterDrawingPayment->water_drawing_payment_type->description) ?>
+ = h($waterDrawingPayment->applicant_tax_code) ?>
+
+ = $waterDrawingPayment->can_edit ? $this->Html->link(__('Modifica'), ['controller' => 'WaterDrawingPayments', 'action' => 'edit', $waterDrawingPayment->id], ['class' => 'btn btn-warning btn-xs']) : null ?>
+ = $this->Html->link(__('Dettagli'), ['controller' => 'WaterDrawingPayments', 'action' => 'view', $waterDrawingPayment->id], ['class' => 'btn btn-info btn-xs']) ?>
+ = $waterDrawingPayment->can_delete ? $this->Form->postLink(__('Cancella'), ['controller' => 'WaterDrawingPayments', 'action' => 'delete', $waterDrawingPayment->id], ['confirm' => __('Sei sicuro che vuoi cancellare il pagamento n° "{0}" ?', $waterDrawingPayment->payment_number), 'class' => 'btn btn-danger btn-xs']) : null ?>
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingPayments/view.php b/idrocap_wa/templates/WaterDrawingPayments/view.php
new file mode 100644
index 0000000..c6a26e2
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingPayments/view.php
@@ -0,0 +1,95 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingPayment->water_drawing_fee->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dettagli pagamento'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingPayment, ['role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Form->control('water_drawing_fee_id', ['label' => __('Anno'), 'options' => $waterDrawingFees, 'empty' => true, 'disabled' => true]); ?>
+
+
+ = $this->Form->control('water_drawing_payment_type_id', ['label' => __('Tipologia di pagamento'), 'empty' => true, 'disabled' => true]); ?>
+
+
+ = $this->Form->control('amount', ['label' => __('Importo'), 'min' => 0, 'disabled' => true]); ?>
+
+
+ = $this->Form->control('payment_number', ['label' => __('Numero del pagamento'), 'disabled' => true]); ?>
+
+
+
+
+ = $this->Form->control('receipt_number', ['label' => __('Numero quietanza'), 'disabled' => true]); ?>
+
+
+ = $this->Form->control('receipt_amount', ['label' => __('Importo quietanza'), 'min' => 0, 'disabled' => true]); ?>
+
+
+ = $this->Form->control('applicant_tax_code', ['label' => __('Codice fiscale concessionario'), 'disabled' => true]); ?>
+
+
+
+
+ = $this->Form->control('payment_date', ['label' => __('Data pagamento'), 'disabled' => true]); ?>
+
+
+ = $this->Form->control('receipt_date', ['label' => __('Data quietanza'), 'type' => 'date', 'disabled' => true]); ?>
+
+
+
+
+ = $this->Form->control('notes', ['label' => __('Note'), 'disabled' => true]); ?>
+
+
+ Form->end(); ?>
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingReturnPoints/add.php b/idrocap_wa/templates/WaterDrawingReturnPoints/add.php
new file mode 100644
index 0000000..a0baa52
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingReturnPoints/add.php
@@ -0,0 +1,125 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Aggiungi Punto di restituzione'),
+ 'icon' => 'fa fa-plus',
+ ],
+]);
+?>
+
+
+
+
+ Form->create($waterDrawingReturnPoint, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Punto di prelievo/derivazione'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => false, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => false, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => false, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lon'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lat'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ ],
+ 'geo_resources' => [ // Array = null -> null/[] = geo_resources serve a specificare delle geo-risorse dalle quali vogliamo estrarre degli attributi. per ogni geo-risorsa, tra le altre cose, bisogna specificare il mapping dei campi nella forma "attributo_geo_risorsa":"id-campo-nel-form"
+ [
+ 'external' => true, // se la geo-risorsa è un servizio esterno, bisogna specificare 'external' => true!
+ 'url' // se la geo-risorsa è esterna va specificata la 'url' per chiamare il servizio
+ => 'https://wms.cartografia.agenziaentrate.gov.it/inspire/ajax/ajax.php?op=getDatiOggetto',
+ 'lon_parameter_name' => 'lon', // lon_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lon'
+ 'lat_parameter_name' => 'lat', // lat_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lat'
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'FOGLIO' => 'cadastral-sheet',
+ 'NUM_PART' => 'cadastral-parcel',
+ ],
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'requred' => true]) ?>
+
+
+ = $this->Form->control('cadastral_sheet', ['label' => __('Foglio di Mappa'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('cadastral_parcel', ['label' => __('Particella'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('longitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lon'), 'readonly' => true]) ?>
+
+
+ = $this->Form->control('latitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lat'), 'readonly' => true]) ?>
+
+
+
+ Form->submit(__('Salva'), ['id' => 'submitForm']); ?>
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingReturnPoints/edit.php b/idrocap_wa/templates/WaterDrawingReturnPoints/edit.php
new file mode 100644
index 0000000..aff970c
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingReturnPoints/edit.php
@@ -0,0 +1,124 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingReturnPoint->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Modifica Punto di restituzione'),
+ 'icon' => 'fa fa-pencil-alt',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingReturnPoint, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Punto di prelievo/derivazione'),
+ 'geocoding' => true, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => true, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => false, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => false, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => false, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lon'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lat'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ ],
+ 'geo_resources' => [ // Array = null -> null/[] = geo_resources serve a specificare delle geo-risorse dalle quali vogliamo estrarre degli attributi. per ogni geo-risorsa, tra le altre cose, bisogna specificare il mapping dei campi nella forma "attributo_geo_risorsa":"id-campo-nel-form"
+ [
+ 'external' => true, // se la geo-risorsa è un servizio esterno, bisogna specificare 'external' => true!
+ 'url' // se la geo-risorsa è esterna va specificata la 'url' per chiamare il servizio
+ => 'https://wms.cartografia.agenziaentrate.gov.it/inspire/ajax/ajax.php?op=getDatiOggetto',
+ 'lon_parameter_name' => 'lon', // lon_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lon'
+ 'lat_parameter_name' => 'lat', // lat_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lat'
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'FOGLIO' => 'cadastral-sheet',
+ 'NUM_PART' => 'cadastral-parcel',
+ ],
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'requred' => true]) ?>
+
+
+ = $this->Form->control('cadastral_sheet', ['label' => __('Foglio di Mappa'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('cadastral_parcel', ['label' => __('Particella'), 'requred' => true, 'min' => 0]) ?>
+
+
+ = $this->Form->control('longitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lon'), 'readonly' => true]) ?>
+
+
+ = $this->Form->control('latitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lat'), 'readonly' => true]) ?>
+
+
+
+ Form->submit(__('Salva'), ['id' => 'submitForm']); ?>
+
+ Form->end(); ?>
+
+
+
diff --git a/idrocap_wa/templates/WaterDrawingReturnPoints/index.php b/idrocap_wa/templates/WaterDrawingReturnPoints/index.php
new file mode 100644
index 0000000..4a1e400
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingReturnPoints/index.php
@@ -0,0 +1,54 @@
+ $waterDrawingReturnPoints
+ */
+?>
+
+ = $this->Html->link(__('New Water Drawing Return Point'), ['action' => 'add'], ['class' => 'button float-right']) ?>
+
= __('Water Drawing Return Points') ?>
+
+
+
+
+ = $this->Paginator->sort('id') ?>
+ = $this->Paginator->sort('latitude') ?>
+ = $this->Paginator->sort('longitude') ?>
+ = $this->Paginator->sort('district') ?>
+ = $this->Paginator->sort('cadastral_sheet') ?>
+ = $this->Paginator->sort('cadastral_parcel') ?>
+ = $this->Paginator->sort('water_drawing_paperwork_id') ?>
+ = __('Actions') ?>
+
+
+
+
+
+ = $this->Number->format($waterDrawingReturnPoint->id) ?>
+ = h($waterDrawingReturnPoint->latitude) ?>
+ = h($waterDrawingReturnPoint->longitude) ?>
+ = h($waterDrawingReturnPoint->district) ?>
+ = $waterDrawingReturnPoint->cadastral_sheet === null ? '' : $this->Number->format($waterDrawingReturnPoint->cadastral_sheet) ?>
+ = $waterDrawingReturnPoint->cadastral_parcel === null ? '' : $this->Number->format($waterDrawingReturnPoint->cadastral_parcel) ?>
+ = $waterDrawingReturnPoint->hasValue('water_drawing_paperwork') ? $this->Html->link($waterDrawingReturnPoint->water_drawing_paperwork->id, ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingReturnPoint->water_drawing_paperwork->id]) : '' ?>
+
+ = $this->Html->link(__('View'), ['action' => 'view', $waterDrawingReturnPoint->id]) ?>
+ = $this->Html->link(__('Edit'), ['action' => 'edit', $waterDrawingReturnPoint->id]) ?>
+ = $this->Form->postLink(__('Delete'), ['action' => 'delete', $waterDrawingReturnPoint->id], ['confirm' => __('Are you sure you want to delete # {0}?', $waterDrawingReturnPoint->id)]) ?>
+
+
+
+
+
+
+
+
+
= $this->Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>
+
+
diff --git a/idrocap_wa/templates/WaterDrawingReturnPoints/view.php b/idrocap_wa/templates/WaterDrawingReturnPoints/view.php
new file mode 100644
index 0000000..26f6132
--- /dev/null
+++ b/idrocap_wa/templates/WaterDrawingReturnPoints/view.php
@@ -0,0 +1,128 @@
+Breadcrumb->render([
+ [
+ 'title' => 'Home',
+ 'icon' => 'fa fa-home',
+ 'url' => '/',
+ ],
+ [
+ 'title' => __('Documenti'),
+ 'icon' => 'fa fa-book',
+ ],
+ [
+ 'title' => __('Lista Pratiche di attingimento'),
+ 'icon' => 'fa fa-list',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'index'],
+ ],
+ [
+ 'title' => __('Dettagli Pratica di attingimento'),
+ 'icon' => 'fa fa-info',
+ 'url' => ['controller' => 'WaterDrawingPaperworks', 'action' => 'view', $waterDrawingReturnPoint->water_drawing_paperwork_id],
+ ],
+ [
+ 'title' => __('Dettagli Punto di restituzione'),
+ 'icon' => 'fa fa-info',
+ ],
+]);
+?>
+
+
+
+ Form->create($waterDrawingReturnPoint, ['id' => 'myForm', 'role' => 'form', 'type' => 'file']); ?>
+
+
+
+ = $this->Cell('Map', [
+ null, // Array $layer_ids = null -> null = nessun layer verrà caricato. [] = tutti i layers della table maps verranno caricati. [1,2,3] = solamente i layers della table maps con id 1,2 e 3 verranno caricati
+ false, // Bool $get_current_position = false -> true = viene eseguito lo zoom in mappa sulla posizione utente (se disponibile dal browser e l'utente da i permessi)
+ [ // Array $tools = null -> null/[] = nessun tool verrà visualizzato in mappa. Altrimenti verranno inseriti i tools specificati e le relative configurazioni come specificato di seguito
+ 'drawing_layer_name' // String $drawing_layer_name = null -> se specificato, verrà utilizzato come nome del layer che gestisce le geometrie disegnate. Se lasciato vuoto o null, il nome di default verrà utilizzato
+ => __('Posizione Punto di prelievo/derivazione'),
+ 'geocoding' => false, // Bool $geocoding = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "freccia di localizzazione" per accedere alla funzione di geocoding. se l'indirizzo inserito è valido, verrà inserito un punto in mappa nella relativa location individuata
+ 'point' => false, // Bool $point = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "marker" per attivare la funzione di inserimento punti in mappa
+ 'multiple_points' => false, // Bool $multiple_points = false -> se true, permette l'inserimento di più punti in mappa. ATTENZIONE: se il tool di geocoding è attivo, $multiple_points non verrà considerato e non sarà permesso inserire più punti in mappa!
+ 'polygon' => false, // Bool $polygon = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "polygon" per attivare la funzione di disegno poligoni in mappa
+ 'circle' => false, // Bool $circle = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "circle" per attivare la funzione di disegno cerchi in mappa
+ 'delete_geometry' => false, // Bool $delete-geometry = false -> se true, visualizza in mappa (nel riquadro dei tools in alto a sinistra) un button con icona "cestino" per attivare la funzione di cancellazione geometrie (puntare sulla geometria precedentemente disegnata che si vuole eliminare). ATTENZIONE: se nessuno tra $geocoding, $point, $polygon e $circle è true, il button di cancellazione non verrà renderizzato!
+ 'fields' => [ // Array $fields = null -> null/[] = nessun campo verrà renderizzato o fillato. Altrimenti verranno gestiti i campi in base alle relative configurazioni come specificato di seguito
+ 'longitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'longitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'longitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lon'),
+ ],
+ 'latitude' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => true, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'latitude',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'latitude',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Coordinata WGS84 EPSG:4326 Lat'),
+ ],
+ 'district' => [ // Array = null -> null/[] = il campo feature_collection non verrà gestito. Altrimenti verrà gestito come specificato di seguito
+ 'render' => false, // Bool $render = false -> se true, verrà renderizzato il campo. Nota: se $render è false, $hidden, $name e $description (se specificati) non verranno utilizzati. Invece $id (se specificato) permetterà il filling del campo esistente con id specificato
+ 'hidden' => false, // Bool $hidden = false -> se true, verrà renderizzato il campo NASCOSTO. Nota: se $render = false, non verrà preso in considerazione
+ 'readonly' => false, // Bool $readonly = false -> se true, verrà renderizzato il campo in modalità READ ONLY. Nota: se $render = false, non verrà preso in considerazione
+ 'id' // String $id = null -> se specificato, verrà utilizzato come id del campo. Nota: se $render è false, questo id verrà utilizzato per il filling del campo già esistente con l'id specifiato
+ => 'district',
+ 'name' // String $name = null -> se specificato, verrà utilizzato come name del campo. Nota: se $render = false, non verrà preso in considerazione
+ => 'district',
+ 'label' // String $label = null -> se specificato, verrà utilizzato come label del campo. Nota: se $render = false, non verrà preso in considerazione
+ => __('Comune'),
+ ],
+ ],
+ 'geo_resources' => [ // Array = null -> null/[] = geo_resources serve a specificare delle geo-risorse dalle quali vogliamo estrarre degli attributi. per ogni geo-risorsa, tra le altre cose, bisogna specificare il mapping dei campi nella forma "attributo_geo_risorsa":"id-campo-nel-form"
+ [
+ 'external' => true, // se la geo-risorsa è un servizio esterno, bisogna specificare 'external' => true!
+ 'url' // se la geo-risorsa è esterna va specificata la 'url' per chiamare il servizio
+ => 'https://wms.cartografia.agenziaentrate.gov.it/inspire/ajax/ajax.php?op=getDatiOggetto',
+ 'lon_parameter_name' => 'lon', // lon_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lon'
+ 'lat_parameter_name' => 'lat', // lat_parameter_name specifica come si chiama il parametro del servizio esterno per fornire in input la coordinata 'lat'
+ 'attributes_fields' => [ // elenco key/value che specifica gli attributi(KEY) da estrarre dalla geo-risorsa ed il corrispondere ID del campo(VALUE) del form a cui assegnare il valore estratto dall'attributo.
+ 'FOGLIO' => 'cadastral-sheet',
+ 'NUM_PART' => 'cadastral-parcel',
+ ],
+ ],
+ ],
+ ],
+ null, // Int $zoom_to_layer_with_id = null -> se si specifica un Int, verrà eseguito lo zoom sull'extent del layer con quell'id
+ ]); ?>
+ = $this->Form->control('feature_collection', ['type' => 'hidden']); ?>
+
+
+ = $this->Form->control('district', ['label' => __('Comune'), 'type' => 'text', 'requred' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('cadastral_sheet', ['label' => __('Foglio di Mappa'), 'requred' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('cadastral_parcel', ['label' => __('Particella'), 'requred' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('longitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lon'), 'disabled' => true, 'disabled' => true]) ?>
+
+
+ = $this->Form->control('latitude', ['label' => __('Coordinata WGS84 EPSG:4326 Lat'), 'disabled' => true, 'disabled' => true]) ?>
+
+ Form->end(); ?>
+
+
+ Html->link(__('Modifica'), ['action' => 'edit', $waterDrawingReturnPoint->id], ['class' => 'btn btn-warning btn-xs', 'style' => 'margin-right:1rem']);
+ echo $this->Form->postLink(__('Cancella'), ['action' => 'delete', $waterDrawingReturnPoint->id], ['confirm' => __('Sei sicuro che vuoi cancellare la pratica di attingimento "{0}" ?', $waterDrawingReturnPoint->id), 'class' => 'btn btn-danger btn-xs']);
+ ?>
+
+
+
+
+
diff --git a/idrocap_wa/templates/cell/.gitkeep b/idrocap_wa/templates/cell/.gitkeep
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/idrocap_wa/templates/cell/.gitkeep
@@ -0,0 +1 @@
+
diff --git a/idrocap_wa/templates/cell/DistrictProvince/display.php b/idrocap_wa/templates/cell/DistrictProvince/display.php
new file mode 100644
index 0000000..2388116
--- /dev/null
+++ b/idrocap_wa/templates/cell/DistrictProvince/display.php
@@ -0,0 +1,41 @@
+
+
+
+
+
+ = $this->element("provinceSelect", [
+ 'provinceConfig' => $provinceCellConfig,
+ "provinces" => $provinces['options'] ?? null
+ ]) ?>
+
+
+
+
+
+ = $this->element("districtSelect", [
+ 'districtConfig' => $districtCellConfig,
+ "codReg" => $codReg,
+ "provinces" => isset($provinces) && is_array($provinces) ? $provinces['map'] : null
+ ]) ?>
+
+
diff --git a/idrocap_wa/templates/cell/FilterInput/display.php b/idrocap_wa/templates/cell/FilterInput/display.php
new file mode 100644
index 0000000..cf532dd
--- /dev/null
+++ b/idrocap_wa/templates/cell/FilterInput/display.php
@@ -0,0 +1,12 @@
+
+
+
+ Form->control('filters[' . $name . '][]', ['label' => $label, 'type' => $type, 'options' => $options, 'value' => $value, 'class' => "form-control$additional_classes"]);
+ ?>
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/cell/Filters/display.php b/idrocap_wa/templates/cell/Filters/display.php
new file mode 100755
index 0000000..d06a21a
--- /dev/null
+++ b/idrocap_wa/templates/cell/Filters/display.php
@@ -0,0 +1,152 @@
+
+
+
+ = $this->Form->create(null, ['role' => 'form', 'onsubmit' => 'cleanPage()', 'id' => 'formFilters']); ?>
+
+
+ = $this->Form->control('filter_id', ['label' => __('Aggiungi un filtro'), 'class' => 'd-flex flex-column idrocap-filter-select', 'options' => $available_filters, 'empty' => true]); ?>
+
+
+
+ $values): ?>
+
+ = $this->Cell('FilterInput', [(int)explode("filter_id_", $filter_id)[1], $value]); ?>
+
+
+
+
+
+
+ = $this->Form->submit(__('Reset'), ['class' => 'btn btn-danger mr-3', 'onclick' => 'reset_filters()']); ?>
+
+
+ = $this->Form->submit(__('Applica'), ['class' => 'btn btn-success']); ?>
+
+
+
+ = $this->Form->end(); ?>
+
+
+
+Html->script('moment'); ?>
+Html->script('jixel-primitives'); ?>
+
diff --git a/idrocap_wa/templates/cell/IntendedUses/display.php b/idrocap_wa/templates/cell/IntendedUses/display.php
new file mode 100644
index 0000000..8a7f713
--- /dev/null
+++ b/idrocap_wa/templates/cell/IntendedUses/display.php
@@ -0,0 +1 @@
+Element('WaterDrawingPaperworks/intended_uses', ['intended_use_item_block' => $intended_use_item_block, 'intendedUseTypes' => $intendedUseTypes, 'cadastralCropTypes' => $cadastralCropTypes, 'wateringSystems' => $wateringSystems]); ?>
diff --git a/idrocap_wa/templates/cell/Map/display.php b/idrocap_wa/templates/cell/Map/display.php
new file mode 100755
index 0000000..bd4e174
--- /dev/null
+++ b/idrocap_wa/templates/cell/Map/display.php
@@ -0,0 +1,13 @@
+Element('Map', ['layers' => $layers, 'get_current_position' => $get_current_position, 'tools' => $tools, 'drawing_layer_name' => $drawing_layer_name, 'geocoding' => $geocoding, 'point' => $point, 'multiple_points' => $multiple_points, 'polygon' => $polygon, 'circle' => $circle, 'delete_geometry' => $delete_geometry, 'feature_collection_id' => $feature_collection['id'] ?? 'feature-collection', 'longitude_id' => $longitude['id'] ?? 'longitude', 'latitude_id' => $latitude['id'] ?? 'latitude', 'coordinates_id' => $coordinates['id'] ?? 'coordinates', 'cap_id' => $cap['id'] ?? 'cap', 'province_id' => $province['id'] ?? 'province', 'district_code_id' => $district_code['id'] ?? 'district-code', 'district_id' => $district['id'] ?? 'district', 'address_id' => $address['id'] ?? 'address', 'description_id' => $description['id'] ?? 'description', 'geo_resources' => $geo_resources]);
+ if ($feature_collection !== false && isset($feature_collection['render']) && $feature_collection['render'] === true) echo $this->Form->control($feature_collection['name'] ?? 'feature_collection', ['id' => $feature_collection['id'] ?? 'feature-collection', 'type' => isset($feature_collection['hidden']) && $feature_collection['hidden'] === true ? 'hidden' : 'text', 'label' => $feature_collection['label'] ?? null, 'readonly' => isset($feature_collection['readonly']) && $feature_collection['readonly'] === true]);
+ if ($longitude !== false && isset($longitude['render']) && $longitude['render'] === true) echo $this->Form->control($longitude['name'] ?? 'longitude', ['id' => $longitude['id'] ?? 'longitude', 'type' => isset($longitude['hidden']) && $longitude['hidden'] === true ? 'hidden' : 'text', 'label' => $longitude['label'] ?? null, 'readonly' => isset($longitude['readonly']) && $longitude['readonly'] === true]);
+ if ($latitude !== false && isset($latitude['render']) && $latitude['render'] === true) echo $this->Form->control($latitude['name'] ?? 'latitude', ['id' => $latitude['id'] ?? 'latitude', 'type' => isset($latitude['hidden']) && $latitude['hidden'] === true ? 'hidden' : 'text', 'label' => $latitude['label'] ?? null, 'readonly' => isset($latitude['readonly']) && $latitude['readonly'] === true]);
+ if ($coordinates !== false && isset($coordinates['render']) && $coordinates['render'] === true) echo $this->Form->control($coordinates['name'] ?? 'coordinates', ['id' => $coordinates['id'] ?? 'coordinates', 'type' => isset($coordinates['hidden']) && $coordinates['hidden'] === true ? 'hidden' : 'text', 'label' => $coordinates['label'] ?? null, 'readonly' => isset($coordinates['readonly']) && $coordinates['readonly'] === true]);
+ if ($cap !== false && isset($cap['render']) && $cap['render'] === true) echo $this->Form->control($cap['name'] ?? 'cap', ['id' => $cap['id'] ?? 'cap', 'type' => isset($cap['hidden']) && $cap['hidden'] === true ? 'hidden' : 'text', 'label' => $cap['label'] ?? null, 'readonly' => isset($cap['readonly']) && $cap['readonly'] === true]);
+ if ($province !== false && isset($province['render']) && $province['render'] === true) echo $this->Form->control($province['name'] ?? 'province', ['id' => $province['id'] ?? 'province', 'type' => isset($province['hidden']) && $province['hidden'] === true ? 'hidden' : 'text', 'label' => $province['label'] ?? null, 'readonly' => isset($province['readonly']) && $province['readonly'] === true]);
+ if ($district_code !== false && isset($district_code['render']) && $district_code['render'] === true) echo $this->Form->control($district_code['name'] ?? 'district_code', ['id' => $district_code['id'] ?? 'district-code', 'type' => isset($district_code['hidden']) && $district_code['hidden'] === true ? 'hidden' : 'text', 'label' => $district_code['label'] ?? null, 'readonly' => isset($district_code['readonly']) && $district_code['readonly'] === true]);
+ if ($district !== false && isset($district['render']) && $district['render'] === true) echo $this->Form->control($district['name'] ?? 'district', ['id' => $district['id'] ?? 'district', 'type' => isset($district['hidden']) && $district['hidden'] === true ? 'hidden' : 'text', 'label' => $district['label'] ?? null, 'readonly' => isset($district['readonly']) && $district['readonly'] === true]);
+ if ($address !== false && isset($address['render']) && $address['render'] === true) echo $this->Form->control($address['name'] ?? 'address', ['id' => $address['id'] ?? 'address', 'type' => isset($address['hidden']) && $address['hidden'] === true ? 'hidden' : 'text', 'label' => $address['label'] ?? null, 'readonly' => isset($address['readonly']) && $address['readonly'] === true]);
+ if ($description !== false && isset($description['render']) && $description['render'] === true) echo $this->Form->control($description['name'] ?? 'description', ['id' => $description['id'] ?? 'description', 'type' => isset($description['hidden']) && $description['hidden'] === true ? 'hidden' : 'text', 'label' => $description['label'] ?? null, 'readonly' => isset($description['readonly']) && $description['readonly'] === true]);
+?>
\ No newline at end of file
diff --git a/idrocap_wa/templates/element/Map.php b/idrocap_wa/templates/element/Map.php
new file mode 100755
index 0000000..da37f83
--- /dev/null
+++ b/idrocap_wa/templates/element/Map.php
@@ -0,0 +1,622 @@
+= $this->element('./MapCore/MapPrimitives') ?>
+
+
diff --git a/idrocap_wa/templates/element/MapCore/MapPrimitives.php b/idrocap_wa/templates/element/MapCore/MapPrimitives.php
new file mode 100644
index 0000000..42cfb31
--- /dev/null
+++ b/idrocap_wa/templates/element/MapCore/MapPrimitives.php
@@ -0,0 +1,373 @@
+Html->css('/node_modules/ol/ol'); ?>
+Html->css('/ol-ext/ol-ext.min'); ?>
+Html->css('jixel_ol'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Html->script('/node_modules/ol/dist/ol'); ?>
+Html->script('/ol-ext/ol-ext.min'); ?>
+Html->script('moment'); ?>
+Html->script('jixel-primitives'); ?>
+
diff --git a/idrocap_wa/templates/element/WaterDrawingPaperworks/applicants.php b/idrocap_wa/templates/element/WaterDrawingPaperworks/applicants.php
new file mode 100644
index 0000000..bcac0ce
--- /dev/null
+++ b/idrocap_wa/templates/element/WaterDrawingPaperworks/applicants.php
@@ -0,0 +1,196 @@
+province ?? null) : null;
+$district = $applicant ? ($applicant->district ?? null) : null;
+?>
+
+
+
+
= $applicant_item_block == 0 ? __("Concessionario principale") : __("Concessionario aggiuntivo") ?>
+
+
+
+ = $this->Form->control('select2applicants-' . $applicant_item_block, ['id' => 'select2applicants-' . $applicant_item_block, 'label' => __('Ricerca concessionario'), 'type' => 'select', 'options' => (isset($applicant) ? [$applicant->id => $applicant->tax_code . ' - ' . $applicant->name . ' ' . $applicant->surname] : []), 'empty' => true, 'style' => 'width:50%;']) ?>
+
+
+
+ = $this->Form->hidden('applicants.' . $applicant_item_block . '.id', ['id' => 'applicants-' . $applicant_item_block . '-id', 'readonly' => true, 'disabled' => (!isset($applicant)), 'type' => 'number']) ?>
+ = $this->Form->hidden('applicants.' . $applicant_item_block . '._joinData.is_primary_applicant', ['value' => ($applicant_item_block == 0 ? 1 : 0)]) ?>
+ 5): ?>
+
+ = $this->Form->hidden('applicants.' . $applicant_item_block . '.id', ['id' => 'applicants-' . $applicant_item_block . '-id', 'readonly' => true, 'disabled' => (!isset($applicant)), 'type' => 'number']) ?>
+ = $this->Form->hidden('applicants.' . $applicant_item_block . '._joinData.is_primary_applicant', ['value' => ($applicant_item_block == 0 ? 1 : 0)]) ?>
+ = $this->Form->control('applicants.' . $applicant_item_block . '.name', ['label' => __('Nome'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? 'text' : 'hidden'), 'required' => true]) ?>
+
+ 5):
+ ?>
+
+ = $this->Form->control('applicants.' . $applicant_item_block . '.surname', ['label' => __('Cognome'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? 'text' : 'hidden'), 'required' => true]) ?>
+
+
+
+ = $this->Form->control('applicants.' . $applicant_item_block . '.tax_code', ['label' => __('Codice fiscale'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => 'text', 'required' => true]) ?>
+
+ 5):
+ ?>
+ = $this->Form->control('applicants.' . $applicant_item_block . '.company_name', ['label' => __('Ragione sociale'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? 'text' : 'hidden')]) ?>
+
+
+
+ = $this->Form->control('applicants.' . $applicant_item_block . '.vat_number', ['label' => __('Partita IVA'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => 'text']) ?>
+
+ 5):
+ ?>
+
+ = $this->Form->control('applicants.' . $applicant_item_block . '.address', ['label' => __('Indirizzo'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? 'text' : 'hidden'), 'required' => true]) ?>
+
+ 5):
+ ?>
+ = $this->Cell("DistrictProvince", [
+ new ProvinceCellDto(
+ fieldId: 'applicants-' . $applicant_item_block . '-province',
+ fieldName: 'applicants.' . $applicant_item_block . '.province',
+ formContext: $formContext ?? null,
+ fieldRequired: true,
+ disabled: (isset($is_view) || isset($applicant->id)),
+ fieldType: ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? InputFieldType::SELECT : InputFieldType::HIDDEN),
+ fieldValue: $province
+ ),
+ new DistrictCellDto(
+ fieldId: 'applicants-' . $applicant_item_block . '-district',
+ fieldName: 'applicants.' . $applicant_item_block . '.district',
+ provinceFieldId: 'applicants-' . $applicant_item_block . '-province',
+ fieldRequired: true,
+ disabled: (isset($is_view) || isset($applicant->id)),
+ fieldType: ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? InputFieldType::SELECT : InputFieldType::HIDDEN),
+ fieldValue: $district,
+ entity: $applicant
+ )
+ ]
+ ) ?>
+ 5):
+ ?>
+
+ = $this->Form->control('applicants.' . $applicant_item_block . '.pec_address', ['label' => __('Indirizzo PEC'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? 'text' : 'hidden')]) ?>
+
+ 5):
+ ?>
+
+ = $this->Form->control('applicants.' . $applicant_item_block . '.email_address', ['label' => __('Indirizzo email'), 'disabled' => (isset($is_view) || isset($applicant->id)), 'type' => ((!isset($water_drawing_paperwork_status_id) || $water_drawing_paperwork_status_id > 5) ? 'text' : 'hidden')]) ?>
+
+
+
+ 0 && !(isset($is_view))) : ?>
+
+
+
Modifica
+
+
+
+
diff --git a/idrocap_wa/templates/element/WaterDrawingPaperworks/intended_uses.php b/idrocap_wa/templates/element/WaterDrawingPaperworks/intended_uses.php
new file mode 100644
index 0000000..980e8ec
--- /dev/null
+++ b/idrocap_wa/templates/element/WaterDrawingPaperworks/intended_uses.php
@@ -0,0 +1,151 @@
+
+
+
+
= __("Impiego risorsa - ") . ($intended_use_item_block + 1) ?>
+ water_drawing_intended_uses) && isset($waterDrawingPaperwork->water_drawing_intended_uses[$intended_use_item_block]->water_drawing_intended_use_type_id) && $waterDrawingPaperwork->water_drawing_intended_uses[$intended_use_item_block]->water_drawing_intended_use_type_id == 1) {
+ if ($waterDrawingPaperwork->water_drawing_intended_uses[$intended_use_item_block]->vegetation_match_status == -1) {
+ ?>
+ = ' ' . __('Attenzione, è stato selezionato l\'uso "IRRIGUO" su un foglio/particella non afferente ad un\'area vegetativa') ?>
+ water_drawing_intended_uses[$intended_use_item_block]->vegetation_match_status == 0) {
+ ?>
+ = ' ' . __('Attenzione, è stato selezionato l\'uso "IRRIGUO". La piattaforma sta effettuando i controlli per verificare che il foglio/particella è afferente ad un\'area vegetativa') ?>
+ water_drawing_intended_uses[$intended_use_item_block]->vegetation_match_status == 1) {
+ ?>
+ = ' ' . __('L\'uso "IRRIGUO" selezionato per questo foglio/particella è afferente ad un\'area vegetativa') ?>
+
+
+
+
+
+ = $this->Form->hidden('water_drawing_intended_uses.' . $intended_use_item_block . '.id', []) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.water_drawing_intended_use_type_id', ['id' => 'select2water-drawing-use-type-id-' . $intended_use_item_block, 'label' => __('Uso'), 'options' => $intendedUseTypes, 'empty' => true, "onChange" => "changeIntendedUseTypes($intended_use_item_block)" , 'disabled' => (isset($is_view))]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.area', ['label' => __('Superficie da irrigare ( 00.00.00 ha )'), 'pattern' => '\d{2}([.,]\d{2}){2}', 'disabled' => (isset($is_view))]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.cadastral_code', ['label' => __('Codice comune'), 'type' => 'text', 'disabled' => (isset($is_view))]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.cadastral_sheet', ['label' => __('Foglio di mappa'), 'type' => 'text', 'disabled' => (isset($is_view)), 'type' => 'number', 'min' => 0]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.cadastral_parcel', ['label' => __('Particella da irrigare'), 'type' => 'text', 'disabled' => (isset($is_view)), 'type' => 'number', 'min' => 0]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.water_drawing_watering_system_id', ['id' => 'select2watering-system-id-' . $intended_use_item_block, 'label' => __('Sistema di irrigazione'), 'options' => $wateringSystems, 'empty' => true, 'disabled' => (isset($is_view))]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.cadastral_crop_types._ids', ['id' => 'select2cadastra-crop-type-ids-' . $intended_use_item_block, 'label' => __('Tipo coltura'), 'options' => $cadastralCropTypes, 'multiple' => true, 'disabled' => (isset($is_view))]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.consortium_area', ['label' => __('Area consortile'), 'type' => 'text', 'disabled' => (isset($is_view))]) ?>
+ = $this->Form->control('water_drawing_intended_uses.' . $intended_use_item_block . '.rated_power_produced', ['label' => __('Potenza nominale prodotta (kW)'), 'type' => 'number', 'disabled' => (isset($is_view)), 'min' => 0]) ?>
+
+
+ 0 && !(isset($is_view))) : ?>
+
+
+
+
diff --git a/idrocap_wa/templates/element/attachmentPreview.php b/idrocap_wa/templates/element/attachmentPreview.php
new file mode 100755
index 0000000..89af461
--- /dev/null
+++ b/idrocap_wa/templates/element/attachmentPreview.php
@@ -0,0 +1,41 @@
+ [
+ 'html' => ' ',
+ 'width' => '256px',
+ 'height' => '256px',
+ 'background' => 'url(\'/img/giphy.gif\')',
+ ],
+ 'video/mp4' => [
+ 'html' => '
+
+ '. __("Il tuo browser non supporta HTML5 video tag. Prova ad aggiornare il tuo browser.") .'
+ ',
+ 'width' => '256px',
+ 'height' => '256px',
+ 'background' => 'url(\'/img/giphy.gif\')',
+ ],
+ 'application/pdf' => [
+ 'html' => '',
+ 'width' => '500px',
+ 'height' => '500px',
+ 'background' => 'none',
+ ]
+ ];
+
+ if(isset($element[$mimetype])){
+ $result = $element[$mimetype];
+ }
+ else
+ {
+ $result = ['html' => __("Anteprima non disponibile"), 'width' => '200px', 'height' => '50px', 'background' => 'none'];
+ }
+?>
+ = $result['html'] ?>
+
diff --git a/idrocap_wa/templates/element/attachments.php b/idrocap_wa/templates/element/attachments.php
new file mode 100755
index 0000000..7a9c8f2
--- /dev/null
+++ b/idrocap_wa/templates/element/attachments.php
@@ -0,0 +1,341 @@
+
+ aggiunge un prefisso a tutti gli element html e js per evitare conflitti
+ 'input_name_for_attachments' --------> opzionale override degli input name 'attachments'
+ 'input_name_for_removefiles' --------> opzionale override degli input name 'removefiles'
+ 'filepicker' => true/false --------> inserisce il filepicker oppure no
+ 'georeferenced' => true/false --------> stabilisce se ogni singolo allegato va georeferenziato oppure no. (se è true allore upload_single viene forzato anche a true!!!!!)
+ 'upload_single' => true/false --------> decide se l'upload è singolo o se sono consentiti upload multipli da più paths
+ 'accept_only' => [] --------> se si passa questo array, i tipi di files accettati saranno solo quelli specificati
+ 'viewer' => true/false --------> inserisce o meno il file viewer
+ 'coId' --------> controllable object id, necessario se la proprietà precedente 'viewer' è true
+ 'currentFilesRemovable' => true/false --------> decide se è possibile eliminare i files già presenti o meno
+ 'enableRelated' => true/false --------> visualizza anche gli allegati degli oggetti associati (esempio in un evento visualizza anche gli allegati delle observations)
+ 'allow_private' => true/false --------> stabilisce se devono esserci files pubblici e privati o soltanto pubblci
+ 'public_required' => true/false --------> setta allegato pubblico come obbligatorio oppure no
+ 'required' => true/false --------> setta l'allegato come obbligatorio oppure no
+ 'tags' => [] --------> serve a passare uno o + tags (vedi tabella Tags) per creare diverse sezioni di allegati. ogni elemento key=>value dell'array va inserito come code/description della sezione che si vuole creare. esempio: 'tags' => ['code1' => 'Allegati di tipo 1', 'code2' => 'Allegati di tipo 2', 'code3' => 'Allegati di tipo 3']
+ 'view_in_frame_with_id' --------> se settato, viene effettuato il rendering dell'allegato all'interno deill'iframe con id specificato
+ */
+
+ $prefix = isset($prefix) && is_string($prefix) ? $prefix : '';
+ $input_name_for_attachments = isset($input_name_for_attachments) && is_string($input_name_for_attachments) ? $input_name_for_attachments : 'attachments';
+ $input_name_for_removefiles = isset($input_name_for_removefiles) && is_string($input_name_for_removefiles) ? $input_name_for_removefiles : 'removefiles';
+ $accept = isset($accept_only) && is_array($accept_only) && count($accept_only) > 0 ? ('accept="' . implode(",", $accept_only) . '"') : '';
+ $acceptText = isset($accept_only) && is_array($accept_only) && count($accept_only) > 0 ? __('di tipo: "{0}"', implode(",", $accept_only)) : '';
+ $georeferenced = isset($georeferenced) && $georeferenced;
+ $multiple = $georeferenced || isset($upload_single) && $upload_single ? '': 'multiple="multiple"';
+ $oneFilePicker = isset($upload_single) && $upload_single;
+ $public_required = isset($public_required) && $public_required;
+ $required = isset($required) && $required;
+ $coRelated = isset($coRelated) && $coRelated;
+
+ if (isset($enableRelated) && $enableRelated) {
+ echo '' . __('Mostra allegati correlati') . ' ';
+ echo ' ';
+ }
+?>
+
+
+
+ ($oneFilePicker ? __('Allega un file ') : __('Allega files ')) . $acceptText];
+ }
+ else
+ {
+ if($allow_private)
+ {
+ $attachment_scope = ['public' => __('Allega file pubblico ') . $acceptText, 'private' => ($oneFilePicker ? __('Allega un file privato ') : __('Allega files privati ')) . $acceptText];
+ }
+ else
+ {
+ $attachment_scope = ['' => __('Allega files...')];
+ }
+ }
+
+ if(isset($tags)){
+ $attachment_scope = [];
+ foreach ($tags as $tag => $description) {
+ $attachment_scope[$tag] = __('Allega files {1} {0}',$description,$acceptText);
+ }
+ $csv_tags = implode(',',array_keys($tags));
+ }
+ if (isset($filepicker) && $filepicker) {
+
+ $attachment_index = $georeferenced ? '[0]' : '[]';
+ $col = (12 / count($attachment_scope)) > 6 ? (12 / count($attachment_scope)) : 6;
+ foreach($attachment_scope as $scope => $label)
+ {
+ echo '
';
+ echo '
' . $label . ' ';
+ echo '
';
+ echo '
';
+ echo '
';
+ echo '
';
+ echo '
';
+ echo '
';
+ echo '
';
+ }
+
+ }
+ echo $this->Form->hidden($prefix.'removecurrentfiles', ['id' => $prefix.'removecurrentfiles', 'value' => isset($currentFilesRemovable) && $currentFilesRemovable ? 'true' : 'false']);
+?>
+
+
+
+
+
+
+
+
+ $label)
+ {
+ if ($scope == "public" || $oneFilePicker) {
+ continue;
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/element/districtSelect.php b/idrocap_wa/templates/element/districtSelect.php
new file mode 100644
index 0000000..a6b51f6
--- /dev/null
+++ b/idrocap_wa/templates/element/districtSelect.php
@@ -0,0 +1,210 @@
+ $districtCellConfig->fieldId,
+ 'label' => __($districtCellConfig->fieldLabel),
+ 'type' => $districtCellConfig->fieldType->value,
+ "empty" => true,
+ "disabled" => $districtCellConfig->disabled,
+ 'required' => $districtCellConfig->fieldRequired
+];
+
+if (!empty($districtCellConfig->fieldValue)) {
+ $options['data-value'] = $districtCellConfig->fieldValue;
+}
+?>
+
+fieldId !== null && $districtCellConfig->fieldName !== null): ?>
+ = $this->Form->control($districtCellConfig->fieldName, $options) ?>
+ entity) && $districtCellConfig->entity->hasErrors($districtCellConfig->fieldName)): ?>
+
+ entity->getError($districtCellConfig->fieldName);
+
+ /*
+ * Qui ci finisco solo se siamo in un ciclo e quindi il nome del field non matcha con la rule
+ */
+ if(empty($errors)) {
+ $errors = $districtCellConfig->entity->getError("district");
+ }
+
+ if (is_array($errors) && isset($errors['validDistrict'])) {
+ echo h($errors['validDistrict']);
+ } else {
+ echo is_array($errors) ? h(implode(', ', $errors)) : h($errors);
+ }
+ ?>
+
+
+
+
+
diff --git a/idrocap_wa/templates/element/flash/default.php b/idrocap_wa/templates/element/flash/default.php
new file mode 100644
index 0000000..061c700
--- /dev/null
+++ b/idrocap_wa/templates/element/flash/default.php
@@ -0,0 +1,15 @@
+
+= $message ?>
diff --git a/idrocap_wa/templates/element/flash/error.php b/idrocap_wa/templates/element/flash/error.php
new file mode 100644
index 0000000..2ebf235
--- /dev/null
+++ b/idrocap_wa/templates/element/flash/error.php
@@ -0,0 +1,11 @@
+
+= $message ?>
diff --git a/idrocap_wa/templates/element/flash/info.php b/idrocap_wa/templates/element/flash/info.php
new file mode 100644
index 0000000..e25b730
--- /dev/null
+++ b/idrocap_wa/templates/element/flash/info.php
@@ -0,0 +1,11 @@
+
+= $message ?>
diff --git a/idrocap_wa/templates/element/flash/success.php b/idrocap_wa/templates/element/flash/success.php
new file mode 100644
index 0000000..73eaac4
--- /dev/null
+++ b/idrocap_wa/templates/element/flash/success.php
@@ -0,0 +1,11 @@
+
+= $message ?>
diff --git a/idrocap_wa/templates/element/flash/warning.php b/idrocap_wa/templates/element/flash/warning.php
new file mode 100644
index 0000000..605537c
--- /dev/null
+++ b/idrocap_wa/templates/element/flash/warning.php
@@ -0,0 +1,11 @@
+
+= $message ?>
diff --git a/idrocap_wa/templates/element/provinceSelect.php b/idrocap_wa/templates/element/provinceSelect.php
new file mode 100644
index 0000000..ee9fb73
--- /dev/null
+++ b/idrocap_wa/templates/element/provinceSelect.php
@@ -0,0 +1,145 @@
+ $provinceConfig->fieldId,
+ 'label' => __($provinceConfig->fieldLabel),
+ 'type' => $provinceConfig->fieldType->value,
+ "empty" => true,
+ 'options' => $provinces ?? [],
+ 'disabled' => $provinceConfig->disabled,
+ 'required' => $provinceConfig->fieldRequired
+];
+
+if (!empty($provinceConfig->fieldValue)) {
+ $options['value'] = $provinceConfig->fieldValue;
+}
+
+$formContext = $provinceConfig->formContext ?? null;
+
+/**
+ * Passo il contesto perchè CakePHP genera una nuova VIEW e altrimenti non sarebbe visibile alla view dell'element.
+ * Vedi caso in cui dobbiamo gestire il valore selected per edit o view
+ * Inoltre anche nel caso di errori in questo caso manteniamo la gestione nativa di cakephp.
+ */
+if (isset($formContext)) {
+ $this->Form->create($formContext, ['type' => 'context', 'id' => false, 'url' => false]);
+}
+?>
+
+fieldId !== null && $provinceConfig->fieldName !== null): ?>
+ = $this->Form->control($provinceConfig->fieldName, $options) ?>
+
+
+
+ Form->end();
+ }
+endif; ?>
diff --git a/idrocap_wa/templates/email/html/default.php b/idrocap_wa/templates/email/html/default.php
new file mode 100644
index 0000000..bf4c131
--- /dev/null
+++ b/idrocap_wa/templates/email/html/default.php
@@ -0,0 +1,22 @@
+ ' . $line . " \n";
+endforeach;
diff --git a/idrocap_wa/templates/email/text/default.php b/idrocap_wa/templates/email/text/default.php
new file mode 100644
index 0000000..bb8461e
--- /dev/null
+++ b/idrocap_wa/templates/email/text/default.php
@@ -0,0 +1,18 @@
+fetch('content');
diff --git a/idrocap_wa/templates/layout/default.php b/idrocap_wa/templates/layout/default.php
new file mode 100644
index 0000000..de042c7
--- /dev/null
+++ b/idrocap_wa/templates/layout/default.php
@@ -0,0 +1,47 @@
+
+
+
+
+ = $this->Html->charset() ?>
+
+
+ = \Cake\Core\Configure::read('Theme.title') ?>:
+ = $this->fetch('title') ?>
+
+ = $this->Html->meta('icon') ?>
+
+
+
+ = $this->Html->css(['normalize.min', 'milligram.min', 'cake']) ?>
+
+ = $this->fetch('meta') ?>
+ = $this->fetch('css') ?>
+ = $this->fetch('script') ?>
+
+
+
+
+ = $this->Flash->render() ?>
+ = $this->fetch('content') ?>
+
+
+
+
+
diff --git a/idrocap_wa/templates/layout/email/html/default.php b/idrocap_wa/templates/layout/email/html/default.php
new file mode 100644
index 0000000..96b0e73
--- /dev/null
+++ b/idrocap_wa/templates/layout/email/html/default.php
@@ -0,0 +1,25 @@
+
+
+
+
+ = $this->fetch('title') ?>
+
+
+ = $this->fetch('content') ?>
+
+
diff --git a/idrocap_wa/templates/layout/email/text/default.php b/idrocap_wa/templates/layout/email/text/default.php
new file mode 100644
index 0000000..cd51169
--- /dev/null
+++ b/idrocap_wa/templates/layout/email/text/default.php
@@ -0,0 +1,17 @@
+fetch('content');
diff --git a/idrocap_wa/templates/layout/error.php b/idrocap_wa/templates/layout/error.php
new file mode 100644
index 0000000..28c09ba
--- /dev/null
+++ b/idrocap_wa/templates/layout/error.php
@@ -0,0 +1,41 @@
+
+
+
+
+ = $this->Html->charset() ?>
+
+ = $this->fetch('title') ?>
+
+ = $this->Html->meta('icon') ?>
+
+
+
+ = $this->Html->css(['normalize.min', 'milligram.min', 'cake']) ?>
+
+ = $this->fetch('meta') ?>
+ = $this->fetch('css') ?>
+ = $this->fetch('script') ?>
+
+
+
+ = $this->Flash->render() ?>
+ = $this->fetch('content') ?>
+ = $this->Html->link(__('Back'), 'javascript:history.back()') ?>
+
+
+
diff --git a/idrocap_wa/templates/layout/view_public.php b/idrocap_wa/templates/layout/view_public.php
new file mode 100644
index 0000000..d44e591
--- /dev/null
+++ b/idrocap_wa/templates/layout/view_public.php
@@ -0,0 +1,68 @@
+CakeLte
+ */
+
+?>
+
+
+
+
+
+
+
+ = $this->fetch('title') . ' | ' . strip_tags($this->CakeLte->getConfig('app-name')) ?>
+
+ = $this->Html->meta('icon') ?>
+ = $this->fetch('meta') ?>
+
+
+
+
+ = $this->Html->css('/adminlte/plugins/fontawesome-free/css/all.min.css') ?>
+
+ = $this->Html->css('/adminlte/dist/css/adminlte.min.css') ?>
+ = $this->Html->css('CakeLte.style') ?>
+ = $this->Html->css('idrocap-styles') ?>
+ = $this->element('CakeLte.extra/css') ?>
+
+ = $this->Html->css('citizen-registration.css') ?>
+
+ = $this->fetch('css') ?>
+
+
+
+
+
+ = $this->CakeLte->getConfig('app-name') ?>
+
+
+
+
+
+
+ = $this->fetch('content') ?>
+
+
+ = $this->Html->link(__('Torna al login'), ['controller' => 'Users', 'action' => 'login'], ['class' => 'btn btn-info']) ?>
+
+
+
+
+
+
+
+ = $this->Html->script('/adminlte/plugins/jquery/jquery.min.js') ?>
+
+ = $this->Html->script('/adminlte/plugins/bootstrap/js/bootstrap.bundle.min.js') ?>
+
+ = $this->Html->script('/adminlte/dist/js/adminlte.min.js') ?>
+
+ = $this->element('CakeLte.extra/script') ?>
+ = $this->fetch('script') ?>
+
+
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/plugin/BootstrapUI/element/flash/default.php b/idrocap_wa/templates/plugin/BootstrapUI/element/flash/default.php
new file mode 100644
index 0000000..5bffbfb
--- /dev/null
+++ b/idrocap_wa/templates/plugin/BootstrapUI/element/flash/default.php
@@ -0,0 +1,30 @@
+Html->icon($icon, $params['iconOptions']);
+ }
+ $message = $icon . "$message
";
+}
+
+if (in_array('alert-dismissible', $class)) {
+ $button = <<×
+BUTTON;
+ $message = $button . $message;
+}
+if (is_array($class)) {
+ $class = join(' ', $class);
+}
+echo $this->Html->div($class, $message, $params['attributes']);
diff --git a/idrocap_wa/templates/plugin/CakeLte/element/footer/main.php b/idrocap_wa/templates/plugin/CakeLte/element/footer/main.php
new file mode 100644
index 0000000..b132fe8
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/element/footer/main.php
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
diff --git a/idrocap_wa/templates/plugin/CakeLte/element/header/main.php b/idrocap_wa/templates/plugin/CakeLte/element/header/main.php
new file mode 100644
index 0000000..4ac2fc1
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/element/header/main.php
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ = $this->element('CakeLte.header/menu') ?>
+ = $this->element('CakeLte.header/notifications') ?>
+
diff --git a/idrocap_wa/templates/plugin/CakeLte/element/header/menu.php b/idrocap_wa/templates/plugin/CakeLte/element/header/menu.php
new file mode 100644
index 0000000..a50ed2a
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/element/header/menu.php
@@ -0,0 +1,2 @@
+
+= $this->Sections->create($menu_sections) ?>
diff --git a/idrocap_wa/templates/plugin/CakeLte/element/header/notifications.php b/idrocap_wa/templates/plugin/CakeLte/element/header/notifications.php
new file mode 100644
index 0000000..b84917f
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/element/header/notifications.php
@@ -0,0 +1,51 @@
+Html->script('jixel-primitives'); ?>
+
+= $this->Notifications->create($user_notifications) ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/plugin/CakeLte/element/sidebar/main.php b/idrocap_wa/templates/plugin/CakeLte/element/sidebar/main.php
new file mode 100644
index 0000000..fd685e5
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/element/sidebar/main.php
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/idrocap_wa/templates/plugin/CakeLte/element/sidebar/menu.php b/idrocap_wa/templates/plugin/CakeLte/element/sidebar/menu.php
new file mode 100644
index 0000000..203861d
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/element/sidebar/menu.php
@@ -0,0 +1,33 @@
+
+
+
+
+
+ Html->image($logged_user_photo, ['class' => 'img-circle', 'alt' => ' ', 'width' => '30', 'height' => '30', 'style' => 'margin-right: 5px;']); ?>
+
+ = $logged_user_description ?>
+
+
+
+
+
+
+
+ = $this->Menu->create($menu_items) ?>
+
+
+ Menu->create($sys_admin_menu_items); ?>
+
\ No newline at end of file
diff --git a/idrocap_wa/templates/plugin/CakeLte/layout/default.php b/idrocap_wa/templates/plugin/CakeLte/layout/default.php
new file mode 100644
index 0000000..0d04294
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/layout/default.php
@@ -0,0 +1,108 @@
+CakeLte
+ */
+
+?>
+
+
+
+
+
+
+
+
+ = strip_tags($this->fetch('title') . ' | ' . $this->CakeLte->getConfig('app-name')) ?>
+
+ = $this->Html->meta('icon') ?>
+ = $this->fetch('meta') ?>
+
+
+
+
+ = $this->Html->css('/adminlte/plugins/fontawesome-free/css/all.min.css') ?>
+
+ = $this->Html->css('/adminlte/dist/css/adminlte.min.css') ?>
+ = $this->Html->css('CakeLte.style') ?>
+ = $this->Html->css('idrocap-styles') ?>
+
+ Html->css('/bower_components/select2/dist/css/select2.min'); ?>
+
+ = $this->Html->css('/adminlte/plugins/daterangepicker/daterangepicker') ?>
+ element('CakeLte.extra/css') ?>
+ = $this->fetch('css') ?>
+
+
+
+
+
+
+ = $this->element('CakeLte.header/main') ?>
+
+
+
+
+
+
+
+
+
+
+
+ = $this->Flash->render() ?>
+ = $this->fetch('content') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->element('CakeLte.footer/main') ?>
+
+
+
+
+
+ = $this->Html->script('/adminlte/plugins/jquery/jquery.min.js') ?>
+
+ = $this->Html->script('/adminlte/plugins/bootstrap/js/bootstrap.bundle.min.js') ?>
+
+ = $this->Html->script('/adminlte/dist/js/adminlte.min.js') ?>
+
+ = $this->element('CakeLte.extra/script') ?>
+
+ Html->script('/bower_components/select2/dist/js/select2.min'); ?>
+
+ Html->script('/adminlte/plugins/daterangepicker/daterangepicker'); ?>
+
+ = $this->fetch('script') ?>
+
+
+
diff --git a/idrocap_wa/templates/plugin/CakeLte/layout/login.php b/idrocap_wa/templates/plugin/CakeLte/layout/login.php
new file mode 100644
index 0000000..965a9d9
--- /dev/null
+++ b/idrocap_wa/templates/plugin/CakeLte/layout/login.php
@@ -0,0 +1,111 @@
+CakeLte
+ */
+
+?>
+
+
+
+
+
+
+
+ = $this->fetch('title') . ' | ' . strip_tags($this->CakeLte->getConfig('app-name')) ?>
+
+ = $this->Html->meta('icon') ?>
+ = $this->fetch('meta') ?>
+
+
+
+
+ = $this->Html->css('/adminlte/plugins/fontawesome-free/css/all.min.css') ?>
+
+ = $this->Html->css('/adminlte/dist/css/adminlte.min.css') ?>
+ = $this->Html->css('CakeLte.style') ?>
+ = $this->Html->css('idrocap-styles') ?>
+ = $this->element('CakeLte.extra/css') ?>
+
+ = $this->Html->css('citizen-registration.css') ?>
+
+ = $this->fetch('css') ?>
+
+
+
+
+
+ = $this->CakeLte->getConfig('app-name') ?>
+
+
+
+
+
+
+
+ = $this->Flash->render(); ?>
+ isShowAlert()): ?>
+
+
= __('Sei un cittadino e non sei ancora registrato?') ?>
+ = $this->Html->link(__('Clicca qui per registrarti'), ['action' => 'add_citizen']) ?>
+
+
+ = $this->fetch('content') ?>
+
+
+ = $this->Html->link($login_layout_link_label, ['action' => $login_layout_link_action], ['style' => ['color:black']]) ?>
+
+
+
+
+ = $this->Html->link($login_layout_privacy_label, ['controller' => 'Privacy','action' => $login_layout_privacy_link], ['style' => ['color:black']]) ?>
+
+
+
+
+
+ = $this->Flash->render(); ?>
+ = $this->fetch('content') ?>
+
+
+
+
+
+
+
+
+ = $this->Html->script('/adminlte/plugins/jquery/jquery.min.js') ?>
+
+ = $this->Html->script('/adminlte/plugins/bootstrap/js/bootstrap.bundle.min.js') ?>
+
+ = $this->Html->script('/adminlte/dist/js/adminlte.min.js') ?>
+
+ = $this->element('CakeLte.extra/script') ?>
+ = $this->fetch('script') ?>
+
+
+
+
diff --git a/idrocap_wa/tests/Fixture/.gitkeep b/idrocap_wa/tests/Fixture/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/tests/TestCase/ApplicationTest.php b/idrocap_wa/tests/TestCase/ApplicationTest.php
new file mode 100644
index 0000000..6a65c52
--- /dev/null
+++ b/idrocap_wa/tests/TestCase/ApplicationTest.php
@@ -0,0 +1,85 @@
+bootstrap();
+ $plugins = $app->getPlugins();
+
+ $this->assertTrue($plugins->has('Bake'), 'plugins has Bake?');
+ $this->assertFalse($plugins->has('DebugKit'), 'plugins has DebugKit?');
+ $this->assertTrue($plugins->has('Migrations'), 'plugins has Migrations?');
+ }
+
+ /**
+ * Test bootstrap add DebugKit plugin in debug mode.
+ *
+ * @return void
+ */
+ public function testBootstrapInDebug()
+ {
+ Configure::write('debug', true);
+ $app = new Application(dirname(__DIR__, 2) . '/config');
+ $app->bootstrap();
+ $plugins = $app->getPlugins();
+
+ $this->assertTrue($plugins->has('DebugKit'), 'plugins has DebugKit?');
+ }
+
+ /**
+ * testMiddleware
+ *
+ * @return void
+ */
+ public function testMiddleware()
+ {
+ $app = new Application(dirname(__DIR__, 2) . '/config');
+ $middleware = new MiddlewareQueue();
+
+ $middleware = $app->middleware($middleware);
+
+ $this->assertInstanceOf(ErrorHandlerMiddleware::class, $middleware->current());
+ $middleware->seek(1);
+ $this->assertInstanceOf(AssetMiddleware::class, $middleware->current());
+ $middleware->seek(2);
+ $this->assertInstanceOf(RoutingMiddleware::class, $middleware->current());
+ }
+}
diff --git a/idrocap_wa/tests/TestCase/Controller/Component/.gitkeep b/idrocap_wa/tests/TestCase/Controller/Component/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/tests/TestCase/Controller/PagesControllerTest.php b/idrocap_wa/tests/TestCase/Controller/PagesControllerTest.php
new file mode 100644
index 0000000..73f9452
--- /dev/null
+++ b/idrocap_wa/tests/TestCase/Controller/PagesControllerTest.php
@@ -0,0 +1,115 @@
+get('/pages/home');
+ $this->assertResponseOk();
+ $this->assertResponseContains('CakePHP');
+ $this->assertResponseContains('');
+ }
+
+ /**
+ * Test that missing template renders 404 page in production
+ *
+ * @return void
+ */
+ public function testMissingTemplate()
+ {
+ Configure::write('debug', false);
+ $this->get('/pages/not_existing');
+
+ $this->assertResponseError();
+ $this->assertResponseContains('Error');
+ }
+
+ /**
+ * Test that missing template in debug mode renders missing_template error page
+ *
+ * @return void
+ */
+ public function testMissingTemplateInDebug()
+ {
+ Configure::write('debug', true);
+ $this->get('/pages/not_existing');
+
+ $this->assertResponseFailure();
+ $this->assertResponseContains('Missing Template');
+ $this->assertResponseContains('stack-frames');
+ $this->assertResponseContains('not_existing.php');
+ }
+
+ /**
+ * Test directory traversal protection
+ *
+ * @return void
+ */
+ public function testDirectoryTraversalProtection()
+ {
+ $this->get('/pages/../Layout/ajax');
+ $this->assertResponseCode(403);
+ $this->assertResponseContains('Forbidden');
+ }
+
+ /**
+ * Test that CSRF protection is applied to page rendering.
+ *
+ * @return void
+ */
+ public function testCsrfAppliedError()
+ {
+ $this->post('/pages/home', ['hello' => 'world']);
+
+ $this->assertResponseCode(403);
+ $this->assertResponseContains('CSRF');
+ }
+
+ /**
+ * Test that CSRF protection is applied to page rendering.
+ *
+ * @return void
+ */
+ public function testCsrfAppliedOk()
+ {
+ $this->enableCsrfToken();
+ $this->post('/pages/home', ['hello' => 'world']);
+
+ $this->assertThat(403, $this->logicalNot(new StatusCode($this->_response)));
+ $this->assertResponseNotContains('CSRF');
+ }
+}
diff --git a/idrocap_wa/tests/TestCase/Model/Behavior/.gitkeep b/idrocap_wa/tests/TestCase/Model/Behavior/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/tests/TestCase/View/Helper/.gitkeep b/idrocap_wa/tests/TestCase/View/Helper/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/idrocap_wa/tests/bootstrap.php b/idrocap_wa/tests/bootstrap.php
new file mode 100644
index 0000000..1cb386d
--- /dev/null
+++ b/idrocap_wa/tests/bootstrap.php
@@ -0,0 +1,66 @@
+ 'Cake\Database\Connection',
+ 'driver' => 'Cake\Database\Driver\Sqlite',
+ 'database' => TMP . 'debug_kit.sqlite',
+ 'encoding' => 'utf8',
+ 'cacheMetadata' => true,
+ 'quoteIdentifiers' => false,
+]);
+
+ConnectionManager::alias('test_debug_kit', 'debug_kit');
+
+// Fixate sessionid early on, as php7.2+
+// does not allow the sessionid to be set after stdout
+// has been written to.
+session_id('cli');
+
+// Use migrations to build test database schema.
+//
+// Will rebuild the database if the migration state differs
+// from the migration history in files.
+//
+// If you are not using CakePHP's migrations you can
+// hook into your migration tool of choice here or
+// load schema from a SQL dump file with
+// use Cake\TestSuite\Fixture\SchemaLoader;
+// (new SchemaLoader())->loadSqlFiles('./tests/schema.sql', 'test');
+
+(new Migrator())->run();
diff --git a/idrocap_wa/tests/schema.sql b/idrocap_wa/tests/schema.sql
new file mode 100644
index 0000000..c7e4d3f
--- /dev/null
+++ b/idrocap_wa/tests/schema.sql
@@ -0,0 +1,4 @@
+-- Test database schema.
+--
+-- If you are not using CakePHP migrations you can put
+-- your application's schema in this file and use it in tests.
diff --git a/idrocap_wa/webroot/.gitignore b/idrocap_wa/webroot/.gitignore
new file mode 100644
index 0000000..5cccb96
--- /dev/null
+++ b/idrocap_wa/webroot/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+bower_components
+
diff --git a/idrocap_wa/webroot/.htaccess b/idrocap_wa/webroot/.htaccess
new file mode 100644
index 0000000..f5f2d63
--- /dev/null
+++ b/idrocap_wa/webroot/.htaccess
@@ -0,0 +1,5 @@
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.php [L]
+
diff --git a/idrocap_wa/webroot/adminlte b/idrocap_wa/webroot/adminlte
new file mode 120000
index 0000000..be2cf15
--- /dev/null
+++ b/idrocap_wa/webroot/adminlte
@@ -0,0 +1 @@
+/var/www/jixel/vendor/almasaeed2010/adminlte/
\ No newline at end of file
diff --git a/idrocap_wa/webroot/bower.json b/idrocap_wa/webroot/bower.json
new file mode 100644
index 0000000..728e78e
--- /dev/null
+++ b/idrocap_wa/webroot/bower.json
@@ -0,0 +1,17 @@
+{
+ "name": "webroot",
+ "description": "",
+ "main": "",
+ "license": "MIT",
+ "homepage": "",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ],
+ "dependencies": {
+ "select2": "~4.0"
+ }
+}
diff --git a/idrocap_wa/webroot/css/cake.css b/idrocap_wa/webroot/css/cake.css
new file mode 100644
index 0000000..fbb0de9
--- /dev/null
+++ b/idrocap_wa/webroot/css/cake.css
@@ -0,0 +1,299 @@
+/* Milligram overrides */
+:root {
+ /* The following are official CakePHP colors */
+ --color-cakephp-red: #d33c43;
+ --color-cakephp-gray: #404041;
+ --color-cakephp-blue: #2f85ae;
+ --color-cakephp-lightblue: #34bdd7;
+
+ /* These are additional colors */
+ --color-lightgray: #606c76;
+ --color-white: #fff;
+
+ --color-main-bg: #f5f7fa;
+ --color-links: var(--color-cakephp-blue);
+ --color-links-active: #2a6496;
+ --color-headings: #363637;
+
+ --color-message-success-bg: #e3fcec;
+ --color-message-success-text: #1f9d55;
+ --color-message-success-border: #51d88a;
+
+ --color-message-warning-bg: #fffabc;
+ --color-message-warning-text: #8d7b00;
+ --color-message-warning-border: #d3b800;
+
+ --color-message-error-bg: #fcebea;
+ --color-message-error-text: #cc1f1a;
+ --color-message-error-border: #ef5753;
+
+ --color-message-info-bg: #eff8ff;
+ --color-message-info-text: #2779bd;
+ --color-message-info-border: #6cb2eb;
+}
+
+.button, button, input[type='button'], input[type='reset'], input[type='submit'] {
+ background-color: var(--color-cakephp-red);
+ border-color: var(--color-cakephp-red);
+}
+
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 400;
+ background: var(--color-main-bg);
+}
+
+.top-nav-links,
+.side-nav,
+h1, h2, h3, h4, h5, h6 {
+ font-family: "Raleway", sans-serif;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: 400;
+ color: var(--color-headings);
+}
+
+a {
+ color: var(--color-links);
+ transition: color 0.2s linear;
+}
+
+a:hover,
+a:focus,
+a:active {
+ color: var(--color-links-active);
+ transition: color 0.2s ease-out;
+}
+
+.side-nav a,
+.top-nav-links a,
+th a,
+.actions a {
+ color: var(--color-lightgray);
+}
+
+.side-nav a:hover,
+.side-nav a:focus,
+.actions a:hover,
+.actions a:focus {
+ color: var(--color-links-active);
+}
+
+/* Utility */
+.table-responsive {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+/* Main */
+.content {
+ padding: 2rem;
+ background: var(--color-white);
+ border-radius: 0.4rem;
+ /* Thanks Stripe */
+ box-shadow: 0 7px 14px 0 rgba(60, 66, 87, 0.1),
+ 0 3px 6px 0 rgba(0, 0, 0, 0.07);
+}
+.content form {
+ margin: 0;
+}
+.actions a {
+ font-weight: bold;
+ padding: 0 0.4rem;
+}
+.actions a:first-child {
+ padding-left: 0;
+}
+th {
+ white-space: nowrap;
+}
+
+/* Nav bar */
+.top-nav {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ max-width: 112rem;
+ padding: 2rem;
+ margin: 0 auto;
+}
+.top-nav-title a {
+ font-size: 2.4rem;
+ color: var(--color-cakephp-red);
+}
+.top-nav-title span {
+ color: var(--color-cakephp-gray);
+}
+.top-nav-links a {
+ margin: 0 0.5rem;
+}
+.top-nav-title a,
+.top-nav-links a {
+ font-weight: bold;
+}
+.side-nav-item {
+ display: block;
+ padding: 0.5rem 0;
+}
+
+/* View action */
+.view.content .text {
+ margin-top: 1.2rem;
+}
+.related {
+ margin-top: 2rem;
+}
+
+/* Flash messages */
+.message {
+ padding: .5rem 1rem;
+ background: var(--color-message-info-bg);
+ color: var(--color-message-info-text);
+ border-color: var(--color-message-info-border);
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 4px;
+ margin-bottom: 1rem;
+ cursor: pointer;
+}
+.message.hidden {
+ display: none;
+}
+.message.success {
+ background: var(--color-message-success-bg);
+ color: var(--color-message-success-text);
+ border-color: var(--color-message-success-border);
+}
+.message.warning {
+ background: var(--color-message-warning-bg);
+ color: var(--color-message-warning-text);
+ border-color: var(--color-message-warning-border);
+}
+.message.error {
+ background: var(--color-message-error-bg);
+ color: var(--color-message-error-text);
+ border-color: var(--color-message-error-border);
+}
+
+/* Forms */
+.input.radio,
+.input.checkbox,
+.input.multicheckbox {
+ margin-bottom: 2.0rem;
+}
+.input.radio input,
+.input.checkbox input,
+.input.multicheckbox input {
+ margin: 0;
+}
+.input.radio label,
+.input.checkbox label,
+.input.multicheckbox label {
+ margin: 0;
+ display: flex;
+ align-items: center;
+}
+.input.radio label > input,
+.input.checkbox label > input,
+.input.multicheckbox label > input {
+ margin-right: 1.0rem;
+}
+input[type='color'] {
+ max-width: 4rem;
+ padding: 0.3rem .5rem 0.3rem;
+}
+
+/* Paginator */
+.paginator {
+ text-align: right;
+}
+.paginator p {
+ margin-bottom: 0;
+}
+.pagination {
+ display: flex;
+ justify-content: center;
+ list-style: none;
+ margin: 0 0 1rem 0;
+ padding: 0;
+}
+.pagination li {
+ display: inline-block;
+ margin: 0.25em;
+ text-align: center;
+}
+.pagination a {
+ color: var(--color-cakephp-blue);
+ display: inline-block;
+ font-size: 1.25rem;
+ line-height: 3rem;
+ min-width: 3rem;
+ padding: 0;
+ position: relative;
+ text-decoration: none;
+ transition: background .3s,color .3s;
+}
+.pagination li.active a,
+.pagination a:hover {
+ text-decoration: underline;
+}
+.pagination .disabled a {
+ cursor: not-allowed;
+ color: var(--color-lightgray);
+ text-decoration: none;
+}
+.first a,
+.prev a,
+.next a,
+.last a {
+ padding: 0 .75rem;
+}
+.disabled a:hover {
+ background: initial;
+ color: initial;
+}
+.asc:after {
+ content: " \2193";
+}
+.desc:after {
+ content: " \2191";
+}
+
+/* Error in non debug mode */
+.error-container {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ justify-content: center;
+}
+
+@media screen and (max-width: 640px) {
+ /* Fix milligram not having a responsive column system */
+ .row .column[class*='column-'] {
+ flex: 0 0 100%;
+ max-width: 100%
+ }
+ .top-nav {
+ margin: 0 auto;
+ }
+ .side-nav {
+ margin-bottom: 1rem;
+ }
+ .heading {
+ margin-bottom: 1rem;
+ }
+ .side-nav-item {
+ display: inline;
+ margin: 0 1.5rem 0 0;
+ }
+ .asc:after {
+ content: " \2192";
+ }
+ .desc:after {
+ content: " \2190";
+ }
+}
diff --git a/idrocap_wa/webroot/css/citizen-registration.css b/idrocap_wa/webroot/css/citizen-registration.css
new file mode 100644
index 0000000..bf2f717
--- /dev/null
+++ b/idrocap_wa/webroot/css/citizen-registration.css
@@ -0,0 +1,14 @@
+.add-citizen.add-citizen {
+ width: 80%;
+}
+
+.login-page {
+ margin-top: 76px;
+ margin-bottom: 76px;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+.card-primary.card-outline {
+ border-top: none;
+}
diff --git a/idrocap_wa/webroot/css/fonts.css b/idrocap_wa/webroot/css/fonts.css
new file mode 100644
index 0000000..1ba4808
--- /dev/null
+++ b/idrocap_wa/webroot/css/fonts.css
@@ -0,0 +1,80 @@
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../font/raleway-400-cyrillic-ext.woff2') format('woff2');
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../font/raleway-400-cyrillic.woff2') format('woff2');
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../font/raleway-400-vietnamese.woff2') format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../font/raleway-400-latin-ext.woff2') format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../font/raleway-400-latin.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../font/raleway-700-cyrillic-ext.woff2') format('woff2');
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../font/raleway-700-cyrillic.woff2') format('woff2');
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../font/raleway-700-vietnamese.woff2') format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../font/raleway-700-latin-ext.woff2') format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Raleway';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../font/raleway-700-latin.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
diff --git a/idrocap_wa/webroot/css/home.css b/idrocap_wa/webroot/css/home.css
new file mode 100644
index 0000000..4648ed3
--- /dev/null
+++ b/idrocap_wa/webroot/css/home.css
@@ -0,0 +1,75 @@
+/* Home page styles */
+@font-face {
+ font-family: 'cakefont';
+ src: url('../font/cakedingbats-webfont.eot');
+ src: url('../font/cakedingbats-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../font/cakedingbats-webfont.woff2') format('woff2'),
+ url('../font/cakedingbats-webfont.woff') format('woff'),
+ url('../font/cakedingbats-webfont.ttf') format('truetype'),
+ url('../font/cakedingbats-webfont.svg#cake_dingbatsregular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+body {
+ padding: 60px 0;
+}
+header {
+ margin-bottom: 60px;
+}
+img {
+ margin-bottom: 30px;
+}
+h1 {
+ font-weight: bold;
+}
+ul {
+ list-style-type: none;
+ margin: 0 0 30px 0;
+ padding-left: 25px;
+}
+a {
+ color: #0071BC;
+ text-decoration: underline;
+}
+hr {
+ border-bottom: 1px solid #e7e7e7;
+ border-top: 0;
+ margin-bottom: 35px;
+}
+
+.text-center {
+ text-align: center;
+}
+.links a {
+ margin-right: 10px;
+}
+.release-name {
+ color: #D33C43;
+ font-weight: 400;
+ font-style: italic;
+}
+.bullet:before {
+ font-family: 'cakefont', sans-serif;
+ font-size: 18px;
+ display: inline-block;
+ margin-left: -1.3em;
+ width: 1.2em;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ vertical-align: -1px;
+}
+.success:before {
+ color: #88c671;
+ content: "\0056";
+}
+.problem:before {
+ color: #d33d44;
+ content: "\0057";
+}
+.cake-error {
+ padding: 10px;
+ margin: 10px 0;
+}
+#url-rewriting-warning {
+ display: none;
+}
diff --git a/idrocap_wa/webroot/css/idrocap-styles.css b/idrocap_wa/webroot/css/idrocap-styles.css
new file mode 100644
index 0000000..a1bf189
--- /dev/null
+++ b/idrocap_wa/webroot/css/idrocap-styles.css
@@ -0,0 +1,33 @@
+.select2-container {
+ width: 100% !important;
+}
+
+.select2-selection {
+ height: calc(2.25rem + 2px) !important;
+}
+
+.select2-container--default .select2-selection--single .select2-selection__arrow.select2-selection__arrow {
+ top: 6px;
+}
+
+.idrocap-filter-select {
+ width: 100%;
+ height: 2.25rem;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #495057;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #ced4da;
+ border-radius: 0.25rem;
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+.tox-promotion {
+ display: none;
+}
+.tox-statusbar__branding {
+ display: none;
+}
\ No newline at end of file
diff --git a/idrocap_wa/webroot/css/jixel_ol.css b/idrocap_wa/webroot/css/jixel_ol.css
new file mode 100644
index 0000000..7449f92
--- /dev/null
+++ b/idrocap_wa/webroot/css/jixel_ol.css
@@ -0,0 +1,66 @@
+.jixel-ol-tools-button {
+ top: 65px;
+ left: .5em;
+}
+
+.ol-attribution li {
+ font-size: 1.3rem;
+}
+
+.layerup {
+ display:none !important;
+}
+
+.ol-layerswitcher .panel li label {
+ max-width: 40em !important;
+}
+.olmap {
+ height: 500px;
+ width: 100%;
+}
+.jixel-ol-popup {
+ position: absolute;
+ background-color: white;
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
+ filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
+ padding: 15px;
+ border-radius: 10px;
+ border: 1px solid #cccccc;
+ bottom: 12px;
+ left: -50px;
+ min-width: 280px;
+}
+.jixel-ol-popup:after, .jixel-ol-popup:before {
+ top: 100%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+.jixel-ol-popup:after {
+ border-top-color: white;
+ border-width: 10px;
+ left: 48px;
+ margin-left: -10px;
+}
+.jixel-ol-popup:before {
+ border-top-color: #cccccc;
+ border-width: 11px;
+ left: 48px;
+ margin-left: -11px;
+}
+.jixel-ol-popup-closer {
+ text-decoration: none;
+ position: absolute;
+ top: 5px;
+ right: 10px;
+}
+.jixel-ol-popup-closer:after {
+ content: "✖";
+}
+.jixel-ol-popup-content {
+ height: 200px;
+ overflow-y: scroll;
+}
diff --git a/idrocap_wa/webroot/css/milligram.min.css b/idrocap_wa/webroot/css/milligram.min.css
new file mode 100644
index 0000000..958f687
--- /dev/null
+++ b/idrocap_wa/webroot/css/milligram.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Milligram v1.4.1
+ * https://milligram.io
+ *
+ * Copyright (c) 2020 CJ Patoilo
+ * Licensed under the MIT license
+ */
+
+*,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#606c76;font-family:'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}blockquote{border-left:0.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#9b4dca;border:0.1rem solid #9b4dca;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#9b4dca;border-color:#9b4dca}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#9b4dca}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#606c76;color:#606c76}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#9b4dca}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#9b4dca}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#606c76}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#9b4dca}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#f4f5f6;border-left:0.3rem solid #9b4dca;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #f4f5f6;margin:3.0rem 0}input[type='color'],input[type='date'],input[type='datetime'],input[type='datetime-local'],input[type='email'],input[type='month'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],input[type='week'],input:not([type]),textarea,select{-webkit-appearance:none;background-color:transparent;border:0.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem .7rem;width:100%}input[type='color']:focus,input[type='date']:focus,input[type='datetime']:focus,input[type='datetime-local']:focus,input[type='email']:focus,input[type='month']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,input[type='week']:focus,input:not([type]):focus,textarea:focus,select:focus{border-color:#9b4dca;outline:0}select{background:url('data:image/svg+xml;utf8, ') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8, ')}select[multiple]{background:none;height:auto}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.container{margin:0 auto;max-width:112.0rem;padding:0 2.0rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-40{margin-left:40%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-60{margin-left:60%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}a{color:#9b4dca;text-decoration:none}a:focus,a:hover{color:#606c76}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;overflow-x:auto;text-align:left;width:100%}td,th{border-bottom:0.1rem solid #e1e1e1;padding:1.2rem 1.5rem}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}@media (min-width: 40rem){table{display:table;overflow-x:initial}}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}img{max-width:100%}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right}
diff --git a/idrocap_wa/webroot/css/normalize.min.css b/idrocap_wa/webroot/css/normalize.min.css
new file mode 100644
index 0000000..bde07fc
--- /dev/null
+++ b/idrocap_wa/webroot/css/normalize.min.css
@@ -0,0 +1,8 @@
+/**
+ * Minified by jsDelivr using clean-css v4.2.1.
+ * Original file: /npm/normalize.css@8.0.1/normalize.css
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
diff --git a/idrocap_wa/webroot/favicon.ico b/idrocap_wa/webroot/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..86c1a8c093c89251410271942191652b2d69a293
GIT binary patch
literal 227390
zcmeEP2YeL8_fNl)gcdrXcSs1mgx;Hq1sk9!ilQPaHWa(q8}|OQV*?v1c2p2hR74R4
z1Z)(0@8$i!-?@8tlg;ksl3W7#&+u8^?9{!@`|g{0^X5%bQZoL1kd%b~n)9vyaw<+U#u?~Y*zFWFo-c%0%r)}DG?6R7!b)5HhSuLYf+txB#*QQ!V
z)3k0`skWzmYCD>qD5~w3r9G{y)NUiz^V;R@a(24iRwClskM^PWUTtfBqNv?ZS=!Y4
zT9@};!7a}%&8vQC(w)y$nz}6Od@kp`-CnFbyIfh~`a7y<^!r>}C3HZ9CTAie(tI
ztlo!Gz5jPBuXQ!gyLL23>u8GCy`3IU`&wSh>b>^kMV;mCdYb1|*G|`ZPHLA)WL%$Z
zXQcd{JL7Ye^_k-RyRrR51bxo(wx#Wq=DA8!wzSWu&r_CqcAc`e6Hgo3b|NYJ)%NVT
zo#vLV`AXv{qh(8?+Llr+ulGtdU8!3-(-^c2sU7Tex42!lym4*c*^cv>m~W?P+^fE`
zJ*}_x?EKQSVb{|(ooTVsODe0+r_`;yGp#gbopnpP*LSnCP(JU@@+|Q_M`@qg?Qg=q
zG}!Ty(wt@WnYEr$J6-G8XEiSEmKlC
zXT8$g+kKQJ&c3vs_N(_*H2QA%E}TK%57X_qvz+ET)3r^dTF&j>t9?7&u4nhpAaPPA@yJr22LpyR03z+beHe+f{0}=at5Ew>-OUMaT6S%0l^U
zTF;JaT1ixYo3mVL+VX0{+2+o0Z$GQX6G{0S8I*?Zy#Ke~iFc{^bK>pSt3|K+ny%EV
zzNWKWyk)gcMNoZ?9Yy(@c2wUL-LKnk(=?@g20O0L6i$xo-8jqYy-n?QHLiWLoTfSB
zZud-M(E4sv+p}q?Rmn&NSX@z8$ygYn?<};Zl^ip&N6zh)Gn`SN}1;jTAt~4
zzE|9?Z`XB8cjoK88`b_b&u%ZCJh$?i#x^y0#WkPQ>ly4a<%w(iv8eqVvC28~%39Ca
zPNMJ2`&{L%&)-v08{r~F{{CL|oMpYrd8KBSXb-2rE9)T
z-O9P8xwXr36%p*`D{q|7SKc=Cx7+R5?b>l?S!bTzMyz;6)nmI1+IQ%#=>N{&;4G{6
zWu@AG(O#p^6sujWt7Wte-ZMDUL#d(von@S5_1>m-n|8WeT+7;hYMNVlJIz_n*+!!7
z?LI3y?)**8{z}Ssmgjw0>bSL25ozJai}0X6uUoqIufIpBrYrSI_sVycciw9~rJ7I5
zpy^6AO{tyEGzLwxsirHn^GX|M8w_?m=e?b0$4y0-x|*IyYWG_eFZ%aN^!sr8yRi=q
zc7K{is_B}hbu``U-Y&0Y?e^??Zs~S?jXTR}8+N{y(KPMbSyt2Sa$48Uv*TLUE~jZ)
zj+DWs8V}_Z&C|3*Q~P;h#o2GH{Hna@`|)~L`nTh|V$gSH$DL`WV7RQtW0lvowXC-1
zOt;%8sjRl)R?co$<92zCYo7LNQ*Bq%oOSfxtDL55AI|d5d%L{W(X@)7+J9*%pTn)Z
zSGrr-ib#vM|9H!l^%=E&rEEvzO6|7oG*b}&+4)-EndiLMa$a@gP1knVzShyWvrkRe
zayGT|?6|XxTbs`E&U?0@!ER5}ooSkG*U@;QsaxMwX;EHE=(|WuOEZ645ix(qKp+s$
z-&3C#x7+Y~8vwT`M>!>oX{I#!Y6N|JiLgtLSrTx|UU{=}MjHT3^$Z
zvb-I4*0=NQxRxs~Wt(=p8dvIU-z(i&&h0){UFKER#b>LGzVscG)K^74k7v7-SAYNg
zcO%gG|NQe$epr6-IW_1r>piJkn&!LJwbQh|mbYoFcD0m&iS6RD^
z-G-*SQD<9jWi-uMR-Y}Alzk<#ykT29}8qWZVn(LU@nx42!-j@xCu((N*gYdNLP{6yWe{jy$s2D`5F
z-p<<*@rr&PZQn_~eyhRO>i0jqe80nwlNVlD_Aum@kFqN{nN>{Cx_VFQmS*SMal5P?
z*LG}b*KqlV5aBfvSJNvcEloZ!Cw4B~6
z)%192S?eXF{p!`LE3UHMe)s)52JAjTG8%Q1y#8b4`IldN4%n(sd=Y<^{BnC{rZMoj
z7~H5nbErh|zm3+@a@vNL*L=PADyQjoc}=sao$uBr%WBZLQafGSj5p1zjac0&&(#BB-l7#0=aoI_Q0wCu6l3n
z-NY_p`m=dgp%!;b?mk^?kw-TcY6*kqg2~+
zqb%br=e&2TSDrNOvow_bIm_!aIMa*VEC2jIqG|Z8Jzjrn^@Ed+I_aJH1{*>S?PfD=!5D7HwARYUS!Tf9Pw~Lp)zF_+oUmb<|oQHL(
zfU9#k+bmCg*3HAkzdQf_?+jPd-~aey?7ELOpYhU?<@4q(Sh)0>Tkihg{41{i^t3rw
zY&rG3%XY!*(h{Ee(l4jaI`@Zt4xRo_r-8dkwPpnp!2BxMe_RMp8~>8vCnCYk|4Q(|
zr4k%DQ34nvX5wnwdxY#h>BxVNKINRBW}Sce*RwCUvdDEh?s+lYNu6cA?zNs*zE^r_
z>$#Q3Z`yX+oXfZH?|=0zcYSd0{3l*}@zv$`uls1znc$P%z%R|hd}FXi=1NbGn6D@g
zD$kXNCbBKB=g>aNOvB$8GhhEVG-s&$^Dn=QU-rh^cU*V-y&q1UdB$%8$4!zpy@pHO
zcD7$Q8aXQpQ<__u)33<+KlNkNI|*-kUVL4J+%FECbb{g!VPWBTnTpEB6|
z8cGTM@0PA#BUy>bLEA4CwPh84
zd-k{AeSZirwQ~HF8UHlwScvz8?|E~6v-bp_oGHO;=Sy(mD)8AB3BLD(1lRvAL5__!
z{vD=_J1^$x<;>H%c6~eUR^F~-m$l<=^_cHg#+hc_Z~jMulu4h3absi2D^7f|4lj-u
zBYj%!miis(Z&u2-^m6;HS`PFh&9}>kcq&vY%XY0mp_8P;8gzd!ka{IKxt5Py(Q
zz%S$*KgJOaz(?b!9Q!Zk5pRF^ZE+r6@M&Q@#cK+TbH*#{Dgd$l$n{SJga!%
zy&YoZYo4=?UBA3>yN?p%{5@ezrD06G|Lyn9U)N*AKB2jK>z)!k_(TcLUmlW6ilzS|
zUnKfBZN_&e(QWRE?WyeMxMsl$2~Ivqg0NwsE~wkEz2ugA9^CNbPd`rp4^mHN*4x7X
zh{d~#5hsqcj^-ztYWpQp3s(Wmt4=xd;{7%Ez~bI3!eoepdTh%eZS*_bJbk8S+e_3ZRS#Y=h?
zlMfqil~=)yAAfqmF{hsMdySS|F*fcZ!NX6N;L=a3Fja-kBG?Qh>U|JnOFxzBd(Ofd
zVHc_1vWrYR>8w9CZ2I^TU@MFG^3ZW8ZxbsTSE^}=#F4Wt?aPy5eSvvN_zk{IpL}-S
z5g7X#`+_#TBzV>h5?uRp6|NG+M^)_lbvaa4UUYSArb){kB(d2)B`ZDEf2ttU>(*>11`>SwO|SDKyueHc?wY!PDxg`Y@n-i5FgE0CsL1_{={
z-Vu@3xZ>5#$HHEs@)YMqsBR>}v!=iI!TRfl?tO4*?P|gd3BLQiw~axZf8#2d5yhA%
zzwZR^vOLdLp1Q$J|4O54f0BZMkX41mm10ZjHp%a^PU^KgN_@E;jLp%>eZ6InVqq
z9mjo9WR4Y@YuWNk@wN@RjT@01thXDKFo&nz)+bG8#ZnCs9s9bTTC+c3?k5I}}
zV*j__f8XP{*>iplaNp6`gC)4?n<{KoDz8V!jpV(`k~@{vkK#!wKca&pJJ@?mNe*JYH@^2iWB4rl4S4wq1n2yK!sM
zC!cLOdE|amLbifuU0*d8Oduca$~dl&XWxX4f1Wx)H%u`timOn3n>5M40y@KvGHjp8
zviXzG&zO71!-@%;zcr0i)9tiG#Ufs;8nu^$jy~y+AAkHw^@TQ%llK)1nr`DEk#TL`(9gd5F$uQr
zClA@{Ao1tsOK|Q3RpY@O^j)EjVn^vID)PH$bb_n@E@mg_trMhN(u-IN#|v%TF>Sjv
z?|g^h+y3xfj6Eo`m%Y0|v7~%%W5+Gc&M$9V+cy+)EBTGL-@PFZ{_+AXVVC>RYoY!4
zJBYt3@^4(#cIC@Wek1+9
zaM`C-`u8eqB?Ma>3l_B#bi;}>&3W&{7W4JmCLMdd1N*`eQn!6Cfe*G4@c%(yg2pc;-bvN?sp=h+hX;(E;38WmsCXb&?6`fe>0VTEruo|>ulE|M
z(Q>TRZrelde(13`fUBBeY^e-UoGEqUP1Bt;-f~(``!kf!z-PfTy+nDoUMpFrkGVtjtc*ip+V`9tZ|B^6amn~1c3R_k4sdCMy+`cXDI>C~#!hE}o-p5KSS|-MrkQj;ZdU*g-
zin@{hs>XyBC_AWYrM>h21DofNPSCk`xF`mqx+Hr)}!@$w|MBvD+4Q;RnC4mipBwRnYL&gah_ZGJkRQ`9PHco6zxux6nHQ!k$njXRy?J|n3Z^hz$x4cB8
zRbi_lFr{r`Oqem}dZ`XswPeW>Old`qJN`IHs!;=ajr+@_)7T;S(cj~s#q9)@?-djF
zy~bnFveaW8w&|+NaFbh#8}fcdhAM11_$8sd%lX#L3&d9~TON6YuDwLoty?F(diRv%
z#!bcl;L8<0HcaU6vECJR7sdAuE1#3s6(_N%8_u*1yPlTQJiS*MN_QC(st(=_M{a3e
zSSw9gwh_S<Y0ElfWBW
zD_(wWE}O2&YtCkLg4{b?L?=i-xA9=(z)rXEV3)De?Y8W=wxea0GCgXSkpnw;hs~24
zW|aTk@)D7z?N?zdk(ko9h^@z8mz10wx%!%`!^jGe+y8gF1gd38#<^GTQnIVKPEhgT
zq{{b+qT0S!d#+2hg)PNHA}Mqk85iCtnKi1(!iC%h8x7xl
z^NsZH-&d0R43fZ_A9fwRMiDzf^1Jf99Vh>5x?;hZujyr>&bHZxjjf0-L+4xMesl&ENQz4wn`~45{;3vwzu&wN!x#lG;Z8T-hJ;qS8UC@
zf1acRd%n9C?bO(E*9j^HoP2MmyTuh3O0|sMD^|2!&DVQ7U-Ot&BDS1ZQvNRucARZ!
zU1z$sZ7BZuNw})?gk{B&T@UlD!1HS)sZnD&1`5XPeDg(aFn01k4Lx=Iy(@(qNiiszjaJ(d8oh$IlhQ!UcY|LnUK@T;*uf7-!*WtIV^vOnRmaFz)SEc$>-<&vQNYZyO6-k>!bIV-7e`P
z$4SQF$4hYi@5U!N*Vz217r;2SNFT-Q1eK4K+BmS|Zuy#~RPp4b%-1wKu4y*awn$ZO
zl{nw32y7{iZ2W0j03be1{-;+-`tfH;QtS4ToSr7BvnUAw%-?XsFis`Z>y%f!?Z+IZ4!qe93-_1#?|w#nw>)C@#P}Y5S#lov)^Wy&8-FWbyHUk}*0V8V$KC4M
zb?ms-bE{)x%XNLr2^-~oXL_RUwf!o&RU)RGV_nBR`F!&~l0NfXV{dWS-FFqklqPKW
z=p$*evWTIc7
zPCxxLNy7f)z)K%S$Aj@c190Vk_FYNsGf=v9?WA0|&^!A%kQ%p6%Q3zLgI@{1CEjcS-l93*}Y%n7t+Aw2LM9;znt9
z&W|CvW6nZQTqw19*)4AKzvgS2lQQ3KSK~@G-|b%0NHuQDtzvpYH>@b{yX7S!P22x}
zfGx+EDqdb@IpT=2DLl^)Zu&<8Z+$8L`(HBio1_-4rFzZka>S8G$j6_cLJ8rbi!PMp
zI(3bX!L%Fiv*0-bOEwwZ14cG-*4byt4?p}MmtJ<6^z7YBh721jwXw&!?|^=?;`J4B
z>#O_r}-|pK>{y+D2=ZCRtk(iLFHNH
zTg8bR)v|V8ta@5rsT+puw(PiDyP8&_+#;{L1+R3svZYC@!j{d~P7LuL`-20kzLLNT
z?~5Py6B%b;C8_&PmZXlIVb4@U>ea6+fT~dTV~;;3f$A6&UU_Fk
z_7%~6E1vb)Hsd)MhmM?jy=3Sg0$D-njQLWZzJ;>;o_omqYu}eu@4REMl?gpYljcpO
zb-OmQ_Ja@PJ&X;93?C{fn2+tV?|9j|ZL4fpzfST;kClvtD<$wb_6|SryW|hw7CyU2
z`Cj=}`CIRmYPyq_l+W@kqvhXKKb
zQ|AJ?>E@eE≶HfpqECRqnm-Ub+8)`=PVwAcr4uxS3~BZk-5!IENlKMP9&B+ru!|
zGJ3^cg;Mj3C#B<_UqW|b^Rped`C573joLh4ntbictxh~?tRHhsXk#G4^I`sXVy-mz
zcDv4c+7EH{{{ve(wu7yLSu=g;70Ec~Y9ou1yY@2kpfq5pI`%U*$G5+*u(wQ{aDbe3
z)|qn8J$K78%x^yX{4@Fe_uu10Qt@Kc!5?+hH1yR7Ht_EipL2cmr(~RdsnJ)M@hD{$
zbR}u#vvFit&a@-!l3`%DZZinbgmxHfbVRV`oU)fv<;k7s|(q5t}OiJJaksT1L}I?KC@Xm$A!f
z`t`s=Ua04Zk*b$PUj$~gC$qS(Uo8XaJl
zp4hXzG$dDnt8`$kafc4lzC(L?{)Oj_-f!rLVKQpWXu09W8|2U_hl(%gmyx4KnKbGQ
zGXg#{F5K^c{pA3BADTekrC>an+O)Z(A9DW?iI;mptzlkjyPuN4{e{6-31GFzn!hWete7D=~OLOgi-~lpbw=u?k@s(F!ky)qBl1%JtCa%_R
zSTBngFP5&OMoZe%nMTi;`QhKv?A)Kgli=-QIzi=MrR0B&lj>!s+i@++H2czYyS|<8
z)rOW=s&(vp8(WdJW80okd0wevLhlnz|2x>S@q~F3zxnAWo{N3G10}h3ZL^lz8}@rA
zopho+vG57#^FHykPfrAPN^0Y`-+z-aqen_|zahqU)?f?2!G~w>I^z_XbN;!KHRn1b
zw^9#1R>qDQCEx$>y_wr_?JB2kZMkypRdVNDcM9bfW#H^H&yWWmd{E9i|2(PRsG-z>
zp5@x>t`)9hcZI$_wMU_3oOGT97H^P7*ZpGY1Z`fm`CHR%N`AKQ-Qw|Bcmhkqfw_%&n0=5|wqdu%TZiQc{xi{Y||ATz;
zop6q1z$U6;-~RIQ;+G|6f#pMN4x`pYlB$Y-Aw*Qa~}S9SWm62Kt0DhSXY_@Eb|%aVC^=edbXt1tbzUd
z)g=SI34@s5Wns+5%a66Elv+8GLfiA3=1Xu>Xm3>j>(PGf`I>vpHRjQen05pYn3svL
zSK|6`NrAXN3UaCk)`xGr{yI4lwoNtb*OSyv-NXldN#LEYq{fPWq}?RwE{v{Sd6HE5
zRny$=HBG5kSxwh=S>9R4E6-WZ?cO^rhCg`aa|MsylU7uS^nt(Kj>i@;wHCU(r{0!~
zOK+F7!%r~&os+utk)$^5%|5~u*y#Acs}0}>ddT2`a_+h3$g8iuYV^(}@n0hIxtI90
zWv{^&W2)rlHZ<$VoZF>i9Ot|BQSm>pSp4@s7qTsfZo+rvU7_o`2gLvAawBsi-!1&^
z^t+ysf%}Y?FX6L>ervccOk0bOHhvU&?0^6LSJu3{S}uXyJL>3Zax!eEE}lDA&b#~y
z8ME)c;-|fB<0g_09b?LVhe!s_B{KdG(SG)O|62Y8mH(AbNn^z|U#S~5w7%W8UEZsX
zUC&uw+fu6eTF1UuxfPc^VMSs}vAT0$i}DHk^yq^&Wyly~50s5>elzHdd*M60C+xb9
zz<2m$tbNj6i0h!MR;`jBfAqG8jWA?_BV3z$^Q||HeN#QisN}l!B<+C1%zASWI?2eG
zRoA55DC{62woc%C-^&}M_R!I?@QKIG)6$nAZ7R4ntbukEXI*@;wA$wYNt<|tq(Ud3
zhCN#8w?T&A^Q@!;$Nqw{m;KIfw#X5@&1}0
zB?I>CwBO}#q@4$Kdi;Jce2#VM%dWgq@}?apzS|xb-`iiAy~3Ut29_f7kk7K|Uuksh
zPf{=dI54_)CmzV7dTE}0uRN@2daq@bZj&y3A#b5W?9_XMbnNk_bm+ERI`(`=3JO0%
zI&r3DN$qy*xaQeu8Yk7bwx#zmv87nDX`->@Y_F8qN|1if=0EIt;@;cztV}uN(8;oC
z)21B_p}0K5}13XRb%V)}6LW^hIqjMP9alPf2lnOEQi-Q_?3MX~u==XU~=WCQUMD
zoP725SF-2cd&$`t=WhREyW9d_HQfjF7a!)922(2U_&wqkM_N60
zv1PAsMR*+`V4OkILU)P%U)xRwLnYy=Tzf+BCFdTr)!Q39wKM6+2{4ZTmMmQ=dtp6^
z{-slT^bP4B=-;BWm?92{2jIhp`By6Dj46eKWVeGS8`(tN-_g^LF?+CPL52+&G*HrD
zTbl&?!L(Z+lk`_NN&2!+#kb<~kX{Em(xCd7alshZPKx^zwE2{Az1(=!!cRZSqmWE0
zDEt)X3a>MAsZGIC(zx}du*2E|IBFvP%xuYR+6eaegXE}VrpXy+&Xxlw?2q467g&QG
zWV`Eu!_O^@Y5#7N{kx@Wn*Gd7v$0id?KrWhiDENWyE_(J(2=E0I#L=nY9Oz_{yNz?
z;i0T!$xopNpFR6@X#m@yWbk*!sTWD$&Fvvf#UnFpe&77B@v+N!5Pd9h|9mpel5CGT
z)qC%~D?k78v&_KRK^XzR*$12r+%<36LVEY@BO_tcwEKjKGVbVOW%n5~rP-jNlG>_m
zXdgcJf4MvhaaDcUUk;rh`OnFZ_C3aI5e#jSPJK3FJhw{Pc6nY}bi7+~TU{h|bB_j&
zcE@)H`;!ArCEZ^WYu44JW2X)>6*j@N5&i&n_uSvC@0~iImtTHa`t~oBG=GjXYk#xB
zLD6TipM!CIRxccBzFpSFR%Gp1<(3-;RCc-LB_hooTdjLYuy8jCt^_Z+{OzJ+k+O~v
zQ4in!z-u2%Qp+|nY0|_UY9nC-nl|mUA@9)xb_~#;r(tc^|I}Nd@mI`u;W0+z?|fmc
zqz@V;Dfu|puJ-^*?a&Fj_)NL^mRpQ$Jo}up!KWFLnvo`>$Br?3g}D!mKBE5k<9GQP
zW70RElRV|rQ>1Y}=pwNXlV>=%+0YYL*+tG6vH4bcQpa`!{E*<TzR=X``oj#Wy==%`|rQ)
z*H|o0yW+xreK1CBDeby027a9LFZ(&2aeZz#tSP?!YuNJOC;OZ26^H(edka&s2kK_n
zA?ys{t+(GcIH%m8KN%nN#*p
z)Y;UkQ`_vVI_ThoiujHH6LwL{AkU9E_k3wKaj3a{dM9%f0jN71}7S
zgRb(cuf8&NmnxS^^LOLkmOAxnOYKI7x{M9I@MNdEVN26Wg)NmSrIAmim2=uhGTu=V
zuF9Klk>_ZOiZR90i@g0~mga9)*0Ni-ZZ)6jMskM*0b7
zOAV|WKlRj8^7GF>V}Ig4ayRy?aE>*0_ub4IaSzx!(q7mE=nGe1PyV6z%$G)YKP9w#
z@?+i4JdejS8NaO530?!8pxHZ2o($>0IX`OCc@eO5q133mH)Ka!$fKG@7PV>D3O2r@
zWafz{2=Kj)ZdgOi%R>x|M>F{?0K04dDs+ka(Ni@iVdZTCEjbC)S0h&(R4lA
zu7dsQ#)HQQu28s~*eb)=kl4Z;-4AR%`e^7(#nS$*SpH}5=X1|L2fq=^g&6tuw_hV;
z{aEdhZ^%R3SJkQO{Exf_xe!_#ijIBDA)kS-+t0ItsHfPr
zZ5!-rA253vhr&lF?bbEi|IkCy;@m4FV>N8Lh$Rm^6?s041*sG4G@RqS?M4sYy3=D)
zzv)cKrCw%ir*oqNCmw+P{#VFLu#Kmk)GxpOqFq-w<(|$A$j25P?gU;!`jP1TO7Rkl
zIx(kZUFDXpZ^eU$M3;%+3oo^D<7+~cG%lQ
ze=CO{G1cg?uY>K+-S^xh56^$t*!4XGp1tk%+l+10fd}r7eI~8Vd8tPK2i;xZ{U77w
zW0gtqQ2JHF+H!h&icmJSY~2cemku;K_7S5-$hCMz>IJ!HnBkR|7faK^ev%HEPG17C
z=er@yht3`T6aEChl)Ub%q)D4AB&!zmjF3%r>eqqZZZO`**=FC@=UYDCp>x}pVC$HL
zF?W+TS4kJ6J5g+q+PJafS|%!^ipw-tY`N(&bZn=*pJ+^Jd)j_E#)V3jREZe
zsXr)7pdM=Zisi;13-?|$ZQcwzfpjy@O2R(CG}x;8g8}G=1IAV=4fcn`a}x9k^g+fs
zm9FE)!^cHrMO@hWS5kqk?$~oheLnqFbjNvI)L)Fm9+Qtg`pE3B=l9{*<7U9t3H}41
z*GS)eKjU+{q-P?oYApLlTJ679a+{wI9Z5cZYZm(GhP@`|%Ij~u9+y30S>AnF>hL?~
z3uc+Mu&CTp?AX)|TVD8M*_d|l%I`K+jM-_4j8_7-VvHBT7lBtdN=o-WX8-(CPd`(UApz?ZuYekV@av-aS1!Sj9C{O+xdXnH(+d9691MOPY%qb
zVgJ>|7lq`~#g|@U_I+^g$0@T;k!!BK#_Y>K25VcCvrU>dmK50Z2Ntg@_FQ__g;Lsr
zWUl&I>P)y(GPAqGKTVdAQQWV^G3U-0W}Y+?^0c0`>!P|s8$-@G?=?-SjX#Yu&sA=D
zjR_-spGYt{+A7iq{uY&|%TWH~*pO!eLypkLik@d*UcR6ni$0^D$KH-JuxGIU!2VK;
z_J5FB$=GjUF!sb7u(yJafcV05lovy;_0ewnv9slJ?Dya^alCpJ>}yZQ+F4!L8+XTC
zPjxw~u&1j@_a2e~Kkeq3^c{t11XGw>@q6H31V8V)PXw=K<2%yD>}%m!uRCktnqhwD
zJgJs59P4MBfCn2JHg+^_Q^xhO>oLysQelfQ_z%dfICz%$0-vYAPkBSEBU6V)n}|e)
zZ@>N4=o0ADuU|j-HiE91Hi0QaMoY#V_~)aXpq)b^O*^jymRO83x@u
zF;5$M`ih}HT!u}XH_1rkrA?SBf$+W)FRb#c*NpS7k!1M2;C_J9&p6%eqfX@es))8|
zgPak_l%{R30~XxYx7@J9G{ui%N~vAm64S-WZ#j0&xZp-tnPr}ZvI^_i
zsq}-3ePE-p50W+y74@FC)gVHk-T2-8#xn|TQ*iSPHJOE(-muWKGRAy
z--_^k1OLwnWB$+6UhY*0AZHD!Ew;VQFOiR6dyvw*
zzcj&Kjz!Nba{ieryocrAqd&amwIJtek@sl1{x+#RQ(#kRHndVtMyNw-f
z^xj*r{?@ibJ2S`P8OXE)shLwt_JzMG?i=0!yPzghXNZ6OA5kpxeZV%%?AgLI4S_F0
z%Br&1MI`FQaUJmt_-l+;_w+7oCR?;>F4b#~HtTNDF`i;dsp5$Du`VaBSk}f?#GX*G
zMLxGfgzxRd1ji$N;Jxo0*b3vz|Mc6E+#%o0Q(jxPEKzI`S38^!agCGnAFjnDx9uny
zXI*8^k25-tcrgZC@Juv1q?cC|7lRf~54f>AZIS8AuFO1=>H{Ou?$Iim}jhOd^
z`|v;TlB8hYbq&l9={s>p>;HHL3dgls7)R4KH=c0j*=I_sucoxhf5=5$)uatzcBYeV!6TiJp0BKoN%
z#>^fQ@Ho%X3C6p}1bPwQEsx?nplm7VQegbv5>NCgc=06{o3Wt!jp1**^zzHahjAZ$
z5(c$G7k|nA;Zi?*rT40gzcA
zm4FfA#tTP^Jtwv_-BoU>E<^d8ysvSkHXafg*Y=a~{-fAx6R#b792hAHL$UJl?e_m~
zA^5A2^u?J1Yd=_m|Ni^Z2IIvf=oB;HYa<={!gP!Q$Kf0Wjvseqpp2zY
zN7}uBGljm}s1J%K@T{V`4eG-7>cki_%ZV4gw{fNzQmSQ0L*?T1MWZ~gI7=j+?6$O@
zofBJO-1)A50DdXz%HY9+Nu
z@osR*O|sANC(0=3^LE=~H|PoXlNPXf;#od>>^V+4L6*@5>Ij_A%5fIcso!YVv!^+y
z|Y;WiWKrI}%@%G1T9Wz&Me92vWz6mw?JJ>K(A2<-7KN@ptcS@bVt~GF^`IPN>5;
z4eQ0LanC(s9N&HZ`R8&AY|m*w(g=DR+MqM6U$@T4h7;kxlV{QGs6brLI(-)AoLHm4
z`T+Nz(7w1d;ndSk4cTG1?%9gs!p2B(U58>xsa;RgbWB*pKcN#_#EtTNqA=vuj`p)t
z%PlkJBEGJ;W2e9ud5gX+s8=>JtOaa-uew|OOE*icigWS?3?3+x4?RRShjkrVzcMK89QTJkGi}y=
znT@d)mnug>zEY0G8~6e<1+epoN`#SbQI&q=cvE`9h+^%ca
zi#aCr!jJO5SAKcYwe6i>ZWX~7#)ml5v`=Agvqn@|Jm=NVyYId$c{tPi@WZDVd#&j+
zj+N%ES_mo6N6_&6^UoVU?eiDR2d17ka*wu!D!+(T>P)z<|ML5!|u0Gw9$IOKz0%3wuMTpY9BOz>+0PO8aL|Sb5@MF6`uZhKTB<
zFM(Yy*MqtLoq_vc=r4kMmuRC;KBeyq?#o;Nn-Kch-nKntx6byizu|f#zj%J~maSVL
z!+tV4d-`qU-rb4_Tn|10=Qi*>l&qSC(x%{Pst(=_I~9c~?Q7S>Rv2%7_=Qhy+Ctj2X=VJk
zR0PkJ)aIMeF}I~1E_|_5SHUyn211{?=KVF1s`QCLSw%et&$Oe>>Qz_I#h#MuaW2A(
z*nhUd$g53Z{v}2!^Nv5^c(XT+XM%HY7tc0Mw4DmE%yaw(4;^H1P#b<|I`()A`xd{F
z)&&dAxbV!g&WQY$(nO9u?pV}sX#CuS9f65`{0dBf91RuPH{lIC}v{CwLGbocgF29iY?dmE#>#hq`S78YQs7z-*RHr1i#Vkpcdzvy
zo@Lh;X9x{|9~$<}IU4nay`hg;^vpA^UC|zddJXF0XJAaoy~#Y^nCIA)6nGX2{UmT-
zOP6k4g>yijPeIv8S(}uc4BdDq<6DFN35)6)uwMiFK>S(x`1b5qCVx*HXL3C(7yb^5
z?%lWXq}Yg+rg=8Lw4P#(dG;QYhz?%mmhyQOwiGj^p~M&bICGD03eIfk3!k)$VK43$
zIPc+E!76X)yKE2G7SWF-_f^q;R_8jg)^kpR?QGK)&EWfXl<|Snt50uZE9llImP8
zG5gTK^XdBITubWNy}}K!i6A~`Cr_RH{SQ1Kd&38tKD%9yW7IWRm$>+nOU$}8%MxzBRkHaQpvGHBAapT5FR~!S=uO?+1eIHVO(q{m}
z(~B0tkJix<+4D8lynFW@3x9<#hkaB>c{8e)+lI3fR!VxXIecj!8|kMskz*2OegYsstefGlGv5z^wxS&gC;|t(S
z?4Nq!#TR8R^o^W5wQk$Sd@txfnz-UPmx1~k&OtS-UcE|MwjB#!@3fPk&ccm%qu4s`
z_!(L?Zc3~V96SJi+=e*(V%Yd7Yut$|y|>4Nk^Ngc3R@AG1!0+t7ng)<*U%FJJFd3p
zHV!#PT=g~1r9a>JpJ~>tv77^2B0YzZ`?I*GUjyg*v`J;S@ur*1+@JAtFpuKgi1V;k
zZCk?!?O5YykoY^{#F=sy+N51O$A)U>NZkbIVbmFLe#QOz)JyUl0-eXL->}}yzn*{L
zdAR~QcG~H(Y(MzSp**C$hx)ZW7uewVliz^TvBt&u8qbv+g|TR}7R}9iFVk*{D@!
z$|fO!l38B#Ve
zaR0~DBc>XD=D6$7!=@P7L*JoXv!#75ZTp^k?m1JBHi0~=o4(rSL1#e!?z+dG{LQ%@
z&wZqS!29OSGx|B&Kxu!}F>?MzyYjvE*&A}^PGhUV^{+nhW1*)M+x#
zy*8YKQD4BZE60bllcIi|a*O@}C^IQjS%-Q?4g8)oY~j=|IC-1%Eu4#sv$M)F-=Yt~
zKo-tofn7)FygS8(_T#+Q^mwRUSFshU=Q1W#Y`Nh_dEYHB5oy|fGTwa@Ta{&(0h@82
z6>fYh(bfWIUi)TWX7==(^8~g)_TY@gj6R33IT=2*ObEXjO7LUi-4fHKctZ`h)`4w?SeDk-lEq(_We*EzV
z_?g;MTI4+rIpVZIvUwKctDf(|Mz=k_F^5ECt!X5V|4u&jB&yuq#hF
z4Chht%!v2jYep
zq^&FQgb|0yV}5d4im@fsHRJa%Z=?MN_myxQXqV-F4vyg0)6>e@Lz<#V5ku_tYf7%sW=QX^aS_r0_FZE4YF6lBtS;jx;{!#1{{bA#PFb?_4=
z9T*v#YCEwg=URh?41|4eKg&0U-4Ek-U(UFFul1Pbmac6vuhi>X%KKh;DQ~*Auh^=2
z&qI&BQM)46j^Ur0SfU-EALsV^?|a_(7fZ$YTjZq_Q2L)u-Fp&zyVsK4b{ivY3UMCV
zu(6WXFjwl<$&q@w4JEDrP)WzW_tZAn0}Gx_!B{Ww`sX1ZHt^?eWSJMfbR0>H;f&(6
zEANsq
zfuvvCtL9#1bRFEQ%YE>~u-e13uXWJ>(T3@r)$f=w-4$0}AqPR9!m%jleH_zipsb|)
z+l)0k`k|p5fLj
zqARP0wz%?v_M8!&4_7vZddGcdNQ-#AzDI^`RlS-*ar
zOocu?fc0Sd@uN&Q2kSMhx^|VECQZzmRJR^D!*I8Kjh`5v=fypgk-3@5EH?`L`Ej0i
zgW+Rj6>I`ETyWuqMz6LFV?>VqD6i;?lzRku&Np@U)Q3=Z&_?)GT--a%vee6y9*cD)
zj?XwoB%V0$;r%VQ-V)gt!*v0U6cY_o#!ROl6=fqm84ELH~q}?}SN{u~vMub;f}=-*P=UP^~Av6=Nf9
zn1)OEk9tq;Gj7r0E~_8KK)h5j<@S7DX>nsqaiF}f_lcz1wxM`s6^kwMH^+pSR|Q^P
zFTOLckhE^SasENJ+yp(b2HFJiybt=I<#(7i3-mwBwO*d7Ks&X$kO@8E=kF_w*FM9#
z?>?9(rH?y6GS0YM(g(nAOq}O`aO~(i`cydp-*>LxQr=Lfz_}6ea2@Q?IcK7NkNX=p
zZrTJaOf|X*>Kuq8%BkTvk7NwwEHS~c9(5#xh7LCKFzOgj!@3v!>9Q>4l?Lh+ImhGJ
zkl3Aj_0?wn#`=_LPb^$$in6bqy0xV%z9Y1MrHtczkk32uph;%_rE7H5op7C*?~5{3
z!@6}JNV~k@u$x`!Ay1T_L;O#_F&x*896dZ@->+?XQR+1(A9^rs6Psgw%xzuE4Ht^H
zqWu?_VRku<+td|Xwho?rZU^OmJ1voMZC}TPm7{|v#&GfckPM8=nvB~QynVg=gt0oq
ziSQE<#JbdA@F#s^a=#$YA)w6!zx9+=9r8OG-808!8zDz}^zJ1|IHQE}(09$e(A>&R
zUfF3F8&cLKL${HVo@&mSV;@`trVfz4m1qaGZ22-X|DukLxv+5{+Jv*dm7B`T}#k6ODhtz>rJ`gO`%`Qs;hpiSoH3#D
zJJy^saJFz-vzBH|RvWrN>bM!`OP4&vISuC(oTqay6XUe$nS^-;$7tlShOira2j6i9
zVj&RpNh;5<0-hr4%aB_cm|La64`&9>E=lK^cElJy?}63dN^0N1k_$cLn{P#JqfCSN
zk7Gm5Yv}uu=M&F?%%V>*?#CzYXsbcpGuN7ESH>0EdUO*k4kbG?OmSQ9K7*ajvP>!5EMFG2-n>=*`;abuic>?{a>@^Wiv7qdgsY
zoc0Q|qu?2gd%`xsH|P4$7%+@wKh935HDshrJ#@148Z=1!7$>D&J5T)Yd=v69S}R8m
z!I+d|LOYP3IS%Extgv69Sp#F=2cb{eRkXprW1gMNeI3+$pMZ0@Y0E@i1=q()!Wv~A
z_bU=Fv=gQ-qaVhd&pi9A!7TC2c_;VxbIq+K_F1bRgBdsyu=z_qZm&N&PE@WZ5_
zkIsK={&vQr_Z$;e!tvIm7Z$UQJ92>W~1Q@W#gUbIlcC{ayGOqVp)~l|TQyMDg
zf-PM;Rz7!PsWRkNDXG8_$^M_=)G8a{cGCPd=7CPdrsJ7A%zjbdzSD#kn2)^iDkH
z82J!5yaPIeQG4zwwFZxn)TuKisa>7~ads>HRoH=JL+;h*`Y-J!I5wrvKJK+AhUzt}
zZ*+lw{`IGs=Uj;OXJVe?M*8?9?x~NUEtPGDOU&`Psbl227HtLFwr?j5avPbw{~Tv=
zEt`5$`U$1YE`1rcZr8@lMfuHX+_Z_2pZ4=={Ez#DC9xpz45?7QM$2>bQvr%QXRap`=Vws-t?Q`b$uEj(wDyju9b7|@p)aG{c=1nqg+A)%T)G6Yl&D4fJLpYmuveB&*Ge7_Ile~<%$}HH~
z_37Uieu-)ty(D#Qs#~DWfckH)?e;~PjDXMR5Gc=RgF!te&r>GmxaLG#dF~UY%@l2@
zXm`u+0ddCX=GxUKpMGNWdbIspj(x<`op3Ff?X&^Ds4J!3khr2OrTqoJEwr=ZoR8yB
z?oT1+I9_&!mtR>d9Sa6wo#}xvuPcwb@v!n}G>_*xX4M=V(i8p~^)=w^hxZ&0cIn3P
z;3&s@i_Q$|xspcMfbpZUx@h3R}XfC4I;k
zNo~*&XI^AT2F?KITGHl^H=A$$8CYkckAK>Kb6u3SwT1oq8a+4VLuZ`Fz=G&4ROf_?a1x_32uggO7B-7d#xTr;DsRIfh0%-r$l
z=|`J2a{dIqYsbOrz3@#N9kIRA_vEDXkCTn>TyCoi!#LJH;-&U8
zIOA?@Xc;>%x;L_R+lU>!jV&ktS2Wgk3b_@sSBK6J81vuym}E>oTGBdomDHLw!E>Eu
zB;*zK6`YT7yhi@pZ4c;_q3fVuGRhC`4Wu6!>g5^8%W9)a`Scp}0GD76cQkA!rp!1_
zCPD`BtYMBHoo5+@?1ku4)@QIvJp$)`Toa(Kfnzt$w&?{3bIlBY
zP^kqS4flx9{)qChH}*tdiuodKHMswZV@le6wP@AStdntW#WggJCHWoUnUlVt-;68y
z+bNsbFW0KMc1B!Mp7EQ)Z&0&VLt%q{cLXPjm!gz>sXS^^rel27YYqG(bi^}EH1AS>
zpBtsFGIT!pOJQuWJ#F9Se@(Odv&+Vl?$w4pCX8UKq%mPd;46YD{OwH~?<@&d<>?9C
z#)+JJVNPUhH{SkA{Fp1H!PX+FQ#bL0x9F4NN7xnp1zx5Mpni-t92^UBUX~A@T!#7A
z2k_%`67&fJVFSy3f#hlG3plo;Z=NRJv#Sw(2jxgx5uDYpq$|NjPk2N
zqlN~@>o#H}aWtyPUdp%>FEXPgsulA{{Y$r1?#>b0@}$OX8n%uWFbh
zwe7MryrqPeI93j
zcDfz6>)UZHL#lDbRuNw`D!1G)v|fAK-KWWk0b2)?VGn=6B+OqCW#%#ie{CrHZCvm~W^
zA0zX~yY%BiTcJsq7aa$&Vy+GNV!Tr=iH0(hwB8~k4!ADgIy%`=$xC;k37e6oI7%^McKu`z5A4D{7z8U
zNm+FBEw`Bc(d?V+*ld?J9MqN22Nb^r)TuOS*3`(~nXttez1yMEyxlp#27O^r=Wg?#
z&C?pUsg~Ui-=9xnpGZx)a_*Jp`Mmz4tz)e^wWL9_)585}d)gN7HBM^h+i^S3D_zUD
zwHFgx#E6Zh2;Y|nJSEhP^nrJ`^I+?PUyNO^|905R-~5R9?|fSP55FqDhnGk?;;E-!
zDoI^>ntd6mSvX6iLnlecIMR2^Ba#7KqaS;`0?=Dz;>_aFlMj(QU_VNI0qp`eZrW({
z2=rA>c|%(U@-_EB(O)}xo#Q?Yl#};h&A1lylv6MUd>La<+BeOIOyb;!b0PY_<=PYN
zj1GrQI_*^(&e3+G$(|HS8_
zE|EGE;-Bm1wEf_mk7GaD>{7llpX+N3-+lKD#?3cKyZi&BW!|IUWm`XJ^SRBxcAR|s
z1#EifLe^F*(Wff+2BiC|x%iw>{&(xsPSbLv`W%|C)XuZZYnMc*6LtxyhezC`_A{e}(9x-#ct(_o)YJv+y8ly$Tvq0JKKeq&+JOIv%|
zWH3-SL49F8)Te%)y2odqd(Mn4x#mFsXanG5jbmG`uW5MZnWv?o>j-Jw`r5D!Au*=B
zO6qlS-S~6(6`WwsDBkc2H5W=zcVe`G+m!{iP>)2H5XgR%C
zs_9Ycvc9EbLgjZGGs^#VS|a1x{tnf_yJE`?cU%K|=WATwnEl5_2SV&|o~Gr2E&n6S
zB(r%7nT2uL`PW@96Hhxs1|2m+@+M6&cENQmX-ge#USX)~&ey#xWmpz>9nM
zsUMH*X@(yu+DX#yg{~tLceHJ%JfdAN_dRhA_&w*7VY$iu`IHM>Kd0|C>IW%%slTDU
zRcb~m^gCx8`OEcl;*++78kWBHD&~Iur9tzvv3C4%nD?W+7#*uAPcv^j=4&rNH_-_4
za8eOHjkc?lx}rftun)2()&gSMQ`zln|88l_v$12x?Rr|*&R3hKB7SvMZYiHTvBUI=
z3fkwcfi2>PII^*%m{N*7o=Hsmroc_}CH*nX$rrDe4C?v0jth$nhQ5r76$SuogidXtWif9)tQo
zVmIBN4j)$eQaE5g%n8>Rn?K5~0q|!-|MD7MUGfU%kzJ&I(^+ABg?W@Zd83!Nd3Gz-
zr#3=n?FSppx@LT;?YL3uV>;xw#~DEThh?LU4ds73%`5IKYnRhJQu|^Vy+UO|>sv*z
zrE*L8yrOXA)^4Ovyt^b^J62Dq_$Uu04rqsgF(l9AHk9K;rpJ4E^^a{Ix!3+8?RrBl
zR?EW}Zj!+k`JOf;++)l&F4a%a_L2K0DSPOjg?Y4_qWv)g_Y+f|QJ+5h%-PU&ylUhg
zeQ;3!&oN_CN|IT7puFRlkv`VAA0;_GV9q&h(&l>XvD(AJJ!Um0iLsr?Xf-YWIN8lxoguFO{7llQK)Or>+E*zcx-G$v18Y9
z#zQ!Y;)?k;wu4;M%VumyU)I4**k3|i
zd0{4=bkwhR->;HC96VIGO6QO@Jju$oD2z@*C
z_sr+I8}}X4c8hvJjsdyXnB%>q)D*KmMtMm6B5fb&SA(*#Lw*NyUL0jie(!bAyAQ$~
z?noosh`%)G@u`#No-qw~-*cDLuHPDXyvqXz+p%x*HTcMA2R%wpvp-DhdQq-P&{taB
z#>aZJ>4gi$m{-20+c?rXcADafY4(^frd@{ODZ=~Z1(8R6ZQt~Vcev}xtuSV2GnEd1
z0m&T;aPD0lNvlyqQn2=%+@h7FbA0&5mZ;rsJXo^J0Jk}dewU8pV1wF6|L$9*b*Cp_
z=QA8O7Cm8GJO?_zS1=yq{`(QePJ^79H0C;t5ZNwfSpEaeFUjdY_vFtBtH|eV)xC-&acF2wOkOlW*f7Eoz
zZN3k5-+MytG>Q25AdgbNPt4FhpW{N>C{Z`hb0it=x%Xb9N9XvEc2D*hTbzf{hLV1(
zQ!}!qcEf|;A{yfG@tp*c{
z&b=@eH+I(WB4d3ohAWz`sP
zfp$^dfR#?zk48Hx2Kq}Qjwsvc=ac@?=of=BjCi9?uwIj6pfliJ5nG?m=b#QU6C7HUmD^X$L~RVaNPDjNATad`Lb1
z#1qEWgmbq0u*Z|@ShUxA0e1BD8`hKh&0srdaO~uhNGK#J6eCy%I-oSIm!j_EzjVF?p5?dwkV=P`RPag4vD*#z#d{|?Cl~lX7
z?6vn^G3Aw$CpgARqaP@oArw<~0e4ZIp#AqNDZU+Jvo|n4$~F7@*+0imo3Re|^wUop
zTR^T){bcQHpS4G(ZXVgYRBQ~C@H*>_3pQr8!a&V8I$YPmm08@EySL}Q(*7PJs|YeT$aEyv@$T3
z%sB0mkPV`RuK@b>)(P5t;1vh&c6kvt6Lny>enD9t&$SMDmijwiW;-+HEUwE?-rEj)
z^mCy9KiahO`s>T3QL~ZoKfNK$-+XT3Yl$>%H5NL3>i4dT_`hx4>2a)^jmMa_8Gb``
zW2@VsQGK)Cbu!*N?fOf?7}xALKHxe-&3b#`dDZuPQ5;0)Vw!GKeZTs<^xjGBe8-p&
zzSr>*+;s4YrwH$BLOH1uUy=6l98qlTD7i&ULH9@hXOu1U$D*Z2H(%}
z2JSc7YwtZJ8Eap@3va?XlYd3*HL_R#Q-V&=`L}i4L(kB*^E1$8*D|`v@;<9w|HP9|
zH2bNd{%UPr48_N)4-I<4?Z(>?$1FEw!@m%K~fOW
zIczt2Na`G^^J~)PYUn19GiTJL`f6dFxH0sYx0X03qnzcQm`sc>a-i?0ey8~NzFECl=hwlqby{TjiEpWf(gWSI@mCsUycpI{qd-x_2{sa=8zr
zq;I9ogYm?92I@%IzotNMm=2p<`nb-5xp(Pwf;Ml2;$46(@^KpWJxgUorwU?Vy%R34)(;3n|$f!OPEy!?&zEQYP{p?2aab1~+-)vOUj>ur~o9q+}u
z*gh`fOycm1usow4aU-zyDD)Kl&Dt{UyGpW$;<`EQxO~A(;B&fZBQ*cA-y5Hu_tD=F
zeLhW7s`Z?8G~ZPRuVX?RBN3iQqQ>p~(!^uoQ`=7Pn6Q-CBCZy%lay|Kq&{p3XxBr3
zVHFv;E<+zL{;Z&+z^`tdna@He2wk?Bf9v0|bktz0^CBa+xK}@s;p%JQPb5$a=M*pU
zz!vQ@Zh}2jSL{Q>hr$ZK{q_s|NKH5SHh&iseg@1u4s5Lt^SJ(An}5S;_-@b^q*~69
zxbej`ha=$gB+VDVdi4QjE^7B5#gz7^{gWzYl-g+;w`r;5R)p_M10NI7>a+xc&_Mt
z>!OPTjnWl=vEI@I}1^=U1@;?IvlvLH(f*=TJ6oeOVaG_MT{M-$@l$N;Thk
z&-AF=%8Abx4RPRx2^$~fiMwN~GUr>6S^gK+N>Zc7ayWdOm-M%a^>-|59@l3lVQ+sm
z_>b{rwZVGpd0`zF|Nb`b>EG6iQct)H7-(pGNtg9`-0IP$J|j>a`+Mhy&pEZ9fp!^h
zz!tX~&RZI0{PfU9k$aM}Fz)5K5WH`Y+Z1EQJ;L)ZyS`#c)AU}crjshZh8h2Eb1s}y
zY(38T{QR5JHz>~+Pxog+hd35GpBJom>%@xot5o~9%Q^F0vE?=wTiBw!h=X
zgc$ny;O{d7b1d%BjTJcWqU{iU%5cu~9(>Nw$29F(X&XR27X4dnfeopixfrWGJCE(s
zKgO^TLorUw#5}(UYH6;r$}}vFv`z8t1$5XVo;=3i+*7
zek0u`^_re;{L#}#568P)qoz+e`u(L{70)NS9(IM4UzycgW3F|d#oKmUPM)>-S<7vQ
zP2*ce4;a9^qJMm@&6gBt%YPo`jrAMBpJP_r@Ndy?m$P5(%Zu9O8IO($tv&r-dP3#<
z^5Ti@xCL$BP`nq82`ld0$d6s-V9xbU6IS
zjD(MgF0jLE(Y&cNgzvFB_#W5HsUbC?qo+T4`gG6BYmYOvLi^%%pRe6+tT^?EJQt)d
z)@pshput#fs|(E8+M%&j?6C~({i@@Pg6_S#n)AV8^;McY`p77XE#-Nh`@ITletGa!
zb-HPi{toHakp2Z|cl8nY{>Y<_G_r$xyhe^5VdQhvK1tgmAG^ivG%W)=1xLJCv73=^TS?y=KEZ`c5UPgbv__%k!cf_S-q>Z2Bv-3^#9sB^H@u+yUzFGcDpzC
z>ZRN6wA=2c-EMcs&SE=GNLZZUgkYAzL{R{R5I{2t84-v8#R38mkZ2f|padM01PBNc
z3BhP40~r)#Ad8YXVp9lYfe?XhjYjZC{upM0F28Tx_qq4`e(#*By7$(5{knZis`uM}
zr|zlW@13esXQ8ajBj3bFXZr29@Jv|BffBEjC-d?q`4vBTW8b%wSFtbawwq&4QRIo9
z-5I;2e9*kzm&UpgH^u%PyW(5P)@!aEZ8>vpwDmb(9s9O^+vtkelVr#1-Z;|!Cs%T6
zZ@bvLLHoLHiTxY)$C|XS{@z!u+TXMZz8-%bkF_WCj`QWudrrjko`~J^<7dTYT?pk@
zEyo^swsg?6=yZs9q}CLuKdg@iXCcy>-P^jCDHuEAjldvsu$n>%wV04y^;A
zy_B{7l=kX-{@1*q`R=5`GNRO?8U`(`Mo1j#eWxHjR_XF?kX
zPrEg5ek@{ladJ!jg0XkxwwP;mF6Qb!67vB$J{jvle0R)uIvD*LTW-3!>Eqb>mUtd|
z-zS=VS2gabS$8IKb28^%<2N|Nx8_3b`oO0~SA6?_8f}YjWY3HBEPS3jW%Yr27gt<=
z)qP*t>@Br(@7d9@lMluF%}1L1x#n3h`Wa5%_Re^3-`Dw!+oybV)F$kR_pR|*bL-29
zdHL7e@QRp&f23I>PHTp0Em5sEs`XJdM^fK$55>B`CvHC3tk0%3y|qU1mAkKvcduB}
zxB7pg6x%tbMe7;y&*FR7&qSO3!ti@@tc`qKT<`Ii6Y!Oh!`~70ajF@w@fBb7+-9uh
z`8&?V|Ep70kEyIRV>ly^*6^@VjumsO^u9%V1zaS5YPOTS3Wcq44>zveiuhNXb0FFk
zz2oRmTc!T2b1|NFYwZ8Hg^#Ar>M>~He))_l~V)SKa
zPRCk;zt@yC&!6#LkiQk}!SkC~RiD?flRq3W#ke`%8yNR=bo9DdZ+56d-^+IFIvn4o
z|6o-vT)5}cF^2u#n7{nWW*r-SSJ1ivS|4X`{9n=fy&5a5HBiTSceHt4RG-4(qYuV9
zYrnb5-`X}z@$2n_)8cdL_s6&A81Jb0W%>@M|34aIFP~>)Pp+dej$hY$%kY-)g_l!#eFR~2H;Q1i5S?p-1@tJ8*Ptu&`!nL%bHK5Q)~P+
z>paI=omai{zc>4uw2r4O23&x!G^HRdWRhSV>@y4j27*c*Q04Ut<%BS!xu%HVl4-rw(v{VDd{
z7Hil4bW?=(bkO>S+V@y%o$B4@S4E5f|KKFt__wgtKV&iL*E0mckJP74@X;d
zck?WC=X3t|=%!oW8uR-1O`drdDNA!Zzv;nmjP~iy=$q5GUt&(V^^wTA6VYezte9K;
zv(36T+K2gqqT7bdQa9D&)edHP%!nIzZ=fO(lrF
zAb3g7d07{_WMTy;Wx)5CuHoo9bY15QFUe{=_=1k()7!1$I!~S}iu)lB_v5&H
zU%cF^=E$NsX7*Z7@E2n4@N=X7Cw)wsL-@bqyVd!at8~2C$7|u>UvZ%IZ}uG+uNR~D
zpxyiLiN25fCUflPEl2atPMx_W`rBR+aYZZ%>V4}k<2%v$=%3#)dRNR@)))xw74h;{
zyu8^zh&>-3e942&y1vhheKk+q^0c_NJ4U;&J`?>8{)~xlk6-5r&obg1S=NUJx<0%b
zM3*vwS%0j@{H?kCS}BZ-`I9*y>lzttoqzx&9V3&@!jgyW}Sz&
zJ?>}82Yu^)?GL=R8P}u!=xc8Ht|ou={dU*7O`#p?~!NfH_`fp2M!;d
z?4hSM3e|`4*0;Si-U)weq;&-KjZ5oY>;H+yoSZuUp3#A8UeNUEP2b;$*;)*Te9dzr
zHV#|tCw+bBkMm;M7Qq+HvNpfoZngFkDsLunZ}>d<)Mhg&W0G63&cKn49;-Wap2hR!
z;s4n+clhz!1V|0(5e0`j+iM?4LZr13~y77AU`>E(N)LxU?3*sAM{e#bZ_A~KqH`=(kHnms!
z=BqvI*5;PScMT`*$pNR~Wm|H?b-{r(o6L85Y)iXUc;8YE(5_5k-gs>}f((1;E;uRY
zvdOK;tNwF`A8*FAX`bzcJI{|k`mv8Kk^&Q3wHaDJZSR3+#y8pn&ARUs;T*`1z2Qe=
z-paKxzSZ|-B)0ys$&VAaJ{)Tko@>?})&4{plcDuQwTAEgFS@^J_p}!FvE#?0@8ibN
zZ84@;c{%;QX_W=f`S4smy{_r=D>fy4=i#U10~x+tN4#lYhCLH9E+gj!ao?36
zi^wTs#RjctCTIW#XF|_u;^g9`K0mMJFpm?0{p-T`OAUbaAGH~Q2+GUQ*ck!99
zlv~8S@+Rlpyt!2K)07o=c}tudJ63n#{F;3|LGDki?;hin^lf&i{LFd^7
zp4uZ}o%Eppr`GYJrjCv5&uoRujCcHd2_1G
zZcPalhMfWOi_dyVsJ@#jO0kx$;wdd2q9n__P-9UuSr$KrYL%bN8s)IXTV
zPEF(AeG|9vpmSU!&k%j_!5wD(8clibC*#H3;`^3zfIM;t-j*Zt$}W%GTImzK(Cjf%
zyFdN-H=T`rDPs+^A@WOWQE9G6+?-~=)>-pP`purF&78>JsjR6x{$2W}tp50$&;45T
ze;#l8*SBon((DB*KX3fWpNRLrXEc2n*B$?!mUTCXV{*Xj4O!-u_^tzvUd=ah={t_S
zLwo@JnXvQw7WuNwt(G=U>z*}xj64v1)3(RR>gN`}CtWzthd0EWq&r4=PMP9#mgDC%
zz9`1-JulYG)mX$?4voin>C0jd%RTDX)862W6(XL9zcJK%m-^NZAAL!D3wv3-du@q5
zR?av3oj>)?r^WtTKi>E_bI1E_e24og;a*=}UI|ARnP_kzIxd4J9oGYQK0NG^(QZ93
zD$I=}mw=Nt1;#qSNf~j^FTH0%`UGF5Jx09FxmWYT$C`P$>OZ{w!fo;0=#OSeiB-Cq
z1AIQl^J)F}zleVESq`;(nnS2H1E=Hu_)WwVbimjzNNdX+KmDd=9InXu
z{kNz5G&_HPYQC}Kn>q!`23g78^^l{VWtqzLF$OQ8#9eC&i
zoevIdv%?-J8`pOq=m7nhaPsZg`!aIg5c`=w6ix14a((ct`UEHAnW*QXpvG_fx9I;q
z7h~F=(#$RCNQa_WbJ|awyeZ~$y{;%PGGiN_*M9%^Mc<0nB=o&O^xKFzekXLy?~nN#
zTDy~ZRJY&tSIwBH{YRb`bE!U;VikKJeo8cPopsO!q6h8JWwZLp`fGiSza6i7CZsRJ
z^9Y>SA1asR2jAdL8F7Cvopy_Hf-~(g;`ewKJlcX-D|h$)J7b-s>*t#PrFAm37bAN>
z7IP^vHNO7ocRek}=iaxnZYI}EOgWT{*n=;g*2(=s(|#Si?!|#??=E!F1Hu=~C%!Y^
zY4_uN$I$^whHrR4>|72n!?6zIGCIB;6aVXxTb`%*Z_10?yZQUz2kaAE8$RnH^O|4ZwXSSRm6^%kk3EF;9oRp*@fPj>t-g1UG2#!X>jZZ_@gI-=`-ftW
zyYEUm{}^jk^ZT-m)51$<$u{e8U9OvTM5E`jHXCGa_fI3{9T#%TW8QJ{%y~oLo>!N~
zGhx#w7~=#7>l5^Q)PYAof%YiT9Fl`a4mR@(*J~|B&5QoevHxB3JlHvYg4iU^_#N<{
zX!_-~r@}NxkzwOB_H9u5ZsT~D9rA1gEy!8YMNcyH#yr}s!nb437tbfhU1tbmc@Nz|=o@?)=%6J-YucVrbUiNzBPE
z-tl9;i}u_b_u+eN*8C2oll}Mcn{A-^P55wn%q!$p>3wU6yy@fP(#Wl*Pmq0wsaxuN
zqv3en%LCWExEY_PHC{ANe#qn9zwz!^k8E$OoAh&$54Gn({q9m-lz7w;GGJdmdO){#
z9JwHTLGT*Crc?6gJp7IQ)0c7N%$je<#JT50iRbb~ar{@F37;5#j{V=;+{He43OK=>s)Au24T^GOTW;)wsJ><^s;-QP4Abs%F{f=|4DE8O$nBhfZrkzX?|)a+iUZ?2zT(fiAvF
zaK*OyzDc|F^)cpY^6i-1s^w44x0>EO{7G&_UQOGrjoini@?1C`CwP(i1ZQd!$N6T>UIoimf(YpV;hckFS+jp41O?
zNe*wNjAktWc-Xa-pJi@al1+2V`U%OcoI}vW|2(vaTz|~Vec@@GVRw?%q<`DL_T%p#8C1%a?95$b9}}=ib{Jmo;ysR
zpx5(e$2FGk{i7YbpE7#k*WSNs-;PQ0v>;#n;ul9>|BVkc`@gN-)7WDuKTdJvT+~yfrl*+ehrrN
zGOt8up8J<9%i(#u)w>VABdrz^Z?4>8oZzPG6ZHGrhO4jYQ}J#21*799ZWulC$B*<%
zFRdA`HcRW{o_+csNBl5PtF0`T5nu3f{K0R7?gM-0^|8fHx{gC-)y19EU60##>ABo}_wnKSZGI%fUxvuszJ_C)<^D`K>4T@;TF)G+<6^bKbEgcfR90Uq1T9xBgg%kmoS{=k9Qh;|$ry%LnZ^RWjaa~j;C>j_6z
zY`1EC@U?uHmEV@L7dN-!IdI>fUy6N#+|O>P`M-y*e`(~{$(Vb5b@X#+4YNJXJ`8&f
zJiD1gqW!2=zhe($*2zB6@6yA6$v*R(&VDnE-x9yI-O9N&iThHL48)t15ibMk
zgWtIKEsYcW`Mk%7*Yo9uD}Q24d+dkYoXz-lj}?y>;aw-Tz?!|wOFnCI_=4ai`!*hS
zH6Jd|evpapIC_~kof}#BzLj&UL@%0Bo1@*jZ2AOsf9E}k5n#zrmuzi(P2;eyKQBXg
z$u9G-De1#QC)=bu{cd(x
ziYIs;KN)x0f1}%iXSrx(C5V2OmH640>mYL;K9PyeIQl?rGR$)KgYG}YGxjG(2XE0D
zYOT4I+n1K~=oGd2+R)tE746k!*(ccRe|?UJTD-tV-)V5-v__X~i9xr8hrY|;0kf|7
zoXCJ~gO0;o4zkS8G=9;C9_tmxJeB$~$OmG-Gl7x<_KCfQ#Q)ayZnuApIB^yIgsCte#r%VyEfw*0mlA9?Ls#V_WTkITq;MC^M$42k1^{o1W)v+DZ}d!1eG
zII))@zZ<@2Vhmo1uJPdG$LY*NCJ4^;WL>9S7uyV7AD`H{E_y(hWjy;?O&9tyyxl70
zP0qKH&b+)yZplHkU4!-$K6(2Dx#t;rY)O`B^gX8Fp^r`GL%S`y4w0ju{klBkSr;Gf
zA03CThb}zyGT+Na$6>ZFwp*TCr93L}=FO#SH_5G`p9z~j!4F+ZbBFz2tq1P0Cc{tOJd1jfUR^v!5<~FM=m{bd1Q);9m%%e(j(h07xiyd8`s7wT2R^y`
z1U(kOJr0PG%tN;ZLw_Na+A@j-o%P(c{
zzBShzlgoDQaO-nj?H>2#&k}=KH^&=t=V!b`W0$WPU0{}H+VyHaWmD2~p8LfQ5Si<*
zmQBBJO>&F(tx^uUr7fZ(93qbBo~h|kY^q~;5#i|uV+GXtd2tT{A~K4s0`Zbh3l*Eqpt|6w5?i5KF8Sb_$&>9xsZpM7SUGO{ju*?-n^dvLdL
z962z{L`#lr=%}liSKqp;gka``JMH8(5Ky6^}faTtx24(Btxd#a%5iFq>Q#PPrLp;_SSmR
zttVKz?~C$?17a)F@?Vmb^j376{TQ*swu@fTTeX)XHbBaR7UV=$g6Jc|Ci9UC7Ia#F
zS3!SOAN=H*kla#!DAxTT_MJB*j{nwYLOly^?tO>7t~V=AEcx|ip2wNvZd1eEm*djM
z7kp@!t>BZG&N9*YEcq+hQ64b+snPgH?sUd|4YkR*4BoetGo{>`HJ99nqKAKXSgzN>B2um|KrNF*@+!FI__W4pZNo5fTHsHe$qirE5lx
zeo4o9t`DB&PCM@U;DXXA(ay(D)`y=V{xZKtqwf%1c*We}nXr^YCEl$0)22VkEh$BQ
zO~*Vv`^BSufB4ww^!NUArB5*L51`*Fo}c`FWKPe6Qzo$HBg>(IHM`75Kf|oIq}M(#
zZgic@oLg;qQInPOvBZ=8B)4+AwdWZx8a?Gd{`u&_vp+Yw@T|`)&!!GOyR3&z8w;Nu
zoxA(d(ScjO&YuZO?G`cb@n6fOMfjAn`hDxnU86lWJ!5p}^f!+VpML4`T-L!Q5d()#
zJviEX;;zW8yGFnMp5Ohbp2O5;#6g@p4o`4Bj){NTt#`lo_db5@*?UHNZ@Oc&@1~~)
zyf8jbUI@D7?2@~!bkPU8yoPt_;@4r#R~x^poSJQm-J~AF7F_iS?y$y3$L|BY62uR%
zq|=92vgiJl>`VI6tMT!H90as`PlpWWy|1UrJ
zH}CzgZ+qvb-}IKZe@f?@(^=xJ)p@vRoApH3$|>nyY~GvR^6;Aa=yOf^H+mf+1LDth
z+IYwWvk#Yn_tn84b`H6=>IT8
zYtvoI#<4X-J*eJ~{OO;5a9bfmi1~tOP!{EE-L`F8gU2)?`)0cFbe?c1An
zVURsZ2R
z46j#R2ewO&4GIfnLIX_jQPRQr*jsA0@iPa~p83Dbv^^cPQN~cYBvR9~4MZP$XvlTU0(A}OI}XpG%fW%JHxE9qAKB@cr_7QKzJTat
z+WC_8J!Gc?IHuOp@H4EHTjS4a-`5X*`5i#`v%*@ref{>;>vLVDYk~JH_`QA0
zaXs)1xnA*gKnv<{8eWZG(#*_aWR5bZSt#l5v1L#8x`sz#6Z{#|~K1lPvRBSPKFC
z;)H8h!nOBxJ?eyd2j=@Beu+0LKl{kEmtT{iGY>5Jtno_xw%_a5vxu$xSub4Iw;m_g
zyB@wT2cNlqMEmbTUgArS!)=@|c}<>1Jj#ulF?
z9eA$mIC6)`;o-jzA01%HN9I8Tu@%gR^IQ)+>pPuw+?VTtXMOQ&JeQ#}53KpA@#iVS
zZSV_pSs#2JyG3pK+Dnhae~WmcbvQ%^KC(v9{$xIO8Jfui%{urh@oT(^vp`BZ$g@m*
zc<4Bkj03$AM8~1)Ie#eJ{m+BzIi>wDlw`i^J&EQ7AWF8eHBl&)RJ#p3gOHllo$wGrh|2EWar
z%fJQu9O$D9o$cXw=^?K{_v?5`-{radlD_k@K6J@v7f*g&$II!Gb?LVG#kX{ZIJuS~
zd~GHlL)KHtSE=661FAkas2kBWJnOoBO@^;FT`v&ftO#Is6bt4_>HtVs1%|KKlLeGPyTEWYGA@
z{2C3v2HhVxP&R(xLp;Z`4m3J#e(;rT;Nv6H@N3ZhfdljPz#j_MuBnSp`CWQ0myKv0
z&adHP&GFxwP8S~^B|XV9zfC{uE<$@bj%S~eIS<-xGA?}`z%e!c>%PE|Lu2OP5Sp&-&Sk}O@29`Cjtbt_>ENfs{1Irp%*1%<61OE=K+lM;<
literal 0
HcmV?d00001
diff --git a/idrocap_wa/webroot/favicon2.ico b/idrocap_wa/webroot/favicon2.ico
new file mode 100644
index 0000000000000000000000000000000000000000..49a060fc46e2bdfb8f3908c1873a45aa0e9babd0
GIT binary patch
literal 15086
zcmeHN33OD|8GdXgfGk>Z0d2xEnSI~)C7H=&5|*$8g0gCbs@R^?9$R|^6zfv$k$T!%
zk9Ku|7Vs!b5<({Pwn+d%IK|U~wg?I$t(DM<0f9`vJ2Q_=;+x4tskL_I%suzLyZrxu
z|NAfZ|KFvkLDUdx>{tqQDYbkkMOi3{DlJXDuSff@(5BO+-z5|k8b?twj6oM>q}owY
z6vq88{Tjlr56YL`u!$b(QgKq7oUgaa`3EgB{yEe?^=P?k1sD-Wbck2aj13x@VL}_J
zeFmn;D(4ZZD7m0h&W#u5liH`F$DqH~BInj(d=u!|3p#0^
zfm4$H<^|C4a>56n+H`6gV&-4$Sd%6jvHMZYbAt8n1@)dGvIx
zN7J#;Bj@MVSlQ770+z?%l`A$3sxq_JdDYxhyOMtlzG}N!#velYz$}fQflWSdlEM$j
z_~Su4J0%y$x#8Af5hpWxet^x(-c>o6tK2HK!7AhS!zQ22VY3sky~l&rcrW~O!)?QY
zme>UNw17j+eAlMnHo{Ns1k6<-OYFK_v`+WOitS478LaK1G3D!f`Ila_NVx=j-?4}-
zt_Ygw@z|FN_`dJKC%kNtvEUVV#)vVdvbX@Fo6u6_h-I~cPEFH9@b+j1o^JS=e_@>m
zaemltSF+E+7p-w9_y(^wzO2H;E_16n;*0)bk;aKX6>y2x@Q!w6M2CTKLVfM2)TX0qvmUZ26|G&vwe(L
z$A)nRY&1*S$uU{<7xDh~s)&2jWYNxa;~jJN44GNpSX>uw962k{G1;l+c32f`lS9R<
z@@kptuq8Ti7I-BFquSb9Qe&jA7wZ#it99)v_8V!5TiaFx*=n#WnWrE_8^F&Nn}Y3d
zsQK;HPS!Lpvh517`C@G^Jh`{m9*T_#o46a@YWB_~zhpd-hjU_kO!O~gY44?f0=&i3
zxM5*)`*@!|=69&M1wIp(ldr-&pPsI=$yuWN7YR;dkN$j0reS}M1=IK!1^HniYjlE3
zPY0aPdxw(U2%R}(ktX$!oY@azP4gbPt1;{P1I8WKLSA1NTdPU3lB0;}D67|Lm%5&_9-(ReR0L@!l=$O~3XEFrojaZDo8`{j)0@
zfu9)&{(R|7jwARTlK$`yX#E4mZ_k0>t!^JF|R8
zu~X6h4E7YVe|c#z!e85z%!Y`&X^gn^rCKYk>{U)J{T)aZgKNRuD5MMPzmk+|v{T=YmfIsI^cSD|1
zd?n9P?gH9AM)?4G`KC?AM_~h=M65lh!pcloR=+W;-V1oM)pZro;;@Om!E0dEE)DC0
zO`GY{@(Uc&_!3)L`%Qa>7{RcW}Mk*DYO?j@KxeK
zBG(TYhzrO#bW)vTI*X_=rxVneuEd~IiG(+iIFd+oqyH>*p`??d$8=KEr^*G2@*)+H
z3qykBDRd}{Q7+{vL{BsrQ1}%%P~bp;0|gEgIPibSfgdmZVDOUa-NiG5o5#)#GUMlX
z_f3rGc1psE_@w!+U3upqz6jPWinJG3+1QexA@299cP;m5m`9OUTJMm@TWm`DHLH?&
z)256cwMg6Fb12yTGkkPj`HBA|?ehZM$cTxvd)55+k-ut0p64)$caTTyHXxU1NXCRD
z21~_Q#xgFIA5rips{QPx?_T-RxS+PJsIG$T^}Q?KxtZhYtC%Z8I;IZsRul5Jr$}5z
zV!+HeFjs7hb-p*%)6p;e--zrhu5q@Nmh0Inua;hESFu}=6KxIZ>E*M1Exo>7X404I
zd76v;x>LixhN2?|mt$q6z%w&c;)%^1*UZ-MnalZHT33R8%L4Krcg7ANaYq#`{
z8PTF@M{IJrftd;!T;otO%_M(|*!nE;w~1s)$K0vBKw1`&TOhnc4m4I9pf7z_?@Mpr
zcb{?dB=G&6%p3!e9pq>erX+6=-y^m+N#h?Oray+<@B!pN5!Z8@oO1rxer@~De0pwe
zg*o;}*u?w@ecO>II0}A><|~D@i`KvgUHizZ;yiun%=YfoY?2^fcRVv!V?f>#JUi)9
zvYc1NKjqc1w^kT9Z`jf{Wp;V%xcRd;3}5}teM2*0E{g2E26>-95*`wn5b_$Lbf)<)
z)`xjrP6;2#gq`czt=%XwOPS+@|Hw_Au`AeCkCs_cX`?j@t74;?o^Q!3f3Z0H#yGpO
z{eU1JJvx+@yX1F}R4zBU*T~fX-$~%(VKZ7xa`wYiJKtrOGI`VQRBn-2kT1pe5ZgWatWOtx68c;pvc{BiL(Hi4&psi#r}HYejPYutYusgVU%t5K&s;nD=Gi~T
zt)hYdR;|2i@DCa`U2*^2e9>*Q_T1>zajkYW&AQdh6Mkc~F5+la)CK7)pLv`WrB@8&
z;!x|=ivrQSa*Sg0`?lSF%epHfp62UAX4)9gw@nQg+E(Bj!VjIQ_|tYJz0Rd>+lCxv
ztH;2%
z#3$suK*UR?h@G*VYLFSnuKhxa1$_SpNvv(BFuOVpj=5E~Gd(fe#o6QRL2Qc!W_|BPIr2>?Y6#jW_x#PH%W{#rq}sF
z6mI|f(T#J|g&zHeUSFbH;B{{L)8~#Zn}pBXf4S7JNK7&s^b;Ka{W8$=Pl5i+yJrLE
z|Epg{`N>=U%S~G*S>$y3eygBgg1xxByv?OwDZhg=d>M&fn7recCG$29cPl%7mx?z)
zcRKFMh3j(n5!w+mCG@E6s#tVpaO;51lhxLan_O!4C9|B#c~|Um)13*=AY;!vRrL0d
zt681R*5_)kt!)|QH%I3p-fl9>*;B-y_2haoa_Qc7E?RT-)km5};tr18P4ZWY_H8y9_gCDNJ_GqmeydN$^`F5{5c)}h
ztaRa=^)7NgZMfU@aL~+E)K;}-y-$~m*8chyh4vL!y0({uEN%XPCcccEuW*m)C7d-|
zkY{)ed-W#b&Lg;IaNJTBKVgx?Pgte#<7hjInD#B3g5HBW`ccHie{gAIkK>$mS6CMh
zO}Fxr`e1AXyEgHK#|ig+`;Ec%HGJ`$(5qwXD`Vs9e7j2{`uG%2Sx1?3%1&v8YL{fT
zd-ufpN`AtO(92`%rpAUZn}1|Tf4nO67dTMhK!F1V4iq@>RpmhH5|MD3=yKHLUJ~GR
zrt8&I;vC+)(L}AHDBNA@q`b)*x0p~5K_{unjV4lKatZ2-iNv5pEJ;sE5?+E%!9Cjp
z_adf{|LRpq_!rV}SEuU~JhE}#41E2(gHDRjnOKc`Qv^6JU=@-2QXw28@0X|kH%qw6
AlmGw#
literal 0
HcmV?d00001
diff --git a/idrocap_wa/webroot/font/Raleway-License.txt b/idrocap_wa/webroot/font/Raleway-License.txt
new file mode 100644
index 0000000..94dce24
--- /dev/null
+++ b/idrocap_wa/webroot/font/Raleway-License.txt
@@ -0,0 +1,51 @@
+License for 'Raleway'
+SIL Open Font License
+Copyright (c) 2010, Matt McInerney (matt@pixelspread.com),
+Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com),
+Copyright (c) 2011, Rodrigo Fuenzalida (www.rfuenzalida.com|hello@rfuenzalida.com), with Reserved Font Name Raleway
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+—————————————————————————————-
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+—————————————————————————————-
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+“Font Software” refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
+
+“Reserved Font Name” refers to any names specified as such after the copyright statement(s).
+
+“Original Version” refers to the collection of Font Software components as distributed by the Copyright Holder(s).
+
+“Modified Version” refers to any derivative made by adding to, deleting, or substituting—in part or in whole—any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
+
+“Author” refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/idrocap_wa/webroot/font/cakedingbats-webfont.eot b/idrocap_wa/webroot/font/cakedingbats-webfont.eot
new file mode 100644
index 0000000000000000000000000000000000000000..e8605d92685dc69e3555a2d46c934332ade64789
GIT binary patch
literal 75538
zcmb@v37izg`8VFxJ>5O`eP28G?Cj3Y9dT=s;++O
zsi&%Itx3X-Oc0K6Joo*7gu9VY&bUb|I3sfKx@Gjn2hU*VNiR2oo6B9uE#yMnNNy>2
zF}IkT2hJ*PB~loW(Zb5|}0-;A667NL6avbBrq
zUmn$r>-Rb0y>ZFHxeJ4VUhV4;d&Ft@%xtlVCAZ;e&rV&
ziH%17`sFJYF5k7{$!#2ocO!lOWeevm`m|yCWR4^naV-I~b-34t{p3v=zO8?llK1F1e8tIhD9TL`NZZB@`a#=9AA^p6`CxT?Q|guU)Z{
zYvBy>Q{pdkHWcG|?l|ID8fmfk3Fr{J524M;Q(~l_0YK>N>HyBN3i`8a#I9+a!*XIuel^jK(a3mUwCz8df
zlG1cpro5uEDqH=Zq@4x7=KpWr6j#NSa%1rdS8*x4ibts+k@oRc)dw7hmm@v4m(xt@
z+)c=qu3mEbx?XN%ppVmV!g+Jb(3jGoP}|axyU6*t;L~7~gh2`EQ2Q<+-ae%>+7;>v
z^>i%g3AKlo%w4cc6=xwL7WQK^Ia)iScn7Y>KocI}_kxoiJOU%0CasiZ?8c(o#BYUi#N-!87Jr-#a%+8GV+>h9_B^`IX4>t1gEKQRdR&y1El11$j=
zXo9_0;Z|Oot0S9oYsAQj
zKeVdu#gj!(KV2uS5+CE@+%Rr!FV|Gw%asF7=3dTu2q9v}rY03Coh8wt&Q
zT!d5q1Ia)Q1%<>C2q%yLYJqluCXPU2^SkIqn(}@~!dqS1kGH%AVMS#;NE~)aHj-#0
zkt9lx;A^U_b+xfqs4=+QK
z8KI`SiN|BAV<||Gxa=}}sCcx3!ye>a8XDuwXQq!knW(9*ts_l%z-NdAvraoqt?}qp
zdfkav)LNDLWEbJ_PbCV(<9BPU0f(R!#d=vIs#Oo^%*1u#6;UlB-Q}{?q%&IWl4`S<
zk~KP~$YdbWqXQ+@i?Udd3zmzIsa$G}&LIx;sCcrD=Ls(feCe14Lt+!gjV=<^Jil7S
z=QgP9Mz3z52ZbOjO=S%u6UCz%N_4p!gd#z&%M0LnHz>O(BzV3c6of|)m5O(6p5{&Q
z5$M?tZVpVKYq_=ku$7E>6O>yg>6{D$PUhnTOsp54~p|de1!c
zo_Xj!^U!+A_rmy6;f+_7?uA?x3@;Vl
zJQ0sB!{f1)lMLP~_T2Es6%jm+_;(M9CQHf^ZzOn}>?IWHjDk!bC-Oxj%8Q8iG+V{q
zPdskCm@f2zCZUeKs)Cb7DY-~gm~#1LleTSKQKpi3O*m9CW$mQ%Ki_m0nflnht7y}G2sq_^1x
zQI~WYL42#bW&_Wscl>bbi@*M0z|yvXwtoR-!);*bG^H#UbDY#ab4B<
zTV{zm(KTV)sL3~7wJ=s13EN#2lWc!BG*+il6%%cL)~6r8Hh1cSC&_G!r?j?s`E|F9
z^VT(uEH0ZizQw5%j=6l2I_A*WHI#@utht{IdFd*1&{DUyDbYH#+GDf_Pd$E9CbsFR
zw=QnqxOP!uXolJ`r_Z;~5VvA{9Rs8H2JSKL5cf2Tyu_GioiU
z`JnotH!bKUd%0?Ge!)0XxP6Q>7Mym*DMuO@Ar1Y|>4Vht0=1+-ttwF06{y<^)WZd;
zuRy()r||Mu1qGGMslv;RmlmT7-hCslk|mWX;mT`Q5i{`
zWef_gjF8NTj3qaTwuq6Jn}qClQdtf`$$f@kJ{c5jRZXhFt^^4gRT4K6HZ?x-+Ocm4
zx#|s4@tf-tp&7OE)^9JVoe@f0|C`*QH?GQ^{^rrfOQ=gh5eyd8YHJHsdjn-;0
z8?{E~{|cLO#1m4h@}>UAE`CF=Uo(ba+EnPkC9f
zMKT&pvZU3>B2Ofp)n{*9JhqhCAD4J-cpqZuyScqELqr%js?uIgh6XD-#Ky2V^kE$O
zFb=&HN4hxlVI2A}4t*GhK8!;j#-R`6(1&s8!#GCMI7ZVrM$`DiJ7gXagQfn
zYBk5gJ~>k?>ouaNF~~`A>+z$r?*HQk+3EJ!^<@*53>~^;LYdy~aXaN}{_vBTr#hDH
zx^BAFv0~R}Tep6;YlXu)?b;_V6ug;Xk?628FHA@}H9EZ@@H6oa=!Q5qp1X=$u@{z*
znzQ0LGV9R_>(L6E&kF0&iZRd13_?FzqMI6oSr~+^nA%Z;a4eDuc=}@zDWaJ~v`q@M
z9yGN(DBlIzmFI^+hiTi<<_ar=4sFG_(tP=L!Zik?a72$$EXK?e0cNFMqB#g_Ss@ms
z8i)#Tv4IK$nJS3U4NOVlx!(%ak1Zu%gyZp0&Q?0MJ|vt&IVGSFmQc>gH{zkMnjgyj
zHuqWXMDBR*ub_Uq_v+kzkoLuJ{EMSM*nN5H
zgd2YOx7=U0&D`_okDJtLmBFo2PkW|o6L!GBowx+tAV8D>%c(h4mFG9E`>Hy-fIAv;$B$6^LNNS6)|7xni!GEwtB)KkI6UDhtO)u|aG&uX~)ou6<@p%gnZVgD9vi&+5&ZX&RGkP~{%o
zCJde1ebe0&Cft2<_uQevz`CZ~j3&NZFd7^dvqc-!dAxp|U2E6t)oNKX=*?EEL8B3M
z^R9QoRu%X%wN`7;$!bZu-{%)4JEWnl`=gDfdWHjpy
z>J55HIzIpP7a!>!Gp75I7hj*hd-v{_H5!K=f=xvZqd_I8b$W}<<}jIHbV`CC4l7@#
zHb^#6r4uEUAW6BGE>`~0chrRESTF4tUjcX=j{Ep`*95Ctr)yzhY1RS9r=7<0)T^w^<9`
z#moTlLRKxPUhcHHkBFRz$zl|#qDWPek82gV-$C%70e&_NU=0WlkOCTj4xkHI3akY-
z1KWX}Kp$`bFwE{H?I=MRWS2oVjDvc8i%m_ZfHS4Mmjn?z1N4k?YGacu=L8Z!Ezk~3
z0~P_RfsMd6Up
zqP9ZR*1<}hr4Xf3XDI{&^;>vyJMa`~zkV3uI)wWW?nBRg8$I`N_B3g#!{8pqvp#L^
zCH6xA==(sof^N;z=Yl?$^^HCbL)c683heh5_EN$6=aw_-5JzC$
zQx*F#DEgx9<(@*i9iV!-AK>O3I+qsjGslW!KGe^73s)TCL*SGYI77f0h2qkjlMyb*
zYjPo{!b>?V&z*_zLd2e*zowJOr*M5a!sQ6B$zT6Z{`!{u_1*dF=McVT?&W@tklz2-
z2!D-6p!Bgr7^owd)Hl=Ve-WX+1I!!#>ow*Xyu)IbN=XC*!Y~qc*rC;Nm8h{`j30_Q
zYc0kLXMkk?4JBhxrw#{<64ZPO|JO^{UlulR{cak|yiD|-&TJTS+b{+jU>He;Wm|-n
zn|dfvm%J;34ojF0C#f%Eu!e=1F?Ez60cwFf)Q2U~AKc;pm^zNa|KFq&k2nH;Gp|zd
z7Jnf3xjp#rFZklf(6rZ}`ADaZsZKtoiplzqGzM?FG162L+!rj}M1M;*mC|3)kqDU0
zfrKO7X!a*^pa09H-weJId+H<6aN=9L(_v1#qdtTtgyN_Zjl}`7OyxB4R-;ozmIaDu
zp7{H$`D$V%c7s*tl(iThEjm5l>h$tHFG2AWf?zRPjBaNli1AZZ%<~?1?$7Yj*_;j+
zFR%m#tx@B!7I`r9Hci7Q9;eg$F@`i9AWw2Nbsle3p&let$coI=b9+Ot1LvuLQS}|AT9u|_LEnc2a
z@&ei3zTjGO&!m(
zKvTVQKImUUGwr|t-p^ft+wOpN>xZTqq?VxoHpaU&&+Fx`Megg6djrCabmFK%IXplL
zXaG8ZE?_CJ7T64I2X+E|zyaV0a11yO3Bbn62SaUI^+sMqLi74OBmzk8X@Yy<8hamO^AH
zM6L&254s*h-ld2)vKHT3pzh97%82m9nNA4lC1ZZMsNfnb%v^7@;b{?~#I~wIpft`D}nV!eGdK
zq_^7ixd(N;T`&7b#O$^tUdKdr*rw)Xr{(0QW*6ZJAr1DBF876SQ?7YNAaSMM>DH0v
zk>?pb#*XgNBNpvI->Ev`00mhVE{_F74Nq)F+2rC?8e2ID$4X--B
zmP*lLlRIegS~PltpmjOSh$Mo6HzpinT2xJRS}ZPara8_FRP#p~(_R|JhPnI|G5bwE
zo89ZR+k6AxU^&x}``BP0GvQq?S6TIv-6_b$L81M;rifWE>IR-SyIf{|B%JaRZbA68
zFMnXZ1gn}3e1u+r|VkGnvG>3%r
zP9Oo)0`0&wU=gqy*a&O`b^v>Tmx05;$H3P>egWq!g(xnkvlOy|Ri_)(=|*+BQJrp7
zryJGjMs>PToo-a88`bGXb-GcVZd9im)#*lcx>23(!Rnl)5T!b2DFlYO0Ijr*DmrCN
zs-K(9>6rojBdEFym@PdQ|m?Di<
zt36&9O?6J27>>EDR$HPjTHHBpQaE<<{W}7|aQN2n)O31Eq$Z4ilrEVNx?|v7n>9$r
z#mhYvw$JRgqTDkvO7gRvHGxb#C#nsy)8TLmUpeXm5`1J0X0tmO^lD;>c_=~>x7Vqw
zMV(xUtAym#Yqir(J!>ovh9{gmBb}YnP-HV!(2Fj1L8KptCX}S7;`aDgP0PdRK;Vwt
zwOFJrkCCxOHrr>ma!+|Y_YBM`j`LAJllB+lGn@r%Bcs|tDFfXQP;_$D
zPw1*NT|g<~)civ%)k(yOlp