From b156ec460149324b240d95e1cc3613f03f6ba9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Viguier?= Date: Sat, 26 Oct 2024 12:41:14 +0200 Subject: [PATCH] Version 6 (#2504) --------- Co-authored-by: Martin Stone <1611702+d7415@users.noreply.github.com> --- .env.example | 7 +- .github/dependabot.yml | 16 + .github/workflows/.env.legacy.mariadb | 2 +- .github/workflows/.env.legacy.postgresql | 2 +- .github/workflows/.env.legacy.sqlite | 2 +- .github/workflows/.env.mariadb | 21 + .github/workflows/.env.postgresql | 18 + .github/workflows/.env.sqlite | 14 + .github/workflows/CICD.yml | 45 +- .github/workflows/CICD_no_legacy.yml | 209 + .github/workflows/dependency-check.yml | 14 - .github/workflows/js_check.yml | 37 +- .github/workflows/php_dist.yml | 12 +- .github/workflows/php_no_legacy_dist.yml | 94 + .github/workflows/php_no_legacy_tests.yml | 117 + .github/workflows/php_tests.yml | 26 +- .github/workflows/scorecard.yml | 5 + .php-cs-fixer.php | 1 + .phpstorm.meta.php | 1498 +----- Makefile | 15 +- .../Album/ListAlbums.php} | 70 +- app/Actions/Album/PositionData.php | 3 +- app/Actions/Album/SetHeader.php | 32 + app/Actions/Album/SetProtectionPolicy.php | 2 +- .../Album/SetSmartProtectionPolicy.php | 26 + app/Actions/Album/Transfer.php | 32 + app/Actions/Albums/PositionData.php | 8 +- app/Actions/Db/OptimizeDb.php | 2 +- app/Actions/Diagnostics/Diagnostics.php | 2 +- app/Actions/Diagnostics/Errors.php | 2 + .../Pipes/Checks/BasicPermissionCheck.php | 6 +- .../Pipes/Checks/ConfigSanityCheck.php | 10 +- .../Pipes/Checks/ForeignKeyListInfo.php | 2 +- .../Pipes/Checks/IniSettingsCheck.php | 9 + .../Pipes/Checks/SupporterCheck.php | 42 + .../Pipes/Checks/UpdatableCheck.php | 4 +- .../Pipes/Infos/CountForeignKeyInfo.php | 2 +- .../Pipes/Infos/InstallTypeInfo.php | 13 +- .../Diagnostics/Pipes/Infos/SystemInfo.php | 18 +- .../Diagnostics/Pipes/Infos/VersionInfo.php | 31 +- app/Actions/Import/Exec.php | 4 +- app/Actions/Import/FromServer.php | 2 +- app/Actions/InstallUpdate/CheckUpdate.php | 2 +- app/Actions/InstallUpdate/DefaultConfig.php | 6 +- .../Pipes/AbstractUpdateInstallerPipe.php | 4 +- app/Actions/Photo/Archive.php | 2 +- app/Actions/Photo/Create.php | 50 + app/Actions/Photo/Duplicate.php | 13 +- app/Actions/Photo/Move.php | 2 +- .../Standalone/CreateOriginalSizeVariant.php | 1 + .../Photo/Pipes/Standalone/PlacePhoto.php | 14 + .../Standalone/ReplaceOriginalWithBackup.php | 26 + app/Actions/Profile/UpdateLogin.php | 83 + app/Actions/Sharing/ListShare.php | 3 +- app/Actions/Sharing/ListedAlbum.php | 13 - app/Actions/Sharing/Share.php | 34 + app/Actions/Sharing/SharedAlbum.php | 14 - app/Actions/Sharing/UserShared.php | 11 - app/Actions/Statistics/Spaces.php | 411 ++ app/Actions/User/Create.php | 18 +- app/Actions/User/Save.php | 17 +- app/Assets/ArrayToTextTable.php | 2 +- app/Assets/Helpers.php | 30 - ...tGroupedWithRandomSuffixNamingStrategy.php | 9 +- app/Casts/MustNotSetCast.php | 13 +- app/Console/Commands/Diagnostics.php | 2 +- .../Commands/ImageProcessing/ExifLens.php | 3 +- .../Commands/ImageProcessing/Takedate.php | 3 +- .../Commands/Laravel/LangFilesToJson.php | 90 + app/Console/Commands/Laravel/Optimize.php | 2 +- app/Console/Commands/Legacy/ResetAdmin.php | 2 +- .../Http/Requests/HasAbstractAlbum.php | 13 + .../Http/Requests/HasAccessPermission.php | 13 + .../Requests/HasAccessPermissionResource.php | 13 + app/Contracts/Http/Requests/HasAlbum.php | 13 + app/Contracts/Http/Requests/HasAlbumId.php | 11 + app/Contracts/Http/Requests/HasAlbumIds.php | 11 + .../Requests/HasAlbumSortingCriterion.php | 13 + app/Contracts/Http/Requests/HasAlbums.php | 16 + app/Contracts/Http/Requests/HasBaseAlbum.php | 13 + .../Http/Requests/HasCompactBoolean.php | 8 + app/Contracts/Http/Requests/HasConfigs.php | 14 + app/Contracts/Http/Requests/HasCopyright.php | 11 + .../Http/Requests/HasDescription.php | 11 + app/Contracts/Http/Requests/HasLicense.php | 13 + app/Contracts/Http/Requests/HasNote.php | 11 + app/Contracts/Http/Requests/HasOwnerId.php | 11 + .../Http/Requests/HasParentAlbum.php | 13 + app/Contracts/Http/Requests/HasPassword.php | 11 + app/Contracts/Http/Requests/HasPhoto.php | 13 + app/Contracts/Http/Requests/HasPhotoIds.php | 11 + .../Http/Requests/HasPhotoLayout.php | 13 + .../Requests/HasPhotoSortingCriterion.php | 13 + app/Contracts/Http/Requests/HasPhotos.php | 14 + app/Contracts/Http/Requests/HasQuotaKB.php | 11 + .../Http/Requests/HasSeStatusBoolean.php | 8 + .../Http/Requests/HasSizeVariant.php | 13 + app/Contracts/Http/Requests/HasTagAlbum.php | 13 + app/Contracts/Http/Requests/HasTags.php | 11 + app/Contracts/Http/Requests/HasTerms.php | 11 + app/Contracts/Http/Requests/HasTitle.php | 11 + app/Contracts/Http/Requests/HasUploadDate.php | 13 + app/Contracts/Http/Requests/HasUser.php | 21 + app/Contracts/Http/Requests/HasUserId.php | 11 + app/Contracts/Http/Requests/HasUserIds.php | 11 + app/Contracts/Http/Requests/HasUsername.php | 11 + .../Http/Requests/RequestAttribute.php | 93 + app/Contracts/Livewire/Openable.php | 32 - app/Contracts/Livewire/Params.php | 17 - app/Contracts/Livewire/Reloadable.php | 8 - app/Contracts/Models/AbstractAlbum.php | 9 +- .../AbstractSizeVariantNamingStrategy.php | 5 +- app/DTO/AbstractDTO.php | 6 +- app/DTO/AlbumSortingCriterion.php | 2 + app/DTO/BaseImportReport.php | 5 + app/DTO/ImageDimension.php | 2 +- app/DTO/PhotoCreate/InitDTO.php | 2 +- app/DTO/PhotoCreate/StandaloneDTO.php | 1 + app/DTO/PhotoSortingCriterion.php | 2 + app/DTO/SortingCriterion.php | 2 + app/DTO/TopAlbumDTO.php | 4 +- app/DTO/Version.php | 2 +- app/Eloquent/FixedQueryBuilderTrait.php | 16 +- app/Enum/AlbumDecorationOrientation.php | 16 - app/Enum/AlbumDecorationType.php | 17 - app/Enum/AspectRatioCSSType.php | 18 + app/Enum/AspectRatioType.php | 33 +- app/Enum/ColumnSortingAlbumType.php | 17 - app/Enum/ColumnSortingPhotoType.php | 18 - app/Enum/ConfigType.php | 21 + app/Enum/DateOrderingType.php | 14 + app/Enum/DownloadVariantType.php | 2 +- app/Enum/{Livewire => }/FileStatus.php | 2 +- app/Enum/ImageOverlayType.php | 16 - app/Enum/Livewire/NotificationType.php | 11 - app/Enum/OrderSortingType.php | 14 - app/Enum/PhotoLayoutType.php | 17 - app/Enum/Traits/WireableEnumTrait.php | 35 - app/Exceptions/Handler.php | 6 +- app/Exceptions/QuotaExceededException.php | 20 + app/Factories/AlbumFactory.php | 33 +- .../Admin/DiagnosticsController.php | 162 + app/Http/Controllers/Admin/JobsController.php | 29 + .../Admin/Maintenance/Cleaning.php | 89 + .../Admin}/Maintenance/FixJobs.php | 35 +- .../Controllers/Admin/Maintenance/FixTree.php | 43 + .../Admin/Maintenance/GenSizeVariants.php | 76 + .../Admin/Maintenance/MissingFileSizes.php | 69 + .../Admin/Maintenance/Model/Album.php | 20 + .../Admin/Maintenance/Optimize.php | 28 + .../Admin/Maintenance/RegisterController.php | 32 + .../Controllers/Admin/SettingsController.php | 95 + .../Controllers/Admin/UpdateController.php | 133 + .../Admin/UserManagementController.php | 102 + app/Http/Controllers/AuthController.php | 89 + .../Controllers/Gallery/AlbumController.php | 327 ++ .../Controllers/Gallery/AlbumsController.php | 22 + .../Controllers/Gallery/ConfigController.php | 54 + .../Controllers/Gallery/FrameController.php | 104 + .../Controllers/Gallery/MapController.php | 48 + .../Controllers/Gallery/PhotoController.php | 230 + .../Controllers/Gallery/SearchController.php | 66 + .../Controllers/Gallery/SharingController.php | 117 + .../Controllers/Install/EnvController.php | 5 - .../Install/MigrationController.php | 20 +- .../Install/PermissionsController.php | 28 +- .../Install/RequirementsController.php | 34 +- .../Install/SetUpAdminController.php | 24 +- .../Controllers/Install/WelcomeController.php | 18 +- .../Controllers/LandingPageController.php | 18 + app/Http/Controllers/Oauth.php | 85 - app/Http/Controllers/OauthController.php | 177 + app/Http/Controllers/ProfileController.php | 87 + app/Http/Controllers/RSSController.php | 30 + app/Http/Controllers/StatisticsController.php | 97 + app/Http/Controllers/UsersController.php | 34 + app/Http/Controllers/VersionController.php | 20 + app/Http/Controllers/VueController.php | 55 + .../WebAuthn/WebAuthnManageController.php | 28 +- .../WebAuthn/WebAuthnRegisterController.php | 2 + app/Http/Kernel.php | 17 +- app/Http/Middleware/AcceptContentType.php | 1 - app/Http/Middleware/CacheControl.php | 27 + app/Http/Middleware/Checks/HasAdminUser.php | 10 +- app/Http/Middleware/Checks/IsInstalled.php | 4 +- app/Http/Middleware/DisableCSP.php | 14 +- app/Http/Middleware/LoginRequired.php | 36 +- app/Http/Middleware/QueryStringFixer.php | 42 - app/Http/Requests/Album/AddAlbumRequest.php | 54 + .../Requests/Album/AddTagAlbumRequest.php | 52 + .../Requests/Album/DeleteAlbumsRequest.php | 50 + .../Requests/Album/DeleteTrackRequest.php | 37 + app/Http/Requests/Album/GetAlbumRequest.php | 59 + .../Requests/Album/MergeAlbumsRequest.php | 53 + app/Http/Requests/Album/MoveAlbumsRequest.php | 53 + .../Requests/Album/RenameAlbumRequest.php | 49 + .../Album/SetAlbumProtectionPolicyRequest.php | 87 + .../Requests/Album/SetAlbumTrackRequest.php | 48 + app/Http/Requests/Album/SetAsCoverRequest.php | 61 + .../Requests/Album/SetAsHeaderRequest.php | 69 + .../Requests/Album/TargetListAlbumRequest.php | 60 + .../Requests/Album/TransferAlbumRequest.php | 55 + .../Requests/Album/UnlockAlbumRequest.php | 48 + .../Requests/Album/UpdateAlbumRequest.php | 144 + .../Requests/Album/UpdateTagAlbumRequest.php | 94 + app/Http/Requests/Album/ZipRequest.php | 136 + app/Http/Requests/BaseApiRequest.php | 6 +- .../Diagnostics/DiagnosticsRequest.php | 22 + app/Http/Requests/Frame/FrameRequest.php | 51 + .../Requests/Install/SetUpAdminRequest.php | 10 +- app/Http/Requests/Jobs/ShowJobsRequest.php | 19 + .../Requests/Maintenance/CleaningRequest.php | 47 + .../Maintenance/CreateThumbsRequest.php | 48 + .../Maintenance/MaintenanceRequest.php | 19 + .../Requests/Maintenance/MigrateRequest.php | 66 + .../Requests/Maintenance/RegisterRequest.php | 41 + .../Requests/Maintenance/UpdateRequest.php | 19 + app/Http/Requests/Map/MapDataRequest.php | 45 + app/Http/Requests/Photo/CopyPhotosRequest.php | 50 + .../Requests/Photo/DeletePhotosRequest.php | 47 + app/Http/Requests/Photo/EditPhotoRequest.php | 80 + app/Http/Requests/Photo/FromUrlRequest.php | 77 + app/Http/Requests/Photo/MovePhotosRequest.php | 47 + .../Requests/Photo/RenamePhotoRequest.php | 51 + .../Requests/Photo/RotatePhotoRequest.php | 49 + .../Photo/SetPhotosStarredRequest.php | 52 + .../Requests/Photo/SetPhotosTagsRequest.php | 48 + .../Requests/Photo/UploadPhotoRequest.php | 93 + .../Requests/Profile/ChangeTokenRequest.php} | 10 +- .../Requests/Profile/ClearOauthRequest.php | 41 + .../Requests/Profile/UpdateProfileRequest.php | 88 + app/Http/Requests/Search/GetSearchRequest.php | 62 + .../Requests/Search/InitSearchRequest.php | 50 + app/Http/Requests/Session/LoginRequest.php | 18 +- .../Settings/GetAllConfigsRequest.php | 23 + .../Settings/SetCSSSettingRequest.php | 43 + .../Requests/Settings/SetConfigsRequest.php | 59 + .../Requests/Settings/SetJSSettingRequest.php | 43 + .../Requests/Sharing/AddSharingRequest.php | 72 + .../Requests/Sharing/DeleteSharingRequest.php | 57 + .../Requests/Sharing/EditSharingRequest.php | 71 + .../Sharing/ListAllSharingRequest.php | 24 + .../Requests/Sharing/ListSharingRequest.php | 48 + .../Statistics/SpacePerAlbumRequest.php | 60 + .../Statistics/SpacePerUserRequest.php | 35 + .../Statistics/SpaceSizeVariantRequest.php | 60 + .../AuthorizeCanEditAlbumAlbumsTrait.php | 29 + .../Authorize/AuthorizeCanEditAlbumTrait.php | 22 + .../Authorize/AuthorizeCanEditPhotoTrait.php | 22 + .../AuthorizeCanEditPhotosAlbumTrait.php | 34 + .../Authorize/AuthorizeCanEditPhotosTrait.php | 28 + .../Requests/Traits/HasAbstractAlbumTrait.php | 18 + .../HasAccessPermissionResourceTrait.php | 18 + .../Traits/HasAccessPermissionTrait.php | 18 + app/Http/Requests/Traits/HasAlbumIdTrait.php | 16 + app/Http/Requests/Traits/HasAlbumIdsTrait.php | 19 + .../Traits/HasAlbumSortingCriterionTrait.php | 18 + app/Http/Requests/Traits/HasAlbumTrait.php | 18 + app/Http/Requests/Traits/HasAlbumsTrait.php | 24 + .../Requests/Traits/HasAspectRatioTrait.php | 18 + .../Requests/Traits/HasBaseAlbumTrait.php | 18 + .../Traits/HasCompactBooleanTrait.php | 13 + app/Http/Requests/Traits/HasConfigsTrait.php | 20 + .../Requests/Traits/HasCopyrightTrait.php | 16 + .../Requests/Traits/HasDescriptionTrait.php | 16 + app/Http/Requests/Traits/HasLicenseTrait.php | 18 + app/Http/Requests/Traits/HasNoteTrait.php | 16 + app/Http/Requests/Traits/HasOwnerIdTrait.php | 16 + .../Requests/Traits/HasParentAlbumTrait.php | 18 + app/Http/Requests/Traits/HasPasswordTrait.php | 31 + app/Http/Requests/Traits/HasPhotoIdsTrait.php | 19 + .../Requests/Traits/HasPhotoLayoutTrait.php | 18 + .../Traits/HasPhotoSortingCriterionTrait.php | 18 + app/Http/Requests/Traits/HasPhotoTrait.php | 18 + app/Http/Requests/Traits/HasPhotosTrait.php | 22 + app/Http/Requests/Traits/HasQuotaKBTrait.php | 19 + .../Traits/HasSeStatusBooleanTrait.php | 22 + .../Requests/Traits/HasSizeVariantTrait.php | 18 + app/Http/Requests/Traits/HasTagAlbumTrait.php | 18 + app/Http/Requests/Traits/HasTagsTrait.php | 19 + app/Http/Requests/Traits/HasTermsTrait.php | 19 + app/Http/Requests/Traits/HasTitleTrait.php | 16 + .../Requests/Traits/HasUploadDateTrait.php | 18 + app/Http/Requests/Traits/HasUserIdTrait.php | 19 + app/Http/Requests/Traits/HasUserIdsTrait.php | 19 + app/Http/Requests/Traits/HasUserTrait.php | 29 + app/Http/Requests/Traits/HasUsernameTrait.php | 16 + .../UserManagement/AddUserRequest.php | 84 + .../UserManagement/DeleteUserRequest.php | 45 + .../ManagmentListUsersRequest.php | 23 + .../UserManagement/SetUserSettingsRequest.php | 95 + app/Http/Requests/Users/ListUsersRequest.php | 19 + app/Http/Requests/Users/UsersRequest.php | 32 + .../WebAuthn/DeleteCredentialRequest.php | 7 +- .../WebAuthn/EditCredentialRequest.php | 50 + .../Collections/ConfigCollectionResource.php | 36 + .../Collections/PositionDataResource.php | 41 + .../Collections/RootAlbumResource.php | 73 + .../Resources/Diagnostics/CleaningState.php | 23 + app/Http/Resources/Diagnostics/ErrorLine.php | 40 + .../Resources/Diagnostics/Permissions.php | 16 + app/Http/Resources/Diagnostics/TreeState.php | 18 + .../Resources/Diagnostics/UpdateCheckInfo.php | 16 + app/Http/Resources/Diagnostics/UpdateInfo.php | 18 + .../Editable/EditableBaseAlbumResource.php | 65 + .../Editable/EditableConfigResource.php | 19 + .../Resources/Editable/UploadMetaResource.php | 21 + app/Http/Resources/Frame/FrameData.php | 17 + .../Resources/GalleryConfigs/AlbumConfig.php | 69 + .../Resources/GalleryConfigs/FooterConfig.php | 43 + .../Resources/GalleryConfigs/InitConfig.php | 94 + .../GalleryConfigs/LandingPageResource.php | 30 + .../GalleryConfigs/MapProviderData.php | 22 + .../GalleryConfigs/PhotoLayoutConfig.php | 26 + .../Resources/GalleryConfigs/RegisterData.php | 14 + .../Resources/GalleryConfigs/RootConfig.php | 68 + .../Resources/GalleryConfigs/UploadConfig.php | 41 + .../Models/AbstractAlbumResource.php | 20 + .../Models/AccessPermissionResource.php | 39 + app/Http/Resources/Models/AlbumResource.php | 95 + app/Http/Resources/Models/ConfigResource.php | 34 + .../Resources/Models/JobHistoryResource.php | 33 + .../Resources/Models/LightUserResource.php | 25 + app/Http/Resources/Models/PhotoResource.php | 102 + .../Resources/Models/SizeVariantResource.php | 30 + .../Resources/Models/SizeVariantsResouce.php | 46 + .../Resources/Models/SmartAlbumResource.php | 51 + .../Resources/Models/TagAlbumResource.php | 78 + .../Resources/Models/TargetAlbumResource.php | 43 + .../Resources/Models/ThumbAlbumResource.php | 106 + app/Http/Resources/Models/ThumbResource.php | 43 + .../Models/UserManagementResource.php | 47 + app/Http/Resources/Models/UserResource.php | 24 + .../Models/Utils}/AlbumProtectionPolicy.php | 7 +- .../Models/Utils/PreComputedPhotoData.php | 49 + .../Models/Utils/PreFormattedAlbumData.php} | 38 +- .../Models/Utils/PreformattedPhotoData.php | 60 + app/Http/Resources/Models/Utils/UserToken.php | 15 + .../Resources/Models/WebAuthnResource.php | 27 + .../Resources/Oauth/OauthRegistrationData.php | 18 + .../Resources/Rights/AlbumRightsResource.php | 40 + .../Resources/Rights/GlobalRightsResource.php | 23 + .../Resources/Rights/PhotoRightsResource.php | 31 + .../Rights/RootAlbumRightsResource.php | 22 + .../Rights/SettingsRightsResource.php | 30 + .../Rights/UserManagementRightsResource.php | 26 + .../Resources/Rights/UserRightsResource.php | 20 + app/Http/Resources/Root/AuthConfig.php | 30 + app/Http/Resources/Root/VersionResource.php | 38 + app/Http/Resources/Search/InitResource.php | 21 + app/Http/Resources/Search/ResultsResource.php | 75 + .../Sharing/ListedAlbumsResource.php | 22 + .../Resources/Sharing/SharedAlbumResource.php | 30 + app/Http/Resources/Sharing/SharesResource.php | 40 + .../Resources/Sharing/UserSharedResource.php | 20 + app/Http/Resources/Statistics/Album.php | 37 + app/Http/Resources/Statistics/Sizes.php | 37 + app/Http/Resources/Statistics/UserSpace.php | 36 + app/Http/Resources/Traits/HasHeaderUrl.php | 72 + .../Traits/HasPrepPhotoCollection.php | 34 + .../RuleSets/Album/ArchiveAlbumRuleSet.php | 23 - .../Album/SetAlbumDescriptionRuleSet.php | 25 - .../RuleSets/Album/SetAlbumLicenseRuleSet.php | 26 - .../RuleSets/Album/SetAlbumNSFWRuleSet.php | 24 - .../Album/SetAlbumSortingRuleSetLegacy.php | 28 - .../RuleSets/Album/SetPhotoSortingRuleSet.php | 28 - app/Image/Handlers/GdHandler.php | 6 +- app/Image/Handlers/ImagickHandler.php | 4 +- app/Image/SizeVariantDefaultFactory.php | 2 +- app/Image/SizeVariantDimensionHelpers.php | 2 +- app/Legacy/Actions/Photo/Create.php | 2 +- .../Photo/Strategies/AbstractAddStrategy.php | 2 +- .../Actions/Settings/UpdateLogin.php | 2 +- app/Legacy/AdminAuthentication.php | 2 + app/Legacy/BaseConfigMigration.php | 4 + app/{ => Legacy/V1}/Actions/Albums/Tree.php | 10 +- .../Requests/HasAlbumSortingCriterion.php | 13 + .../Http/Requests/HasAspectRatio.php | 13 + .../Requests/HasPhotoSortingCriterion.php | 13 + .../Administration/DiagnosticsController.php | 2 +- .../Administration/SettingsController.php | 15 +- .../Administration/SharingController.php | 2 +- .../Administration/UserController.php | 2 +- app/Legacy/V1/Controllers/AlbumController.php | 4 +- .../V1/Controllers/AlbumsController.php | 4 +- app/Legacy/V1/Controllers/IndexController.php | 4 +- .../V1/Controllers/LegacyController.php | 2 +- app/Legacy/V1/Controllers/PhotoController.php | 8 +- .../V1/Controllers/RedirectController.php | 12 +- app/{ => Legacy/V1}/DTO/DiagnosticInfo.php | 5 +- app/Legacy/V1/Middleware/LoginRequiredV1.php | 7 - .../V1/Requests/Album/AddAlbumRequest.php | 2 +- .../V1/Requests/Album/AddTagAlbumRequest.php | 2 +- .../V1/Requests/Album/DeleteAlbumsRequest.php | 2 +- .../V1/Requests/Album/DeleteTrackRequest.php | 2 +- .../V1/Requests/Album/GetAlbumRequest.php | 2 +- .../V1/Requests/Album/MergeAlbumsRequest.php | 2 +- .../V1/Requests/Album/MoveAlbumsRequest.php | 2 +- .../Requests/Album/SetAlbumCoverRequest.php | 2 +- .../Requests/Album/SetAlbumHeaderRequest.php | 2 +- .../Album/SetAlbumProtectionPolicyRequest.php | 2 +- .../V1/Requests/Album/SetAlbumTagsRequest.php | 2 +- .../Requests/Album/SetAlbumsTitleRequest.php | 2 +- .../V1/Requests/Album/UnlockAlbumRequest.php | 2 +- .../Requests/Import/ImportFromUrlRequest.php | 2 +- .../Requests/Import/ImportServerRequest.php | 2 +- .../Requests/Legacy/TranslateIDRequest.php | 2 +- .../V1/Requests/Photo/AddPhotoRequest.php | 2 +- .../Requests/Photo/ArchivePhotosRequest.php | 5 +- .../V1/Requests/Photo/DeletePhotosRequest.php | 2 +- .../Requests/Photo/DuplicatePhotosRequest.php | 2 +- .../V1/Requests/Photo/GetPhotoRequest.php | 2 +- .../V1/Requests/Photo/MovePhotosRequest.php | 2 +- .../V1/Requests/Photo/RotatePhotoRequest.php | 2 +- .../Photo/SetPhotoDescriptionRequest.php | 2 +- .../Requests/Photo/SetPhotoLicenseRequest.php | 2 +- .../Photo/SetPhotoUploadDateRequest.php | 2 +- .../Photo/SetPhotosStarredRequest.php | 2 +- .../Requests/Photo/SetPhotosTagsRequest.php | 2 +- .../Requests/Photo/SetPhotosTitleRequest.php | 2 +- .../V1/Requests/User/ChangeLoginRequest.php | 2 +- .../V1/Requests/User/SetEmailRequest.php | 2 +- .../V1/Requests/Users/AddUserRequest.php | 2 +- .../Requests/Users/SetUserSettingsRequest.php | 2 +- .../Collections/AlbumForestResource.php | 2 +- .../Collections/PositionDataResource.php | 2 +- .../Collections/TopAlbumsResource.php | 2 +- .../V1/Resources/Models/AlbumResource.php | 2 +- .../Resources/Models/SmartAlbumResource.php | 2 +- .../V1/Resources/Models/TagAlbumResource.php | 2 +- .../Sharing/ListedAlbumsResource.php | 34 - .../Resources/Sharing/SharedAlbumResource.php | 37 - .../V1/Resources/Sharing/SharesResource.php | 44 - .../Resources/Sharing/UserSharedResource.php | 34 - .../V1}/RuleSets/AddAlbumRuleSet.php | 2 +- .../V1}/RuleSets/Album/AddAlbumRuleSet.php | 2 +- .../V1}/RuleSets/Album/AddTagAlbumRuleSet.php | 2 +- .../RuleSets/Album/BasicAlbumIdRuleSet.php | 2 +- .../RuleSets/Album/DeleteAlbumsRuleSet.php | 2 +- .../V1}/RuleSets/Album/MergeAlbumsRuleSet.php | 2 +- .../V1}/RuleSets/Album/MoveAlbumsRuleSet.php | 2 +- .../RuleSets/Album/SetAlbumCoverRuleSet.php | 2 +- .../RuleSets/Album/SetAlbumHeaderRuleSet.php | 2 +- .../RuleSets/Album/SetAlbumSortingRuleSet.php | 2 +- .../V1}/RuleSets/Album/SetAlbumTagRuleSet.php | 2 +- .../RuleSets/Album/SetAlbumsTitleRuleSet.php | 2 +- .../V1}/RuleSets/Album/UnlockAlbumRuleSet.php | 2 +- .../V1}/RuleSets/ChangeLoginRuleSet.php | 2 +- .../RuleSets/Import/ImportFromUrlRuleSet.php | 2 +- .../RuleSets/Import/ImportServerRuleSet.php | 2 +- .../V1}/RuleSets/LoginRuleSet.php | 2 +- .../V1}/RuleSets/Photo/AddPhotoRuleSet.php | 2 +- .../RuleSets/Photo/ArchivePhotosRuleSet.php | 2 +- .../RuleSets/Photo/DeletePhotosRuleSet.php | 2 +- .../RuleSets/Photo/DuplicatePhotosRuleSet.php | 2 +- .../V1}/RuleSets/Photo/GetPhotoRuleSet.php | 2 +- .../V1}/RuleSets/Photo/MovePhotosRuleSet.php | 2 +- .../V1}/RuleSets/Photo/RotatePhotoRuleSet.php | 2 +- .../Photo/SetPhotoDescriptionRuleSet.php | 2 +- .../RuleSets/Photo/SetPhotoLicenseRuleSet.php | 2 +- .../Photo/SetPhotoUploadDateRuleSet.php | 2 +- .../Photo/SetPhotosStarredRuleSet.php | 2 +- .../RuleSets/Photo/SetPhotosTagsRuleSet.php | 2 +- .../RuleSets/Photo/SetPhotosTitleRuleSet.php | 2 +- .../V1}/RuleSets/Session/LoginRuleSet.php | 2 +- .../V1}/RuleSets/User/ChangeLoginRuleSet.php | 2 +- .../V1}/RuleSets/User/SetEmailRuleSet.php | 2 +- .../V1}/RuleSets/Users/AddUserRuleSet.php | 2 +- .../RuleSets/Users/SetUserSettingsRuleSet.php | 2 +- .../WebAuthn/DeleteCredentialRuleSet.php | 2 +- app/Livewire/Components/Base/ContextMenu.php | 78 - app/Livewire/Components/Base/Modal.php | 88 - .../Forms/Add/ImportFromDropbox.php | 44 - .../Components/Forms/Add/ImportFromServer.php | 53 - .../Components/Forms/Add/ImportFromUrl.php | 113 - app/Livewire/Components/Forms/Add/Upload.php | 177 - .../Components/Forms/Album/AddTrack.php | 105 - .../Components/Forms/Album/Create.php | 102 - .../Components/Forms/Album/CreateTag.php | 104 - .../Components/Forms/Album/Delete.php | 101 - .../Components/Forms/Album/DeletePanel.php | 89 - .../Components/Forms/Album/DeleteTrack.php | 88 - app/Livewire/Components/Forms/Album/Merge.php | 134 - app/Livewire/Components/Forms/Album/Move.php | 127 - .../Components/Forms/Album/MovePanel.php | 111 - .../Components/Forms/Album/Properties.php | 207 - .../Components/Forms/Album/Rename.php | 93 - .../Components/Forms/Album/SetHeader.php | 99 - .../Components/Forms/Album/ShareWith.php | 159 - .../Components/Forms/Album/ShareWithLine.php | 83 - .../Components/Forms/Album/Transfer.php | 121 - .../Components/Forms/Album/UnlockAlbum.php | 84 - .../Components/Forms/Album/Visibility.php | 188 - .../Components/Forms/Confirms/SaveAll.php | 47 - .../Components/Forms/Photo/CopyTo.php | 124 - .../Components/Forms/Photo/Delete.php | 95 - .../Components/Forms/Photo/Download.php | 69 - app/Livewire/Components/Forms/Photo/Move.php | 116 - .../Components/Forms/Photo/Rename.php | 83 - app/Livewire/Components/Forms/Photo/Tag.php | 95 - .../Components/Forms/Profile/GetApiToken.php | 111 - .../Forms/Profile/ManageSecondFactor.php | 92 - .../Components/Forms/Profile/Oauth.php | 80 - .../Components/Forms/Profile/SecondFactor.php | 65 - .../Components/Forms/Profile/SetEmail.php | 67 - .../Components/Forms/Profile/SetLogin.php | 92 - .../Base/BaseConfigDoubleDropDown.php | 95 - .../Settings/Base/BaseConfigDropDown.php | 69 - .../Forms/Settings/Base/BooleanSetting.php | 77 - .../Forms/Settings/Base/PasswordSetting.php | 24 - .../Forms/Settings/Base/StringSetting.php | 76 - .../SetAlbumDecorationOrientationSetting.php | 34 - .../Settings/SetAlbumDecorationSetting.php | 34 - .../Forms/Settings/SetAlbumSortingSetting.php | 56 - .../Forms/Settings/SetLangSetting.php | 35 - .../Forms/Settings/SetLayoutSetting.php | 34 - .../Settings/SetLicenseDefaultSetting.php | 34 - .../Forms/Settings/SetMapProviderSetting.php | 39 - .../Forms/Settings/SetPhotoOverlaySetting.php | 34 - .../Forms/Settings/SetPhotoSortingSetting.php | 56 - app/Livewire/Components/Menus/AlbumAdd.php | 127 - .../Components/Menus/AlbumDropdown.php | 68 - .../Components/Menus/AlbumsDropdown.php | 61 - app/Livewire/Components/Menus/LeftMenu.php | 137 - .../Components/Menus/PhotoDropdown.php | 139 - .../Components/Menus/PhotosDropdown.php | 102 - app/Livewire/Components/Modals/About.php | 56 - app/Livewire/Components/Modals/Login.php | 129 - .../Diagnostics/AbstractPreSection.php | 46 - .../Modules/Diagnostics/Configurations.php | 18 - .../Components/Modules/Diagnostics/Errors.php | 73 - .../Components/Modules/Diagnostics/Infos.php | 18 - .../Components/Modules/Diagnostics/Space.php | 54 - .../Components/Modules/Jobs/Feedback.php | 86 - .../Modules/Maintenance/Cleaning.php | 116 - .../Modules/Maintenance/FixTree.php | 62 - .../Modules/Maintenance/GenSizeVariants.php | 137 - .../Modules/Maintenance/MissingFileSizes.php | 93 - .../Modules/Maintenance/Optimize.php | 45 - .../Components/Modules/Maintenance/Update.php | 102 - .../Components/Modules/Users/UserLine.php | 110 - app/Livewire/Components/Pages/AllSettings.php | 75 - app/Livewire/Components/Pages/Diagnostics.php | 34 - app/Livewire/Components/Pages/Frame.php | 128 - .../Components/Pages/Gallery/Album.php | 269 -- .../Components/Pages/Gallery/Albums.php | 131 - .../Pages/Gallery/BaseAlbumComponent.php | 170 - .../Components/Pages/Gallery/Search.php | 173 - .../Pages/Gallery/SensitiveWarning.php | 60 - app/Livewire/Components/Pages/Jobs.php | 59 - app/Livewire/Components/Pages/Landing.php | 43 - app/Livewire/Components/Pages/Login.php | 52 - app/Livewire/Components/Pages/Maintenance.php | 35 - app/Livewire/Components/Pages/Map.php | 91 - app/Livewire/Components/Pages/Profile.php | 58 - app/Livewire/Components/Pages/Settings.php | 97 - app/Livewire/Components/Pages/Sharing.php | 76 - app/Livewire/Components/Pages/Users.php | 122 - app/Livewire/DTO/AlbumFlags.php | 35 - app/Livewire/DTO/AlbumRights.php | 52 - app/Livewire/DTO/AlbumsFlags.php | 41 - app/Livewire/DTO/Layouts.php | 30 - app/Livewire/DTO/OauthData.php | 22 - app/Livewire/DTO/PhotoFlags.php | 22 - app/Livewire/DTO/ProtectedCollection.php | 52 - app/Livewire/DTO/SessionFlags.php | 34 - app/Livewire/Forms/AllConfigsForms.php | 76 - app/Livewire/Forms/ImportFromUrlForm.php | 77 - app/Livewire/Forms/PhotoUpdateForm.php | 106 - app/Livewire/Synth/AlbumFlagsSynth.php | 80 - app/Livewire/Synth/AlbumSynth.php | 42 - app/Livewire/Synth/PhotoSynth.php | 38 - app/Livewire/Synth/SessionFlagsSynth.php | 81 - .../Traits/AlbumsPhotosContextMenus.php | 89 - .../Traits/InteractWithContextMenu.php | 18 - app/Livewire/Traits/InteractWithModal.php | 45 - app/Livewire/Traits/Notify.php | 24 - app/Livewire/Traits/SilentUpdate.php | 23 - app/Livewire/Traits/UseOpenable.php | 47 - app/Livewire/Traits/UsePhotoViewActions.php | 145 - app/Livewire/Traits/UseValidator.php | 37 - app/Livewire/Traits/UseWireable.php | 54 - app/Metadata/Extractor.php | 6 + app/Metadata/Json/JsonRequestFunctions.php | 14 +- app/Metadata/RateLimiterStore.php | 25 - app/Metadata/Versions/GitHubVersion.php | 10 +- app/Metadata/Versions/InstalledVersion.php | 2 + .../Versions/Remote/AbstractGitRemote.php | 2 + app/ModelFunctions/MOVFormat.php | 3 + app/Models/AccessPermission.php | 7 +- app/Models/Album.php | 31 +- app/Models/BaseAlbumImpl.php | 10 +- app/Models/Builders/AlbumBuilder.php | 4 +- app/Models/Builders/TagAlbumBuilder.php | 2 +- app/Models/Configs.php | 52 +- app/Models/Extensions/BaseAlbum.php | 10 +- app/Models/Extensions/BaseConfigMigration.php | 1 + .../ForwardsToParentImplementation.php | 10 +- .../HasBidirectionalRelationships.php | 2 +- .../HasRandomIDAndLegacyTimeBasedID.php | 2 +- app/Models/Extensions/SizeVariants.php | 2 +- app/Models/Extensions/Thumb.php | 48 +- app/Models/JobHistory.php | 3 +- app/Models/OauthCredential.php | 2 +- app/Models/Photo.php | 19 +- app/Models/SizeVariant.php | 35 +- app/Models/SymLink.php | 4 +- app/Models/TagAlbum.php | 5 +- app/Models/User.php | 15 +- app/Policies/AlbumPolicy.php | 20 + app/Policies/AlbumQueryPolicy.php | 113 +- app/Policies/PhotoQueryPolicy.php | 59 + app/Policies/SettingsPolicy.php | 16 +- app/Providers/AppServiceProvider.php | 33 +- app/Providers/RouteServiceProvider.php | 32 +- app/Relations/BaseHasManyPhotos.php | 23 +- app/Relations/HasAlbumThumb.php | 7 +- app/Relations/HasManyBidirectionally.php | 11 +- app/Relations/HasManyChildAlbums.php | 3 +- app/Relations/HasManyChildPhotos.php | 4 +- app/Relations/HasManyPhotosByTag.php | 8 +- app/Relations/HasManyPhotosRecursively.php | 9 +- app/Relations/HasManySizeVariants.php | 8 +- app/Rules/AlbumIDRule.php | 5 +- app/Rules/BooleanRequireSupportRule.php | 38 + app/Rules/ConfigKeyRequireSupportRule.php | 44 + app/Rules/ConfigKeyRule.php | 28 + app/Rules/ConfigValueRule.php | 67 + app/Rules/ExtensionRule.php | 96 + app/Rules/FileUuidRule.php | 88 + app/Rules/IntegerRequireSupportRule.php | 37 + app/Rules/StringRequireSupportRule.php | 38 + app/Services/Auth/SessionOrTokenGuard.php | 3 +- app/SmartAlbums/BaseSmartAlbum.php | 4 +- app/SmartAlbums/UnsortedAlbum.php | 17 + app/SmartAlbums/Utils/MimicModel.php | 49 - app/View/Components/BackButtonHeader.php | 43 - app/View/Components/Footer.php | 74 - .../Components/Gallery/Album/SharingLinks.php | 30 - .../Components/Gallery/Album/Thumbs/Album.php | 87 - .../Gallery/Album/Thumbs/AlbumThumb.php | 48 - .../Components/Gallery/Album/Thumbs/Photo.php | 180 - .../Components/Gallery/Photo/Download.php | 62 - app/View/Components/Meta.php | 74 +- codecov.yml | 11 +- composer.json | 20 +- composer.lock | 4070 ++++++++++++----- config/app.php | 11 +- config/cache.php | 2 +- config/data.php | 201 + config/database.php | 2 +- config/features.php | 18 +- config/feed.php | 2 +- config/filesystems.php | 18 +- config/livewire.php | 158 - config/log-viewer.php | 8 +- config/scramble.php | 50 - config/secure-headers.php | 4 +- config/session.php | 2 +- config/typescript-transformer.php | 86 + .../factories/AccessPermissionFactory.php | 134 + database/factories/PhotoFactory.php | 10 + database/factories/TagAlbumFactory.php | 44 + ...04_18_174417_fix_live_photo_short_path.php | 4 +- ...6_214241_thumb_min_max_take_date_order.php | 29 + ...2024_07_12_183751_add_auto_play_config.php | 21 + .../2024_07_26_120007_simplify_config.php | 26 + .../2024_07_29_172018_fix_settings.php | 33 + .../2024_08_09_205532_white_theme.php | 21 + .../2024_08_31_090626_config_help_popup.php | 28 + ..._description_always_hover_hidden_photo.php | 23 + .../2024_09_14_143949_add_settings_level.php | 31 + ...024_09_14_153948_fix_more_descriptions.php | 98 + ...2024_09_27_144741_add_supporter_fields.php | 49 + ...024_10_05_125328_add_slideshow_timeout.php | 22 + ...024_10_05_125833_lang_is_admin_setting.php | 21 + .../2024_10_05_184315_bump_version060000.php | 26 + ...4_10_09_191528_image_processing_backup.php | 22 + ...10_image_processing_details_and_others.php | 41 + ...2024_10_10_101333_set_dropbox_disabled.php | 32 + ..._10_11_173054_add_space_quota_per_user.php | 36 + ...1_173106_add_space_quota_configuration.php | 23 + .../2024_10_13_134419_oath_group_to_users.php | 25 + ...10_14_104644_show_nsfw_in_smart_albums.php | 23 + ...efine_text_enable_unsorted_smart_album.php | 21 + ...24_10_20_125449_move-socials-to-footer.php | 22 + ...0_20_173904_add_photo_layout_per_album.php | 30 + .../2024_10_23_222857_change_header.php | 22 + ...2024_10_23_225332_warning_html_content.php | 21 + .../NestedSetForAlbums_AlbumModel.php | 4 +- .../RefactorAlbumModel_AlbumModel.php | 4 +- developer-notes.md | 16 + lang/en/lychee.php | 2 +- package-lock.json | 1688 +++++-- package.json | 36 +- phpstan.neon | 74 +- phpunit.ci.xml | 52 + phpunit.xml | 13 +- postcss.config.js | 2 +- public/.htaccess | 2 +- public/dist/custom.js | 0 public/installer/assets/css/style.css | 6 +- resources/css/app.css | 145 - resources/js/app.ts | 106 +- .../diagnostics/ConfigurationsDiagnostics.vue | 21 + .../diagnostics/ErrorsDiagnostics.vue | 40 + .../diagnostics/InfoDiagnostics.vue | 21 + .../diagnostics/SpaceDiagnostics.vue | 24 + resources/js/components/drawers/AlbumEdit.vue | 99 + .../js/components/drawers/AlbumStatistics.vue | 116 + .../js/components/drawers/PhotoDetails.vue | 120 + resources/js/components/drawers/PhotoEdit.vue | 141 + .../js/components/footers/GalleryFooter.vue | 73 + .../js/components/footers/LandingFooter.vue | 64 + .../forms/album/AlbumCreateDialog.vue | 75 + .../forms/album/AlbumCreateTagDialog.vue | 92 + .../js/components/forms/album/AlbumDelete.vue | 41 + .../js/components/forms/album/AlbumMove.vue | 63 + .../forms/album/AlbumProperties.vue | 399 ++ .../js/components/forms/album/AlbumShare.vue | 67 + .../components/forms/album/AlbumTransfer.vue | 59 + .../forms/album/AlbumVisibility.vue | 148 + .../forms/album/SearchTargetAlbum.vue | 71 + .../forms/album/SearchTargetUser.vue | 78 + .../js/components/forms/album/Unlock.vue | 71 + .../components/forms/basic/InputPassword.vue | 35 + .../js/components/forms/basic/InputText.vue | 37 + .../js/components/forms/basic/Password.vue | 221 + .../js/components/forms/basic/Textarea.vue | 38 + .../gallery-dialogs/AlbumMergeDialog.vue | 110 + .../forms/gallery-dialogs/DeleteDialog.vue | 109 + .../forms/gallery-dialogs/MoveDialog.vue | 169 + .../forms/gallery-dialogs/RenameDialog.vue | 82 + .../forms/photo/PhotoCopyDialog.vue | 109 + .../components/forms/photo/PhotoTagDialog.vue | 100 + .../js/components/forms/profile/ApiToken.vue | 102 + .../js/components/forms/profile/SetLogin.vue | 136 + .../js/components/forms/profile/SetOauth.vue | 81 + .../forms/profile/SetSecondFactor.vue | 66 + .../forms/profile/SetSecondFactorLine.vue | 67 + .../js/components/forms/search/SearchBox.vue | 53 + .../components/forms/settings/BoolField.vue | 56 + .../components/forms/settings/NumberField.vue | 69 + .../js/components/forms/settings/OldField.vue | 52 + .../components/forms/settings/ResetField.vue | 3 + .../components/forms/settings/SelectField.vue | 48 + .../components/forms/settings/SelectLang.vue | 51 + .../forms/settings/SelectOptionsField.vue | 65 + .../components/forms/settings/SliderField.vue | 40 + .../components/forms/settings/StringField.vue | 56 + .../forms/settings/ZipSliderField.vue | 42 + .../forms/sharing/CreateSharing.vue | 89 + .../js/components/forms/sharing/ShareLine.vue | 83 + .../forms/upload/DropBoxChooser.vue | 84 + .../components/forms/upload/UploadingLine.vue | 158 + .../components/forms/users/CreateEditUser.vue | 171 + .../js/components/forms/users/ListUser.vue | 118 + resources/js/components/gallery/AlbumHero.vue | 103 + .../js/components/gallery/AlbumThumbPanel.vue | 55 + .../js/components/gallery/PhotoThumbPanel.vue | 62 + .../components/gallery/SensitiveWarning.vue | 24 + .../components/gallery/photo/DockButton.vue | 18 + .../components/gallery/photo/MapInclude.vue | 43 + .../components/gallery/photo/NextPrevious.vue | 33 + .../js/components/gallery/photo/Overlay.vue | 34 + .../components/gallery/thumbs/AlbumThumb.vue | 90 + .../gallery/thumbs/AlbumThumbDecorations.vue | 50 + .../gallery/thumbs/AlbumThumbImage.vue | 67 + .../gallery/thumbs/AlbumThumbOverlay.vue | 53 + .../components/gallery/thumbs/PhotoThumb.vue | 98 + .../components/gallery/thumbs/ThumbBadge.vue | 23 + .../js/components/headers/AlbumHeader.vue | 207 + .../js/components/headers/AlbumsHeader.vue | 295 ++ .../js/components/headers/BackLinkButton.vue | 17 + .../js/components/headers/OpenLeftMenu.vue | 12 + .../js/components/headers/PhotoHeader.vue | 116 + resources/js/components/icons/MiniIcon.vue | 18 + resources/js/components/icons/SETag.vue | 13 + .../maintenance/MaintenanceCleaning.vue | 72 + .../maintenance/MaintenanceFilesize.vue | 67 + .../maintenance/MaintenanceFixJobs.vue | 67 + .../maintenance/MaintenanceFixTree.vue | 67 + .../MaintenanceGenSizevariants.vue | 94 + .../maintenance/MaintenanceOptimize.vue | 53 + .../maintenance/MaintenanceUpdate.vue | 73 + .../js/components/modals/AboutLychee.vue | 94 + .../js/components/modals/DownloadPhoto.vue | 58 + resources/js/components/modals/DropBox.vue | 49 + .../js/components/modals/ImportFromLink.vue | 63 + .../js/components/modals/ImportFromServer.vue | 41 + .../js/components/modals/KeybindingsHelp.vue | 142 + resources/js/components/modals/LoginModal.vue | 129 + .../js/components/modals/RegisterLychee.vue | 91 + resources/js/components/modals/ShareAlbum.vue | 81 + .../js/components/modals/UploadPanel.vue | 213 + .../js/components/modals/WebauthnModal.vue | 67 + .../js/components/settings/AllSettings.vue | 289 ++ .../js/components/settings/EasySettings.vue | 425 ++ .../js/components/statistics/AlbumsTable.vue | 78 + .../statistics/SizeVariantMeter.vue | 84 + .../js/components/statistics/TotalCard.vue | 29 + .../js/composables/album/albumRefresher.ts | 85 + .../js/composables/album/albumStatistics.ts | 109 + .../js/composables/album/albumsRefresher.ts | 87 + .../js/composables/album/searchRefresher.ts | 86 + .../js/composables/album/uploadEvents.ts | 81 + .../composables/contextMenus/contextMenu.ts | 351 ++ .../contextMenus/contextMenuAlbumAdd.ts | 90 + .../contextMenus/contextMenuAlbumsAdd.ts | 68 + .../modalsTriggers/galleryModals.ts | 91 + resources/js/composables/photo/basePhoto.ts | 105 + resources/js/composables/photo/slideshow.ts | 88 + .../js/composables/preview/getPreviewInfo.ts | 65 + .../js/composables/selections/selections.ts | 220 + resources/js/config/axios-config.ts | 68 + resources/js/config/constants.ts | 147 + resources/js/config/csrf-getter.ts | 66 + resources/js/data/panel/index.ts | 14 - resources/js/data/panel/photoFormPanel.ts | 69 - resources/js/data/panel/photoListingPanel.ts | 25 - resources/js/data/panel/photoSidebarPanel.ts | 41 - resources/js/data/panel/searchPanel.ts | 40 - resources/js/data/qrcode/qrBuilder.ts | 23 - resources/js/data/views/albumView.ts | 343 -- resources/js/data/views/dropboxView.ts | 39 - resources/js/data/views/index.ts | 16 - resources/js/data/views/map.types.d.ts | 38 - resources/js/data/views/mapView.ts | 198 - resources/js/data/views/photoView.ts | 139 - resources/js/data/views/types.d.ts | 176 - resources/js/data/views/uploadView.ts | 107 - resources/js/data/webauthn/index.ts | 10 - resources/js/data/webauthn/loginWebAuthn.ts | 75 - .../js/data/webauthn/registerWebAuthn.ts | 46 - resources/js/global.d.ts | 10 - resources/js/layouts/PhotoLayout.ts | 43 + .../js/{lycheeOrg => }/layouts/types.d.ts | 0 .../js/{lycheeOrg => }/layouts/useGrid.ts | 1 - .../js/{lycheeOrg => }/layouts/useJustify.ts | 15 +- .../js/{lycheeOrg => }/layouts/useMasonry.ts | 1 - .../js/{lycheeOrg => }/layouts/useSquare.ts | 0 resources/js/lychee.d.ts | 611 +++ .../js/lycheeOrg/actions/albumActions.ts | 66 - resources/js/lycheeOrg/actions/keybindings.ts | 237 - resources/js/lycheeOrg/actions/selection.ts | 239 - .../js/lycheeOrg/actions/swipeActions.ts | 75 - resources/js/lycheeOrg/backend.d.ts | 458 -- resources/js/lycheeOrg/flags/albumFlags.ts | 13 - resources/js/lycheeOrg/flags/photoFlags.ts | 36 - resources/js/lycheeOrg/layouts/PhotoLayout.ts | 48 - resources/js/menus/LeftMenu.vue | 265 ++ resources/js/router/routes.ts | 125 + resources/js/services/album-service.ts | 166 + resources/js/services/auth-service.ts | 35 + resources/js/services/constants.ts | 27 + resources/js/services/diagnostics-service.ts | 34 + resources/js/services/init-service.ts | 25 + resources/js/services/jobs-service.ts | 18 + resources/js/services/maintenance-service.ts | 56 + resources/js/services/oauth-service.ts | 37 + resources/js/services/photo-service.ts | 70 + resources/js/services/profile-service.ts | 24 + resources/js/services/search-service.ts | 21 + resources/js/services/settings-service.ts | 32 + resources/js/services/sharing-service.ts | 45 + .../sidebarMap.ts => services/sidebar-map.ts} | 55 +- resources/js/services/statistics-service.ts | 19 + resources/js/services/upload-service.ts | 43 + .../js/services/user-management-service.ts | 36 + resources/js/services/users-service.ts | 25 + resources/js/services/webauthn-service.ts | 58 + resources/js/stores/Auth.ts | 30 + resources/js/stores/LycheeState.ts | 146 + resources/js/style/preset-full.ts | 3608 +++++++++++++++ resources/js/style/preset.ts | 968 ++++ .../js/utils/StatsSizeVariantToColours.ts | 42 + resources/js/utils/keybindings-utils.ts | 78 + resources/js/vendor/webauthn/webauthn.ts | 4 - resources/js/views/App.vue | 27 + resources/js/views/Diagnostics.vue | 39 + resources/js/views/Error.vue | 106 + resources/js/views/Jobs.vue | 63 + resources/js/views/Landing.vue | 92 + resources/js/views/Maintenance.vue | 43 + resources/js/views/Permissions.vue | 50 + resources/js/views/Profile.vue | 26 + resources/js/views/Settings.vue | 42 + resources/js/views/Sharing.vue | 65 + resources/js/views/Statistics.vue | 70 + resources/js/views/Users.vue | 118 + resources/js/views/gallery-panels/Album.vue | 400 ++ resources/js/views/gallery-panels/Albums.vue | 241 + resources/js/views/gallery-panels/Frame.vue | 70 + resources/js/views/gallery-panels/Map.vue | 278 ++ resources/js/views/gallery-panels/Photo.vue | 345 ++ resources/js/views/gallery-panels/Search.vue | 327 ++ resources/sass/app.scss | 141 + resources/{css => sass}/fonts.css | 0 .../components/context-menu/item.blade.php | 8 - .../context-menu/separator.blade.php | 1 - .../views/components/footer-landing.blade.php | 25 - resources/views/components/footer.blade.php | 40 - .../components/forms/buttons/action.blade.php | 7 - .../components/forms/buttons/cancel.blade.php | 7 - .../components/forms/buttons/create.blade.php | 7 - .../components/forms/buttons/danger.blade.php | 7 - .../components/forms/defaulttickbox.blade.php | 7 - .../views/components/forms/dropdown.blade.php | 12 - .../components/forms/error-message.blade.php | 4 - .../components/forms/inputs/date.blade.php | 6 - .../forms/inputs/important.blade.php | 7 - .../forms/inputs/password.blade.php | 15 - .../components/forms/inputs/text.blade.php | 7 - .../views/components/forms/textarea.blade.php | 3 - .../views/components/forms/tickbox.blade.php | 9 - .../views/components/forms/toggle.blade.php | 6 - .../gallery/album/details.blade.php | 49 - .../components/gallery/album/hero.blade.php | 15 - .../gallery/album/login-dialog.blade.php | 10 - .../gallery/album/menu/danger.blade.php | 8 - .../gallery/album/menu/item.blade.php | 10 - .../gallery/album/menu/menu.blade.php | 47 - .../gallery/album/sharing-links.blade.php | 35 - .../album/thumbs/album-thumb.blade.php | 16 - .../gallery/album/thumbs/album.blade.php | 92 - .../gallery/album/thumbs/photo.blade.php | 47 - .../views/components/gallery/badge.blade.php | 8 - .../components/gallery/divider.blade.php | 4 - .../components/gallery/photo/button.blade.php | 4 - .../gallery/photo/downloads.blade.php | 20 - .../components/gallery/photo/line.blade.php | 7 - .../gallery/photo/next-previous.blade.php | 14 - .../gallery/photo/overlay.blade.php | 20 - .../gallery/photo/properties.blade.php | 45 - .../gallery/photo/sidebar.blade.php | 117 - .../gallery/view/photo-listing.blade.php | 25 - .../components/gallery/view/photo.blade.php | 130 - .../components/header/actions-menus.blade.php | 34 - .../components/header/back-button.blade.php | 3 - .../views/components/header/back.blade.php | 3 - .../views/components/header/bar.blade.php | 7 - .../views/components/header/button.blade.php | 4 - .../views/components/header/title.blade.php | 5 - .../views/components/help/cell.blade.php | 2 - .../views/components/help/head.blade.php | 1 - resources/views/components/help/kbd.blade.php | 1 - .../views/components/help/table.blade.php | 3 - .../views/components/icons/iconic.blade.php | 2 - .../views/components/layouts/app.blade.php | 25 - .../leftbar/disabled-leftbar-item.blade.php | 10 - .../components/leftbar/leftbar-item.blade.php | 11 - .../components/maintenance/button.blade.php | 4 - .../components/maintenance/card.blade.php | 4 - .../views/components/maintenance/h1.blade.php | 3 - .../components/maintenance/loading.blade.php | 1 - .../views/components/maintenance/p.blade.php | 4 - resources/views/components/meta.blade.php | 13 +- .../views/components/notifications.blade.php | 71 - .../views/components/shortcuts.blade.php | 116 - .../views/components/update-status.blade.php | 3 - .../views/components/webauthn/login.blade.php | 30 - resources/views/install/env.blade.php | 23 +- .../views/install/setup-success.blade.php | 2 +- .../components/context-menu.blade.php | 16 - .../livewire/components/left-menu.blade.php | 80 - .../views/livewire/components/modal.blade.php | 22 - .../context-menus/album-add.blade.php | 22 - .../context-menus/album-dropdown.blade.php | 10 - .../context-menus/albums-dropdown.blade.php | 7 - .../context-menus/photo-dropdown.blade.php | 22 - .../context-menus/photos-add.blade.php | 15 - .../context-menus/photos-dropdown.blade.php | 14 - .../livewire/forms/add/create-tag.blade.php | 23 - .../views/livewire/forms/add/create.blade.php | 19 - .../forms/add/import-from-dropbox.blade.php | 30 - .../forms/add/import-from-server.blade.php | 15 - .../add/import-from-server.old.blade.php | 47 - .../forms/add/import-from-url.blade.php | 19 - .../views/livewire/forms/add/upload.blade.php | 98 - .../livewire/forms/album/add-track.blade.php | 27 - .../forms/album/delete-panel.blade.php | 6 - .../forms/album/delete-track.blade.php | 16 - .../livewire/forms/album/delete.blade.php | 22 - .../livewire/forms/album/merge.blade.php | 37 - .../livewire/forms/album/move-panel.blade.php | 15 - .../views/livewire/forms/album/move.blade.php | 37 - .../livewire/forms/album/properties.blade.php | 49 - .../livewire/forms/album/rename.blade.php | 21 - .../forms/album/search-album.blade.php | 49 - .../livewire/forms/album/set-header.blade.php | 61 - .../forms/album/share-with-line.blade.php | 20 - .../livewire/forms/album/share-with.blade.php | 114 - .../livewire/forms/album/transfer.blade.php | 11 - .../forms/album/unlock-album.blade.php | 36 - .../livewire/forms/album/visibility.blade.php | 52 - .../forms/confirms/save-all.blade.php | 11 - .../views/livewire/forms/default.blade.php | 29 - .../livewire/forms/photo/copyTo.blade.php | 16 - .../livewire/forms/photo/delete.blade.php | 21 - .../livewire/forms/photo/download.blade.php | 9 - .../views/livewire/forms/photo/move.blade.php | 16 - .../livewire/forms/photo/rename.blade.php | 23 - .../views/livewire/forms/photo/tag.blade.php | 29 - .../forms/profile/get-api-token.blade.php | 22 - .../profile/manage-second-factor.blade.php | 4 - .../livewire/forms/profile/oauth.blade.php | 40 - .../forms/profile/set-login.blade.php | 27 - .../forms/settings/double-drop-down.blade.php | 9 - .../forms/settings/drop-down.blade.php | 6 - .../livewire/forms/settings/input.blade.php | 9 - .../forms/settings/password.blade.php | 9 - .../livewire/forms/settings/toggle.blade.php | 11 - .../views/livewire/modals/about.blade.php | 27 - .../views/livewire/modals/login.blade.php | 60 - .../modules/diagnostics/pre-colored.blade.php | 11 - .../modules/diagnostics/pre.blade.php | 11 - .../diagnostics/with-action-call.blade.php | 19 - .../gallery/sensitive-warning.blade.php | 15 - .../livewire/modules/jobs/feedback.blade.php | 34 - .../modules/maintenance/cleaning.blade.php | 17 - .../fill-filesize-sizevariants.blade.php | 6 - .../modules/maintenance/fix-jobs.blade.php | 6 - .../modules/maintenance/fix-tree.blade.php | 11 - .../maintenance/gen-sizevariants.blade.php | 6 - .../modules/maintenance/optimize-db.blade.php | 14 - .../modules/maintenance/update.blade.php | 24 - .../modules/profile/second-factor.blade.php | 31 - .../modules/users/user-line.blade.php | 15 - .../livewire/pages/all-settings.blade.php | 52 - .../livewire/pages/diagnostics.blade.php | 14 - .../livewire/pages/gallery/album.blade.php | 73 - .../livewire/pages/gallery/albums.blade.php | 91 - .../livewire/pages/gallery/frame.blade.php | 40 - .../livewire/pages/gallery/map.blade.php | 22 - .../livewire/pages/gallery/search.blade.php | 85 - resources/views/livewire/pages/jobs.blade.php | 25 - .../views/livewire/pages/landing.blade.php | 51 - .../views/livewire/pages/login.blade.php | 31 - .../livewire/pages/maintenance.blade.php | 29 - .../views/livewire/pages/profile.blade.php | 21 - .../views/livewire/pages/settings.blade.php | 70 - .../views/livewire/pages/sharing.blade.php | 58 - .../views/livewire/pages/users.blade.php | 55 - .../vendor/livewire/simple-tailwind.blade.php | 45 - .../views/vendor/livewire/tailwind.blade.php | 171 - .../vendor/pagination/tailwind.blade.php | 148 - resources/views/vueapp.blade.php | 23 + routes/{api.php => api_v1.php} | 35 +- routes/api_v2.php | 225 + routes/{web-admin.php => web-admin-v1.php} | 0 routes/web-admin-v2.php | 19 + routes/web-livewire.php | 64 - routes/{web.php => web_v1.php} | 12 +- routes/web_v2.php | 68 + scripts/delete_legacy.sh | 44 + scripts/post-merge | 8 +- scripts/pre-commit | 2 +- sonar-project.properties | 8 + storage/livewire-tmp/.gitignore | 2 - .../{extract-jobs => tmp/extract}/.gitignore | 0 storage/{image-jobs => tmp/jobs}/.gitignore | 0 storage/{image-tmp => tmp/uploads}/.gitignore | 0 tailwind.config.js => tailwind.config.ts | 117 +- tests/AbstractTestCase.php | 4 +- tests/Constants/FreeVerifyier.php | 49 + tests/Constants/SupporterVerifyier.php | 49 + tests/Feature_v1/Base/BaseSharingTest.php | 2 +- .../Base/BaseSharingTestScenarios.php | 6 +- .../Base/BaseSharingWithNonAdminUser.php | 4 +- tests/Feature_v1/InstallTest.php | 14 +- .../LibUnitTests/AlbumsUnitTest.php | 46 +- .../LibUnitTests/AssertableZipArchive.php | 2 +- .../LibUnitTests/PhotosUnitTest.php | 42 +- .../LibUnitTests/RootAlbumUnitTest.php | 14 +- .../LibUnitTests/SessionUnitTest.php | 14 +- .../LibUnitTests/SharingUnitTest.php | 10 +- .../Feature_v1/LibUnitTests/UsersUnitTest.php | 40 +- tests/Feature_v1/LogsTest.php | 3 - tests/Feature_v1/OptimizeTest.php | 3 - tests/Feature_v1/PhotosAddMethodsTest.php | 6 +- tests/Feature_v1/RedirectTest.php | 6 +- tests/Feature_v1/SearchTest.php | 4 +- tests/Feature_v1/SharingSpecialTest.php | 4 +- tests/Feature_v1/SharingWithAnonUserTest.php | 4 +- .../SharingWithNonAdminUserTest.php | 4 +- tests/Feature_v1/UpdateTest.php | 3 - tests/Feature_v1/WebAuthTest.php | 2 - tests/Feature_v2/Album/AlbumDeleteTest.php | 57 + tests/Feature_v2/Album/AlbumListTest.php | 34 + tests/Feature_v2/Album/AlbumMoveTest.php | 72 + tests/Feature_v2/Album/AlbumRenameTest.php | 54 + tests/Feature_v2/Album/AlbumSetCoverTest.php | 90 + tests/Feature_v2/Album/AlbumSetHeaderTest.php | 156 + tests/Feature_v2/Album/AlbumTest.php | 96 + tests/Feature_v2/Album/AlbumTransferTest.php | 50 + tests/Feature_v2/Album/AlbumUpdateTest.php | 338 ++ tests/Feature_v2/Album/AlbumsTest.php | 165 + tests/Feature_v2/Album/ConfigTest.php | 30 + tests/Feature_v2/Album/SharingTest.php | 57 + tests/Feature_v2/AuthTest.php | 83 + tests/Feature_v2/Base/BaseApiV2Test.php | 124 + .../Base/BaseV2Test.php} | 84 +- tests/Feature_v2/Diagnostics/ConfigTest.php | 36 + tests/Feature_v2/Diagnostics/ErrorsTest.php | 24 + tests/Feature_v2/Diagnostics/InfoTest.php | 36 + .../Feature_v2/Diagnostics/PermissionTest.php | 36 + tests/Feature_v2/Diagnostics/SpaceTest.php | 36 + tests/Feature_v2/Frame/FrameTest.php | 39 + tests/Feature_v2/Jobs/GetJobTest.php | 36 + tests/Feature_v2/LandingTest.php | 24 + tests/Feature_v2/Maintenance/CleaningTest.php | 75 + .../Maintenance/GenSizeVariantsTest.php | 63 + tests/Feature_v2/Maintenance/JobsTest.php | 59 + .../Maintenance/MissingFileSizeTest.php | 45 + tests/Feature_v2/Maintenance/OptimizeTest.php | 30 + tests/Feature_v2/Maintenance/RegisterTest.php | 46 + tests/Feature_v2/Maintenance/TreeTest.php | 45 + tests/Feature_v2/Maintenance/UpdateTest.php | 45 + tests/Feature_v2/Map/MapTest.php | 36 + tests/Feature_v2/Oauth/OauthTest.php | 43 + tests/Feature_v2/PagesTest.php | 52 + tests/Feature_v2/Photo/PhotoRenameTest.php | 58 + tests/Feature_v2/Photo/PhotoTagsTest.php | 181 + tests/Feature_v2/ProfileTest.php | 130 + tests/Feature_v2/Search/SearchTest.php | 77 + .../Settings/GetAllSettingsTest.php | 54 + .../Settings/UpdateSettingsTest.php | 84 + .../Feature_v2/Statistics/AlbumSpaceTest.php | 54 + .../Statistics/SizeVariantSpaceTest.php | 47 + .../Statistics/TotalAlbumSpaceTest.php | 46 + tests/Feature_v2/Statistics/UserSpaceTest.php | 44 + .../UserManagement/CreateUserTest.php | 69 + .../UserManagement/DeleteUserTest.php | 49 + .../UserManagement/EditUserTest.php | 63 + .../UserManagement/ListUserTest.php | 71 + tests/Feature_v2/UsersTest.php | 42 + tests/Feature_v2/VersionTest.php | 24 + tests/Feature_v2/WebAuthTest.php | 453 ++ tests/Livewire/Forms/Album/CreateTagTest.php | 49 - tests/Livewire/Forms/Album/CreateTest.php | 113 - .../Livewire/Forms/Album/DeletePanelTest.php | 52 - tests/Livewire/Forms/Album/DeleteTest.php | 58 - tests/Livewire/Forms/Album/MergeMoveTest.php | 132 - tests/Livewire/Forms/Album/MovePanelTest.php | 66 - tests/Livewire/Forms/Album/PropertiesTest.php | 71 - tests/Livewire/Forms/Album/RenameTest.php | 61 - .../Livewire/Forms/Album/SearchAlbumTest.php | 138 - tests/Livewire/Forms/Album/ShareWithTest.php | 105 - tests/Livewire/Forms/Album/TransferTest.php | 70 - tests/Livewire/Forms/Album/VisibilityTest.php | 127 - tests/Livewire/Forms/ConfirmTest.php | 42 - tests/Livewire/Forms/FormsProfileTest.php | 198 - .../Livewire/Forms/ImportFromDropBoxTest.php | 63 - tests/Livewire/Forms/ImportFromServerTest.php | 47 - tests/Livewire/Forms/ImportFromUrlTest.php | 57 - tests/Livewire/Forms/Photo/CopyToTest.php | 68 - tests/Livewire/Forms/Photo/DeleteTest.php | 58 - tests/Livewire/Forms/Photo/DownloadTest.php | 53 - tests/Livewire/Forms/Photo/MoveTest.php | 68 - tests/Livewire/Forms/Photo/RenameTest.php | 61 - tests/Livewire/Forms/Photo/TagTest.php | 70 - tests/Livewire/Forms/Profile/OauthTest.php | 81 - tests/Livewire/Forms/SettingsTest.php | 89 - tests/Livewire/Forms/UploadTest.php | 90 - tests/Livewire/Menus/AlbumAddTest.php | 67 - tests/Livewire/Menus/AlbumDropdownTest.php | 85 - tests/Livewire/Menus/AlbumsDropdownTest.php | 86 - tests/Livewire/Menus/ContextMenuTest.php | 43 - tests/Livewire/Menus/LeftMenuTest.php | 37 - tests/Livewire/Menus/PhotoDropdownTest.php | 153 - tests/Livewire/Menus/PhotosDropdownTest.php | 119 - tests/Livewire/Modals/AboutTest.php | 30 - tests/Livewire/Modals/LoginTest.php | 39 - tests/Livewire/Modals/ModalTest.php | 46 - tests/Livewire/Modules/ErrorsTest.php | 47 - tests/Livewire/Modules/JobFeedbackTest.php | 48 - tests/Livewire/Modules/SpaceTest.php | 50 - tests/Livewire/Modules/UserLineTest.php | 69 - tests/Livewire/Pages/AlbumTest.php | 134 - tests/Livewire/Pages/AllSettingsTest.php | 59 - tests/Livewire/Pages/DiagnosticsTest.php | 57 - tests/Livewire/Pages/FrameTest.php | 104 - tests/Livewire/Pages/GalleryTest.php | 34 - tests/Livewire/Pages/IndexTest.php | 69 - tests/Livewire/Pages/JobsTest.php | 39 - tests/Livewire/Pages/LandingTest.php | 48 - tests/Livewire/Pages/LoginTest.php | 85 - tests/Livewire/Pages/MaintenanceTest.php | 49 - tests/Livewire/Pages/MapTest.php | 85 - tests/Livewire/Pages/ProfileTest.php | 45 - tests/Livewire/Pages/SearchTest.php | 99 - tests/Livewire/Pages/SettingsTest.php | 48 - tests/Livewire/Pages/SharingTest.php | 56 - tests/Livewire/Pages/UsersTest.php | 94 - tests/Livewire/WireableTest.php | 47 - tests/LoadedSubscriber.php | 7 + tests/MigrateApplication.php | 23 + tests/Traits/CatchFailures.php | 101 +- tests/Traits/RequireSupport.php | 30 + tests/Unit/CoverageTest.php | 53 + tests/Unit/FeaturesUnitTest.php | 55 + tests/{Feature_v1 => Unit}/GitRemoteTest.php | 2 +- .../{Feature_v1 => Unit}/HelpersUnitTest.php | 2 +- tests/{Feature_v1 => Unit}/HoneyPotTest.php | 18 +- tests/{Feature_v1 => Unit}/LangTest.php | 2 +- tests/Unit/Middleware/HasAdminUserTest.php | 47 + tests/Unit/Middleware/LoginRequiredTest.php | 55 + tests/Unit/Middleware/MigrationStatusTest.php | 67 + tests/Unit/Redirections/ToAdminSetterTest.php | 25 + tests/Unit/Redirections/ToHomeTest.php | 26 + tests/Unit/Redirections/ToMigrationTest.php | 26 + tests/{Feature_v1 => Unit}/RootTest.php | 2 +- tests/Unit/Rules/AlbumIDListRuleTest.php | 31 + tests/Unit/Rules/AlbumIDRuleTest.php | 31 + .../Rules/ConfigKeyRequireSupportRuleTest.php | 59 + tests/Unit/Rules/ConfigKeyRuleTest.php | 42 + tests/Unit/Rules/CurrentPasswordRuleTest.php | 28 + tests/Unit/Rules/ExtensionRuleTest.php | 100 + tests/Unit/Rules/FileUuidRuleTest.php | 80 + tests/Unit/Rules/RandomIDListRuleTest.php | 29 + tests/Unit/Rules/RequireSupportRuleTest.php | 108 + tests/Unit/Rules/StringRuleTest.php | 28 + .../VersionDTOUnitTest.php | 2 +- tsconfig.json | 2 +- version.md | 2 +- vite.config.js | 29 - vite.config.ts | 69 + 1227 files changed, 43934 insertions(+), 25512 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/.env.mariadb create mode 100644 .github/workflows/.env.postgresql create mode 100644 .github/workflows/.env.sqlite create mode 100644 .github/workflows/CICD_no_legacy.yml delete mode 100644 .github/workflows/dependency-check.yml create mode 100644 .github/workflows/php_no_legacy_dist.yml create mode 100644 .github/workflows/php_no_legacy_tests.yml rename app/{Livewire/Components/Forms/Album/SearchAlbum.php => Actions/Album/ListAlbums.php} (65%) create mode 100644 app/Actions/Album/SetHeader.php create mode 100644 app/Actions/Album/SetSmartProtectionPolicy.php create mode 100644 app/Actions/Album/Transfer.php create mode 100644 app/Actions/Diagnostics/Pipes/Checks/SupporterCheck.php create mode 100644 app/Actions/Photo/Pipes/Standalone/ReplaceOriginalWithBackup.php create mode 100644 app/Actions/Profile/UpdateLogin.php delete mode 100644 app/Actions/Sharing/ListedAlbum.php create mode 100644 app/Actions/Sharing/Share.php delete mode 100644 app/Actions/Sharing/SharedAlbum.php delete mode 100644 app/Actions/Sharing/UserShared.php create mode 100644 app/Actions/Statistics/Spaces.php create mode 100644 app/Console/Commands/Laravel/LangFilesToJson.php create mode 100644 app/Contracts/Http/Requests/HasAbstractAlbum.php create mode 100644 app/Contracts/Http/Requests/HasAccessPermission.php create mode 100644 app/Contracts/Http/Requests/HasAccessPermissionResource.php create mode 100644 app/Contracts/Http/Requests/HasAlbum.php create mode 100644 app/Contracts/Http/Requests/HasAlbumId.php create mode 100644 app/Contracts/Http/Requests/HasAlbumIds.php create mode 100644 app/Contracts/Http/Requests/HasAlbumSortingCriterion.php create mode 100644 app/Contracts/Http/Requests/HasAlbums.php create mode 100644 app/Contracts/Http/Requests/HasBaseAlbum.php create mode 100644 app/Contracts/Http/Requests/HasCompactBoolean.php create mode 100644 app/Contracts/Http/Requests/HasConfigs.php create mode 100644 app/Contracts/Http/Requests/HasCopyright.php create mode 100644 app/Contracts/Http/Requests/HasDescription.php create mode 100644 app/Contracts/Http/Requests/HasLicense.php create mode 100644 app/Contracts/Http/Requests/HasNote.php create mode 100644 app/Contracts/Http/Requests/HasOwnerId.php create mode 100644 app/Contracts/Http/Requests/HasParentAlbum.php create mode 100644 app/Contracts/Http/Requests/HasPassword.php create mode 100644 app/Contracts/Http/Requests/HasPhoto.php create mode 100644 app/Contracts/Http/Requests/HasPhotoIds.php create mode 100644 app/Contracts/Http/Requests/HasPhotoLayout.php create mode 100644 app/Contracts/Http/Requests/HasPhotoSortingCriterion.php create mode 100644 app/Contracts/Http/Requests/HasPhotos.php create mode 100644 app/Contracts/Http/Requests/HasQuotaKB.php create mode 100644 app/Contracts/Http/Requests/HasSeStatusBoolean.php create mode 100644 app/Contracts/Http/Requests/HasSizeVariant.php create mode 100644 app/Contracts/Http/Requests/HasTagAlbum.php create mode 100644 app/Contracts/Http/Requests/HasTags.php create mode 100644 app/Contracts/Http/Requests/HasTerms.php create mode 100644 app/Contracts/Http/Requests/HasTitle.php create mode 100644 app/Contracts/Http/Requests/HasUploadDate.php create mode 100644 app/Contracts/Http/Requests/HasUser.php create mode 100644 app/Contracts/Http/Requests/HasUserId.php create mode 100644 app/Contracts/Http/Requests/HasUserIds.php create mode 100644 app/Contracts/Http/Requests/HasUsername.php create mode 100644 app/Contracts/Http/Requests/RequestAttribute.php delete mode 100644 app/Contracts/Livewire/Openable.php delete mode 100644 app/Contracts/Livewire/Params.php delete mode 100644 app/Contracts/Livewire/Reloadable.php create mode 100644 app/Enum/AspectRatioCSSType.php create mode 100644 app/Enum/ConfigType.php create mode 100644 app/Enum/DateOrderingType.php rename app/Enum/{Livewire => }/FileStatus.php (86%) delete mode 100644 app/Enum/Livewire/NotificationType.php delete mode 100644 app/Enum/Traits/WireableEnumTrait.php create mode 100644 app/Exceptions/QuotaExceededException.php create mode 100644 app/Http/Controllers/Admin/DiagnosticsController.php create mode 100644 app/Http/Controllers/Admin/JobsController.php create mode 100644 app/Http/Controllers/Admin/Maintenance/Cleaning.php rename app/{Livewire/Components/Modules => Http/Controllers/Admin}/Maintenance/FixJobs.php (55%) create mode 100644 app/Http/Controllers/Admin/Maintenance/FixTree.php create mode 100644 app/Http/Controllers/Admin/Maintenance/GenSizeVariants.php create mode 100644 app/Http/Controllers/Admin/Maintenance/MissingFileSizes.php create mode 100644 app/Http/Controllers/Admin/Maintenance/Model/Album.php create mode 100644 app/Http/Controllers/Admin/Maintenance/Optimize.php create mode 100644 app/Http/Controllers/Admin/Maintenance/RegisterController.php create mode 100644 app/Http/Controllers/Admin/SettingsController.php create mode 100644 app/Http/Controllers/Admin/UpdateController.php create mode 100644 app/Http/Controllers/Admin/UserManagementController.php create mode 100644 app/Http/Controllers/AuthController.php create mode 100644 app/Http/Controllers/Gallery/AlbumController.php create mode 100644 app/Http/Controllers/Gallery/AlbumsController.php create mode 100644 app/Http/Controllers/Gallery/ConfigController.php create mode 100644 app/Http/Controllers/Gallery/FrameController.php create mode 100644 app/Http/Controllers/Gallery/MapController.php create mode 100644 app/Http/Controllers/Gallery/PhotoController.php create mode 100644 app/Http/Controllers/Gallery/SearchController.php create mode 100644 app/Http/Controllers/Gallery/SharingController.php create mode 100644 app/Http/Controllers/LandingPageController.php delete mode 100644 app/Http/Controllers/Oauth.php create mode 100644 app/Http/Controllers/OauthController.php create mode 100644 app/Http/Controllers/ProfileController.php create mode 100644 app/Http/Controllers/RSSController.php create mode 100644 app/Http/Controllers/StatisticsController.php create mode 100644 app/Http/Controllers/UsersController.php create mode 100644 app/Http/Controllers/VersionController.php create mode 100644 app/Http/Controllers/VueController.php create mode 100644 app/Http/Middleware/CacheControl.php delete mode 100644 app/Http/Middleware/QueryStringFixer.php create mode 100644 app/Http/Requests/Album/AddAlbumRequest.php create mode 100644 app/Http/Requests/Album/AddTagAlbumRequest.php create mode 100644 app/Http/Requests/Album/DeleteAlbumsRequest.php create mode 100644 app/Http/Requests/Album/DeleteTrackRequest.php create mode 100644 app/Http/Requests/Album/GetAlbumRequest.php create mode 100644 app/Http/Requests/Album/MergeAlbumsRequest.php create mode 100644 app/Http/Requests/Album/MoveAlbumsRequest.php create mode 100644 app/Http/Requests/Album/RenameAlbumRequest.php create mode 100644 app/Http/Requests/Album/SetAlbumProtectionPolicyRequest.php create mode 100644 app/Http/Requests/Album/SetAlbumTrackRequest.php create mode 100644 app/Http/Requests/Album/SetAsCoverRequest.php create mode 100644 app/Http/Requests/Album/SetAsHeaderRequest.php create mode 100644 app/Http/Requests/Album/TargetListAlbumRequest.php create mode 100644 app/Http/Requests/Album/TransferAlbumRequest.php create mode 100644 app/Http/Requests/Album/UnlockAlbumRequest.php create mode 100644 app/Http/Requests/Album/UpdateAlbumRequest.php create mode 100644 app/Http/Requests/Album/UpdateTagAlbumRequest.php create mode 100644 app/Http/Requests/Album/ZipRequest.php create mode 100644 app/Http/Requests/Diagnostics/DiagnosticsRequest.php create mode 100644 app/Http/Requests/Frame/FrameRequest.php create mode 100644 app/Http/Requests/Jobs/ShowJobsRequest.php create mode 100644 app/Http/Requests/Maintenance/CleaningRequest.php create mode 100644 app/Http/Requests/Maintenance/CreateThumbsRequest.php create mode 100644 app/Http/Requests/Maintenance/MaintenanceRequest.php create mode 100644 app/Http/Requests/Maintenance/MigrateRequest.php create mode 100644 app/Http/Requests/Maintenance/RegisterRequest.php create mode 100644 app/Http/Requests/Maintenance/UpdateRequest.php create mode 100644 app/Http/Requests/Map/MapDataRequest.php create mode 100644 app/Http/Requests/Photo/CopyPhotosRequest.php create mode 100644 app/Http/Requests/Photo/DeletePhotosRequest.php create mode 100644 app/Http/Requests/Photo/EditPhotoRequest.php create mode 100644 app/Http/Requests/Photo/FromUrlRequest.php create mode 100644 app/Http/Requests/Photo/MovePhotosRequest.php create mode 100644 app/Http/Requests/Photo/RenamePhotoRequest.php create mode 100644 app/Http/Requests/Photo/RotatePhotoRequest.php create mode 100644 app/Http/Requests/Photo/SetPhotosStarredRequest.php create mode 100644 app/Http/Requests/Photo/SetPhotosTagsRequest.php create mode 100644 app/Http/Requests/Photo/UploadPhotoRequest.php rename app/{Legacy/V1/Requests/User/U2FRequest.php => Http/Requests/Profile/ChangeTokenRequest.php} (65%) create mode 100644 app/Http/Requests/Profile/ClearOauthRequest.php create mode 100644 app/Http/Requests/Profile/UpdateProfileRequest.php create mode 100644 app/Http/Requests/Search/GetSearchRequest.php create mode 100644 app/Http/Requests/Search/InitSearchRequest.php create mode 100644 app/Http/Requests/Settings/GetAllConfigsRequest.php create mode 100644 app/Http/Requests/Settings/SetCSSSettingRequest.php create mode 100644 app/Http/Requests/Settings/SetConfigsRequest.php create mode 100644 app/Http/Requests/Settings/SetJSSettingRequest.php create mode 100644 app/Http/Requests/Sharing/AddSharingRequest.php create mode 100644 app/Http/Requests/Sharing/DeleteSharingRequest.php create mode 100644 app/Http/Requests/Sharing/EditSharingRequest.php create mode 100644 app/Http/Requests/Sharing/ListAllSharingRequest.php create mode 100644 app/Http/Requests/Sharing/ListSharingRequest.php create mode 100644 app/Http/Requests/Statistics/SpacePerAlbumRequest.php create mode 100644 app/Http/Requests/Statistics/SpacePerUserRequest.php create mode 100644 app/Http/Requests/Statistics/SpaceSizeVariantRequest.php create mode 100644 app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumAlbumsTrait.php create mode 100644 app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumTrait.php create mode 100644 app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotoTrait.php create mode 100644 app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosAlbumTrait.php create mode 100644 app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosTrait.php create mode 100644 app/Http/Requests/Traits/HasAbstractAlbumTrait.php create mode 100644 app/Http/Requests/Traits/HasAccessPermissionResourceTrait.php create mode 100644 app/Http/Requests/Traits/HasAccessPermissionTrait.php create mode 100644 app/Http/Requests/Traits/HasAlbumIdTrait.php create mode 100644 app/Http/Requests/Traits/HasAlbumIdsTrait.php create mode 100644 app/Http/Requests/Traits/HasAlbumSortingCriterionTrait.php create mode 100644 app/Http/Requests/Traits/HasAlbumTrait.php create mode 100644 app/Http/Requests/Traits/HasAlbumsTrait.php create mode 100644 app/Http/Requests/Traits/HasAspectRatioTrait.php create mode 100644 app/Http/Requests/Traits/HasBaseAlbumTrait.php create mode 100644 app/Http/Requests/Traits/HasCompactBooleanTrait.php create mode 100644 app/Http/Requests/Traits/HasConfigsTrait.php create mode 100644 app/Http/Requests/Traits/HasCopyrightTrait.php create mode 100644 app/Http/Requests/Traits/HasDescriptionTrait.php create mode 100644 app/Http/Requests/Traits/HasLicenseTrait.php create mode 100644 app/Http/Requests/Traits/HasNoteTrait.php create mode 100644 app/Http/Requests/Traits/HasOwnerIdTrait.php create mode 100644 app/Http/Requests/Traits/HasParentAlbumTrait.php create mode 100644 app/Http/Requests/Traits/HasPasswordTrait.php create mode 100644 app/Http/Requests/Traits/HasPhotoIdsTrait.php create mode 100644 app/Http/Requests/Traits/HasPhotoLayoutTrait.php create mode 100644 app/Http/Requests/Traits/HasPhotoSortingCriterionTrait.php create mode 100644 app/Http/Requests/Traits/HasPhotoTrait.php create mode 100644 app/Http/Requests/Traits/HasPhotosTrait.php create mode 100644 app/Http/Requests/Traits/HasQuotaKBTrait.php create mode 100644 app/Http/Requests/Traits/HasSeStatusBooleanTrait.php create mode 100644 app/Http/Requests/Traits/HasSizeVariantTrait.php create mode 100644 app/Http/Requests/Traits/HasTagAlbumTrait.php create mode 100644 app/Http/Requests/Traits/HasTagsTrait.php create mode 100644 app/Http/Requests/Traits/HasTermsTrait.php create mode 100644 app/Http/Requests/Traits/HasTitleTrait.php create mode 100644 app/Http/Requests/Traits/HasUploadDateTrait.php create mode 100644 app/Http/Requests/Traits/HasUserIdTrait.php create mode 100644 app/Http/Requests/Traits/HasUserIdsTrait.php create mode 100644 app/Http/Requests/Traits/HasUserTrait.php create mode 100644 app/Http/Requests/Traits/HasUsernameTrait.php create mode 100644 app/Http/Requests/UserManagement/AddUserRequest.php create mode 100644 app/Http/Requests/UserManagement/DeleteUserRequest.php create mode 100644 app/Http/Requests/UserManagement/ManagmentListUsersRequest.php create mode 100644 app/Http/Requests/UserManagement/SetUserSettingsRequest.php create mode 100644 app/Http/Requests/Users/ListUsersRequest.php create mode 100644 app/Http/Requests/Users/UsersRequest.php create mode 100644 app/Http/Requests/WebAuthn/EditCredentialRequest.php create mode 100644 app/Http/Resources/Collections/ConfigCollectionResource.php create mode 100644 app/Http/Resources/Collections/PositionDataResource.php create mode 100644 app/Http/Resources/Collections/RootAlbumResource.php create mode 100644 app/Http/Resources/Diagnostics/CleaningState.php create mode 100644 app/Http/Resources/Diagnostics/ErrorLine.php create mode 100644 app/Http/Resources/Diagnostics/Permissions.php create mode 100644 app/Http/Resources/Diagnostics/TreeState.php create mode 100644 app/Http/Resources/Diagnostics/UpdateCheckInfo.php create mode 100644 app/Http/Resources/Diagnostics/UpdateInfo.php create mode 100644 app/Http/Resources/Editable/EditableBaseAlbumResource.php create mode 100644 app/Http/Resources/Editable/EditableConfigResource.php create mode 100644 app/Http/Resources/Editable/UploadMetaResource.php create mode 100644 app/Http/Resources/Frame/FrameData.php create mode 100644 app/Http/Resources/GalleryConfigs/AlbumConfig.php create mode 100644 app/Http/Resources/GalleryConfigs/FooterConfig.php create mode 100644 app/Http/Resources/GalleryConfigs/InitConfig.php create mode 100644 app/Http/Resources/GalleryConfigs/LandingPageResource.php create mode 100644 app/Http/Resources/GalleryConfigs/MapProviderData.php create mode 100644 app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php create mode 100644 app/Http/Resources/GalleryConfigs/RegisterData.php create mode 100644 app/Http/Resources/GalleryConfigs/RootConfig.php create mode 100644 app/Http/Resources/GalleryConfigs/UploadConfig.php create mode 100644 app/Http/Resources/Models/AbstractAlbumResource.php create mode 100644 app/Http/Resources/Models/AccessPermissionResource.php create mode 100644 app/Http/Resources/Models/AlbumResource.php create mode 100644 app/Http/Resources/Models/ConfigResource.php create mode 100644 app/Http/Resources/Models/JobHistoryResource.php create mode 100644 app/Http/Resources/Models/LightUserResource.php create mode 100644 app/Http/Resources/Models/PhotoResource.php create mode 100644 app/Http/Resources/Models/SizeVariantResource.php create mode 100644 app/Http/Resources/Models/SizeVariantsResouce.php create mode 100644 app/Http/Resources/Models/SmartAlbumResource.php create mode 100644 app/Http/Resources/Models/TagAlbumResource.php create mode 100644 app/Http/Resources/Models/TargetAlbumResource.php create mode 100644 app/Http/Resources/Models/ThumbAlbumResource.php create mode 100644 app/Http/Resources/Models/ThumbResource.php create mode 100644 app/Http/Resources/Models/UserManagementResource.php create mode 100644 app/Http/Resources/Models/UserResource.php rename app/{DTO => Http/Resources/Models/Utils}/AlbumProtectionPolicy.php (92%) create mode 100644 app/Http/Resources/Models/Utils/PreComputedPhotoData.php rename app/{Livewire/DTO/AlbumFormatted.php => Http/Resources/Models/Utils/PreFormattedAlbumData.php} (54%) create mode 100644 app/Http/Resources/Models/Utils/PreformattedPhotoData.php create mode 100644 app/Http/Resources/Models/Utils/UserToken.php create mode 100644 app/Http/Resources/Models/WebAuthnResource.php create mode 100644 app/Http/Resources/Oauth/OauthRegistrationData.php create mode 100644 app/Http/Resources/Rights/AlbumRightsResource.php create mode 100644 app/Http/Resources/Rights/GlobalRightsResource.php create mode 100644 app/Http/Resources/Rights/PhotoRightsResource.php create mode 100644 app/Http/Resources/Rights/RootAlbumRightsResource.php create mode 100644 app/Http/Resources/Rights/SettingsRightsResource.php create mode 100644 app/Http/Resources/Rights/UserManagementRightsResource.php create mode 100644 app/Http/Resources/Rights/UserRightsResource.php create mode 100644 app/Http/Resources/Root/AuthConfig.php create mode 100644 app/Http/Resources/Root/VersionResource.php create mode 100644 app/Http/Resources/Search/InitResource.php create mode 100644 app/Http/Resources/Search/ResultsResource.php create mode 100644 app/Http/Resources/Sharing/ListedAlbumsResource.php create mode 100644 app/Http/Resources/Sharing/SharedAlbumResource.php create mode 100644 app/Http/Resources/Sharing/SharesResource.php create mode 100644 app/Http/Resources/Sharing/UserSharedResource.php create mode 100644 app/Http/Resources/Statistics/Album.php create mode 100644 app/Http/Resources/Statistics/Sizes.php create mode 100644 app/Http/Resources/Statistics/UserSpace.php create mode 100644 app/Http/Resources/Traits/HasHeaderUrl.php create mode 100644 app/Http/Resources/Traits/HasPrepPhotoCollection.php delete mode 100644 app/Http/RuleSets/Album/ArchiveAlbumRuleSet.php delete mode 100644 app/Http/RuleSets/Album/SetAlbumDescriptionRuleSet.php delete mode 100644 app/Http/RuleSets/Album/SetAlbumLicenseRuleSet.php delete mode 100644 app/Http/RuleSets/Album/SetAlbumNSFWRuleSet.php delete mode 100644 app/Http/RuleSets/Album/SetAlbumSortingRuleSetLegacy.php delete mode 100644 app/Http/RuleSets/Album/SetPhotoSortingRuleSet.php rename app/{ => Legacy}/Actions/Settings/UpdateLogin.php (98%) rename app/{ => Legacy/V1}/Actions/Albums/Tree.php (92%) create mode 100644 app/Legacy/V1/Contracts/Http/Requests/HasAlbumSortingCriterion.php create mode 100644 app/Legacy/V1/Contracts/Http/Requests/HasAspectRatio.php create mode 100644 app/Legacy/V1/Contracts/Http/Requests/HasPhotoSortingCriterion.php rename app/{ => Legacy/V1}/DTO/DiagnosticInfo.php (83%) rename app/{Http => Legacy/V1}/Requests/Legacy/TranslateIDRequest.php (96%) delete mode 100644 app/Legacy/V1/Resources/Sharing/ListedAlbumsResource.php delete mode 100644 app/Legacy/V1/Resources/Sharing/SharedAlbumResource.php delete mode 100644 app/Legacy/V1/Resources/Sharing/SharesResource.php delete mode 100644 app/Legacy/V1/Resources/Sharing/UserSharedResource.php rename app/{Http => Legacy/V1}/RuleSets/AddAlbumRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Album/AddAlbumRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Album/AddTagAlbumRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Album/BasicAlbumIdRuleSet.php (90%) rename app/{Http => Legacy/V1}/RuleSets/Album/DeleteAlbumsRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Album/MergeAlbumsRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Album/MoveAlbumsRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Album/SetAlbumCoverRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Album/SetAlbumHeaderRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Album/SetAlbumSortingRuleSet.php (95%) rename app/{Http => Legacy/V1}/RuleSets/Album/SetAlbumTagRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Album/SetAlbumsTitleRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Album/UnlockAlbumRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/ChangeLoginRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Import/ImportFromUrlRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Import/ImportServerRuleSet.php (95%) rename app/{Http => Legacy/V1}/RuleSets/LoginRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Photo/AddPhotoRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Photo/ArchivePhotosRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/DeletePhotosRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Photo/DuplicatePhotosRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/GetPhotoRuleSet.php (90%) rename app/{Http => Legacy/V1}/RuleSets/Photo/MovePhotosRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/RotatePhotoRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/SetPhotoDescriptionRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/SetPhotoLicenseRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/SetPhotoUploadDateRuleSet.php (92%) rename app/{Http => Legacy/V1}/RuleSets/Photo/SetPhotosStarredRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Photo/SetPhotosTagsRuleSet.php (94%) rename app/{Http => Legacy/V1}/RuleSets/Photo/SetPhotosTitleRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Session/LoginRuleSet.php (91%) rename app/{Http => Legacy/V1}/RuleSets/User/ChangeLoginRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/User/SetEmailRuleSet.php (90%) rename app/{Http => Legacy/V1}/RuleSets/Users/AddUserRuleSet.php (93%) rename app/{Http => Legacy/V1}/RuleSets/Users/SetUserSettingsRuleSet.php (94%) rename app/{Http => Legacy/V1}/RuleSets/WebAuthn/DeleteCredentialRuleSet.php (88%) delete mode 100644 app/Livewire/Components/Base/ContextMenu.php delete mode 100644 app/Livewire/Components/Base/Modal.php delete mode 100644 app/Livewire/Components/Forms/Add/ImportFromDropbox.php delete mode 100644 app/Livewire/Components/Forms/Add/ImportFromServer.php delete mode 100644 app/Livewire/Components/Forms/Add/ImportFromUrl.php delete mode 100644 app/Livewire/Components/Forms/Add/Upload.php delete mode 100644 app/Livewire/Components/Forms/Album/AddTrack.php delete mode 100644 app/Livewire/Components/Forms/Album/Create.php delete mode 100644 app/Livewire/Components/Forms/Album/CreateTag.php delete mode 100644 app/Livewire/Components/Forms/Album/Delete.php delete mode 100644 app/Livewire/Components/Forms/Album/DeletePanel.php delete mode 100644 app/Livewire/Components/Forms/Album/DeleteTrack.php delete mode 100644 app/Livewire/Components/Forms/Album/Merge.php delete mode 100644 app/Livewire/Components/Forms/Album/Move.php delete mode 100644 app/Livewire/Components/Forms/Album/MovePanel.php delete mode 100644 app/Livewire/Components/Forms/Album/Properties.php delete mode 100644 app/Livewire/Components/Forms/Album/Rename.php delete mode 100644 app/Livewire/Components/Forms/Album/SetHeader.php delete mode 100644 app/Livewire/Components/Forms/Album/ShareWith.php delete mode 100644 app/Livewire/Components/Forms/Album/ShareWithLine.php delete mode 100644 app/Livewire/Components/Forms/Album/Transfer.php delete mode 100644 app/Livewire/Components/Forms/Album/UnlockAlbum.php delete mode 100644 app/Livewire/Components/Forms/Album/Visibility.php delete mode 100644 app/Livewire/Components/Forms/Confirms/SaveAll.php delete mode 100644 app/Livewire/Components/Forms/Photo/CopyTo.php delete mode 100644 app/Livewire/Components/Forms/Photo/Delete.php delete mode 100644 app/Livewire/Components/Forms/Photo/Download.php delete mode 100644 app/Livewire/Components/Forms/Photo/Move.php delete mode 100644 app/Livewire/Components/Forms/Photo/Rename.php delete mode 100644 app/Livewire/Components/Forms/Photo/Tag.php delete mode 100644 app/Livewire/Components/Forms/Profile/GetApiToken.php delete mode 100644 app/Livewire/Components/Forms/Profile/ManageSecondFactor.php delete mode 100644 app/Livewire/Components/Forms/Profile/Oauth.php delete mode 100644 app/Livewire/Components/Forms/Profile/SecondFactor.php delete mode 100644 app/Livewire/Components/Forms/Profile/SetEmail.php delete mode 100644 app/Livewire/Components/Forms/Profile/SetLogin.php delete mode 100644 app/Livewire/Components/Forms/Settings/Base/BaseConfigDoubleDropDown.php delete mode 100644 app/Livewire/Components/Forms/Settings/Base/BaseConfigDropDown.php delete mode 100644 app/Livewire/Components/Forms/Settings/Base/BooleanSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/Base/PasswordSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/Base/StringSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetAlbumDecorationOrientationSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetAlbumDecorationSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetAlbumSortingSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetLangSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetLayoutSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetLicenseDefaultSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetMapProviderSetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetPhotoOverlaySetting.php delete mode 100644 app/Livewire/Components/Forms/Settings/SetPhotoSortingSetting.php delete mode 100644 app/Livewire/Components/Menus/AlbumAdd.php delete mode 100644 app/Livewire/Components/Menus/AlbumDropdown.php delete mode 100644 app/Livewire/Components/Menus/AlbumsDropdown.php delete mode 100644 app/Livewire/Components/Menus/LeftMenu.php delete mode 100644 app/Livewire/Components/Menus/PhotoDropdown.php delete mode 100644 app/Livewire/Components/Menus/PhotosDropdown.php delete mode 100644 app/Livewire/Components/Modals/About.php delete mode 100644 app/Livewire/Components/Modals/Login.php delete mode 100644 app/Livewire/Components/Modules/Diagnostics/AbstractPreSection.php delete mode 100644 app/Livewire/Components/Modules/Diagnostics/Configurations.php delete mode 100644 app/Livewire/Components/Modules/Diagnostics/Errors.php delete mode 100644 app/Livewire/Components/Modules/Diagnostics/Infos.php delete mode 100644 app/Livewire/Components/Modules/Diagnostics/Space.php delete mode 100644 app/Livewire/Components/Modules/Jobs/Feedback.php delete mode 100644 app/Livewire/Components/Modules/Maintenance/Cleaning.php delete mode 100644 app/Livewire/Components/Modules/Maintenance/FixTree.php delete mode 100644 app/Livewire/Components/Modules/Maintenance/GenSizeVariants.php delete mode 100644 app/Livewire/Components/Modules/Maintenance/MissingFileSizes.php delete mode 100644 app/Livewire/Components/Modules/Maintenance/Optimize.php delete mode 100644 app/Livewire/Components/Modules/Maintenance/Update.php delete mode 100644 app/Livewire/Components/Modules/Users/UserLine.php delete mode 100644 app/Livewire/Components/Pages/AllSettings.php delete mode 100644 app/Livewire/Components/Pages/Diagnostics.php delete mode 100644 app/Livewire/Components/Pages/Frame.php delete mode 100644 app/Livewire/Components/Pages/Gallery/Album.php delete mode 100644 app/Livewire/Components/Pages/Gallery/Albums.php delete mode 100644 app/Livewire/Components/Pages/Gallery/BaseAlbumComponent.php delete mode 100644 app/Livewire/Components/Pages/Gallery/Search.php delete mode 100644 app/Livewire/Components/Pages/Gallery/SensitiveWarning.php delete mode 100644 app/Livewire/Components/Pages/Jobs.php delete mode 100644 app/Livewire/Components/Pages/Landing.php delete mode 100644 app/Livewire/Components/Pages/Login.php delete mode 100644 app/Livewire/Components/Pages/Maintenance.php delete mode 100644 app/Livewire/Components/Pages/Map.php delete mode 100644 app/Livewire/Components/Pages/Profile.php delete mode 100644 app/Livewire/Components/Pages/Settings.php delete mode 100644 app/Livewire/Components/Pages/Sharing.php delete mode 100644 app/Livewire/Components/Pages/Users.php delete mode 100644 app/Livewire/DTO/AlbumFlags.php delete mode 100644 app/Livewire/DTO/AlbumRights.php delete mode 100644 app/Livewire/DTO/AlbumsFlags.php delete mode 100644 app/Livewire/DTO/Layouts.php delete mode 100644 app/Livewire/DTO/OauthData.php delete mode 100644 app/Livewire/DTO/PhotoFlags.php delete mode 100644 app/Livewire/DTO/ProtectedCollection.php delete mode 100644 app/Livewire/DTO/SessionFlags.php delete mode 100644 app/Livewire/Forms/AllConfigsForms.php delete mode 100644 app/Livewire/Forms/ImportFromUrlForm.php delete mode 100644 app/Livewire/Forms/PhotoUpdateForm.php delete mode 100644 app/Livewire/Synth/AlbumFlagsSynth.php delete mode 100644 app/Livewire/Synth/AlbumSynth.php delete mode 100644 app/Livewire/Synth/PhotoSynth.php delete mode 100644 app/Livewire/Synth/SessionFlagsSynth.php delete mode 100644 app/Livewire/Traits/AlbumsPhotosContextMenus.php delete mode 100644 app/Livewire/Traits/InteractWithContextMenu.php delete mode 100644 app/Livewire/Traits/InteractWithModal.php delete mode 100644 app/Livewire/Traits/Notify.php delete mode 100644 app/Livewire/Traits/SilentUpdate.php delete mode 100644 app/Livewire/Traits/UseOpenable.php delete mode 100644 app/Livewire/Traits/UsePhotoViewActions.php delete mode 100644 app/Livewire/Traits/UseValidator.php delete mode 100644 app/Livewire/Traits/UseWireable.php delete mode 100644 app/Metadata/RateLimiterStore.php create mode 100644 app/Rules/BooleanRequireSupportRule.php create mode 100644 app/Rules/ConfigKeyRequireSupportRule.php create mode 100644 app/Rules/ConfigKeyRule.php create mode 100644 app/Rules/ConfigValueRule.php create mode 100644 app/Rules/ExtensionRule.php create mode 100644 app/Rules/FileUuidRule.php create mode 100644 app/Rules/IntegerRequireSupportRule.php create mode 100644 app/Rules/StringRequireSupportRule.php delete mode 100644 app/View/Components/BackButtonHeader.php delete mode 100644 app/View/Components/Footer.php delete mode 100644 app/View/Components/Gallery/Album/SharingLinks.php delete mode 100644 app/View/Components/Gallery/Album/Thumbs/Album.php delete mode 100644 app/View/Components/Gallery/Album/Thumbs/AlbumThumb.php delete mode 100644 app/View/Components/Gallery/Album/Thumbs/Photo.php delete mode 100644 app/View/Components/Gallery/Photo/Download.php create mode 100644 config/data.php delete mode 100644 config/livewire.php delete mode 100644 config/scramble.php create mode 100644 config/typescript-transformer.php create mode 100644 database/factories/AccessPermissionFactory.php create mode 100644 database/factories/TagAlbumFactory.php create mode 100644 database/migrations/2024_07_06_214241_thumb_min_max_take_date_order.php create mode 100644 database/migrations/2024_07_12_183751_add_auto_play_config.php create mode 100644 database/migrations/2024_07_26_120007_simplify_config.php create mode 100644 database/migrations/2024_07_29_172018_fix_settings.php create mode 100644 database/migrations/2024_08_09_205532_white_theme.php create mode 100644 database/migrations/2024_08_31_090626_config_help_popup.php create mode 100644 database/migrations/2024_08_31_090740_fix_description_always_hover_hidden_photo.php create mode 100644 database/migrations/2024_09_14_143949_add_settings_level.php create mode 100644 database/migrations/2024_09_14_153948_fix_more_descriptions.php create mode 100644 database/migrations/2024_09_27_144741_add_supporter_fields.php create mode 100644 database/migrations/2024_10_05_125328_add_slideshow_timeout.php create mode 100644 database/migrations/2024_10_05_125833_lang_is_admin_setting.php create mode 100644 database/migrations/2024_10_05_184315_bump_version060000.php create mode 100644 database/migrations/2024_10_09_191528_image_processing_backup.php create mode 100644 database/migrations/2024_10_09_194010_image_processing_details_and_others.php create mode 100644 database/migrations/2024_10_10_101333_set_dropbox_disabled.php create mode 100644 database/migrations/2024_10_11_173054_add_space_quota_per_user.php create mode 100644 database/migrations/2024_10_11_173106_add_space_quota_configuration.php create mode 100644 database/migrations/2024_10_13_134419_oath_group_to_users.php create mode 100644 database/migrations/2024_10_14_104644_show_nsfw_in_smart_albums.php create mode 100644 database/migrations/2024_10_14_104823_refine_text_enable_unsorted_smart_album.php create mode 100644 database/migrations/2024_10_20_125449_move-socials-to-footer.php create mode 100644 database/migrations/2024_10_20_173904_add_photo_layout_per_album.php create mode 100644 database/migrations/2024_10_23_222857_change_header.php create mode 100644 database/migrations/2024_10_23_225332_warning_html_content.php create mode 100644 phpunit.ci.xml delete mode 100644 public/dist/custom.js delete mode 100644 resources/css/app.css create mode 100644 resources/js/components/diagnostics/ConfigurationsDiagnostics.vue create mode 100644 resources/js/components/diagnostics/ErrorsDiagnostics.vue create mode 100644 resources/js/components/diagnostics/InfoDiagnostics.vue create mode 100644 resources/js/components/diagnostics/SpaceDiagnostics.vue create mode 100644 resources/js/components/drawers/AlbumEdit.vue create mode 100644 resources/js/components/drawers/AlbumStatistics.vue create mode 100644 resources/js/components/drawers/PhotoDetails.vue create mode 100644 resources/js/components/drawers/PhotoEdit.vue create mode 100644 resources/js/components/footers/GalleryFooter.vue create mode 100644 resources/js/components/footers/LandingFooter.vue create mode 100644 resources/js/components/forms/album/AlbumCreateDialog.vue create mode 100644 resources/js/components/forms/album/AlbumCreateTagDialog.vue create mode 100644 resources/js/components/forms/album/AlbumDelete.vue create mode 100644 resources/js/components/forms/album/AlbumMove.vue create mode 100644 resources/js/components/forms/album/AlbumProperties.vue create mode 100644 resources/js/components/forms/album/AlbumShare.vue create mode 100644 resources/js/components/forms/album/AlbumTransfer.vue create mode 100644 resources/js/components/forms/album/AlbumVisibility.vue create mode 100644 resources/js/components/forms/album/SearchTargetAlbum.vue create mode 100644 resources/js/components/forms/album/SearchTargetUser.vue create mode 100644 resources/js/components/forms/album/Unlock.vue create mode 100644 resources/js/components/forms/basic/InputPassword.vue create mode 100644 resources/js/components/forms/basic/InputText.vue create mode 100644 resources/js/components/forms/basic/Password.vue create mode 100644 resources/js/components/forms/basic/Textarea.vue create mode 100644 resources/js/components/forms/gallery-dialogs/AlbumMergeDialog.vue create mode 100644 resources/js/components/forms/gallery-dialogs/DeleteDialog.vue create mode 100644 resources/js/components/forms/gallery-dialogs/MoveDialog.vue create mode 100644 resources/js/components/forms/gallery-dialogs/RenameDialog.vue create mode 100644 resources/js/components/forms/photo/PhotoCopyDialog.vue create mode 100644 resources/js/components/forms/photo/PhotoTagDialog.vue create mode 100644 resources/js/components/forms/profile/ApiToken.vue create mode 100644 resources/js/components/forms/profile/SetLogin.vue create mode 100644 resources/js/components/forms/profile/SetOauth.vue create mode 100644 resources/js/components/forms/profile/SetSecondFactor.vue create mode 100644 resources/js/components/forms/profile/SetSecondFactorLine.vue create mode 100644 resources/js/components/forms/search/SearchBox.vue create mode 100644 resources/js/components/forms/settings/BoolField.vue create mode 100644 resources/js/components/forms/settings/NumberField.vue create mode 100644 resources/js/components/forms/settings/OldField.vue create mode 100644 resources/js/components/forms/settings/ResetField.vue create mode 100644 resources/js/components/forms/settings/SelectField.vue create mode 100644 resources/js/components/forms/settings/SelectLang.vue create mode 100644 resources/js/components/forms/settings/SelectOptionsField.vue create mode 100644 resources/js/components/forms/settings/SliderField.vue create mode 100644 resources/js/components/forms/settings/StringField.vue create mode 100644 resources/js/components/forms/settings/ZipSliderField.vue create mode 100644 resources/js/components/forms/sharing/CreateSharing.vue create mode 100644 resources/js/components/forms/sharing/ShareLine.vue create mode 100644 resources/js/components/forms/upload/DropBoxChooser.vue create mode 100644 resources/js/components/forms/upload/UploadingLine.vue create mode 100644 resources/js/components/forms/users/CreateEditUser.vue create mode 100644 resources/js/components/forms/users/ListUser.vue create mode 100644 resources/js/components/gallery/AlbumHero.vue create mode 100644 resources/js/components/gallery/AlbumThumbPanel.vue create mode 100644 resources/js/components/gallery/PhotoThumbPanel.vue create mode 100644 resources/js/components/gallery/SensitiveWarning.vue create mode 100644 resources/js/components/gallery/photo/DockButton.vue create mode 100644 resources/js/components/gallery/photo/MapInclude.vue create mode 100644 resources/js/components/gallery/photo/NextPrevious.vue create mode 100644 resources/js/components/gallery/photo/Overlay.vue create mode 100644 resources/js/components/gallery/thumbs/AlbumThumb.vue create mode 100644 resources/js/components/gallery/thumbs/AlbumThumbDecorations.vue create mode 100644 resources/js/components/gallery/thumbs/AlbumThumbImage.vue create mode 100644 resources/js/components/gallery/thumbs/AlbumThumbOverlay.vue create mode 100644 resources/js/components/gallery/thumbs/PhotoThumb.vue create mode 100644 resources/js/components/gallery/thumbs/ThumbBadge.vue create mode 100644 resources/js/components/headers/AlbumHeader.vue create mode 100644 resources/js/components/headers/AlbumsHeader.vue create mode 100644 resources/js/components/headers/BackLinkButton.vue create mode 100644 resources/js/components/headers/OpenLeftMenu.vue create mode 100644 resources/js/components/headers/PhotoHeader.vue create mode 100644 resources/js/components/icons/MiniIcon.vue create mode 100644 resources/js/components/icons/SETag.vue create mode 100644 resources/js/components/maintenance/MaintenanceCleaning.vue create mode 100644 resources/js/components/maintenance/MaintenanceFilesize.vue create mode 100644 resources/js/components/maintenance/MaintenanceFixJobs.vue create mode 100644 resources/js/components/maintenance/MaintenanceFixTree.vue create mode 100644 resources/js/components/maintenance/MaintenanceGenSizevariants.vue create mode 100644 resources/js/components/maintenance/MaintenanceOptimize.vue create mode 100644 resources/js/components/maintenance/MaintenanceUpdate.vue create mode 100644 resources/js/components/modals/AboutLychee.vue create mode 100644 resources/js/components/modals/DownloadPhoto.vue create mode 100644 resources/js/components/modals/DropBox.vue create mode 100644 resources/js/components/modals/ImportFromLink.vue create mode 100644 resources/js/components/modals/ImportFromServer.vue create mode 100644 resources/js/components/modals/KeybindingsHelp.vue create mode 100644 resources/js/components/modals/LoginModal.vue create mode 100644 resources/js/components/modals/RegisterLychee.vue create mode 100644 resources/js/components/modals/ShareAlbum.vue create mode 100644 resources/js/components/modals/UploadPanel.vue create mode 100644 resources/js/components/modals/WebauthnModal.vue create mode 100644 resources/js/components/settings/AllSettings.vue create mode 100644 resources/js/components/settings/EasySettings.vue create mode 100644 resources/js/components/statistics/AlbumsTable.vue create mode 100644 resources/js/components/statistics/SizeVariantMeter.vue create mode 100644 resources/js/components/statistics/TotalCard.vue create mode 100644 resources/js/composables/album/albumRefresher.ts create mode 100644 resources/js/composables/album/albumStatistics.ts create mode 100644 resources/js/composables/album/albumsRefresher.ts create mode 100644 resources/js/composables/album/searchRefresher.ts create mode 100644 resources/js/composables/album/uploadEvents.ts create mode 100644 resources/js/composables/contextMenus/contextMenu.ts create mode 100644 resources/js/composables/contextMenus/contextMenuAlbumAdd.ts create mode 100644 resources/js/composables/contextMenus/contextMenuAlbumsAdd.ts create mode 100644 resources/js/composables/modalsTriggers/galleryModals.ts create mode 100644 resources/js/composables/photo/basePhoto.ts create mode 100644 resources/js/composables/photo/slideshow.ts create mode 100644 resources/js/composables/preview/getPreviewInfo.ts create mode 100644 resources/js/composables/selections/selections.ts create mode 100644 resources/js/config/axios-config.ts create mode 100644 resources/js/config/constants.ts create mode 100644 resources/js/config/csrf-getter.ts delete mode 100644 resources/js/data/panel/index.ts delete mode 100644 resources/js/data/panel/photoFormPanel.ts delete mode 100644 resources/js/data/panel/photoListingPanel.ts delete mode 100644 resources/js/data/panel/photoSidebarPanel.ts delete mode 100644 resources/js/data/panel/searchPanel.ts delete mode 100644 resources/js/data/qrcode/qrBuilder.ts delete mode 100644 resources/js/data/views/albumView.ts delete mode 100644 resources/js/data/views/dropboxView.ts delete mode 100644 resources/js/data/views/index.ts delete mode 100644 resources/js/data/views/map.types.d.ts delete mode 100644 resources/js/data/views/mapView.ts delete mode 100644 resources/js/data/views/photoView.ts delete mode 100644 resources/js/data/views/types.d.ts delete mode 100644 resources/js/data/views/uploadView.ts delete mode 100644 resources/js/data/webauthn/index.ts delete mode 100644 resources/js/data/webauthn/loginWebAuthn.ts delete mode 100644 resources/js/data/webauthn/registerWebAuthn.ts delete mode 100644 resources/js/global.d.ts create mode 100644 resources/js/layouts/PhotoLayout.ts rename resources/js/{lycheeOrg => }/layouts/types.d.ts (100%) rename resources/js/{lycheeOrg => }/layouts/useGrid.ts (95%) rename resources/js/{lycheeOrg => }/layouts/useJustify.ts (78%) rename resources/js/{lycheeOrg => }/layouts/useMasonry.ts (96%) rename resources/js/{lycheeOrg => }/layouts/useSquare.ts (100%) create mode 100644 resources/js/lychee.d.ts delete mode 100644 resources/js/lycheeOrg/actions/albumActions.ts delete mode 100644 resources/js/lycheeOrg/actions/keybindings.ts delete mode 100644 resources/js/lycheeOrg/actions/selection.ts delete mode 100644 resources/js/lycheeOrg/actions/swipeActions.ts delete mode 100644 resources/js/lycheeOrg/backend.d.ts delete mode 100644 resources/js/lycheeOrg/flags/albumFlags.ts delete mode 100644 resources/js/lycheeOrg/flags/photoFlags.ts delete mode 100644 resources/js/lycheeOrg/layouts/PhotoLayout.ts create mode 100644 resources/js/menus/LeftMenu.vue create mode 100644 resources/js/router/routes.ts create mode 100644 resources/js/services/album-service.ts create mode 100644 resources/js/services/auth-service.ts create mode 100644 resources/js/services/constants.ts create mode 100644 resources/js/services/diagnostics-service.ts create mode 100644 resources/js/services/init-service.ts create mode 100644 resources/js/services/jobs-service.ts create mode 100644 resources/js/services/maintenance-service.ts create mode 100644 resources/js/services/oauth-service.ts create mode 100644 resources/js/services/photo-service.ts create mode 100644 resources/js/services/profile-service.ts create mode 100644 resources/js/services/search-service.ts create mode 100644 resources/js/services/settings-service.ts create mode 100644 resources/js/services/sharing-service.ts rename resources/js/{lycheeOrg/actions/sidebarMap.ts => services/sidebar-map.ts} (57%) create mode 100644 resources/js/services/statistics-service.ts create mode 100644 resources/js/services/upload-service.ts create mode 100644 resources/js/services/user-management-service.ts create mode 100644 resources/js/services/users-service.ts create mode 100644 resources/js/services/webauthn-service.ts create mode 100644 resources/js/stores/Auth.ts create mode 100644 resources/js/stores/LycheeState.ts create mode 100644 resources/js/style/preset-full.ts create mode 100644 resources/js/style/preset.ts create mode 100644 resources/js/utils/StatsSizeVariantToColours.ts create mode 100644 resources/js/utils/keybindings-utils.ts create mode 100644 resources/js/views/App.vue create mode 100644 resources/js/views/Diagnostics.vue create mode 100644 resources/js/views/Error.vue create mode 100644 resources/js/views/Jobs.vue create mode 100644 resources/js/views/Landing.vue create mode 100644 resources/js/views/Maintenance.vue create mode 100644 resources/js/views/Permissions.vue create mode 100644 resources/js/views/Profile.vue create mode 100644 resources/js/views/Settings.vue create mode 100644 resources/js/views/Sharing.vue create mode 100644 resources/js/views/Statistics.vue create mode 100644 resources/js/views/Users.vue create mode 100644 resources/js/views/gallery-panels/Album.vue create mode 100644 resources/js/views/gallery-panels/Albums.vue create mode 100644 resources/js/views/gallery-panels/Frame.vue create mode 100644 resources/js/views/gallery-panels/Map.vue create mode 100644 resources/js/views/gallery-panels/Photo.vue create mode 100644 resources/js/views/gallery-panels/Search.vue create mode 100644 resources/sass/app.scss rename resources/{css => sass}/fonts.css (100%) delete mode 100644 resources/views/components/context-menu/item.blade.php delete mode 100644 resources/views/components/context-menu/separator.blade.php delete mode 100644 resources/views/components/footer-landing.blade.php delete mode 100644 resources/views/components/footer.blade.php delete mode 100644 resources/views/components/forms/buttons/action.blade.php delete mode 100644 resources/views/components/forms/buttons/cancel.blade.php delete mode 100644 resources/views/components/forms/buttons/create.blade.php delete mode 100644 resources/views/components/forms/buttons/danger.blade.php delete mode 100644 resources/views/components/forms/defaulttickbox.blade.php delete mode 100644 resources/views/components/forms/dropdown.blade.php delete mode 100644 resources/views/components/forms/error-message.blade.php delete mode 100644 resources/views/components/forms/inputs/date.blade.php delete mode 100644 resources/views/components/forms/inputs/important.blade.php delete mode 100644 resources/views/components/forms/inputs/password.blade.php delete mode 100644 resources/views/components/forms/inputs/text.blade.php delete mode 100644 resources/views/components/forms/textarea.blade.php delete mode 100644 resources/views/components/forms/tickbox.blade.php delete mode 100644 resources/views/components/forms/toggle.blade.php delete mode 100644 resources/views/components/gallery/album/details.blade.php delete mode 100644 resources/views/components/gallery/album/hero.blade.php delete mode 100644 resources/views/components/gallery/album/login-dialog.blade.php delete mode 100644 resources/views/components/gallery/album/menu/danger.blade.php delete mode 100644 resources/views/components/gallery/album/menu/item.blade.php delete mode 100644 resources/views/components/gallery/album/menu/menu.blade.php delete mode 100644 resources/views/components/gallery/album/sharing-links.blade.php delete mode 100644 resources/views/components/gallery/album/thumbs/album-thumb.blade.php delete mode 100644 resources/views/components/gallery/album/thumbs/album.blade.php delete mode 100644 resources/views/components/gallery/album/thumbs/photo.blade.php delete mode 100644 resources/views/components/gallery/badge.blade.php delete mode 100644 resources/views/components/gallery/divider.blade.php delete mode 100644 resources/views/components/gallery/photo/button.blade.php delete mode 100644 resources/views/components/gallery/photo/downloads.blade.php delete mode 100644 resources/views/components/gallery/photo/line.blade.php delete mode 100644 resources/views/components/gallery/photo/next-previous.blade.php delete mode 100644 resources/views/components/gallery/photo/overlay.blade.php delete mode 100644 resources/views/components/gallery/photo/properties.blade.php delete mode 100644 resources/views/components/gallery/photo/sidebar.blade.php delete mode 100644 resources/views/components/gallery/view/photo-listing.blade.php delete mode 100644 resources/views/components/gallery/view/photo.blade.php delete mode 100644 resources/views/components/header/actions-menus.blade.php delete mode 100644 resources/views/components/header/back-button.blade.php delete mode 100644 resources/views/components/header/back.blade.php delete mode 100644 resources/views/components/header/bar.blade.php delete mode 100644 resources/views/components/header/button.blade.php delete mode 100644 resources/views/components/header/title.blade.php delete mode 100644 resources/views/components/help/cell.blade.php delete mode 100644 resources/views/components/help/head.blade.php delete mode 100644 resources/views/components/help/kbd.blade.php delete mode 100644 resources/views/components/help/table.blade.php delete mode 100644 resources/views/components/icons/iconic.blade.php delete mode 100644 resources/views/components/layouts/app.blade.php delete mode 100644 resources/views/components/leftbar/disabled-leftbar-item.blade.php delete mode 100644 resources/views/components/leftbar/leftbar-item.blade.php delete mode 100644 resources/views/components/maintenance/button.blade.php delete mode 100644 resources/views/components/maintenance/card.blade.php delete mode 100644 resources/views/components/maintenance/h1.blade.php delete mode 100644 resources/views/components/maintenance/loading.blade.php delete mode 100644 resources/views/components/maintenance/p.blade.php delete mode 100644 resources/views/components/notifications.blade.php delete mode 100644 resources/views/components/shortcuts.blade.php delete mode 100644 resources/views/components/update-status.blade.php delete mode 100644 resources/views/components/webauthn/login.blade.php delete mode 100644 resources/views/livewire/components/context-menu.blade.php delete mode 100644 resources/views/livewire/components/left-menu.blade.php delete mode 100644 resources/views/livewire/components/modal.blade.php delete mode 100644 resources/views/livewire/context-menus/album-add.blade.php delete mode 100644 resources/views/livewire/context-menus/album-dropdown.blade.php delete mode 100644 resources/views/livewire/context-menus/albums-dropdown.blade.php delete mode 100644 resources/views/livewire/context-menus/photo-dropdown.blade.php delete mode 100644 resources/views/livewire/context-menus/photos-add.blade.php delete mode 100644 resources/views/livewire/context-menus/photos-dropdown.blade.php delete mode 100644 resources/views/livewire/forms/add/create-tag.blade.php delete mode 100644 resources/views/livewire/forms/add/create.blade.php delete mode 100644 resources/views/livewire/forms/add/import-from-dropbox.blade.php delete mode 100644 resources/views/livewire/forms/add/import-from-server.blade.php delete mode 100644 resources/views/livewire/forms/add/import-from-server.old.blade.php delete mode 100644 resources/views/livewire/forms/add/import-from-url.blade.php delete mode 100644 resources/views/livewire/forms/add/upload.blade.php delete mode 100644 resources/views/livewire/forms/album/add-track.blade.php delete mode 100644 resources/views/livewire/forms/album/delete-panel.blade.php delete mode 100644 resources/views/livewire/forms/album/delete-track.blade.php delete mode 100644 resources/views/livewire/forms/album/delete.blade.php delete mode 100644 resources/views/livewire/forms/album/merge.blade.php delete mode 100644 resources/views/livewire/forms/album/move-panel.blade.php delete mode 100644 resources/views/livewire/forms/album/move.blade.php delete mode 100644 resources/views/livewire/forms/album/properties.blade.php delete mode 100644 resources/views/livewire/forms/album/rename.blade.php delete mode 100644 resources/views/livewire/forms/album/search-album.blade.php delete mode 100644 resources/views/livewire/forms/album/set-header.blade.php delete mode 100644 resources/views/livewire/forms/album/share-with-line.blade.php delete mode 100644 resources/views/livewire/forms/album/share-with.blade.php delete mode 100644 resources/views/livewire/forms/album/transfer.blade.php delete mode 100644 resources/views/livewire/forms/album/unlock-album.blade.php delete mode 100644 resources/views/livewire/forms/album/visibility.blade.php delete mode 100644 resources/views/livewire/forms/confirms/save-all.blade.php delete mode 100644 resources/views/livewire/forms/default.blade.php delete mode 100644 resources/views/livewire/forms/photo/copyTo.blade.php delete mode 100644 resources/views/livewire/forms/photo/delete.blade.php delete mode 100644 resources/views/livewire/forms/photo/download.blade.php delete mode 100644 resources/views/livewire/forms/photo/move.blade.php delete mode 100644 resources/views/livewire/forms/photo/rename.blade.php delete mode 100644 resources/views/livewire/forms/photo/tag.blade.php delete mode 100644 resources/views/livewire/forms/profile/get-api-token.blade.php delete mode 100644 resources/views/livewire/forms/profile/manage-second-factor.blade.php delete mode 100644 resources/views/livewire/forms/profile/oauth.blade.php delete mode 100644 resources/views/livewire/forms/profile/set-login.blade.php delete mode 100644 resources/views/livewire/forms/settings/double-drop-down.blade.php delete mode 100644 resources/views/livewire/forms/settings/drop-down.blade.php delete mode 100644 resources/views/livewire/forms/settings/input.blade.php delete mode 100644 resources/views/livewire/forms/settings/password.blade.php delete mode 100644 resources/views/livewire/forms/settings/toggle.blade.php delete mode 100644 resources/views/livewire/modals/about.blade.php delete mode 100644 resources/views/livewire/modals/login.blade.php delete mode 100644 resources/views/livewire/modules/diagnostics/pre-colored.blade.php delete mode 100644 resources/views/livewire/modules/diagnostics/pre.blade.php delete mode 100644 resources/views/livewire/modules/diagnostics/with-action-call.blade.php delete mode 100644 resources/views/livewire/modules/gallery/sensitive-warning.blade.php delete mode 100644 resources/views/livewire/modules/jobs/feedback.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/cleaning.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/fill-filesize-sizevariants.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/fix-jobs.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/fix-tree.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/gen-sizevariants.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/optimize-db.blade.php delete mode 100644 resources/views/livewire/modules/maintenance/update.blade.php delete mode 100644 resources/views/livewire/modules/profile/second-factor.blade.php delete mode 100644 resources/views/livewire/modules/users/user-line.blade.php delete mode 100644 resources/views/livewire/pages/all-settings.blade.php delete mode 100644 resources/views/livewire/pages/diagnostics.blade.php delete mode 100644 resources/views/livewire/pages/gallery/album.blade.php delete mode 100644 resources/views/livewire/pages/gallery/albums.blade.php delete mode 100644 resources/views/livewire/pages/gallery/frame.blade.php delete mode 100644 resources/views/livewire/pages/gallery/map.blade.php delete mode 100644 resources/views/livewire/pages/gallery/search.blade.php delete mode 100644 resources/views/livewire/pages/jobs.blade.php delete mode 100644 resources/views/livewire/pages/landing.blade.php delete mode 100644 resources/views/livewire/pages/login.blade.php delete mode 100644 resources/views/livewire/pages/maintenance.blade.php delete mode 100644 resources/views/livewire/pages/profile.blade.php delete mode 100644 resources/views/livewire/pages/settings.blade.php delete mode 100644 resources/views/livewire/pages/sharing.blade.php delete mode 100644 resources/views/livewire/pages/users.blade.php delete mode 100644 resources/views/vendor/livewire/simple-tailwind.blade.php delete mode 100644 resources/views/vendor/livewire/tailwind.blade.php delete mode 100644 resources/views/vendor/pagination/tailwind.blade.php create mode 100644 resources/views/vueapp.blade.php rename routes/{api.php => api_v1.php} (88%) create mode 100644 routes/api_v2.php rename routes/{web-admin.php => web-admin-v1.php} (100%) create mode 100644 routes/web-admin-v2.php delete mode 100644 routes/web-livewire.php rename routes/{web.php => web_v1.php} (76%) create mode 100644 routes/web_v2.php create mode 100644 scripts/delete_legacy.sh create mode 100644 sonar-project.properties delete mode 100644 storage/livewire-tmp/.gitignore rename storage/{extract-jobs => tmp/extract}/.gitignore (100%) rename storage/{image-jobs => tmp/jobs}/.gitignore (100%) rename storage/{image-tmp => tmp/uploads}/.gitignore (100%) rename tailwind.config.js => tailwind.config.ts (62%) create mode 100644 tests/Constants/FreeVerifyier.php create mode 100644 tests/Constants/SupporterVerifyier.php create mode 100644 tests/Feature_v2/Album/AlbumDeleteTest.php create mode 100644 tests/Feature_v2/Album/AlbumListTest.php create mode 100644 tests/Feature_v2/Album/AlbumMoveTest.php create mode 100644 tests/Feature_v2/Album/AlbumRenameTest.php create mode 100644 tests/Feature_v2/Album/AlbumSetCoverTest.php create mode 100644 tests/Feature_v2/Album/AlbumSetHeaderTest.php create mode 100644 tests/Feature_v2/Album/AlbumTest.php create mode 100644 tests/Feature_v2/Album/AlbumTransferTest.php create mode 100644 tests/Feature_v2/Album/AlbumUpdateTest.php create mode 100644 tests/Feature_v2/Album/AlbumsTest.php create mode 100644 tests/Feature_v2/Album/ConfigTest.php create mode 100644 tests/Feature_v2/Album/SharingTest.php create mode 100644 tests/Feature_v2/AuthTest.php create mode 100644 tests/Feature_v2/Base/BaseApiV2Test.php rename tests/{Livewire/Base/BaseLivewireTest.php => Feature_v2/Base/BaseV2Test.php} (54%) create mode 100644 tests/Feature_v2/Diagnostics/ConfigTest.php create mode 100644 tests/Feature_v2/Diagnostics/ErrorsTest.php create mode 100644 tests/Feature_v2/Diagnostics/InfoTest.php create mode 100644 tests/Feature_v2/Diagnostics/PermissionTest.php create mode 100644 tests/Feature_v2/Diagnostics/SpaceTest.php create mode 100644 tests/Feature_v2/Frame/FrameTest.php create mode 100644 tests/Feature_v2/Jobs/GetJobTest.php create mode 100644 tests/Feature_v2/LandingTest.php create mode 100644 tests/Feature_v2/Maintenance/CleaningTest.php create mode 100644 tests/Feature_v2/Maintenance/GenSizeVariantsTest.php create mode 100644 tests/Feature_v2/Maintenance/JobsTest.php create mode 100644 tests/Feature_v2/Maintenance/MissingFileSizeTest.php create mode 100644 tests/Feature_v2/Maintenance/OptimizeTest.php create mode 100644 tests/Feature_v2/Maintenance/RegisterTest.php create mode 100644 tests/Feature_v2/Maintenance/TreeTest.php create mode 100644 tests/Feature_v2/Maintenance/UpdateTest.php create mode 100644 tests/Feature_v2/Map/MapTest.php create mode 100644 tests/Feature_v2/Oauth/OauthTest.php create mode 100644 tests/Feature_v2/PagesTest.php create mode 100644 tests/Feature_v2/Photo/PhotoRenameTest.php create mode 100644 tests/Feature_v2/Photo/PhotoTagsTest.php create mode 100644 tests/Feature_v2/ProfileTest.php create mode 100644 tests/Feature_v2/Search/SearchTest.php create mode 100644 tests/Feature_v2/Settings/GetAllSettingsTest.php create mode 100644 tests/Feature_v2/Settings/UpdateSettingsTest.php create mode 100644 tests/Feature_v2/Statistics/AlbumSpaceTest.php create mode 100644 tests/Feature_v2/Statistics/SizeVariantSpaceTest.php create mode 100644 tests/Feature_v2/Statistics/TotalAlbumSpaceTest.php create mode 100644 tests/Feature_v2/Statistics/UserSpaceTest.php create mode 100644 tests/Feature_v2/UserManagement/CreateUserTest.php create mode 100644 tests/Feature_v2/UserManagement/DeleteUserTest.php create mode 100644 tests/Feature_v2/UserManagement/EditUserTest.php create mode 100644 tests/Feature_v2/UserManagement/ListUserTest.php create mode 100644 tests/Feature_v2/UsersTest.php create mode 100644 tests/Feature_v2/VersionTest.php create mode 100644 tests/Feature_v2/WebAuthTest.php delete mode 100644 tests/Livewire/Forms/Album/CreateTagTest.php delete mode 100644 tests/Livewire/Forms/Album/CreateTest.php delete mode 100644 tests/Livewire/Forms/Album/DeletePanelTest.php delete mode 100644 tests/Livewire/Forms/Album/DeleteTest.php delete mode 100644 tests/Livewire/Forms/Album/MergeMoveTest.php delete mode 100644 tests/Livewire/Forms/Album/MovePanelTest.php delete mode 100644 tests/Livewire/Forms/Album/PropertiesTest.php delete mode 100644 tests/Livewire/Forms/Album/RenameTest.php delete mode 100644 tests/Livewire/Forms/Album/SearchAlbumTest.php delete mode 100644 tests/Livewire/Forms/Album/ShareWithTest.php delete mode 100644 tests/Livewire/Forms/Album/TransferTest.php delete mode 100644 tests/Livewire/Forms/Album/VisibilityTest.php delete mode 100644 tests/Livewire/Forms/ConfirmTest.php delete mode 100644 tests/Livewire/Forms/FormsProfileTest.php delete mode 100644 tests/Livewire/Forms/ImportFromDropBoxTest.php delete mode 100644 tests/Livewire/Forms/ImportFromServerTest.php delete mode 100644 tests/Livewire/Forms/ImportFromUrlTest.php delete mode 100644 tests/Livewire/Forms/Photo/CopyToTest.php delete mode 100644 tests/Livewire/Forms/Photo/DeleteTest.php delete mode 100644 tests/Livewire/Forms/Photo/DownloadTest.php delete mode 100644 tests/Livewire/Forms/Photo/MoveTest.php delete mode 100644 tests/Livewire/Forms/Photo/RenameTest.php delete mode 100644 tests/Livewire/Forms/Photo/TagTest.php delete mode 100644 tests/Livewire/Forms/Profile/OauthTest.php delete mode 100644 tests/Livewire/Forms/SettingsTest.php delete mode 100644 tests/Livewire/Forms/UploadTest.php delete mode 100644 tests/Livewire/Menus/AlbumAddTest.php delete mode 100644 tests/Livewire/Menus/AlbumDropdownTest.php delete mode 100644 tests/Livewire/Menus/AlbumsDropdownTest.php delete mode 100644 tests/Livewire/Menus/ContextMenuTest.php delete mode 100644 tests/Livewire/Menus/LeftMenuTest.php delete mode 100644 tests/Livewire/Menus/PhotoDropdownTest.php delete mode 100644 tests/Livewire/Menus/PhotosDropdownTest.php delete mode 100644 tests/Livewire/Modals/AboutTest.php delete mode 100644 tests/Livewire/Modals/LoginTest.php delete mode 100644 tests/Livewire/Modals/ModalTest.php delete mode 100644 tests/Livewire/Modules/ErrorsTest.php delete mode 100644 tests/Livewire/Modules/JobFeedbackTest.php delete mode 100644 tests/Livewire/Modules/SpaceTest.php delete mode 100644 tests/Livewire/Modules/UserLineTest.php delete mode 100644 tests/Livewire/Pages/AlbumTest.php delete mode 100644 tests/Livewire/Pages/AllSettingsTest.php delete mode 100644 tests/Livewire/Pages/DiagnosticsTest.php delete mode 100644 tests/Livewire/Pages/FrameTest.php delete mode 100644 tests/Livewire/Pages/GalleryTest.php delete mode 100644 tests/Livewire/Pages/IndexTest.php delete mode 100644 tests/Livewire/Pages/JobsTest.php delete mode 100644 tests/Livewire/Pages/LandingTest.php delete mode 100644 tests/Livewire/Pages/LoginTest.php delete mode 100644 tests/Livewire/Pages/MaintenanceTest.php delete mode 100644 tests/Livewire/Pages/MapTest.php delete mode 100644 tests/Livewire/Pages/ProfileTest.php delete mode 100644 tests/Livewire/Pages/SearchTest.php delete mode 100644 tests/Livewire/Pages/SettingsTest.php delete mode 100644 tests/Livewire/Pages/SharingTest.php delete mode 100644 tests/Livewire/Pages/UsersTest.php delete mode 100644 tests/Livewire/WireableTest.php create mode 100644 tests/MigrateApplication.php create mode 100644 tests/Traits/RequireSupport.php create mode 100644 tests/Unit/CoverageTest.php create mode 100644 tests/Unit/FeaturesUnitTest.php rename tests/{Feature_v1 => Unit}/GitRemoteTest.php (98%) rename tests/{Feature_v1 => Unit}/HelpersUnitTest.php (97%) rename tests/{Feature_v1 => Unit}/HoneyPotTest.php (74%) rename tests/{Feature_v1 => Unit}/LangTest.php (99%) create mode 100644 tests/Unit/Middleware/HasAdminUserTest.php create mode 100644 tests/Unit/Middleware/LoginRequiredTest.php create mode 100644 tests/Unit/Middleware/MigrationStatusTest.php create mode 100644 tests/Unit/Redirections/ToAdminSetterTest.php create mode 100644 tests/Unit/Redirections/ToHomeTest.php create mode 100644 tests/Unit/Redirections/ToMigrationTest.php rename tests/{Feature_v1 => Unit}/RootTest.php (96%) create mode 100644 tests/Unit/Rules/AlbumIDListRuleTest.php create mode 100644 tests/Unit/Rules/AlbumIDRuleTest.php create mode 100644 tests/Unit/Rules/ConfigKeyRequireSupportRuleTest.php create mode 100644 tests/Unit/Rules/ConfigKeyRuleTest.php create mode 100644 tests/Unit/Rules/CurrentPasswordRuleTest.php create mode 100644 tests/Unit/Rules/ExtensionRuleTest.php create mode 100644 tests/Unit/Rules/FileUuidRuleTest.php create mode 100644 tests/Unit/Rules/RandomIDListRuleTest.php create mode 100644 tests/Unit/Rules/RequireSupportRuleTest.php create mode 100644 tests/Unit/Rules/StringRuleTest.php rename tests/{Feature_v1 => Unit}/VersionDTOUnitTest.php (97%) delete mode 100644 vite.config.js create mode 100644 vite.config.ts diff --git a/.env.example b/.env.example index 43f5f14119b..45f2085441c 100644 --- a/.env.example +++ b/.env.example @@ -17,12 +17,15 @@ APP_FORCE_HTTPS=false # Do note that this disable CSP!! DEBUGBAR_ENABLED=false -# enable or disable the v5 layout. -LIVEWIRE_ENABLED=true +# enable or disable the v6 layout. +VUEJS_ENABLED=true # enable or disable log viewer. By default it is enabled. LOG_VIEWER_ENABLED=true +# enable or disable clockwork. By default it is disabled (and not provided on non-dev build). +CLOCKWORK_ENABLE=false + # enable s3 bucket (required in addition to needing AWS_ACCESS_KEY_ID) # S3_ENABLED=true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..059da0ee618 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: npm + directory: / + schedule: + interval: daily + + - package-ecosystem: composer + directory: / + schedule: + interval: daily \ No newline at end of file diff --git a/.github/workflows/.env.legacy.mariadb b/.github/workflows/.env.legacy.mariadb index d0f5caa9912..d5a1c3812fe 100644 --- a/.github/workflows/.env.legacy.mariadb +++ b/.github/workflows/.env.legacy.mariadb @@ -3,7 +3,7 @@ APP_URL=https://localhost APP_ENV=dev APP_KEY=SomeRandomString APP_DEBUG=true -LIVEWIRE_ENABLED=false +VUEJS_ENABLED=false LEGACY_API_ENABLED=true DB_CONNECTION=mysql diff --git a/.github/workflows/.env.legacy.postgresql b/.github/workflows/.env.legacy.postgresql index 3fd71d2c2bd..2b83015fc72 100644 --- a/.github/workflows/.env.legacy.postgresql +++ b/.github/workflows/.env.legacy.postgresql @@ -3,7 +3,7 @@ APP_URL=https://localhost APP_ENV=dev APP_KEY=SomeRandomString APP_DEBUG=true -LIVEWIRE_ENABLED=false +VUEJS_ENABLED=false LEGACY_API_ENABLED=true DB_CONNECTION=pgsql diff --git a/.github/workflows/.env.legacy.sqlite b/.github/workflows/.env.legacy.sqlite index d2cb2964594..ad87fb4867b 100644 --- a/.github/workflows/.env.legacy.sqlite +++ b/.github/workflows/.env.legacy.sqlite @@ -3,7 +3,7 @@ APP_URL=https://localhost APP_ENV=dev APP_KEY=SomeRandomString APP_DEBUG=true -LIVEWIRE_ENABLED=false +VUEJS_ENABLED=false LEGACY_API_ENABLED=true DB_CONNECTION=sqlite diff --git a/.github/workflows/.env.mariadb b/.github/workflows/.env.mariadb new file mode 100644 index 00000000000..bdff1d00018 --- /dev/null +++ b/.github/workflows/.env.mariadb @@ -0,0 +1,21 @@ +APP_NAME=Lychee +APP_URL=https://localhost +APP_ENV=dev +APP_KEY=SomeRandomString +APP_DEBUG=true +VUEJS_ENABLED=true +LEGACY_API_ENABLED=false + +DB_CONNECTION=mysql +DB_HOST=localhost +DB_PORT=3306 +DB_DATABASE=homestead_test +DB_USERNAME=root +DB_PASSWORD=root +DB_LIST_FOREIGN_KEYS=true + +CACHE_DRIVER=array +SESSION_DRIVER=array +QUEUE_CONNECTION=sync + +PHOTO_PIPES=true diff --git a/.github/workflows/.env.postgresql b/.github/workflows/.env.postgresql new file mode 100644 index 00000000000..2d6e00da19d --- /dev/null +++ b/.github/workflows/.env.postgresql @@ -0,0 +1,18 @@ +APP_NAME=Lychee +APP_URL=https://localhost +APP_ENV=dev +APP_KEY=SomeRandomString +APP_DEBUG=true +VUEJS_ENABLED=true +LEGACY_API_ENABLED=false + +DB_CONNECTION=pgsql +DB_HOST=localhost +DB_PORT=5432 +DB_DATABASE=postgres +DB_USERNAME=postgres +DB_PASSWORD=postgres + +CACHE_DRIVER=array +SESSION_DRIVER=array +QUEUE_CONNECTION=sync diff --git a/.github/workflows/.env.sqlite b/.github/workflows/.env.sqlite new file mode 100644 index 00000000000..d199e593699 --- /dev/null +++ b/.github/workflows/.env.sqlite @@ -0,0 +1,14 @@ +APP_NAME=Lychee +APP_URL=https://localhost +APP_ENV=dev +APP_KEY=SomeRandomString +APP_DEBUG=true +VUEJS_ENABLED=true +LEGACY_API_ENABLED=false + +DB_CONNECTION=sqlite +DB_LIST_FOREIGN_KEYS=true + +CACHE_DRIVER=array +SESSION_DRIVER=array +QUEUE_CONNECTION=sync diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 42fd14fd4d1..3d2e052fb42 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -27,6 +27,11 @@ jobs: # We want to run on external PRs, but not on our own internal PRs as they'll be run by the push to the branch. if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # 0.12.1 with: @@ -38,6 +43,11 @@ jobs: needs: - kill_previous steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Setup PHP Action uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 with: @@ -58,6 +68,11 @@ jobs: needs: - php_syntax_errors steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Set up PHP uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 with: @@ -84,6 +99,11 @@ jobs: needs: - php_syntax_errors steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Checkout code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -101,20 +121,33 @@ jobs: tests_legacy: name: 2️⃣ PHP tests legacy - uses: ./.github/workflows/php_tests.yml needs: - php_syntax_errors + uses: ./.github/workflows/php_tests.yml with: test-suite: 'Feature_v1' env-file: '.env.legacy' + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + tests: + name: 2️⃣ PHP tests + needs: + - php_syntax_errors + uses: ./.github/workflows/php_tests.yml + with: + test-suite: 'Unit,Feature_v2' + env-file: '.env' + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} dist: name: 3️⃣ PHP dist needs: - code_style_errors uses: ./.github/workflows/php_dist.yml - with: - env-file: '.env.legacy' createArtifact: name: 4️⃣ Build Artifact @@ -122,6 +155,7 @@ jobs: needs: - phpstan - dist + - tests - tests_legacy - check_js runs-on: ubuntu-latest @@ -129,6 +163,11 @@ jobs: extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Checkout code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/CICD_no_legacy.yml b/.github/workflows/CICD_no_legacy.yml new file mode 100644 index 00000000000..beafdb9bd71 --- /dev/null +++ b/.github/workflows/CICD_no_legacy.yml @@ -0,0 +1,209 @@ +name: Integrate without legacy support + +# Run this workflow every time a new commit pushed to your repository +on: + push: + paths-ignore: + - '**/*.md' + - 'public/dist/*.js' + - 'public/dist/**/*.js' + - 'public/Lychee-front' + pull_request: + paths-ignore: + - '**/*.md' + - 'public/dist/*.js' + - 'public/dist/**/*.js' + - 'public/Lychee-front' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Declare default permissions as read only. +permissions: read-all + +jobs: + kill_previous: + name: 0️⃣ Kill previous runs + runs-on: ubuntu-latest + # We want to run on external PRs, but not on our own internal PRs as they'll be run by the push to the branch. + if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # 0.12.1 + with: + access_token: ${{ github.token }} + + php_syntax_errors: + name: 1️⃣ PHP 8.2 - Syntax errors + runs-on: ubuntu-latest + needs: + - kill_previous + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Setup PHP Action + uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 + with: + php-version: 8.2 + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Removing legacy files + run: | + sh scripts/delete_legacy.sh + + - name: Install dependencies + uses: ramsey/composer-install@57532f8be5bda426838819c5ee9afb8af389d51a # 3.0.0 + + - name: Check source code for syntax errors + run: vendor/bin/parallel-lint --exclude .git --exclude vendor . + + code_style_errors: + name: 2️⃣ PHP 8.2 - Code Style errors + runs-on: ubuntu-latest + needs: + - php_syntax_errors + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Set up PHP + uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 + with: + php-version: 8.2 + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Removing legacy files + run: | + sh scripts/delete_legacy.sh + + - name: Install dependencies + uses: ramsey/composer-install@57532f8be5bda426838819c5ee9afb8af389d51a # 3.0.0 + + - name: Check source code for code style errors + run: PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --verbose --diff --dry-run + + check_js: + uses: ./.github/workflows/js_check.yml + needs: + - php_syntax_errors + name: 2️⃣ JS front-end + + phpstan: + name: 2️⃣ PHP 8.2 - PHPStan + runs-on: ubuntu-latest + needs: + - php_syntax_errors + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Removing legacy files + run: | + sh scripts/delete_legacy.sh + + - name: Setup PHP + uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 + with: + php-version: 8.2 + coverage: none + + - name: Install Composer dependencies + uses: ramsey/composer-install@57532f8be5bda426838819c5ee9afb8af389d51a # 3.0.0 + + - name: Run PHPStan + run: vendor/bin/phpstan analyze + + tests: + name: 2️⃣ PHP tests + needs: + - php_syntax_errors + uses: ./.github/workflows/php_no_legacy_tests.yml + with: + test-suite: 'Unit,Feature_v2' + env-file: '.env' + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + dist: + name: 3️⃣ PHP dist + needs: + - code_style_errors + uses: ./.github/workflows/php_no_legacy_dist.yml + + createArtifact: + name: 4️⃣ Build Artifact + if: github.ref == 'refs/heads/master' + needs: + - phpstan + - dist + - tests + - check_js + runs-on: ubuntu-latest + env: + extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip + + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Removing legacy files + run: | + sh scripts/delete_legacy.sh + + - name: Setup PHP + uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 + with: + php-version: 8.2 + extensions: ${{ env.extensions }} + coverage: none + + - name: Install Composer dependencies + uses: ramsey/composer-install@57532f8be5bda426838819c5ee9afb8af389d51a # 3.0.0 + with: + composer-options: --no-dev + + - name: Use Node.js 20 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 20 + + - name: Install + run: npm install + + - name: Compile Front-end + run: npm run build + + - name: Build Dist + run: | + make clean dist + + - name: Upload a Build Artifact + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: Lychee-Dist.zip + path: Lychee.zip + if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn` diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml deleted file mode 100644 index c6acb29eb1b..00000000000 --- a/.github/workflows/dependency-check.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: PR dependency check - -on: - pull_request_target: - types: [opened, edited, closed, reopened] - -jobs: - check_dependencies: - runs-on: ubuntu-latest - name: Check Dependencies - steps: - - uses: gregsdennis/dependencies-action@4fc2a4879387b43f784920699cb9303dd0524ac4 # 1.3.3 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/js_check.yml b/.github/workflows/js_check.yml index a9cf2fb8fa0..c3370b07d86 100644 --- a/.github/workflows/js_check.yml +++ b/.github/workflows/js_check.yml @@ -9,24 +9,31 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [18, 20] + node-version: + # - 18 + - 20 steps: - - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 - with: - node-version: ${{ matrix.node-version }} + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Install - run: npm install -D + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: ${{ matrix.node-version }} - - name: Check Style - run: npm run check-formatting + - name: Install + run: npm ci -D - - name: Check TypeScript - run: npm run check + - name: Check Style + run: npm run check-formatting - - name: Compile Front-end - run: npm run build + - name: Check TypeScript + run: npm run check + + - name: Compile Front-end + run: npm run build diff --git a/.github/workflows/php_dist.yml b/.github/workflows/php_dist.yml index 4d4367e902c..fcc864bdd64 100644 --- a/.github/workflows/php_dist.yml +++ b/.github/workflows/php_dist.yml @@ -2,11 +2,6 @@ name: PHP Dist on: workflow_call: - inputs: - env-file: - required: true - type: string - description: 'The env files to use' jobs: php_dist: @@ -42,6 +37,11 @@ jobs: extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Checkout code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -75,7 +75,7 @@ jobs: - name: copy Env run: | - cp .github/workflows/${{ inputs.env-file }}.${{ matrix.sql-versions }} Lychee/.env + cp .github/workflows/.env.${{ matrix.sql-versions }} Lychee/.env - name: setup MySQL Database with v3 run: | diff --git a/.github/workflows/php_no_legacy_dist.yml b/.github/workflows/php_no_legacy_dist.yml new file mode 100644 index 00000000000..f853ab74953 --- /dev/null +++ b/.github/workflows/php_no_legacy_dist.yml @@ -0,0 +1,94 @@ +name: Check JS + +on: + workflow_call: + +jobs: + php_dist: + name: ${{ matrix.php-version }} - ${{ matrix.sql-versions }} + runs-on: ubuntu-latest + strategy: + matrix: + php-version: + - 8.2 + sql-versions: + - mariadb + - postgresql + - sqlite + # Service containers to run with `container-job` + services: + # Label used to access the service container + postgres: + # Docker Hub image + image: postgres + # Provide the password for postgres + env: + POSTGRES_PASSWORD: postgres + # Set health checks to wait until postgres has started + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + # Maps tcp port 5432 on service container to the host + - 5432:5432 + env: + extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip + + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Removing legacy files + run: | + sh scripts/delete_legacy.sh + + - name: Set Up Imagick, FFmpeg & Exiftools + run: | + sudo apt-get update + sudo apt-get --fix-broken install + sudo apt-get -y install ffmpeg libimage-exiftool-perl + + - name: setup Databases + run: | + sudo service mysql start + touch database/database.sqlite + mysql -uroot -proot -e 'create database homestead_test;' + + - name: Setup PHP Action + uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 + with: + php-version: ${{ matrix.php-version }} + extensions: ${{ env.extensions }} + tools: pecl, composer + + - name: Install Composer dependencies + uses: ramsey/composer-install@57532f8be5bda426838819c5ee9afb8af389d51a # 3.0.0 + with: + composer-options: --no-dev + + - name: Build Dist + run: | + make dist-clean + + - name: copy Env + run: | + cp .github/workflows/.env.${{ matrix.sql-versions }} Lychee/.env + + - name: setup MySQL Database with v3 + run: | + mysql -uroot -proot homestead_test < .github/workflows/v3.sql + + - name: Generate secure key & Migrate & go backward + run: | + cd Lychee + pwd + php artisan key:generate + php artisan migrate + php artisan migrate:rollback diff --git a/.github/workflows/php_no_legacy_tests.yml b/.github/workflows/php_no_legacy_tests.yml new file mode 100644 index 00000000000..66e81f82063 --- /dev/null +++ b/.github/workflows/php_no_legacy_tests.yml @@ -0,0 +1,117 @@ +name: Check JS + +on: + workflow_call: + inputs: + test-suite: + required: true + type: string + description: 'The test suite to run' + env-file: + required: true + type: string + description: 'The env files to use' + secrets: + SONAR_TOKEN: + required: true + description: 'sonar token secret' + CODECOV_TOKEN: + required: true + description: 'codecov token secret' + +jobs: + tests: + name: ${{ matrix.php-version }} - ${{ matrix.sql-versions }} -- ${{ inputs.test-suite }} + runs-on: ubuntu-latest + strategy: + matrix: + php-version: + # - 8.2 + - 8.3 + sql-versions: + - mariadb + - postgresql + - sqlite + # Service containers to run with `container-job` + services: + # Label used to access the service container + postgres: + # Docker Hub image + image: postgres + # Provide the password for postgres + env: + POSTGRES_PASSWORD: postgres + # Set health checks to wait until postgres has started + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + # Maps tcp port 5432 on service container to the host + - 5432:5432 + env: + extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip + + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Removing legacy files + run: | + sh scripts/delete_legacy.sh + + - name: Set Up Imagick, FFmpeg & Exiftools + run: | + sudo apt-get update + sudo apt-get --fix-broken install + sudo apt-get -y install ffmpeg libimage-exiftool-perl + + - name: setup Databases + run: | + sudo service mysql start + touch database/database.sqlite + mysql -uroot -proot -e 'create database homestead_test;' + + - name: Setup PHP Action + uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # 2.30.0 + with: + php-version: ${{ matrix.php-version }} + extensions: ${{ env.extensions }} + coverage: xdebug + tools: pecl, composer + + - name: Install Composer dependencies + uses: ramsey/composer-install@57532f8be5bda426838819c5ee9afb8af389d51a # 3.0.0 + + - name: copy Env + run: | + cp .github/workflows/${{ inputs.env-file }}.${{ matrix.sql-versions }} .env + + - name: Generate secure key & Optimize application & Migrate + run: | + php artisan key:generate + php artisan optimize + php artisan migrate + + - name: Apply tests ${{ inputs.test-suite }} + run: XDEBUG_MODE=coverage vendor/bin/phpunit --configuration phpunit.ci.xml --testsuite ${{ inputs.test-suite }} + + - name: Make sure we can go backward + run: php artisan migrate:rollback + + - name: Codecov + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/php_tests.yml b/.github/workflows/php_tests.yml index c1c4d8cc401..f208f369e6c 100644 --- a/.github/workflows/php_tests.yml +++ b/.github/workflows/php_tests.yml @@ -11,6 +11,13 @@ on: required: true type: string description: 'The env files to use' + secrets: + SONAR_TOKEN: + required: true + description: 'sonar token secret' + CODECOV_TOKEN: + required: true + description: 'codecov token secret' jobs: tests: @@ -19,7 +26,7 @@ jobs: strategy: matrix: php-version: - - 8.2 + # - 8.2 - 8.3 sql-versions: - mariadb @@ -47,6 +54,11 @@ jobs: extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: Checkout code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -84,12 +96,18 @@ jobs: php artisan migrate - name: Apply tests ${{ inputs.test-suite }} - run: XDEBUG_MODE=coverage vendor/bin/phpunit --testsuite ${{ inputs.test-suite }} + run: XDEBUG_MODE=coverage vendor/bin/phpunit --configuration phpunit.ci.xml --testsuite ${{ inputs.test-suite }} - name: Make sure we can go backward run: php artisan migrate:rollback - name: Codecov - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master env: - token: ${{ secrets.CODECOV_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index f6406de4aba..7b287cfa75d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -31,6 +31,11 @@ jobs: # actions: read steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + - name: "Checkout code" uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 9f825085ffb..653ea58936d 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -23,6 +23,7 @@ function (PhpCsFixer\Finder $finder, $dir) { 'array_indentation' => true, 'fully_qualified_strict_types' => false, 'backtick_to_shell_exec' => true, + 'new_with_parentheses' => true, 'increment_style' => ['style' => 'post'], 'indentation_type' => true, 'multiline_comment_opening_closing' => true, diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index f0dbabea643..ede375a8f8a 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -1,6 +1,8 @@ '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\Illuminate\Container\Container::makeWith(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\Illuminate\Contracts\Container\Container::get(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\Illuminate\Contracts\Container\Container::make(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\Illuminate\Contracts\Container\Container::makeWith(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\App::get(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\App::make(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\App::makeWith(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\app(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\resolve(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\Psr\Container\ContainerInterface::get(0), map([ '' => '@', - 'App\Actions\InstallUpdate\CheckUpdate' => \App\Actions\InstallUpdate\CheckUpdate::class, 'App\Assets\Helpers' => \App\Assets\Helpers::class, 'App\Contracts\Models\AbstractSizeVariantNamingStrategy' => \App\Assets\SizeVariantGroupedWithRandomSuffixNamingStrategy::class, 'App\Contracts\Models\SizeVariantFactory' => \App\Image\SizeVariantDefaultFactory::class, 'App\Factories\AlbumFactory' => \App\Factories\AlbumFactory::class, - 'App\Metadata\Json\CommitsRequest' => \App\Metadata\Json\CommitsRequest::class, - 'App\Metadata\Json\UpdateRequest' => \App\Metadata\Json\UpdateRequest::class, - 'App\Metadata\Versions\FileVersion' => \App\Metadata\Versions\FileVersion::class, 'App\Metadata\Versions\GitHubVersion' => \App\Metadata\Versions\GitHubVersion::class, - 'App\Metadata\Versions\InstalledVersion' => \App\Metadata\Versions\InstalledVersion::class, 'App\Metadata\Versions\Remote\GitCommits' => \App\Metadata\Versions\Remote\GitCommits::class, 'App\Metadata\Versions\Remote\GitTags' => \App\Metadata\Versions\Remote\GitTags::class, 'App\ModelFunctions\SymLinkFunctions' => \App\ModelFunctions\SymLinkFunctions::class, 'App\Policies\AlbumQueryPolicy' => \App\Policies\AlbumQueryPolicy::class, 'App\Policies\PhotoQueryPolicy' => \App\Policies\PhotoQueryPolicy::class, 'Barryvdh\Debugbar\LaravelDebugbar' => \Barryvdh\Debugbar\LaravelDebugbar::class, - 'Dedoc\Scramble\Support\Generator\TypeTransformer' => \Dedoc\Scramble\Support\Generator\TypeTransformer::class, + 'Dedoc\Scramble\Infer' => \Dedoc\Scramble\Infer::class, + 'Dedoc\Scramble\Infer\Scope\Index' => \Dedoc\Scramble\Infer\Scope\Index::class, + 'Dedoc\Scramble\Infer\Services\FileParser' => \Dedoc\Scramble\Infer\Services\FileParser::class, 'Dedoc\Scramble\Support\ServerFactory' => \Dedoc\Scramble\Support\ServerFactory::class, 'Helpers' => \App\Assets\Helpers::class, 'Illuminate\Auth\Console\ClearResetsCommand' => \Illuminate\Auth\Console\ClearResetsCommand::class, - 'Illuminate\Auth\Middleware\RequirePassword' => \Illuminate\Auth\Middleware\RequirePassword::class, 'Illuminate\Broadcasting\BroadcastManager' => \Illuminate\Broadcasting\BroadcastManager::class, - 'Illuminate\Bus\BatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, - 'Illuminate\Bus\DatabaseBatchRepository' => \Illuminate\Bus\DatabaseBatchRepository::class, 'Illuminate\Bus\Dispatcher' => \Illuminate\Bus\Dispatcher::class, - 'Illuminate\Cache\Console\CacheTableCommand' => \Illuminate\Cache\Console\CacheTableCommand::class, - 'Illuminate\Cache\Console\ClearCommand' => \Illuminate\Cache\Console\ClearCommand::class, - 'Illuminate\Cache\Console\ForgetCommand' => \Illuminate\Cache\Console\ForgetCommand::class, 'Illuminate\Cache\Console\PruneStaleTagsCommand' => \Illuminate\Cache\Console\PruneStaleTagsCommand::class, 'Illuminate\Cache\RateLimiter' => \Illuminate\Cache\RateLimiter::class, - 'Illuminate\Console\Scheduling\Schedule' => \Illuminate\Console\Scheduling\Schedule::class, 'Illuminate\Console\Scheduling\ScheduleClearCacheCommand' => \Illuminate\Console\Scheduling\ScheduleClearCacheCommand::class, 'Illuminate\Console\Scheduling\ScheduleFinishCommand' => \Illuminate\Console\Scheduling\ScheduleFinishCommand::class, - 'Illuminate\Console\Scheduling\ScheduleInterruptCommand' => \Illuminate\Console\Scheduling\ScheduleInterruptCommand::class, 'Illuminate\Console\Scheduling\ScheduleListCommand' => \Illuminate\Console\Scheduling\ScheduleListCommand::class, 'Illuminate\Console\Scheduling\ScheduleRunCommand' => \Illuminate\Console\Scheduling\ScheduleRunCommand::class, 'Illuminate\Console\Scheduling\ScheduleTestCommand' => \Illuminate\Console\Scheduling\ScheduleTestCommand::class, 'Illuminate\Console\Scheduling\ScheduleWorkCommand' => \Illuminate\Console\Scheduling\ScheduleWorkCommand::class, 'Illuminate\Contracts\Auth\Access\Gate' => \Illuminate\Auth\Access\Gate::class, - 'Illuminate\Contracts\Broadcasting\Broadcaster' => \Illuminate\Broadcasting\Broadcasters\NullBroadcaster::class, 'Illuminate\Contracts\Console\Kernel' => \App\Console\Kernel::class, - 'Illuminate\Contracts\Debug\ExceptionHandler' => \App\Exceptions\Handler::class, - 'Illuminate\Contracts\Foundation\MaintenanceMode' => \Illuminate\Foundation\FileBasedMaintenanceMode::class, 'Illuminate\Contracts\Http\Kernel' => \App\Http\Kernel::class, - 'Illuminate\Contracts\Pipeline\Hub' => \Illuminate\Pipeline\Hub::class, 'Illuminate\Contracts\Queue\EntityResolver' => \Illuminate\Database\Eloquent\QueueEntityResolver::class, - 'Illuminate\Contracts\Routing\ResponseFactory' => \Illuminate\Routing\ResponseFactory::class, - 'Illuminate\Contracts\Validation\UncompromisedVerifier' => \Illuminate\Validation\NotPwnedVerifier::class, 'Illuminate\Database\Console\DbCommand' => \Illuminate\Database\Console\DbCommand::class, 'Illuminate\Database\Console\DumpCommand' => \Illuminate\Database\Console\DumpCommand::class, - 'Illuminate\Database\Console\Factories\FactoryMakeCommand' => \Illuminate\Database\Console\Factories\FactoryMakeCommand::class, - 'Illuminate\Database\Console\Migrations\FreshCommand' => \Illuminate\Database\Console\Migrations\FreshCommand::class, 'Illuminate\Database\Console\Migrations\InstallCommand' => \Illuminate\Database\Console\Migrations\InstallCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateCommand' => \Illuminate\Database\Console\Migrations\MigrateCommand::class, - 'Illuminate\Database\Console\Migrations\MigrateMakeCommand' => \Illuminate\Database\Console\Migrations\MigrateMakeCommand::class, 'Illuminate\Database\Console\Migrations\RefreshCommand' => \Illuminate\Database\Console\Migrations\RefreshCommand::class, - 'Illuminate\Database\Console\Migrations\ResetCommand' => \Illuminate\Database\Console\Migrations\ResetCommand::class, - 'Illuminate\Database\Console\Migrations\RollbackCommand' => \Illuminate\Database\Console\Migrations\RollbackCommand::class, - 'Illuminate\Database\Console\Migrations\StatusCommand' => \Illuminate\Database\Console\Migrations\StatusCommand::class, - 'Illuminate\Database\Console\MonitorCommand' => \Illuminate\Database\Console\MonitorCommand::class, 'Illuminate\Database\Console\PruneCommand' => \Illuminate\Database\Console\PruneCommand::class, - 'Illuminate\Database\Console\Seeds\SeedCommand' => \Illuminate\Database\Console\Seeds\SeedCommand::class, - 'Illuminate\Database\Console\Seeds\SeederMakeCommand' => \Illuminate\Database\Console\Seeds\SeederMakeCommand::class, 'Illuminate\Database\Console\ShowCommand' => \Illuminate\Database\Console\ShowCommand::class, 'Illuminate\Database\Console\ShowModelCommand' => \Illuminate\Database\Console\ShowModelCommand::class, 'Illuminate\Database\Console\TableCommand' => \Illuminate\Database\Console\TableCommand::class, 'Illuminate\Database\Console\WipeCommand' => \Illuminate\Database\Console\WipeCommand::class, - 'Illuminate\Foundation\Console\AboutCommand' => \Illuminate\Foundation\Console\AboutCommand::class, - 'Illuminate\Foundation\Console\CastMakeCommand' => \Illuminate\Foundation\Console\CastMakeCommand::class, + 'Illuminate\Foundation\Console\ApiInstallCommand' => \Illuminate\Foundation\Console\ApiInstallCommand::class, + 'Illuminate\Foundation\Console\BroadcastingInstallCommand' => \Illuminate\Foundation\Console\BroadcastingInstallCommand::class, 'Illuminate\Foundation\Console\ChannelListCommand' => \Illuminate\Foundation\Console\ChannelListCommand::class, - 'Illuminate\Foundation\Console\ChannelMakeCommand' => \Illuminate\Foundation\Console\ChannelMakeCommand::class, 'Illuminate\Foundation\Console\ClearCompiledCommand' => \Illuminate\Foundation\Console\ClearCompiledCommand::class, - 'Illuminate\Foundation\Console\ComponentMakeCommand' => \Illuminate\Foundation\Console\ComponentMakeCommand::class, - 'Illuminate\Foundation\Console\ConfigCacheCommand' => \Illuminate\Foundation\Console\ConfigCacheCommand::class, - 'Illuminate\Foundation\Console\ConfigClearCommand' => \Illuminate\Foundation\Console\ConfigClearCommand::class, + 'Illuminate\Foundation\Console\ConfigPublishCommand' => \Illuminate\Foundation\Console\ConfigPublishCommand::class, 'Illuminate\Foundation\Console\ConfigShowCommand' => \Illuminate\Foundation\Console\ConfigShowCommand::class, - 'Illuminate\Foundation\Console\ConsoleMakeCommand' => \Illuminate\Foundation\Console\ConsoleMakeCommand::class, 'Illuminate\Foundation\Console\DocsCommand' => \Illuminate\Foundation\Console\DocsCommand::class, 'Illuminate\Foundation\Console\DownCommand' => \Illuminate\Foundation\Console\DownCommand::class, 'Illuminate\Foundation\Console\EnvironmentCommand' => \Illuminate\Foundation\Console\EnvironmentCommand::class, - 'Illuminate\Foundation\Console\EnvironmentDecryptCommand' => \Illuminate\Foundation\Console\EnvironmentDecryptCommand::class, - 'Illuminate\Foundation\Console\EnvironmentEncryptCommand' => \Illuminate\Foundation\Console\EnvironmentEncryptCommand::class, 'Illuminate\Foundation\Console\EventCacheCommand' => \Illuminate\Foundation\Console\EventCacheCommand::class, - 'Illuminate\Foundation\Console\EventClearCommand' => \Illuminate\Foundation\Console\EventClearCommand::class, 'Illuminate\Foundation\Console\EventGenerateCommand' => \Illuminate\Foundation\Console\EventGenerateCommand::class, 'Illuminate\Foundation\Console\EventListCommand' => \Illuminate\Foundation\Console\EventListCommand::class, - 'Illuminate\Foundation\Console\EventMakeCommand' => \Illuminate\Foundation\Console\EventMakeCommand::class, - 'Illuminate\Foundation\Console\ExceptionMakeCommand' => \Illuminate\Foundation\Console\ExceptionMakeCommand::class, - 'Illuminate\Foundation\Console\JobMakeCommand' => \Illuminate\Foundation\Console\JobMakeCommand::class, 'Illuminate\Foundation\Console\KeyGenerateCommand' => \Illuminate\Foundation\Console\KeyGenerateCommand::class, 'Illuminate\Foundation\Console\LangPublishCommand' => \Illuminate\Foundation\Console\LangPublishCommand::class, - 'Illuminate\Foundation\Console\ListenerMakeCommand' => \Illuminate\Foundation\Console\ListenerMakeCommand::class, - 'Illuminate\Foundation\Console\MailMakeCommand' => \Illuminate\Foundation\Console\MailMakeCommand::class, - 'Illuminate\Foundation\Console\ModelMakeCommand' => \Illuminate\Foundation\Console\ModelMakeCommand::class, - 'Illuminate\Foundation\Console\NotificationMakeCommand' => \Illuminate\Foundation\Console\NotificationMakeCommand::class, - 'Illuminate\Foundation\Console\ObserverMakeCommand' => \Illuminate\Foundation\Console\ObserverMakeCommand::class, 'Illuminate\Foundation\Console\OptimizeClearCommand' => \Illuminate\Foundation\Console\OptimizeClearCommand::class, 'Illuminate\Foundation\Console\OptimizeCommand' => \Illuminate\Foundation\Console\OptimizeCommand::class, 'Illuminate\Foundation\Console\PackageDiscoverCommand' => \Illuminate\Foundation\Console\PackageDiscoverCommand::class, - 'Illuminate\Foundation\Console\PolicyMakeCommand' => \Illuminate\Foundation\Console\PolicyMakeCommand::class, - 'Illuminate\Foundation\Console\ProviderMakeCommand' => \Illuminate\Foundation\Console\ProviderMakeCommand::class, - 'Illuminate\Foundation\Console\RequestMakeCommand' => \Illuminate\Foundation\Console\RequestMakeCommand::class, - 'Illuminate\Foundation\Console\ResourceMakeCommand' => \Illuminate\Foundation\Console\ResourceMakeCommand::class, - 'Illuminate\Foundation\Console\RouteCacheCommand' => \Illuminate\Foundation\Console\RouteCacheCommand::class, - 'Illuminate\Foundation\Console\RouteClearCommand' => \Illuminate\Foundation\Console\RouteClearCommand::class, - 'Illuminate\Foundation\Console\RouteListCommand' => \Illuminate\Foundation\Console\RouteListCommand::class, - 'Illuminate\Foundation\Console\RuleMakeCommand' => \Illuminate\Foundation\Console\RuleMakeCommand::class, - 'Illuminate\Foundation\Console\ScopeMakeCommand' => \Illuminate\Foundation\Console\ScopeMakeCommand::class, 'Illuminate\Foundation\Console\ServeCommand' => \Illuminate\Foundation\Console\ServeCommand::class, 'Illuminate\Foundation\Console\StorageLinkCommand' => \Illuminate\Foundation\Console\StorageLinkCommand::class, + 'Illuminate\Foundation\Console\StorageUnlinkCommand' => \Illuminate\Foundation\Console\StorageUnlinkCommand::class, 'Illuminate\Foundation\Console\StubPublishCommand' => \Illuminate\Foundation\Console\StubPublishCommand::class, - 'Illuminate\Foundation\Console\TestMakeCommand' => \Illuminate\Foundation\Console\TestMakeCommand::class, 'Illuminate\Foundation\Console\UpCommand' => \Illuminate\Foundation\Console\UpCommand::class, - 'Illuminate\Foundation\Console\VendorPublishCommand' => \Illuminate\Foundation\Console\VendorPublishCommand::class, 'Illuminate\Foundation\Console\ViewCacheCommand' => \Illuminate\Foundation\Console\ViewCacheCommand::class, - 'Illuminate\Foundation\Console\ViewClearCommand' => \Illuminate\Foundation\Console\ViewClearCommand::class, - 'Illuminate\Foundation\Console\ViewMakeCommand' => \Illuminate\Foundation\Console\ViewMakeCommand::class, - 'Illuminate\Foundation\MaintenanceModeManager' => \Illuminate\Foundation\MaintenanceModeManager::class, + 'Illuminate\Foundation\Exceptions\Renderer\Listener' => \Illuminate\Foundation\Exceptions\Renderer\Listener::class, 'Illuminate\Foundation\Mix' => \Illuminate\Foundation\Mix::class, 'Illuminate\Foundation\PackageManifest' => \Illuminate\Foundation\PackageManifest::class, 'Illuminate\Foundation\Vite' => \Illuminate\Foundation\Vite::class, - 'Illuminate\Http\Client\Factory' => \Illuminate\Http\Client\Factory::class, - 'Illuminate\Mail\Markdown' => \Illuminate\Mail\Markdown::class, - 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, - 'Illuminate\Notifications\Console\NotificationTableCommand' => \Illuminate\Notifications\Console\NotificationTableCommand::class, - 'Illuminate\Queue\Console\BatchesTableCommand' => \Illuminate\Queue\Console\BatchesTableCommand::class, 'Illuminate\Queue\Console\ClearCommand' => \Illuminate\Queue\Console\ClearCommand::class, - 'Illuminate\Queue\Console\FailedTableCommand' => \Illuminate\Queue\Console\FailedTableCommand::class, 'Illuminate\Queue\Console\FlushFailedCommand' => \Illuminate\Queue\Console\FlushFailedCommand::class, 'Illuminate\Queue\Console\ForgetFailedCommand' => \Illuminate\Queue\Console\ForgetFailedCommand::class, 'Illuminate\Queue\Console\ListFailedCommand' => \Illuminate\Queue\Console\ListFailedCommand::class, 'Illuminate\Queue\Console\ListenCommand' => \Illuminate\Queue\Console\ListenCommand::class, - 'Illuminate\Queue\Console\MonitorCommand' => \Illuminate\Queue\Console\MonitorCommand::class, 'Illuminate\Queue\Console\PruneBatchesCommand' => \Illuminate\Queue\Console\PruneBatchesCommand::class, 'Illuminate\Queue\Console\PruneFailedJobsCommand' => \Illuminate\Queue\Console\PruneFailedJobsCommand::class, - 'Illuminate\Queue\Console\RestartCommand' => \Illuminate\Queue\Console\RestartCommand::class, 'Illuminate\Queue\Console\RetryBatchCommand' => \Illuminate\Queue\Console\RetryBatchCommand::class, 'Illuminate\Queue\Console\RetryCommand' => \Illuminate\Queue\Console\RetryCommand::class, - 'Illuminate\Queue\Console\TableCommand' => \Illuminate\Queue\Console\TableCommand::class, - 'Illuminate\Queue\Console\WorkCommand' => \Illuminate\Queue\Console\WorkCommand::class, - 'Illuminate\Routing\Console\ControllerMakeCommand' => \Illuminate\Routing\Console\ControllerMakeCommand::class, - 'Illuminate\Routing\Console\MiddlewareMakeCommand' => \Illuminate\Routing\Console\MiddlewareMakeCommand::class, 'Illuminate\Routing\Contracts\CallableDispatcher' => \Illuminate\Routing\CallableDispatcher::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, - 'Illuminate\Session\Console\SessionTableCommand' => \Illuminate\Session\Console\SessionTableCommand::class, - 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, 'Illuminate\Testing\ParallelTesting' => \Illuminate\Testing\ParallelTesting::class, + 'Laravel\Socialite\Contracts\Factory' => \Laravel\Socialite\SocialiteManager::class, + 'Livewire\EventBus' => \Livewire\EventBus::class, + 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, + 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, 'Opcodes\LogViewer\LogTypeRegistrar' => \Opcodes\LogViewer\LogTypeRegistrar::class, - 'Spatie\ImageOptimizer\OptimizerChain' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'auth' => \Illuminate\Auth\AuthManager::class, - 'auth.driver' => \App\Services\Auth\SessionOrTokenGuard::class, + 'SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface' => \SocialiteProviders\Manager\Helpers\ConfigRetriever::class, 'blade.compiler' => \Illuminate\View\Compilers\BladeCompiler::class, - 'cache' => \Illuminate\Cache\CacheManager::class, - 'cache.psr6' => \Symfony\Component\Cache\Adapter\Psr16Adapter::class, - 'cache.store' => \Illuminate\Cache\Repository::class, - 'clockwork' => \Clockwork\Clockwork::class, 'clockwork.authenticator' => \Clockwork\Authentication\NullAuthenticator::class, - 'clockwork.cache' => \Clockwork\DataSource\LaravelCacheDataSource::class, - 'clockwork.eloquent' => \Clockwork\DataSource\EloquentDataSource::class, - 'clockwork.events' => \Clockwork\DataSource\LaravelEventsDataSource::class, - 'clockwork.laravel' => \Clockwork\DataSource\LaravelDataSource::class, - 'clockwork.notifications' => \Clockwork\DataSource\LaravelNotificationsDataSource::class, - 'clockwork.queue' => \Clockwork\DataSource\LaravelQueueDataSource::class, - 'clockwork.redis' => \Clockwork\DataSource\LaravelRedisDataSource::class, 'clockwork.request' => \Clockwork\Request\Request::class, 'clockwork.storage' => \Clockwork\Storage\FileStorage::class, 'clockwork.support' => \Clockwork\Support\Laravel\ClockworkSupport::class, - 'clockwork.views' => \Clockwork\DataSource\LaravelViewsDataSource::class, 'clockwork.xdebug' => \Clockwork\DataSource\XdebugDataSource::class, 'command.debugbar.clear' => \Barryvdh\Debugbar\Console\ClearCommand::class, 'command.ide-helper.eloquent' => \Barryvdh\LaravelIdeHelper\Console\EloquentCommand::class, 'command.ide-helper.generate' => \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand::class, 'command.ide-helper.meta' => \Barryvdh\LaravelIdeHelper\Console\MetaCommand::class, 'command.ide-helper.models' => \Barryvdh\LaravelIdeHelper\Console\ModelsCommand::class, - 'composer' => \Illuminate\Support\Composer::class, - 'cookie' => \Illuminate\Cookie\CookieJar::class, - 'db' => \Illuminate\Database\DatabaseManager::class, - 'db.connection' => \Illuminate\Database\MySqlConnection::class, 'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class, - 'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class, 'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class, - 'encrypter' => \Illuminate\Encryption\Encrypter::class, - 'events' => \Illuminate\Events\Dispatcher::class, - 'files' => \Illuminate\Filesystem\Filesystem::class, - 'filesystem' => \Illuminate\Filesystem\FilesystemManager::class, - 'filesystem.disk' => \Illuminate\Filesystem\FilesystemAdapter::class, - 'hash' => \Illuminate\Hashing\HashManager::class, - 'hash.driver' => \Illuminate\Hashing\BcryptHasher::class, - 'image-optimizer' => \Spatie\ImageOptimizer\OptimizerChain::class, - 'log' => \Illuminate\Log\LogManager::class, 'log-viewer' => \Opcodes\LogViewer\LogViewerService::class, - 'log-viewer-cache' => \Illuminate\Cache\Repository::class, 'mail.manager' => \Illuminate\Mail\MailManager::class, 'memcached.connector' => \Illuminate\Cache\MemcachedConnector::class, - 'migration.creator' => \Illuminate\Database\Migrations\MigrationCreator::class, 'migration.repository' => \Illuminate\Database\Migrations\DatabaseMigrationRepository::class, - 'migrator' => \Illuminate\Database\Migrations\Migrator::class, - 'pipeline' => \Illuminate\Pipeline\Pipeline::class, - 'queue' => \Illuminate\Queue\QueueManager::class, - 'queue.connection' => \Illuminate\Queue\SyncQueue::class, - 'queue.failer' => \Illuminate\Queue\Failed\DatabaseUuidFailedJobProvider::class, 'queue.listener' => \Illuminate\Queue\Listener::class, - 'queue.worker' => \Illuminate\Queue\Worker::class, - 'redirect' => \Illuminate\Routing\Redirector::class, - 'redis' => \Illuminate\Redis\RedisManager::class, - 'router' => \Illuminate\Routing\Router::class, - 'session' => \Illuminate\Session\SessionManager::class, - 'session.store' => \Illuminate\Session\Store::class, 'translation.loader' => \Illuminate\Translation\FileLoader::class, - 'translator' => \Illuminate\Translation\Translator::class, - 'url' => \Illuminate\Routing\UrlGenerator::class, - 'validation.presence' => \Illuminate\Validation\DatabasePresenceVerifier::class, - 'view' => \Illuminate\View\Factory::class, 'view.engine.resolver' => \Illuminate\View\Engines\EngineResolver::class, - 'view.finder' => \Illuminate\View\FileViewFinder::class, ])); override(\Illuminate\Foundation\Testing\Concerns\InteractsWithContainer::mock(0), map(['' => "@&\Mockery\MockInterface"])); diff --git a/Makefile b/Makefile index 503560bce34..346b99717fc 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,7 @@ formatting: echo " composer install"; \ echo ""; \ fi + npm run format phpstan: vendor/bin/phpstan analyze @@ -138,4 +139,16 @@ build/%UnitTest.done: build/%.done: tests/Feature_v1/%.php build vendor/bin/phpunit --no-coverage --filter $* && touch build/$*.done -all_tests: $(TEST_DONE) \ No newline at end of file +all_tests: $(TEST_DONE) + +test_unit: + vendor/bin/phpunit --testsuite Unit --stop-on-failure --stop-on-error --no-coverage --log-junit report_unit.xml + +test_v1: + vendor/bin/phpunit --testsuite Feature_v1 --stop-on-failure --stop-on-error --no-coverage --log-junit report_v1.xml + +test_v2: + vendor/bin/phpunit --testsuite Feature_v2 --stop-on-failure --stop-on-error --no-coverage --log-junit report_v2.xml + +gen_typescript_types: + php artisan typescript:transform \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Album/SearchAlbum.php b/app/Actions/Album/ListAlbums.php similarity index 65% rename from app/Livewire/Components/Forms/Album/SearchAlbum.php rename to app/Actions/Album/ListAlbums.php index a6ed83d9022..f54ebad59cf 100644 --- a/app/Livewire/Components/Forms/Album/SearchAlbum.php +++ b/app/Actions/Album/ListAlbums.php @@ -1,72 +1,23 @@ albumListSaved = $this->getAlbumsListWithPath($lft, $rgt, $parent_id); - } - - /** - * Give the tree of albums owned by the user. - * - * @return Collection - */ - public function getAlbumListProperty(): Collection - { - $filtered = collect($this->albumListSaved); - if ($this->search !== null && trim($this->search) !== '') { - return $filtered->filter(function (array $album) { - return Str::contains($album['title'], ltrim($this->search), true); - }); - } - - return $filtered; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.search-album'); - } - /** * @param int|null $lft * @param int|null $rgt @@ -74,7 +25,7 @@ public function render(): View * * @return TAlbumSaved[] */ - private function getAlbumsListWithPath(?int $lft, ?int $rgt, ?string $parent_id): array + public function do(?int $lft, ?int $rgt, ?string $parent_id): array { $albumQueryPolicy = resolve(AlbumQueryPolicy::class); $unfiltered = $albumQueryPolicy->applyReachabilityFilter( @@ -88,9 +39,9 @@ private function getAlbumsListWithPath(?int $lft, ?int $rgt, ?string $parent_id) $query = (new SortingDecorator($unfiltered)) ->orderBy($sorting->column, $sorting->order); - /** @var NsCollection $albums */ + /** @var NsCollection $albums */ $albums = $query->get(); - /** @var NsCollection $tree */ + /** @var NsCollection $tree */ $tree = $albums->toTree(null); $flat_tree = $this->flatten($tree); @@ -115,8 +66,8 @@ private function getAlbumsListWithPath(?int $lft, ?int $rgt, ?string $parent_id) /** * Flatten the tree and create bread crumb paths. * - * @param NsCollection|Collection $collection - * @param string $prefix + * @param NsCollection|Collection $collection + * @param string $prefix * * @return TAlbumSaved[] */ @@ -154,7 +105,7 @@ private function shorten(string $title): string { $len = strlen($title); - if ($len < self::SHORTEN_BY) { + if ($len <= self::SHORTEN_BY) { return $title; } /** @var Collection $title_split */ @@ -187,9 +138,4 @@ private function shorten(string $title): string return implode('/', $title_split->all()) . '/' . $last_elem; } - - public function placeholder(): string - { - return "
Loading album list...
"; - } } diff --git a/app/Actions/Album/PositionData.php b/app/Actions/Album/PositionData.php index e9f347014d5..bf8f3c24a26 100644 --- a/app/Actions/Album/PositionData.php +++ b/app/Actions/Album/PositionData.php @@ -4,7 +4,7 @@ use App\Contracts\Models\AbstractAlbum; use App\Enum\SizeVariantType; -use App\Legacy\V1\Resources\Collections\PositionDataResource; +use App\Http\Resources\Collections\PositionDataResource; use App\Models\Album; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -17,6 +17,7 @@ public function get(AbstractAlbum $album, bool $includeSubAlbums = false): Posit $album->all_photos() : $album->photos(); + // @phpstan-ignore-next-line $photoRelation ->with([ 'album' => function (BelongsTo $b) { diff --git a/app/Actions/Album/SetHeader.php b/app/Actions/Album/SetHeader.php new file mode 100644 index 00000000000..501a8f59ea1 --- /dev/null +++ b/app/Actions/Album/SetHeader.php @@ -0,0 +1,32 @@ +header_id = AlbumController::COMPACT_HEADER; + } else { + $album->header_id = ($album->header_id !== $photo?->id || $shall_override) ? $photo?->id : null; + } + $album->save(); + + return $album; + } +} diff --git a/app/Actions/Album/SetProtectionPolicy.php b/app/Actions/Album/SetProtectionPolicy.php index a3f1bf0a11d..0f915767b14 100644 --- a/app/Actions/Album/SetProtectionPolicy.php +++ b/app/Actions/Album/SetProtectionPolicy.php @@ -2,10 +2,10 @@ namespace App\Actions\Album; -use App\DTO\AlbumProtectionPolicy; use App\Exceptions\Internal\FrameworkException; use App\Exceptions\InvalidPropertyException; use App\Exceptions\ModelDBException; +use App\Http\Resources\Models\Utils\AlbumProtectionPolicy; use App\Models\AccessPermission; use App\Models\Extensions\BaseAlbum; use Illuminate\Support\Facades\Hash; diff --git a/app/Actions/Album/SetSmartProtectionPolicy.php b/app/Actions/Album/SetSmartProtectionPolicy.php new file mode 100644 index 00000000000..1d9c081a3bc --- /dev/null +++ b/app/Actions/Album/SetSmartProtectionPolicy.php @@ -0,0 +1,26 @@ +setPublic(); + } else { + $album->setPrivate(); + } + } +} diff --git a/app/Actions/Album/Transfer.php b/app/Actions/Album/Transfer.php new file mode 100644 index 00000000000..77d77e421df --- /dev/null +++ b/app/Actions/Album/Transfer.php @@ -0,0 +1,32 @@ +owner_id = $userId; + $baseAlbum->save(); + + // No longer necessary because we transfer the ownership + AccessPermission::query()->where('base_album_id', '=', $baseAlbum->id)->where('user_id', '=', $userId)->delete(); + + // If this is an Album, we also need to fix the children and photos ownership + if ($baseAlbum instanceof Album) { + $baseAlbum->makeRoot(); + $baseAlbum->save(); + $baseAlbum->fixOwnershipOfChildren(); + } + } +} diff --git a/app/Actions/Albums/PositionData.php b/app/Actions/Albums/PositionData.php index a28a11d2e07..8a58176342a 100644 --- a/app/Actions/Albums/PositionData.php +++ b/app/Actions/Albums/PositionData.php @@ -4,12 +4,10 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\Enum\SizeVariantType; -use App\Legacy\V1\Resources\Collections\PositionDataResource; +use App\Http\Resources\Collections\PositionDataResource; use App\Models\Configs; use App\Models\Photo; use App\Policies\PhotoQueryPolicy; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasMany; class PositionData { @@ -34,14 +32,14 @@ public function do(): PositionDataResource $photoQuery = $this->photoQueryPolicy->applySearchabilityFilter( Photo::query() ->with([ - 'album' => function (BelongsTo $b) { + 'album' => function ($b) { // The album is required for photos to properly // determine access and visibility rights; but we // don't need to determine the cover and thumbnail for // each album $b->without(['cover', 'thumb']); }, - 'size_variants' => function (HasMany $r) { + 'size_variants' => function ($r) { // The web GUI only uses the small and thumb size // variants to show photos on a map; so we can save // hydrating the larger size variants diff --git a/app/Actions/Db/OptimizeDb.php b/app/Actions/Db/OptimizeDb.php index 972081db906..4968cb3d1ab 100644 --- a/app/Actions/Db/OptimizeDb.php +++ b/app/Actions/Db/OptimizeDb.php @@ -8,7 +8,7 @@ class OptimizeDb extends BaseOptimizer { /** - * @return array + * @return array */ public function do(): array { diff --git a/app/Actions/Diagnostics/Diagnostics.php b/app/Actions/Diagnostics/Diagnostics.php index 54f4686ecb3..ff9c2e5e362 100644 --- a/app/Actions/Diagnostics/Diagnostics.php +++ b/app/Actions/Diagnostics/Diagnostics.php @@ -18,6 +18,6 @@ class Diagnostics */ public static function line(string $key, string $value): string { - return sprintf('%-40s %s', $key, $value); + return sprintf('%-42s %s', $key, $value); } } diff --git a/app/Actions/Diagnostics/Errors.php b/app/Actions/Diagnostics/Errors.php index e5bfce77a12..92ee6cf0633 100644 --- a/app/Actions/Diagnostics/Errors.php +++ b/app/Actions/Diagnostics/Errors.php @@ -16,6 +16,7 @@ use App\Actions\Diagnostics\Pipes\Checks\MigrationCheck; use App\Actions\Diagnostics\Pipes\Checks\PHPVersionCheck; use App\Actions\Diagnostics\Pipes\Checks\SmallMediumExistsCheck; +use App\Actions\Diagnostics\Pipes\Checks\SupporterCheck; use App\Actions\Diagnostics\Pipes\Checks\TimezoneCheck; use App\Actions\Diagnostics\Pipes\Checks\UpdatableCheck; use Illuminate\Pipeline\Pipeline; @@ -44,6 +45,7 @@ class Errors DBIntegrityCheck::class, SmallMediumExistsCheck::class, CountSizeVariantsCheck::class, + SupporterCheck::class, ]; /** diff --git a/app/Actions/Diagnostics/Pipes/Checks/BasicPermissionCheck.php b/app/Actions/Diagnostics/Pipes/Checks/BasicPermissionCheck.php index e89f14513df..8d18ca39ddd 100644 --- a/app/Actions/Diagnostics/Pipes/Checks/BasicPermissionCheck.php +++ b/app/Actions/Diagnostics/Pipes/Checks/BasicPermissionCheck.php @@ -7,8 +7,8 @@ use App\Exceptions\Handler; use App\Exceptions\Internal\InvalidConfigOption; use App\Facades\Helpers; +use App\Http\Controllers\Gallery\PhotoController; use App\Image\Files\ProcessableJobFile; -use App\Livewire\Components\Forms\Add\Upload; use App\Models\SymLink; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Support\Facades\Storage; @@ -117,7 +117,7 @@ function (int $gid): string { Storage::disk(StorageDiskType::LOCAL->value), Storage::disk(SymLink::DISK_NAME), Storage::disk(ProcessableJobFile::DISK_NAME), - Storage::disk(Upload::DISK_NAME), + Storage::disk(PhotoController::DISK_NAME), ]; foreach ($disks as $disk) { @@ -243,7 +243,7 @@ private function checkDirectoryPermissionsRecursively(string $path, array &$data (!is_writable($path) && !is_readable($path)) => 'neither readable nor writable', !is_writable($path) => 'not writable', !is_readable($path) => 'not readable', - default => '' + default => '', }; $data[] = sprintf('Error: %s is %s by %s', $this->anonymize($path), $problem, $this->groupNames); } diff --git a/app/Actions/Diagnostics/Pipes/Checks/ConfigSanityCheck.php b/app/Actions/Diagnostics/Pipes/Checks/ConfigSanityCheck.php index 8584bdb6516..dde33e3e0a4 100644 --- a/app/Actions/Diagnostics/Pipes/Checks/ConfigSanityCheck.php +++ b/app/Actions/Diagnostics/Pipes/Checks/ConfigSanityCheck.php @@ -66,12 +66,10 @@ private function checkKeysExistsAndSet(array &$data): void */ private function checkDropBoxKeyWarning(array &$data): void { - if (!isset($this->settings['dropbox_key'])) { - $data[] - = 'Warning: Dropbox import not working. No property for dropbox_key.'; - } elseif ($this->settings['dropbox_key'] === '') { - $data[] - = 'Warning: Dropbox import not working. dropbox_key is empty.'; + $dropbox = Configs::getValueAsString('dropbox_key'); + if ($dropbox === '') { + $data[] = 'Warning: Dropbox import not working. dropbox_key is empty.'; + $data[] = 'Info: To hide this Dropbox warning, set the dropbox_key to "disabled"'; } } diff --git a/app/Actions/Diagnostics/Pipes/Checks/ForeignKeyListInfo.php b/app/Actions/Diagnostics/Pipes/Checks/ForeignKeyListInfo.php index 853f349e347..20e2d24bcd2 100644 --- a/app/Actions/Diagnostics/Pipes/Checks/ForeignKeyListInfo.php +++ b/app/Actions/Diagnostics/Pipes/Checks/ForeignKeyListInfo.php @@ -24,7 +24,7 @@ public function handle(array &$data, \Closure $next): array 'sqlite' => $this->sqlite($data), 'mysql' => $this->mysql($data), 'pgsql' => $this->pgsql($data), - default => '' + default => '', }; return $next($data); diff --git a/app/Actions/Diagnostics/Pipes/Checks/IniSettingsCheck.php b/app/Actions/Diagnostics/Pipes/Checks/IniSettingsCheck.php index 613f599de75..251c5cda9e4 100644 --- a/app/Actions/Diagnostics/Pipes/Checks/IniSettingsCheck.php +++ b/app/Actions/Diagnostics/Pipes/Checks/IniSettingsCheck.php @@ -5,6 +5,7 @@ use App\Contracts\DiagnosticPipe; use App\Facades\Helpers; use App\Models\Configs; +use LycheeVerify\Verify; use function Safe\ini_get; use function Safe\preg_match; @@ -14,6 +15,10 @@ */ class IniSettingsCheck implements DiagnosticPipe { + public function __construct(private Verify $verify) + { + } + /** * {@inheritDoc} */ @@ -23,6 +28,10 @@ public function handle(array &$data, \Closure $next): array // Load settings $settings = Configs::get(); + if (!$this->verify->validate()) { + $data[] = 'Warning: Your installation has been tampered. Please verify the integrity of your files.'; + } + if (Helpers::convertSize(ini_get('upload_max_filesize')) < Helpers::convertSize(('30M'))) { $data[] = 'Warning: You may experience problems when uploading a photo of large size. Take a look in the FAQ for details.'; } diff --git a/app/Actions/Diagnostics/Pipes/Checks/SupporterCheck.php b/app/Actions/Diagnostics/Pipes/Checks/SupporterCheck.php new file mode 100644 index 00000000000..8e46a4cc657 --- /dev/null +++ b/app/Actions/Diagnostics/Pipes/Checks/SupporterCheck.php @@ -0,0 +1,42 @@ +verify = $verify; + } + + /** + * {@inheritDoc} + */ + public function handle(array &$data, \Closure $next): array + { + if (Configs::getValueAsBool('disable_se_call_for_actions')) { + return $next($data); + } + + if (!$this->verify->is_supporter()) { + // @codeCoverageIgnoreStart + $data[] = 'Info: Have you considered supporting Lychee? :)'; + // @codeCoverageIgnoreEnd + } + + return $next($data); + } +} \ No newline at end of file diff --git a/app/Actions/Diagnostics/Pipes/Checks/UpdatableCheck.php b/app/Actions/Diagnostics/Pipes/Checks/UpdatableCheck.php index 810739030bb..675f57175b1 100644 --- a/app/Actions/Diagnostics/Pipes/Checks/UpdatableCheck.php +++ b/app/Actions/Diagnostics/Pipes/Checks/UpdatableCheck.php @@ -39,7 +39,9 @@ public function handle(array &$data, \Closure $next): array try { self::assertUpdatability(); // @codeCoverageIgnoreStart - } catch (ConfigurationException|ExternalComponentMissingException $e) { + } catch (ExternalComponentMissingException $e) { + $data[] = 'Info: ' . $e->getMessage(); + } catch (ConfigurationException $e) { $data[] = 'Warning: ' . $e->getMessage(); } catch (InsufficientFilesystemPermissions|VersionControlException $e) { $data[] = 'Error: ' . $e->getMessage(); diff --git a/app/Actions/Diagnostics/Pipes/Infos/CountForeignKeyInfo.php b/app/Actions/Diagnostics/Pipes/Infos/CountForeignKeyInfo.php index 9431ad1d639..58f0b82ca7a 100644 --- a/app/Actions/Diagnostics/Pipes/Infos/CountForeignKeyInfo.php +++ b/app/Actions/Diagnostics/Pipes/Infos/CountForeignKeyInfo.php @@ -20,7 +20,7 @@ public function handle(array &$data, \Closure $next): array 'sqlite' => $this->sqlite($data), 'mysql' => $this->mysql($data), 'pgsql' => $this->pgsql($data), - default => '' + default => '', }; return $next($data); diff --git a/app/Actions/Diagnostics/Pipes/Infos/InstallTypeInfo.php b/app/Actions/Diagnostics/Pipes/Infos/InstallTypeInfo.php index 0323d947ba3..7632f3702b2 100644 --- a/app/Actions/Diagnostics/Pipes/Infos/InstallTypeInfo.php +++ b/app/Actions/Diagnostics/Pipes/Infos/InstallTypeInfo.php @@ -6,6 +6,7 @@ use App\Assets\Features; use App\Contracts\DiagnosticPipe; use App\Metadata\Versions\InstalledVersion; +use LycheeVerify\Verify; /** * What kind of Lychee install we are looking at? @@ -13,11 +14,10 @@ */ class InstallTypeInfo implements DiagnosticPipe { - private InstalledVersion $installedVersion; - - public function __construct(InstalledVersion $installedVersion) + public function __construct( + private InstalledVersion $installedVersion, + private Verify $verify) { - $this->installedVersion = $installedVersion; } /** @@ -25,13 +25,14 @@ public function __construct(InstalledVersion $installedVersion) */ public function handle(array &$data, \Closure $next): array { - $data[] = Diagnostics::line('composer install:', $this->installedVersion->isDev() ? 'dev' : '--no-dev'); + $data[] = Diagnostics::line('composer install:', ($this->installedVersion->isDev() ? 'dev' : '--no-dev') . ($this->verify->validate() ? '' : '*')); $data[] = Diagnostics::line('APP_ENV:', config('app.env')); // check if production $data[] = Diagnostics::line('APP_DEBUG:', config('app.debug') === true ? 'true' : 'false'); // check if debug is on (will help in case of error 500) $data[] = Diagnostics::line('APP_URL:', config('app.url') !== 'http://localhost' ? 'set' : 'default'); // Some people leave that value by default... It is now breaking their visual. $data[] = Diagnostics::line('APP_DIR:', config('app.dir_url') !== '' ? 'set' : 'default'); // Some people leave that value by default... It is now breaking their visual. $data[] = Diagnostics::line('LOG_VIEWER_ENABLED:', Features::when('log-viewer', 'true', 'false')); - $data[] = Diagnostics::line('LIVEWIRE_ENABLED:', Features::when('livewire', 'true', 'false')); + $data[] = Diagnostics::line('VUEJS_ENABLED:', Features::when('vuejs', 'true', 'false')); + $data[] = Diagnostics::line('PHOTO_PIPES:', Features::when('create-photo-via-pipes', 'true', 'false')); $data[] = ''; return $next($data); diff --git a/app/Actions/Diagnostics/Pipes/Infos/SystemInfo.php b/app/Actions/Diagnostics/Pipes/Infos/SystemInfo.php index 7790115fc6c..718b45393e7 100644 --- a/app/Actions/Diagnostics/Pipes/Infos/SystemInfo.php +++ b/app/Actions/Diagnostics/Pipes/Infos/SystemInfo.php @@ -5,7 +5,7 @@ use App\Actions\Diagnostics\Diagnostics; use App\Contracts\DiagnosticPipe; use App\Facades\Helpers; -use App\Livewire\Components\Forms\Add\Upload; +use App\Http\Resources\GalleryConfigs\UploadConfig; use Carbon\CarbonTimeZone; use Illuminate\Database\QueryException; use Illuminate\Support\Facades\DB; @@ -28,7 +28,7 @@ public function handle(array &$data, \Closure $next): array 'mysql' => ['MySQL', 'select version() as version'], 'sqlite' => ['SQLite', 'select sqlite_version() as version'], 'pgsql' => ['PostgreSQL', 'select version() as version'], - default => [DB::getDriverName(), 'select version() as version'] + default => [DB::getDriverName(), 'select version() as version'], }; $dbtype = $sql[0]; @@ -56,23 +56,11 @@ public function handle(array &$data, \Closure $next): array $data[] = Diagnostics::line('Timezone:', $timeZone?->getName() ?? 'undefined'); $data[] = Diagnostics::line('Max uploaded file size:', ini_get('upload_max_filesize')); $data[] = Diagnostics::line('Max post size:', ini_get('post_max_size')); - $this->getUploadLimit($data); + $data[] = Diagnostics::line('Chunk size:', Helpers::getSymbolByQuantity(UploadConfig::getUploadLimit())); $data[] = Diagnostics::line('Max execution time: ', ini_get('max_execution_time')); $data[] = Diagnostics::line($dbtype . ' Version:', $dbver); $data[] = ''; return $next($data); } - - /** - * @param array $data - * - * @return void - */ - private function getUploadLimit(array &$data): void - { - $size = Upload::getUploadLimit(); - - $data[] = Diagnostics::line('Livewire chunk size:', Helpers::getSymbolByQuantity($size)); - } } diff --git a/app/Actions/Diagnostics/Pipes/Infos/VersionInfo.php b/app/Actions/Diagnostics/Pipes/Infos/VersionInfo.php index 8a19e0238d9..e0bd2586c54 100644 --- a/app/Actions/Diagnostics/Pipes/Infos/VersionInfo.php +++ b/app/Actions/Diagnostics/Pipes/Infos/VersionInfo.php @@ -9,6 +9,8 @@ use App\Metadata\Versions\FileVersion; use App\Metadata\Versions\GitHubVersion; use App\Metadata\Versions\InstalledVersion; +use LycheeVerify\Contract\Status; +use LycheeVerify\Verify; /** * Which version of Lychee are we using? @@ -19,6 +21,7 @@ public function __construct( private InstalledVersion $installedVersion, public FileVersion $fileVersion, public GitHubVersion $gitHubFunctions, + private Verify $verify, ) { $this->fileVersion->hydrate(withRemote: false); } @@ -43,7 +46,7 @@ public function handle(array &$data, \Closure $next): array } } - $data[] = Diagnostics::line('Lychee Version (' . $channelName->value . '):', $lycheeInfoString); + $data[] = Diagnostics::line($this->getVersionString() . ' (' . $channelName->value . '):', $lycheeInfoString); $data[] = Diagnostics::line('DB Version:', $this->installedVersion->getVersion()->toString()); $data[] = ''; @@ -66,4 +69,30 @@ public function getChannelName() return $lycheeChannelName; } + + /** + * Retrieve the version string. + * + * SE for supporter edition + * Plus for premium edition + * The star marks a tampered installation + * + * @return string + */ + private function getVersionString(): string + { + $lychee_version = 'Lychee'; + $lychee_version .= match ($this->verify->get_status()) { + Status::SUPPORTER_EDITION => ' SE', + Status::PLUS_EDITION => ' Plus', + default => '', + }; + + if (!$this->verify->validate()) { + $lychee_version .= '*'; + } + $lychee_version .= ' Version'; + + return $lychee_version; + } } diff --git a/app/Actions/Import/Exec.php b/app/Actions/Import/Exec.php index 2c944b4bd72..d8e802b6d9c 100644 --- a/app/Actions/Import/Exec.php +++ b/app/Actions/Import/Exec.php @@ -238,7 +238,7 @@ private function assertImportNotCancelled(): void { try { // re-read session in case cancelling import was requested - session()->start(); + Session::start(); if (Session::has('cancel')) { Session::forget('cancel'); throw new ImportCancelledException(); @@ -261,7 +261,7 @@ private function assertImportNotCancelled(): void public function do( string $path, ?Album $parentAlbum, - array $ignore_list = [] + array $ignore_list = [], ): void { try { $path = self::normalizePath($path); diff --git a/app/Actions/Import/FromServer.php b/app/Actions/Import/FromServer.php index c8cce64568f..3827b4d4922 100644 --- a/app/Actions/Import/FromServer.php +++ b/app/Actions/Import/FromServer.php @@ -66,7 +66,7 @@ protected function determineMemLimit(): int 'm' => 1024 * 1024, 'g' => 1024 * 1024 * 1024, 't' => 1024 * 1024 * 1024 * 1024, - default => 1 + default => 1, // @codeCoverageIgnoreEnd }; diff --git a/app/Actions/InstallUpdate/CheckUpdate.php b/app/Actions/InstallUpdate/CheckUpdate.php index 2f38f232b06..85369d5b070 100644 --- a/app/Actions/InstallUpdate/CheckUpdate.php +++ b/app/Actions/InstallUpdate/CheckUpdate.php @@ -43,7 +43,7 @@ public function getCode(): UpdateStatus return match (false) { MigrationCheck::isUpToDate() => UpdateStatus::REQUIRE_MIGRATION, $this->fileVersion->isUpToDate() => UpdateStatus::NOT_UP_TO_DATE, - default => UpdateStatus::UP_TO_DATE + default => UpdateStatus::UP_TO_DATE, }; // @codeCoverageIgnoreEnd } diff --git a/app/Actions/InstallUpdate/DefaultConfig.php b/app/Actions/InstallUpdate/DefaultConfig.php index 1b8e674d700..9070c7c089f 100644 --- a/app/Actions/InstallUpdate/DefaultConfig.php +++ b/app/Actions/InstallUpdate/DefaultConfig.php @@ -62,9 +62,9 @@ class DefaultConfig 'storage/framework/cache/' => 'file_exists|is_readable|is_writable|is_executable', 'storage/framework/sessions/' => 'file_exists|is_readable|is_writable|is_executable', 'storage/logs/' => 'file_exists|is_readable|is_writable|is_executable', - 'storage/image-jobs' => 'file_exists|is_readable|is_writable|is_executable', - 'storage/extract-jobs' => 'file_exists|is_readable|is_writable|is_executable', - 'storage/livewire-tmp' => 'file_exists|is_readable|is_writable|is_executable', + 'storage/tmp/extract/' => 'file_exists|is_readable|is_writable|is_executable', + 'storage/tmp/jobs/' => 'file_exists|is_readable|is_writable|is_executable', + 'storage/tmp/uploads/' => 'file_exists|is_readable|is_writable|is_executable', 'bootstrap/cache/' => 'file_exists|is_readable|is_writable|is_executable', 'public/dist/' => 'file_exists|is_readable|is_writable|is_executable', 'public/sym/' => 'file_exists|is_readable|is_writable|is_executable', diff --git a/app/Actions/InstallUpdate/Pipes/AbstractUpdateInstallerPipe.php b/app/Actions/InstallUpdate/Pipes/AbstractUpdateInstallerPipe.php index d2275f1b4ef..44b3bf5a579 100644 --- a/app/Actions/InstallUpdate/Pipes/AbstractUpdateInstallerPipe.php +++ b/app/Actions/InstallUpdate/Pipes/AbstractUpdateInstallerPipe.php @@ -9,10 +9,10 @@ abstract class AbstractUpdateInstallerPipe * @param \Closure(array $output): array $next * * @return array + * + * @codeCoverageIgnore */ - // @codeCoverageIgnoreStart abstract public function handle(array &$output, \Closure $next): array; - // @codeCoverageIgnoreEnd /** * Arrayify a string and append it to $output. diff --git a/app/Actions/Photo/Archive.php b/app/Actions/Photo/Archive.php index ee8a46b769d..03c4dccaa89 100644 --- a/app/Actions/Photo/Archive.php +++ b/app/Actions/Photo/Archive.php @@ -12,7 +12,7 @@ use App\Image\Files\FlysystemFile; use App\Models\Configs; use App\Models\Photo; -use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Storage; use Safe\Exceptions\InfoException; use function Safe\fclose; diff --git a/app/Actions/Photo/Create.php b/app/Actions/Photo/Create.php index 657429ed315..e2f9e799f61 100644 --- a/app/Actions/Photo/Create.php +++ b/app/Actions/Photo/Create.php @@ -8,6 +8,7 @@ use App\Actions\Photo\Pipes\Shared; use App\Actions\Photo\Pipes\Standalone; use App\Actions\Photo\Pipes\VideoPartner; +use App\Actions\Statistics\Spaces; use App\Assets\Features; use App\Contracts\Exceptions\LycheeException; use App\Contracts\Models\AbstractAlbum; @@ -21,11 +22,14 @@ use App\Exceptions\Internal\LycheeLogicException; use App\Exceptions\PhotoResyncedException; use App\Exceptions\PhotoSkippedException; +use App\Exceptions\QuotaExceededException; use App\Image\Files\NativeLocalFile; use App\Legacy\Actions\Photo\Create as LegacyPhotoCreate; use App\Models\Photo; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Pipeline\Pipeline; +use LycheeVerify\Verify; +use User; class Create { @@ -53,10 +57,13 @@ public function __construct(?ImportMode $importMode, int $intendedOwnerId) * @return Photo the newly created or updated photo * * @throws ModelNotFoundException + * @throws QuotaExceededException * @throws LycheeException */ public function add(NativeLocalFile $sourceFile, ?AbstractAlbum $album, ?int $fileLastModifiedTime = null): Photo { + $this->checkQuota($sourceFile); + if (Features::inactive('create-photo-via-pipes')) { $oldCodePath = new LegacyPhotoCreate($this->strategyParameters->importMode, $this->strategyParameters->intendedOwnerId); @@ -160,6 +167,7 @@ private function handleStandalone(InitDTO $initDTO): Photo Shared\Save::class, Standalone\CreateOriginalSizeVariant::class, Standalone\CreateSizeVariants::class, + Standalone\ReplaceOriginalWithBackup::class, Shared\UploadSizeVariantsToS3::class, ]; @@ -245,6 +253,7 @@ private function handlePhotoLivePartner(InitDTO $initDTO): Photo Shared\Save::class, Standalone\CreateOriginalSizeVariant::class, Standalone\CreateSizeVariants::class, + Standalone\ReplaceOriginalWithBackup::class, Shared\UploadSizeVariantsToS3::class, ]; $standAloneDto = $this->executePipeOnDTO($standAlonePipes, $standAloneDto); @@ -278,4 +287,45 @@ private function handlePhotoLivePartner(InitDTO $initDTO): Photo return $this->executePipeOnDTO($finalize, $finalizeDTO)->getPhoto(); } + + /** + * Check whether the user has enough quota to upload the file. + * + * @param NativeLocalFile $sourceFile + * + * @return void + * + * @throws QuotaExceededException + * + * @codeCoverageIgnore + */ + private function checkQuota(NativeLocalFile $sourceFile): void + { + $verify = resolve(Verify::class); + + // if the installation is not validated or + // if the user is not a supporter, we skip. + if (!$verify->validate() || !$verify->is_supporter()) { + return; + } + + $user = \User::find($this->strategyParameters->intendedOwnerId) ?? throw new ModelNotFoundException(); + + // User does not have quota + if ($user->quota_kb === null) { + return; + } + + // Admins can upload without quota + if ($user->may_administrate === true) { + return; + } + + $spaces = (new Spaces())->getFullSpacePerUser($user->id); + $used = $spaces[0]['size']; + + if (($user->quota_kb * 1024) <= $used + $sourceFile->getFilesize()) { + throw new QuotaExceededException(); + } + } } diff --git a/app/Actions/Photo/Duplicate.php b/app/Actions/Photo/Duplicate.php index 29d30ec450d..b2a43364ad3 100644 --- a/app/Actions/Photo/Duplicate.php +++ b/app/Actions/Photo/Duplicate.php @@ -5,24 +5,23 @@ use App\Exceptions\ModelDBException; use App\Models\Album; use App\Models\Photo; -use Illuminate\Database\Eloquent\Collection as EloquentCollection; -use Illuminate\Support\Collection as BaseCollection; +use Illuminate\Support\Collection; class Duplicate { /** * Duplicates a set of photos. * - * @param EloquentCollection $photos the source photos - * @param Album|null $album the destination album; `null` means root album + * @param Collection $photos the source photos + * @param Album|null $album the destination album; `null` means root album * - * @return BaseCollection the duplicates + * @return Collection the duplicates * * @throws ModelDBException */ - public function do(EloquentCollection $photos, ?Album $album): BaseCollection + public function do(Collection $photos, ?Album $album): Collection { - $duplicates = new BaseCollection(); + $duplicates = new Collection(); /** @var Photo $photo */ foreach ($photos as $photo) { $duplicate = $photo->replicate(); diff --git a/app/Actions/Photo/Move.php b/app/Actions/Photo/Move.php index bcc71b9b0dd..9ec7958227c 100644 --- a/app/Actions/Photo/Move.php +++ b/app/Actions/Photo/Move.php @@ -6,7 +6,7 @@ use App\Exceptions\ModelDBException; use App\Models\Album; use App\Models\Photo; -use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Collection; class Move { diff --git a/app/Actions/Photo/Pipes/Standalone/CreateOriginalSizeVariant.php b/app/Actions/Photo/Pipes/Standalone/CreateOriginalSizeVariant.php index 73703122d87..da8dca38cf2 100644 --- a/app/Actions/Photo/Pipes/Standalone/CreateOriginalSizeVariant.php +++ b/app/Actions/Photo/Pipes/Standalone/CreateOriginalSizeVariant.php @@ -18,6 +18,7 @@ public function handle(StandaloneDTO $state, \Closure $next): StandaloneDTO $imageDim = $state->sourceImage?->isLoaded() ? $state->sourceImage->getDimensions() : new ImageDimension($state->exifInfo->width, $state->exifInfo->height); + $state->photo->size_variants->create( SizeVariantType::ORIGINAL, $state->targetFile->getRelativePath(), diff --git a/app/Actions/Photo/Pipes/Standalone/PlacePhoto.php b/app/Actions/Photo/Pipes/Standalone/PlacePhoto.php index 6b738f38846..3b26e8d22e3 100644 --- a/app/Actions/Photo/Pipes/Standalone/PlacePhoto.php +++ b/app/Actions/Photo/Pipes/Standalone/PlacePhoto.php @@ -87,6 +87,7 @@ private function putSourceIntoFinalDestination(StandaloneDTO $state): StreamStat // the image is re-encoded and hence its quality might // be reduced. $streamStat = $state->sourceImage->save($state->targetFile, true); + $this->backupOriginal($state); } else { // If the image does not require normalization the // unaltered source file is copied to the final target. @@ -117,4 +118,17 @@ private function putSourceIntoFinalDestination(StandaloneDTO $state): StreamStat throw new MediaFileOperationException('Could move/copy/symlink source file to final destination', $e); } } + + /** + * When rotating, we backup the original file to prevent data loss. + * + * @param StandaloneDTO $state + * + * @return void + */ + private function backupOriginal(StandaloneDTO $state) + { + $state->backupFile = $state->namingStrategy->createFile(SizeVariantType::ORIGINAL, true); + $state->backupFile->write($state->sourceFile->read(), true); + } } diff --git a/app/Actions/Photo/Pipes/Standalone/ReplaceOriginalWithBackup.php b/app/Actions/Photo/Pipes/Standalone/ReplaceOriginalWithBackup.php new file mode 100644 index 00000000000..97549b8e078 --- /dev/null +++ b/app/Actions/Photo/Pipes/Standalone/ReplaceOriginalWithBackup.php @@ -0,0 +1,26 @@ +backupFile === null) { + return $next($state); + } + + if (Configs::getValueAsBool('keep_original_untouched')) { + $state->targetFile->write($state->backupFile->read()); + $state->targetFile->close(); + } + + $state->backupFile->delete(); + + return $next($state); + } +} diff --git a/app/Actions/Profile/UpdateLogin.php b/app/Actions/Profile/UpdateLogin.php new file mode 100644 index 00000000000..fa34056f2cf --- /dev/null +++ b/app/Actions/Profile/UpdateLogin.php @@ -0,0 +1,83 @@ +username) { + return $user; + } + + // Check if username already exists + if (User::query()->where('username', '=', $username)->count() !== 0) { + Log::channel('login')->warning(__METHOD__ . ':' . __LINE__ . sprintf('User (%s) tried to change their identity to (%s) from %s', $user->username, $username, $ip)); + throw new ConflictingPropertyException('Username already exists.'); + } + + // Change username + Log::channel('login')->notice(__METHOD__ . ':' . __LINE__ . sprintf('User (%s) changed their identity to (%s) from %s', $user->username, $username, $ip)); + $user->username = $username; + + return $user; + } + + /** + * Update the email of the user. + * + * @param User $user + * @param ?string $email + * + * @return User + */ + public function updateEmail(User &$user, ?string $email): User + { + $user->email = $email; + if ($email === null) { + $user->notifications()->delete(); + } + + return $user; + } + + /** + * Update the password of the user. + * + * @param User $user + * @param ?string $password + * + * @return User + */ + public function updatePassword(User &$user, ?string $password): User + { + if ($password === null) { + return $user; + } + + $user->password = Hash::make($password); + + return $user; + } +} diff --git a/app/Actions/Sharing/ListShare.php b/app/Actions/Sharing/ListShare.php index 5c3eab175ad..fbf36d2422e 100644 --- a/app/Actions/Sharing/ListShare.php +++ b/app/Actions/Sharing/ListShare.php @@ -4,7 +4,7 @@ use App\Constants\AccessPermissionConstants as APC; use App\Exceptions\Internal\QueryBuilderException; -use App\Legacy\V1\Resources\Sharing\SharesResource; +use App\Http\Resources\Sharing\SharesResource; use App\Models\AccessPermission; use App\Models\Extensions\BaseAlbum; use App\Models\User; @@ -32,6 +32,7 @@ public function do(?User $participant, ?User $owner, ?BaseAlbum $baseAlbum): Sha try { // Active shares, optionally filtered by album ID, participant ID // and or owner ID + /** @var Collection $shared */ $shared = AccessPermission::query()->select([ APC::ACCESS_PERMISSIONS . '.id', APC::ACCESS_PERMISSIONS . '.user_id', diff --git a/app/Actions/Sharing/ListedAlbum.php b/app/Actions/Sharing/ListedAlbum.php deleted file mode 100644 index a02cbd1ec2e..00000000000 --- a/app/Actions/Sharing/ListedAlbum.php +++ /dev/null @@ -1,13 +0,0 @@ -user_id = $user_id; + $perm->base_album_id = $base_album_id; + $perm->grants_full_photo_access = $accessPermissionResource->grants_full_photo_access; + $perm->grants_download = $accessPermissionResource->grants_download; + $perm->grants_upload = $accessPermissionResource->grants_upload; + $perm->grants_edit = $accessPermissionResource->grants_edit; + $perm->grants_delete = $accessPermissionResource->grants_delete; + $perm->load('user'); + $perm->load('album'); + $perm->save(); + + return $perm; + } +} \ No newline at end of file diff --git a/app/Actions/Sharing/SharedAlbum.php b/app/Actions/Sharing/SharedAlbum.php deleted file mode 100644 index a1e67955e9f..00000000000 --- a/app/Actions/Sharing/SharedAlbum.php +++ /dev/null @@ -1,14 +0,0 @@ - + */ + public function getFullSpacePerUser(?int $owner_id = null): Collection + { + return DB::table('users') + ->when($owner_id !== null, fn ($query) => $query->where('users.id', '=', $owner_id)) + ->joinSub( + query: DB::table('photos')->select(['photos.id', 'photos.owner_id']), + as: 'photos', + first: 'photos.owner_id', + operator: '=', + second: 'users.id', + type: 'left' + ) + ->joinSub( + query: DB::table('size_variants')->select(['size_variants.photo_id', 'size_variants.filesize']), + as: 'size_variants', + first: 'size_variants.photo_id', + operator: '=', + second: 'photos.id', + type: 'left' + ) + ->select( + 'users.id', + 'username', + DB::raw('SUM(size_variants.filesize) as size') + ) + ->groupBy('users.id', 'username') + ->orderBy('users.id', 'asc') + ->get() + ->map(fn ($item) => [ + 'id' => intval($item->id), + 'username' => strval($item->username), + 'size' => intval($item->size), + ]); + } + + /** + * Return the amount of data stored on the server (optionally for a user). + * + * @param int|null $owner_id + * + * @return Collection + */ + public function getSpacePerSizeVariantTypePerUser(?int $owner_id = null): Collection + { + return DB::table('size_variants') + ->when($owner_id !== null, fn ($query) => $query + ->joinSub( + query: DB::table('photos')->select(['photos.id', 'photos.owner_id']), + as: 'photos', + first: 'photos.id', + operator: '=', + second: 'size_variants.photo_id' + ) + ->where('photos.owner_id', '=', $owner_id)) + ->select( + 'size_variants.type', + DB::raw('SUM(size_variants.filesize) as size') + ) + ->groupBy('size_variants.type') + ->orderBy('size_variants.type', 'asc') + ->get() + ->map(fn ($item) => [ + 'type' => SizeVariantType::from($item->type), + 'size' => intval($item->size), + ]); + } + + /** + * Return the amount of data stored on the server (optionally for an album). + * + * @param string $album_id + * + * @return Collection + */ + public function getSpacePerSizeVariantTypePerAlbum(string $album_id): Collection + { + $query = DB::table('albums') + ->where('albums.id', '=', $album_id) + ->joinSub( + query: DB::table('albums', 'descendants')->select('descendants.id', 'descendants._lft', 'descendants._rgt'), + as: 'descendants', + first: function (JoinClause $join) { + $join->on('albums._lft', '<=', 'descendants._lft') + ->on('albums._rgt', '>=', 'descendants._rgt'); + } + ) + ->joinSub( + query: DB::table('photos'), + as: 'photos', + first: 'photos.album_id', + operator: '=', + second: 'descendants.id', + ) + ->joinSub( + query: DB::table('size_variants')->select(['size_variants.id', 'size_variants.photo_id', 'size_variants.type', 'size_variants.filesize']), + as: 'size_variants', + first: 'size_variants.photo_id', + operator: '=', + second: 'photos.id', + ) + ->select( + 'size_variants.type', + DB::raw('SUM(size_variants.filesize) as size') + ) + ->groupBy('size_variants.type') + ->orderBy('size_variants.type', 'asc'); + + return $query->get() + ->map(fn ($item) => [ + 'type' => SizeVariantType::from($item->type), + 'size' => intval($item->size), + ]); + } + + /** + * Return size statistics per album. + * + * @param string|null $album_id + * @param int|null $owner_id + * + * @return Collection + */ + public function getSpacePerAlbum(?string $album_id = null, ?int $owner_id = null) + { + $query = DB::table('albums') + ->when($album_id !== null, + fn ($query) => $query + ->joinSub( + query: DB::table('albums', 'parent')->select('parent.id', 'parent._lft', 'parent._rgt'), + as: 'parent', + first: function (JoinClause $join) { + $join->on('albums._lft', '>=', 'parent._lft') + ->on('albums._rgt', '<=', 'parent._rgt'); + } + ) + ->where('parent.id', '=', $album_id) + ) + ->when($owner_id !== null, fn ($query) => $query->joinSub( + query: DB::table('base_albums')->select(['base_albums.id', 'base_albums.owner_id']), + as: 'base_albums', + first: 'base_albums.id', + operator: '=', + second: 'albums.id' + ) + ->where('base_albums.owner_id', '=', $owner_id)) + ->joinSub( + query: DB::table('photos'), + as: 'photos', + first: 'photos.album_id', + operator: '=', + second: 'albums.id' + ) + ->joinSub( + query: DB::table('size_variants')->select(['size_variants.id', 'size_variants.photo_id', 'size_variants.filesize']), + as: 'size_variants', + first: 'size_variants.photo_id', + operator: '=', + second: 'photos.id' + ) + ->select( + 'albums.id', + 'albums._lft', + 'albums._rgt', + DB::raw('SUM(size_variants.filesize) as size'), + )->groupBy('albums.id') + ->orderBy('albums._lft', 'asc'); + + return $query + ->get() + ->map(fn ($item) => [ + 'id' => strval($item->id), + 'left' => intval($item->_lft), + 'right' => intval($item->_rgt), + 'size' => intval($item->size), + ]); + } + + /** + * Same as above but with full size (including sub-albums). + * + * @param string|null $album_id + * @param int|null $owner_id + * + * @return Collection + */ + public function getTotalSpacePerAlbum(?string $album_id = null, ?int $owner_id = null) + { + $query = DB::table('albums') + ->when($album_id !== null, fn ($query) => $query->where('albums.id', '=', $album_id)) + ->when($owner_id !== null, fn ($query) => $query->joinSub( + query: DB::table('base_albums')->select(['base_albums.id', 'base_albums.owner_id']), + as: 'base_albums', + first: 'base_albums.id', + operator: '=', + second: 'albums.id' + ) + ->where('base_albums.owner_id', '=', $owner_id)) + ->joinSub( + query: DB::table('albums', 'descendants')->select('descendants.id', 'descendants._lft', 'descendants._rgt'), + as: 'descendants', + first: function (JoinClause $join) { + $join->on('albums._lft', '<=', 'descendants._lft') + ->on('albums._rgt', '>=', 'descendants._rgt'); + } + ) + ->joinSub( + query: DB::table('photos'), + as: 'photos', + first: 'photos.album_id', + operator: '=', + second: 'descendants.id' + ) + ->joinSub( + query: DB::table('size_variants')->select(['size_variants.id', 'size_variants.photo_id', 'size_variants.filesize']), + as: 'size_variants', + first: 'size_variants.photo_id', + operator: '=', + second: 'photos.id' + ) + ->select( + 'albums.id', + 'albums._lft', + 'albums._rgt', + DB::raw('SUM(size_variants.filesize) as size'), + )->groupBy('albums.id') + ->orderBy('albums._lft', 'asc'); + + return $query + ->get() + ->map(fn ($item) => [ + 'id' => strval($item->id), + 'left' => intval($item->_lft), + 'right' => intval($item->_rgt), + 'size' => intval($item->size), + ]); + } + + /** + * Return size statistics (number of photos rather than bytes) per album. + * + * @param string|null $album_id + * @param int|null $owner_id + * + * @return Collection + */ + public function getPhotoCountPerAlbum(?string $album_id = null, ?int $owner_id = null) + { + $query = DB::table('albums') + ->when($album_id !== null, + fn ($query) => $query + ->joinSub( + query: DB::table('albums', 'parent')->select('parent.id', 'parent._lft', 'parent._rgt'), + as: 'parent', + first: function (JoinClause $join) { + $join->on('albums._lft', '>=', 'parent._lft') + ->on('albums._rgt', '<=', 'parent._rgt'); + } + ) + ->where('parent.id', '=', $album_id) + ) + ->joinSub( + query: DB::table('base_albums')->select(['base_albums.id', 'base_albums.owner_id', 'base_albums.title', 'base_albums.is_nsfw']), + as: 'base_albums', + first: 'base_albums.id', + operator: '=', + second: 'albums.id' + ) + ->when($owner_id !== null, fn ($query) => $query->where('base_albums.owner_id', '=', $owner_id)) + ->joinSub( + query: DB::table('photos')->select(['photos.id', 'photos.album_id']), + as: 'photos', + first: 'photos.album_id', + operator: '=', + second: 'albums.id' + ) + ->joinSub( + query: DB::table('users')->select(['users.id', 'users.username']), + as: 'users', + first: 'users.id', + operator: '=', + second: 'base_albums.owner_id' + ) + ->select( + 'albums.id', + 'username', + 'base_albums.title', + 'base_albums.is_nsfw', + 'albums._lft', + 'albums._rgt', + DB::raw('COUNT(photos.id) as num_photos'), + )->groupBy( + 'albums.id', + 'username', + 'base_albums.title', + 'base_albums.is_nsfw', + 'albums._lft', + 'albums._rgt', + ) + ->orderBy('albums._lft', 'asc'); + + return $query + ->get() + ->map(fn ($item) => [ + 'id' => strval($item->id), + 'username' => strval($item->username), + 'title' => strval($item->title), + 'is_nsfw' => boolval($item->is_nsfw), + 'left' => intval($item->_lft), + 'right' => intval($item->_rgt), + 'num_photos' => intval($item->num_photos), + 'num_descendants' => intval(($item->_rgt - $item->_lft - 1) / 2), + ]); + } + + /** + * Same as above but including sub-albums. + * + * @param string|null $album_id + * @param int|null $owner_id + * + * @return Collection + */ + public function getTotalPhotoCountPerAlbum(?string $album_id = null, ?int $owner_id = null) + { + $query = DB::table('albums') + ->when($album_id !== null, fn ($query) => $query->where('albums.id', '=', $album_id)) + ->joinSub( + query: DB::table('base_albums')->select(['base_albums.id', 'base_albums.owner_id', 'base_albums.title', 'base_albums.is_nsfw']), + as: 'base_albums', + first: 'base_albums.id', + operator: '=', + second: 'albums.id' + ) + ->when($owner_id !== null, fn ($query) => $query->where('base_albums.owner_id', '=', $owner_id)) + ->joinSub( + query: DB::table('albums', 'descendants')->select('descendants.id', 'descendants._lft', 'descendants._rgt'), + as: 'descendants', + first: function (JoinClause $join) { + $join->on('albums._lft', '<=', 'descendants._lft') + ->on('albums._rgt', '>=', 'descendants._rgt'); + } + ) + ->joinSub( + query: DB::table('photos')->select(['photos.id', 'photos.album_id']), + as: 'photos', + first: 'photos.album_id', + operator: '=', + second: 'descendants.id' + ) + ->joinSub( + query: DB::table('users')->select(['users.id', 'users.username']), + as: 'users', + first: 'users.id', + operator: '=', + second: 'base_albums.owner_id' + ) + ->select( + 'albums.id', + 'username', + 'base_albums.title', + 'base_albums.is_nsfw', + 'albums._lft', + 'albums._rgt', + DB::raw('COUNT(photos.id) as num_photos'), + )->groupBy( + 'albums.id', + 'username', + 'base_albums.title', + 'base_albums.is_nsfw', + 'albums._lft', + 'albums._rgt', + ) + ->orderBy('albums._lft', 'asc'); + + return $query + ->get() + ->map(fn ($item) => [ + 'id' => strval($item->id), + 'username' => strval($item->username), + 'title' => strval($item->title), + 'is_nsfw' => boolval($item->is_nsfw), + 'left' => intval($item->_lft), + 'right' => intval($item->_rgt), + 'num_photos' => intval($item->num_photos), + 'num_descendants' => intval(($item->_rgt - $item->_lft - 1) / 2), + ]); + } +} diff --git a/app/Actions/User/Create.php b/app/Actions/User/Create.php index 555cc3225ad..6b1dd09ed7c 100644 --- a/app/Actions/User/Create.php +++ b/app/Actions/User/Create.php @@ -5,6 +5,7 @@ use App\Exceptions\ConflictingPropertyException; use App\Exceptions\InvalidPropertyException; use App\Exceptions\ModelDBException; +use App\Models\Configs; use App\Models\User; use Illuminate\Support\Facades\Hash; @@ -14,11 +15,22 @@ class Create * @throws InvalidPropertyException * @throws ModelDBException */ - public function do(string $username, string $password, ?string $email = null, bool $mayUpload = false, bool $mayEditOwnSettings = false): User - { + public function do( + string $username, + string $password, + ?string $email = null, + bool $mayUpload = false, + bool $mayEditOwnSettings = false, + ?int $quota_kb = null, + ?string $note = null, + ): User { if (User::query()->where('username', '=', $username)->count() !== 0) { throw new ConflictingPropertyException('Username already exists'); } + if ($quota_kb === 0) { + $default = Configs::getValueAsInt('default_user_quota'); + $quota_kb = $default === 0 ? null : $default; + } $user = new User(); $user->may_upload = $mayUpload; $user->may_edit_own_settings = $mayEditOwnSettings; @@ -26,6 +38,8 @@ public function do(string $username, string $password, ?string $email = null, bo $user->username = $username; $user->email = $email; $user->password = Hash::make($password); + $user->quota_kb = $quota_kb; + $user->note = $note; $user->save(); return $user; diff --git a/app/Actions/User/Save.php b/app/Actions/User/Save.php index 6532495d342..2c525591dee 100644 --- a/app/Actions/User/Save.php +++ b/app/Actions/User/Save.php @@ -22,8 +22,14 @@ class Save * @throws InvalidPropertyException * @throws ModelDBException */ - public function do(User $user, string $username, ?string $password, bool $mayUpload, bool $mayEditOwnSettings): void - { + public function do(User $user, + string $username, + ?string $password, + bool $mayUpload, + bool $mayEditOwnSettings, + ?int $quota_kb = null, + ?string $note = null, + ): void { if (User::query() ->where('username', '=', $username) ->where('id', '!=', $user->id) @@ -32,9 +38,16 @@ public function do(User $user, string $username, ?string $password, bool $mayUpl throw new ConflictingPropertyException('Username already exists'); } + if ($quota_kb === 0) { + $default = \Configs::getValueAsInt('default_user_quota'); + $quota_kb = $default === 0 ? null : $default; + } + $user->username = $username; $user->may_upload = $mayUpload; $user->may_edit_own_settings = $mayEditOwnSettings; + $user->note = $note; + $user->quota_kb = $quota_kb; if ($password !== null && $password !== '') { $user->password = Hash::make($password); } diff --git a/app/Assets/ArrayToTextTable.php b/app/Assets/ArrayToTextTable.php index 27d8e44c29e..2ee010240eb 100644 --- a/app/Assets/ArrayToTextTable.php +++ b/app/Assets/ArrayToTextTable.php @@ -349,7 +349,7 @@ protected static function mb_str_pad( int $pad_length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, - string|null $encoding = null + string|null $encoding = null, ): string { /** @var string $encoding */ $encoding = $encoding === null ? mb_internal_encoding() : $encoding; diff --git a/app/Assets/Helpers.php b/app/Assets/Helpers.php index 1aaffd2dd54..331a8205919 100644 --- a/app/Assets/Helpers.php +++ b/app/Assets/Helpers.php @@ -5,7 +5,6 @@ use App\Exceptions\Internal\ZeroModuloException; use Illuminate\Support\Facades\File; use function Safe\ini_get; -use function Safe\parse_url; class Helpers { @@ -54,35 +53,6 @@ public function trancateIf32(string $id, int $prevShortId = 0, int $phpMax = PHP return (string) $shortId; } - /** - * Returns the extension of the filename (path or URI) or an empty string. - * - * @param string $filename - * @param bool $isURI - * - * @return string extension of the filename starting with a dot - */ - public function getExtension(string $filename, bool $isURI = false): string - { - // If $filename is an URI, get only the path component - if ($isURI === true) { - /** @var string $filename this is true because PHP_URL_PATH is specified */ - $filename = parse_url($filename, PHP_URL_PATH); - } - - $extension = pathinfo($filename, PATHINFO_EXTENSION); - - // Special cases - // https://github.com/electerious/Lychee/issues/482 - list($extension) = explode(':', $extension, 2); - - if ($extension !== '') { - $extension = '.' . $extension; - } - - return $extension; - } - /** * Check if $path has readable and writable permissions. * diff --git a/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php b/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php index 424713dcca9..80ce7eb2ecc 100644 --- a/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php +++ b/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php @@ -106,24 +106,29 @@ public function setPhoto(?Photo $photo): void $this->cachedRndMiddlePath = $matches[1] . DIRECTORY_SEPARATOR . $matches[2] . DIRECTORY_SEPARATOR . $matches[3]; } else { // If we don't have a match, we create a new random base path. + // @codeCoverageIgnoreStart $this->cachedRndMiddlePath = self::createRndMiddlePath(); + // @codeCoverageIgnoreEnd } } else { $this->cachedRndMiddlePath = self::createRndMiddlePath(); } + // @codeCoverageIgnoreStart } catch (PcreException $e) { throw LycheeAssertionError::createFromUnexpectedException($e); } + // @codeCoverageIgnoreEnd } /** * {@inheritDoc} */ - public function createFile(SizeVariantType $sizeVariant): FlysystemFile + public function createFile(SizeVariantType $sizeVariant, bool $isBackup = false): FlysystemFile { $relativePath = $sizeVariant->name() . DIRECTORY_SEPARATOR . $this->cachedRndMiddlePath . + ($isBackup ? '_orig' : '') . $this->generateExtension($sizeVariant); return new FlysystemFile(Storage::disk(StorageDiskType::LOCAL->value), $relativePath); @@ -145,8 +150,10 @@ protected static function createRndMiddlePath(): string substr($rndStr, 2, 2) . DIRECTORY_SEPARATOR . substr($rndStr, 4); + // @codeCoverageIgnoreStart } catch (\Exception $e) { throw new InsufficientEntropyException($e); } + // @codeCoverageIgnoreEnd } } diff --git a/app/Casts/MustNotSetCast.php b/app/Casts/MustNotSetCast.php index e0216775c7b..c28bf377254 100644 --- a/app/Casts/MustNotSetCast.php +++ b/app/Casts/MustNotSetCast.php @@ -40,18 +40,17 @@ public function __construct(?string $alternative = null) * This mutator always throws an exception and thus prevents the attribute * from being altered. * - * @param Model $model the model which owns the attribute - * @param string $key the name of attribute which has been - * attempted to be set - * @param mixed $value the value which has been attempted to assign - * to the attribute - * @param array $attributes all attributes of the model + * @param Model $model the model which owns the attribute + * @param string $key the name of attribute which has been + * attempted to be set + * @param mixed $value the value which has been attempted to assign + * to the attribute + * @param array $attributes all attributes of the model * * @return void * * @throws IllegalOrderOfOperationException */ - /** @phpstan-ignore-next-line Assigning type to array breaks contra-variance */ public function set(Model $model, string $key, mixed $value, array $attributes): void { $msg = 'must not set read-only attribute \'' . get_class($model) . '::$' . $key . '\' directly'; diff --git a/app/Console/Commands/Diagnostics.php b/app/Console/Commands/Diagnostics.php index c7b3b7934a4..93fc920940a 100644 --- a/app/Console/Commands/Diagnostics.php +++ b/app/Console/Commands/Diagnostics.php @@ -40,7 +40,7 @@ class Diagnostics extends Command * @throws SymfonyConsoleException */ public function __construct( - Colorize $colorize + Colorize $colorize, ) { parent::__construct(); diff --git a/app/Console/Commands/ImageProcessing/ExifLens.php b/app/Console/Commands/ImageProcessing/ExifLens.php index eefabe09247..9d89a116081 100644 --- a/app/Console/Commands/ImageProcessing/ExifLens.php +++ b/app/Console/Commands/ImageProcessing/ExifLens.php @@ -10,7 +10,6 @@ use App\Metadata\Extractor; use App\Models\Photo; use Illuminate\Console\Command; -use Illuminate\Database\Eloquent\Relations\HasMany; use Safe\Exceptions\InfoException; use function Safe\filemtime; use function Safe\set_time_limit; @@ -52,7 +51,7 @@ public function handle(): int } // we use lens because this is the one which is most likely to be empty. - $photos = Photo::query()->with(['size_variants' => function (HasMany $r) { + $photos = Photo::query()->with(['size_variants' => function ($r) { $r->where('type', '=', SizeVariantType::ORIGINAL); }]) ->where('lens', '=', '') diff --git a/app/Console/Commands/ImageProcessing/Takedate.php b/app/Console/Commands/ImageProcessing/Takedate.php index 2dc1ea3ab60..b641991d086 100644 --- a/app/Console/Commands/ImageProcessing/Takedate.php +++ b/app/Console/Commands/ImageProcessing/Takedate.php @@ -9,7 +9,6 @@ use App\Metadata\Extractor; use App\Models\Photo; use Illuminate\Console\Command; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Carbon; use Safe\Exceptions\InfoException; use function Safe\filemtime; @@ -106,7 +105,7 @@ public function handle(): int // For faster iteration we eagerly load the original size variant, // but only the original size variant - $photoQuery = Photo::query()->with(['size_variants' => function (HasMany $r) { + $photoQuery = Photo::query()->with(['size_variants' => function ($r) { $r->where('type', '=', SizeVariantType::ORIGINAL); }]); diff --git a/app/Console/Commands/Laravel/LangFilesToJson.php b/app/Console/Commands/Laravel/LangFilesToJson.php new file mode 100644 index 00000000000..55ac053ee30 --- /dev/null +++ b/app/Console/Commands/Laravel/LangFilesToJson.php @@ -0,0 +1,90 @@ + $data + * + * @return array + * + * @throws PcreException + */ + public function convert(array $data): array + { + $result = []; + + foreach ($data as $key => $value) { + if (is_array($value)) { + $result[$key] = $this->convert($value); + } else { + if (strpos($value, ':') !== false) { + $value = preg_replace('/:(\w+)/', '{$1}', $value); + } + $result[$key] = $value; + } + } + + return $result; + } + + /** + * Execute the console command. + */ + public function handle(): void + { + $sourceDir = base_path('lang/'); + $targetDir = base_path('lang/'); + + $languages = array_diff(scandir($sourceDir), ['.', '..']); + + foreach ($languages as $language) { + if (!is_dir($sourceDir . $language)) { + continue; + } + + $languageDir = $sourceDir . $language . '/'; + /** @var string[] */ + $files = array_diff(scandir($languageDir), ['.', '..']); + + $translations = []; + + foreach ($files as $file) { + $filePath = $languageDir . $file; + $translation = require $filePath; + + $translation = $this->convert($translation); + + $translations[str_replace('.php', '', $file)] = $translation; + } + + $targetPath = $targetDir . $language . '.json'; + + file_put_contents($targetPath, json_encode($translations, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + } + + $this->info('Language files compiled to JSON successfully!'); + } +} \ No newline at end of file diff --git a/app/Console/Commands/Laravel/Optimize.php b/app/Console/Commands/Laravel/Optimize.php index 3571abd85b9..a38383210a0 100644 --- a/app/Console/Commands/Laravel/Optimize.php +++ b/app/Console/Commands/Laravel/Optimize.php @@ -56,7 +56,7 @@ public function handle(): void 'assume-yes' => true, 'assume-no' => false, null => null, - default => throw new InvalidOptionException(sprintf('Unexpected option value %s for --dont-confirm', strval($this->option('dont-confirm')))) + default => throw new InvalidOptionException(sprintf('Unexpected option value %s for --dont-confirm', strval($this->option('dont-confirm')))), }; $hasPreviousCache = file_exists($this->laravel->getCachedConfigPath()) || file_exists($this->laravel->getCachedRoutesPath()); diff --git a/app/Console/Commands/Legacy/ResetAdmin.php b/app/Console/Commands/Legacy/ResetAdmin.php index 716c9f0c46e..16027a9b459 100644 --- a/app/Console/Commands/Legacy/ResetAdmin.php +++ b/app/Console/Commands/Legacy/ResetAdmin.php @@ -27,7 +27,7 @@ class ResetAdmin extends Command */ public function handle(): int { - $this->line('Command deprecated. Instead, use php artisan lychee:update_user or lychee:create_user {username} {password} --may_administrate.'); + $this->line('Command deprecated. Instead, use php artisan lychee:update_user or lychee:create_user {username} {password} --may-administrate.'); return 1; } diff --git a/app/Contracts/Http/Requests/HasAbstractAlbum.php b/app/Contracts/Http/Requests/HasAbstractAlbum.php new file mode 100644 index 00000000000..7879c2613fa --- /dev/null +++ b/app/Contracts/Http/Requests/HasAbstractAlbum.php @@ -0,0 +1,13 @@ + + */ + public function albums(): Collection; +} diff --git a/app/Contracts/Http/Requests/HasBaseAlbum.php b/app/Contracts/Http/Requests/HasBaseAlbum.php new file mode 100644 index 00000000000..ebdca5b848e --- /dev/null +++ b/app/Contracts/Http/Requests/HasBaseAlbum.php @@ -0,0 +1,13 @@ + + */ + public function configs(): Collection; +} diff --git a/app/Contracts/Http/Requests/HasCopyright.php b/app/Contracts/Http/Requests/HasCopyright.php new file mode 100644 index 00000000000..c6eb4d601f8 --- /dev/null +++ b/app/Contracts/Http/Requests/HasCopyright.php @@ -0,0 +1,11 @@ + + */ + public function photos(): Collection; +} diff --git a/app/Contracts/Http/Requests/HasQuotaKB.php b/app/Contracts/Http/Requests/HasQuotaKB.php new file mode 100644 index 00000000000..2a5a7b21189 --- /dev/null +++ b/app/Contracts/Http/Requests/HasQuotaKB.php @@ -0,0 +1,11 @@ + $photos * @property Thumb|null $thumb * @property Collection $access_permissions - * - * @extends Arrayable */ -interface AbstractAlbum extends \JsonSerializable, Arrayable, Jsonable +interface AbstractAlbum { /** - * @return Relation|Builder + * @return Relation>|Builder */ public function photos(): Relation|Builder; diff --git a/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php b/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php index 38d88983e9b..d7189cd47c2 100644 --- a/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php +++ b/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php @@ -52,10 +52,13 @@ public function setPhoto(?Photo $photo): void * Creates a file for the designated size variant. * * @param SizeVariantType $sizeVariant the size variant + * @param bool $isBackup whether to create a backup file * * @return FlysystemFile the file * * @throws LycheeException + * + * @codeCoverageIgnore */ - abstract public function createFile(SizeVariantType $sizeVariant): FlysystemFile; + abstract public function createFile(SizeVariantType $sizeVariant, bool $isBackup = false): FlysystemFile; } diff --git a/app/DTO/AbstractDTO.php b/app/DTO/AbstractDTO.php index 893291b31c9..824e620bcef 100644 --- a/app/DTO/AbstractDTO.php +++ b/app/DTO/AbstractDTO.php @@ -49,9 +49,11 @@ public function toJson($options = 0): string } return $json; + // @codeCoverageIgnoreStart } catch (\JsonException $e) { throw new JsonEncodingException('Error encoding DTO [' . get_class($this) . ']', 0, $e); } + // @codeCoverageIgnoreEnd } /** @@ -67,8 +69,8 @@ public function jsonSerialize(): array { try { return $this->toArray(); - } catch (\Exception $e) { // @codeCoverageIgnoreStart + } catch (\Exception $e) { throw new \JsonException(get_class($this) . '::toArray() failed', 0, $e); // @codeCoverageIgnoreEnd } @@ -76,6 +78,8 @@ public function jsonSerialize(): array /** * {@inheritDoc} + * + * @codeCoverageIgnore */ abstract public function toArray(): array; } diff --git a/app/DTO/AlbumSortingCriterion.php b/app/DTO/AlbumSortingCriterion.php index faccb7ca852..e73b23aefdb 100644 --- a/app/DTO/AlbumSortingCriterion.php +++ b/app/DTO/AlbumSortingCriterion.php @@ -6,7 +6,9 @@ use App\Enum\ColumnSortingType; use App\Enum\OrderSortingType; use App\Models\Configs; +use Spatie\TypeScriptTransformer\Attributes\TypeScript; +#[TypeScript()] class AlbumSortingCriterion extends SortingCriterion { /** diff --git a/app/DTO/BaseImportReport.php b/app/DTO/BaseImportReport.php index 32ac42743cc..7bebaa1ee43 100644 --- a/app/DTO/BaseImportReport.php +++ b/app/DTO/BaseImportReport.php @@ -44,5 +44,10 @@ public function toArray(): array ]; } + /** + * @return string + * + * @codeCoverageIgnore + */ abstract public function toCLIString(): string; } diff --git a/app/DTO/ImageDimension.php b/app/DTO/ImageDimension.php index e3972909779..40c69b36b2e 100644 --- a/app/DTO/ImageDimension.php +++ b/app/DTO/ImageDimension.php @@ -6,7 +6,7 @@ class ImageDimension extends ArrayableDTO { public function __construct( public int $width, - public int $height + public int $height, ) { } diff --git a/app/DTO/PhotoCreate/InitDTO.php b/app/DTO/PhotoCreate/InitDTO.php index 07bcacebac1..8eb54e70b0f 100644 --- a/app/DTO/PhotoCreate/InitDTO.php +++ b/app/DTO/PhotoCreate/InitDTO.php @@ -42,7 +42,7 @@ public function __construct( ImportParam $parameters, NativeLocalFile $sourceFile, AbstractAlbum|null $album, - int|null $fileLastModifiedTime = null + int|null $fileLastModifiedTime = null, ) { $this->sourceFile = $sourceFile; $this->importMode = $parameters->importMode; diff --git a/app/DTO/PhotoCreate/StandaloneDTO.php b/app/DTO/PhotoCreate/StandaloneDTO.php index 79821b13941..af9fcbc7c61 100644 --- a/app/DTO/PhotoCreate/StandaloneDTO.php +++ b/app/DTO/PhotoCreate/StandaloneDTO.php @@ -20,6 +20,7 @@ class StandaloneDTO implements PhotoDTO public TemporaryLocalFile|null $tmpVideoFile = null; public FlysystemFile $targetFile; public StreamStats|null $streamStat; + public FlysystemFile|null $backupFile = null; public function __construct( // The resulting photo diff --git a/app/DTO/PhotoSortingCriterion.php b/app/DTO/PhotoSortingCriterion.php index 0d80853eb7e..2546e0c723e 100644 --- a/app/DTO/PhotoSortingCriterion.php +++ b/app/DTO/PhotoSortingCriterion.php @@ -6,7 +6,9 @@ use App\Enum\ColumnSortingType; use App\Enum\OrderSortingType; use App\Models\Configs; +use Spatie\TypeScriptTransformer\Attributes\TypeScript; +#[TypeScript()] class PhotoSortingCriterion extends SortingCriterion { /** diff --git a/app/DTO/SortingCriterion.php b/app/DTO/SortingCriterion.php index fe2b9b3a33c..9d9f767d6f9 100644 --- a/app/DTO/SortingCriterion.php +++ b/app/DTO/SortingCriterion.php @@ -4,7 +4,9 @@ use App\Enum\ColumnSortingType; use App\Enum\OrderSortingType; +use Spatie\TypeScriptTransformer\Attributes\TypeScript; +#[TypeScript()] class SortingCriterion extends ArrayableDTO { /** diff --git a/app/DTO/TopAlbumDTO.php b/app/DTO/TopAlbumDTO.php index bbb12c8a118..4c94c483a6e 100644 --- a/app/DTO/TopAlbumDTO.php +++ b/app/DTO/TopAlbumDTO.php @@ -4,7 +4,7 @@ use Illuminate\Support\Collection; -class TopAlbumDTO extends ArrayableDTO +class TopAlbumDTO { /** * Sorting criterion. @@ -18,7 +18,7 @@ public function __construct( public Collection $smart_albums, public Collection $tag_albums, public Collection $albums, - public ?Collection $shared_albums = null + public ?Collection $shared_albums = null, ) { } } diff --git a/app/DTO/Version.php b/app/DTO/Version.php index 46e4673e15f..d26bcd5ffab 100644 --- a/app/DTO/Version.php +++ b/app/DTO/Version.php @@ -9,7 +9,7 @@ class Version extends ArrayableDTO public function __construct( public int $major, public int $minor, - public int $patch + public int $patch, ) { } diff --git a/app/Eloquent/FixedQueryBuilderTrait.php b/app/Eloquent/FixedQueryBuilderTrait.php index cf037c8fdaf..54d3e0e1072 100644 --- a/app/Eloquent/FixedQueryBuilderTrait.php +++ b/app/Eloquent/FixedQueryBuilderTrait.php @@ -5,9 +5,9 @@ namespace App\Eloquent; use App\Exceptions\Internal\QueryBuilderException; +use Illuminate\Contracts\Database\Query\Expression; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as BaseBuilder; -use Illuminate\Database\Query\Expression; /** * Fixed Eloquent query builder. @@ -50,10 +50,10 @@ trait FixedQueryBuilderTrait /** * Add a basic where clause to the query. * - * @param \Closure|string|array|Expression $column - * @param mixed $operator - * @param mixed $value - * @param string $boolean + * @param \Closure|string|array|Expression $column + * @param mixed $operator + * @param mixed $value + * @param string $boolean * * @return $this * @@ -268,9 +268,9 @@ public function addSelect($column): static /** * Add an "or where" clause to the query. * - * @param \Closure|array|string|Expression $column - * @param mixed $operator - * @param mixed $value + * @param \Closure|string|array|Expression $column + * @param mixed $operator + * @param mixed $value * * @return $this * diff --git a/app/Enum/AlbumDecorationOrientation.php b/app/Enum/AlbumDecorationOrientation.php index 4b6acd40b89..17a26e028a8 100644 --- a/app/Enum/AlbumDecorationOrientation.php +++ b/app/Enum/AlbumDecorationOrientation.php @@ -13,20 +13,4 @@ enum AlbumDecorationOrientation: string case ROW_REVERSE = 'row-reverse'; case COLUMN = 'column'; case COLUMN_REVERSE = 'column-reverse'; - - /** - * Convert the enum into it's translated format. - * Note that it is missing owner. - * - * @return array - */ - public static function localized(): array - { - return [ - self::ROW->value => __('lychee.ALBUM_DECORATION_ORIENTATION_ROW'), - self::ROW_REVERSE->value => __('lychee.ALBUM_DECORATION_ORIENTATION_ROW_REVERSE'), - self::COLUMN->value => __('lychee.ALBUM_DECORATION_ORIENTATION_COLUMN'), - self::COLUMN_REVERSE->value => __('lychee.ALBUM_DECORATION_ORIENTATION_COLUMN_REVERSE'), - ]; - } } diff --git a/app/Enum/AlbumDecorationType.php b/app/Enum/AlbumDecorationType.php index f6a59e6dda1..46543a73f14 100644 --- a/app/Enum/AlbumDecorationType.php +++ b/app/Enum/AlbumDecorationType.php @@ -14,21 +14,4 @@ enum AlbumDecorationType: string case ALBUM = 'album'; case PHOTO = 'photo'; case ALL = 'all'; - - /** - * Convert the enum into it's translated format. - * Note that it is missing owner. - * - * @return array - */ - public static function localized(): array - { - return [ - self::NONE->value => __('lychee.ALBUM_DECORATION_NONE'), - self::LAYERS->value => __('lychee.ALBUM_DECORATION_ORIGINAL'), - self::ALBUM->value => __('lychee.ALBUM_DECORATION_ALBUM'), - self::PHOTO->value => __('lychee.ALBUM_DECORATION_PHOTO'), - self::ALL->value => __('lychee.ALBUM_DECORATION_ALL'), - ]; - } } diff --git a/app/Enum/AspectRatioCSSType.php b/app/Enum/AspectRatioCSSType.php new file mode 100644 index 00000000000..2f99716b1fa --- /dev/null +++ b/app/Enum/AspectRatioCSSType.php @@ -0,0 +1,18 @@ + 'aspect-5/4', - self::aspect4by5 => 'aspect-4/5', - self::aspect3by2 => 'aspect-3/2', - self::aspect1by1 => 'aspect-square', - self::aspect2by3 => 'aspect-2/3', - self::aspect1byx9 => 'aspect-video', + self::aspect5by4 => AspectRatioCSSType::aspect5by4, + self::aspect4by5 => AspectRatioCSSType::aspect4by5, + self::aspect3by2 => AspectRatioCSSType::aspect3by2, + self::aspect1by1 => AspectRatioCSSType::aspect1by1, + self::aspect2by3 => AspectRatioCSSType::aspect2by3, + self::aspect1byx9 => AspectRatioCSSType::aspect1byx9, }; } - - /** - * Convert the enum into it's translated format. - * - * @return array - */ - public static function localized(): array - { - return [ - self::aspect5by4->value => __('aspect_ratio.5by4'), - self::aspect4by5->value => __('aspect_ratio.4by5'), - self::aspect2by3->value => __('aspect_ratio.2by3'), - self::aspect3by2->value => __('aspect_ratio.3by2'), - self::aspect1by1->value => __('aspect_ratio.1by1'), - self::aspect1byx9->value => __('aspect_ratio.1byx9'), - ]; - } } diff --git a/app/Enum/ColumnSortingAlbumType.php b/app/Enum/ColumnSortingAlbumType.php index 4d6cc30b809..8a313b88ebd 100644 --- a/app/Enum/ColumnSortingAlbumType.php +++ b/app/Enum/ColumnSortingAlbumType.php @@ -26,21 +26,4 @@ public function toColumnSortingType(): ColumnSortingType { return ColumnSortingType::from($this->value); } - - /** - * Convert the enum into it's translated format. - * Note that it is missing owner. - * - * @return array - */ - public static function localized(): array - { - return [ - self::CREATED_AT->value => __('lychee.SORT_ALBUM_SELECT_1'), - self::TITLE->value => __('lychee.SORT_ALBUM_SELECT_2'), - self::DESCRIPTION->value => __('lychee.SORT_ALBUM_SELECT_3'), - self::MIN_TAKEN_AT->value => __('lychee.SORT_ALBUM_SELECT_6'), - self::MAX_TAKEN_AT->value => __('lychee.SORT_ALBUM_SELECT_5'), - ]; - } } diff --git a/app/Enum/ColumnSortingPhotoType.php b/app/Enum/ColumnSortingPhotoType.php index b29b4e15fcf..d81645badae 100644 --- a/app/Enum/ColumnSortingPhotoType.php +++ b/app/Enum/ColumnSortingPhotoType.php @@ -31,22 +31,4 @@ public function toColumnSortingType(): ColumnSortingType { return ColumnSortingType::from($this->value); } - - /** - * Convert the enum into it's translated format. - * Note that it is missing owner. - * - * @return array - */ - public static function localized(): array - { - return [ - self::CREATED_AT->value => __('lychee.SORT_PHOTO_SELECT_1'), - self::TAKEN_AT->value => __('lychee.SORT_PHOTO_SELECT_2'), - self::TITLE->value => __('lychee.SORT_PHOTO_SELECT_3'), - self::DESCRIPTION->value => __('lychee.SORT_PHOTO_SELECT_4'), - self::IS_STARRED->value => __('lychee.SORT_PHOTO_SELECT_6'), - self::TYPE->value => __('lychee.SORT_PHOTO_SELECT_7'), - ]; - } } diff --git a/app/Enum/ConfigType.php b/app/Enum/ConfigType.php new file mode 100644 index 00000000000..f1cff76c1b1 --- /dev/null +++ b/app/Enum/ConfigType.php @@ -0,0 +1,21 @@ + SizeVariantType::MEDIUM, self::MEDIUM2X => SizeVariantType::MEDIUM2X, self::ORIGINAL => SizeVariantType::ORIGINAL, - self::LIVEPHOTOVIDEO => null + self::LIVEPHOTOVIDEO => null, }; } } \ No newline at end of file diff --git a/app/Enum/Livewire/FileStatus.php b/app/Enum/FileStatus.php similarity index 86% rename from app/Enum/Livewire/FileStatus.php rename to app/Enum/FileStatus.php index e9ca3b3a38b..996d5209553 100644 --- a/app/Enum/Livewire/FileStatus.php +++ b/app/Enum/FileStatus.php @@ -1,6 +1,6 @@ - */ - public static function localized(): array - { - return [ - self::EXIF->value => __('lychee.OVERLAY_EXIF'), - self::DESC->value => __('lychee.OVERLAY_DESCRIPTION'), - self::DATE->value => __('lychee.OVERLAY_DATE'), - self::NONE->value => __('lychee.OVERLAY_NONE'), - ]; - } } diff --git a/app/Enum/Livewire/NotificationType.php b/app/Enum/Livewire/NotificationType.php deleted file mode 100644 index e6f2dc86faa..00000000000 --- a/app/Enum/Livewire/NotificationType.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ - public static function localized(): array - { - return [ - self::ASC->value => __('lychee.SORT_ASCENDING'), - self::DESC->value => __('lychee.SORT_DESCENDING'), - ]; - } } diff --git a/app/Enum/PhotoLayoutType.php b/app/Enum/PhotoLayoutType.php index efb80cd4ff3..62723582716 100644 --- a/app/Enum/PhotoLayoutType.php +++ b/app/Enum/PhotoLayoutType.php @@ -14,21 +14,4 @@ enum PhotoLayoutType: string case UNJUSTIFIED = 'unjustified'; // ! Legcay case MASONRY = 'masonry'; case GRID = 'grid'; - - /** - * Convert the enum into it's translated format. - * Note that it is missing owner. - * - * @return array - */ - public static function localized(): array - { - // yes, the UNJUSTIFIED is dropped. - return [ - self::SQUARE->value => __('lychee.LAYOUT_SQUARES'), - self::JUSTIFIED->value => __('lychee.LAYOUT_JUSTIFIED'), - self::MASONRY->value => __('lychee.LAYOUT_MASONRY'), - self::GRID->value => __('lychee.LAYOUT_GRID'), - ]; - } } diff --git a/app/Enum/Traits/WireableEnumTrait.php b/app/Enum/Traits/WireableEnumTrait.php deleted file mode 100644 index edf5a498018..00000000000 --- a/app/Enum/Traits/WireableEnumTrait.php +++ /dev/null @@ -1,35 +0,0 @@ -value; - } - - public static function fromLivewire(mixed $value): self - { - if (!is_string($value) && !is_int($value)) { - throw new LycheeLogicException('Enum could not be instanciated from ' . strval($value), null); - } - - return self::from($value); - } - - /** - * @return string[]|int[]|\Closure - * - * @psalm-return array | Closure(string):(int|string) - */ - protected static function values() - { - return function (string $name): string { - return mb_strtolower($name); - }; - } -} \ No newline at end of file diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index df567795dd5..19890bfac07 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -16,7 +16,7 @@ use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Container\Container; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; -use Illuminate\Foundation\ViteManifestNotFoundException; +use Illuminate\Foundation\ViteException; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; @@ -98,7 +98,7 @@ class Handler extends ExceptionHandler TokenMismatchException::class, SessionExpiredException::class, NoWriteAccessOnLogsExceptions::class, - ViteManifestNotFoundException::class, + ViteException::class, ]; /** @var array> */ @@ -114,7 +114,7 @@ class Handler extends ExceptionHandler /** @var array> */ protected $force_exception_to_http = [ - ViteManifestNotFoundException::class, + ViteException::class, ]; /** diff --git a/app/Exceptions/QuotaExceededException.php b/app/Exceptions/QuotaExceededException.php new file mode 100644 index 00000000000..a24e47c5b25 --- /dev/null +++ b/app/Exceptions/QuotaExceededException.php @@ -0,0 +1,20 @@ +findBaseAlbumOrFail($albumID, $withRelations); } + /** + * Same as above but in the case of albumID being null, it returns null. + * + * @param string|null $albumID the ID of the requested album + * @param bool $withRelations indicates if the relations of an + * album (i.e. photos and sub-albums, + * if applicable) shall be loaded, too. + * + * @return AbstractAlbum|null the album for the ID or null if ID is null + * + * @throws ModelNotFoundException thrown, if no album with the given ID exists + * @throws InvalidSmartIdException should not be thrown; otherwise this + * indicates an internal bug + */ + public function findNullalbleAbstractAlbumOrFail(?string $albumID, bool $withRelations = true): ?AbstractAlbum + { + if ($albumID === null) { + return null; + } + + return $this->findAbstractAlbumOrFail($albumID, $withRelations); + } + /** * Returns an existing model instance of an album with the given ID or * fails with an exception. @@ -111,13 +134,9 @@ public function findAbstractAlbumsOrFail(array $albumIDs, bool $withRelations = $smartAlbums = []; foreach ($smartAlbumIDs as $smartID) { - try { - $smartAlbumType = SmartAlbumType::from($smartID); - $smartAlbums[] = $this->createSmartAlbum($smartAlbumType, $withRelations); - } catch (\ValueError $e) { - $e2 = new InvalidSmartIdException($smartID); - throw LycheeAssertionError::createFromUnexpectedException($e2); - } + $smartAlbumType = SmartAlbumType::tryFrom($smartID) + ?? throw LycheeAssertionError::createFromUnexpectedException(new InvalidSmartIdException($smartID)); + $smartAlbums[] = $this->createSmartAlbum($smartAlbumType, $withRelations); } /** @phpstan-ignore-next-line phpstan stan complain of incompatibility of types while both are subtypes... */ diff --git a/app/Http/Controllers/Admin/DiagnosticsController.php b/app/Http/Controllers/Admin/DiagnosticsController.php new file mode 100644 index 00000000000..66e0debad9e --- /dev/null +++ b/app/Http/Controllers/Admin/DiagnosticsController.php @@ -0,0 +1,162 @@ + + */ + public function errors(Errors $errors): array + { + return ErrorLine::collect($errors->get()); + } + + /** + * Get the space usage. + * ! This is slow. + * + * @param DiagnosticsRequest $_request + * @param Space $space + * + * @return string[] + */ + public function space(DiagnosticsRequest $_request, Space $space) + { + return $space->get(); + } + + /** + * Get info of the installation. + * + * @param DiagnosticsRequest $_request + * @param Info $info + * + * @return string[] + */ + public function info(DiagnosticsRequest $_request, Info $info): array + { + return $info->get(); + } + + /** + * Get the configuration of the installation. + * + * @param DiagnosticsRequest $_request + * @param Configuration $config + * + * @return string[] + */ + public function config(DiagnosticsRequest $_request, Configuration $config): array + { + return $config->get(); + } + + /** + * Just call the phpinfo function. + * Cannot be tested. + * + * @param DiagnosticsRequest $_request + * + * @return void + * + * @codeCoverageIgnore + */ + public function phpinfo(DiagnosticsRequest $_request): void + { + phpinfo(); + } + + /** + * Return the table of access permissions currently available on the server. + * + * @return Permissions + */ + public function getFullAccessPermissions(DiagnosticsRequest $_request, AlbumQueryPolicy $albumQueryPolicy): Permissions + { + $data1 = AccessPermission::query() + ->join('base_albums', 'base_albums.id', '=', APC::BASE_ALBUM_ID) + ->select([ + APC::BASE_ALBUM_ID, + APC::IS_LINK_REQUIRED, + APC::GRANTS_FULL_PHOTO_ACCESS, + APC::GRANTS_DOWNLOAD, + APC::GRANTS_EDIT, + APC::GRANTS_UPLOAD, + APC::GRANTS_DELETE, + APC::PASSWORD, + APC::USER_ID, + 'title', + ]) + ->when( + Auth::check(), + fn ($q1) => $q1 + ->where(APC::USER_ID, '=', Auth::id()) + ->orWhere( + fn ($q2) => $q2->whereNull(APC::USER_ID) + ->whereNotIn( + 'access_permissions.' . APC::BASE_ALBUM_ID, + fn ($q3) => $q3->select('acc_per.' . APC::BASE_ALBUM_ID) + ->from('access_permissions', 'acc_per') + ->where(APC::USER_ID, '=', Auth::id()) + ) + ) + ) + ->when( + !Auth::check(), + fn ($q1) => $q1->whereNull(APC::USER_ID) + ) + ->orderBy(APC::BASE_ALBUM_ID) + ->get(); + + $query2 = DB::table('base_albums'); + $albumQueryPolicy->joinSubComputedAccessPermissions($query2, 'base_albums.id', 'inner', '', true); + $data2 = $query2 + ->select([ + APC::BASE_ALBUM_ID, + APC::IS_LINK_REQUIRED, + APC::GRANTS_FULL_PHOTO_ACCESS, + APC::GRANTS_DOWNLOAD, + APC::GRANTS_EDIT, + APC::GRANTS_UPLOAD, + APC::GRANTS_DELETE, + APC::PASSWORD, + APC::USER_ID, + 'title', + ]) + ->orderBy(APC::BASE_ALBUM_ID) + ->get() + ->map(function ($e) { + $e->is_link_required = $e->is_link_required === 1; + $e->grants_download = $e->grants_download === 1; + $e->grants_upload = $e->grants_upload === 1; + $e->grants_delete = $e->grants_delete === 1; + $e->grants_edit = $e->grants_edit === 1; + $e->grants_full_photo_access = $e->grants_full_photo_access === 1; + + return $e; + }); + + return new Permissions(json_encode($data1, JSON_PRETTY_PRINT), json_encode($data2, JSON_PRETTY_PRINT)); + } +} diff --git a/app/Http/Controllers/Admin/JobsController.php b/app/Http/Controllers/Admin/JobsController.php new file mode 100644 index 00000000000..4ebad0b547b --- /dev/null +++ b/app/Http/Controllers/Admin/JobsController.php @@ -0,0 +1,29 @@ + + */ + public function list(ShowJobsRequest $request): PaginatedDataCollection + { + $jobs = JobHistory::with(['owner']) + ->when(!Auth::user()->may_administrate, fn ($query) => $query->where('owner_id', '=', Auth::id())) + ->orderBy('id', 'desc') + ->paginate(Configs::getValueAsInt('log_max_num_line')); + + return JobHistoryResource::collect($jobs, PaginatedDataCollection::class); + } +} diff --git a/app/Http/Controllers/Admin/Maintenance/Cleaning.php b/app/Http/Controllers/Admin/Maintenance/Cleaning.php new file mode 100644 index 00000000000..00f84a8b4cd --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/Cleaning.php @@ -0,0 +1,89 @@ +skip. + * + * @return string[] + */ + public function do(CleaningRequest $request): array + { + if (!$this->check($request)->is_not_empty) { + return []; + } + + $results = []; + foreach (new \DirectoryIterator($request->path()) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + if (in_array($fileInfo->getFilename(), $this->skip, true)) { + continue; + } + $results[] = sprintf(__('maintenance.cleaning.result'), $fileInfo->getFilename()); + + if ($fileInfo->isDir()) { + rmdir($fileInfo->getRealPath()); + continue; + } + unlink($fileInfo->getRealPath()); + } + + return $results; + } + + /** + * Check whether there are files to be removed. + * If not, we will not display the module to reduce complexity. + * + * @return CleaningState + */ + public function check(CleaningRequest $request): CleaningState + { + $cleaning_state = new CleaningState($request->path(), false); + + if (!is_dir($request->path())) { + Log::warning('directory ' . $request->path() . ' not found!'); + $cleaning_state->is_not_empty = false; + + return $cleaning_state; + } + + if (!(new \FilesystemIterator($request->path()))->valid()) { + $cleaning_state->is_not_empty = false; + + return $cleaning_state; + } + + $files_found = false; + foreach (new \DirectoryIterator($request->path()) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + if (in_array($fileInfo->getFilename(), $this->skip, true)) { + continue; + } + $files_found = true; + } + $cleaning_state->is_not_empty = $files_found; + + return $cleaning_state; + } +} diff --git a/app/Livewire/Components/Modules/Maintenance/FixJobs.php b/app/Http/Controllers/Admin/Maintenance/FixJobs.php similarity index 55% rename from app/Livewire/Components/Modules/Maintenance/FixJobs.php rename to app/Http/Controllers/Admin/Maintenance/FixJobs.php index 1c0957f1f78..04ade84bbd5 100644 --- a/app/Livewire/Components/Modules/Maintenance/FixJobs.php +++ b/app/Http/Controllers/Admin/Maintenance/FixJobs.php @@ -1,14 +1,11 @@ getNoWaitingJobsFoundProperty()) { + if ($this->check($_request) === 0) { return; } @@ -56,10 +39,10 @@ public function do(): void * Check if there are any waiting jobs. * If not, we will not display the module to reduce complexity. * - * @return bool + * @return int */ - public function getNoWaitingJobsFoundProperty(): bool + public function check(MaintenanceRequest $_request): int { - return JobHistory::whereIn('status', $this->waitingJobsTypes)->count() === 0; + return JobHistory::whereIn('status', $this->waitingJobsTypes)->count(); } } diff --git a/app/Http/Controllers/Admin/Maintenance/FixTree.php b/app/Http/Controllers/Admin/Maintenance/FixTree.php new file mode 100644 index 00000000000..b706302540e --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/FixTree.php @@ -0,0 +1,43 @@ +skip. + * + * @return int + */ + public function do(MaintenanceRequest $request): int + { + return Album::query()->fixTree(); + } + + /** + * Check whether there are files to be removed. + * If not, we will not display the module to reduce complexity. + * + * @return TreeState + */ + public function check(MaintenanceRequest $request): TreeState + { + $stats = Album::query()->countErrors(); + + return new TreeState( + $stats['oddness'] ?? 0, + $stats['duplicates'] ?? 0, + $stats['wrong_parent'] ?? 0, + $stats['missing_parent'] ?? 0 + ); + } +} diff --git a/app/Http/Controllers/Admin/Maintenance/GenSizeVariants.php b/app/Http/Controllers/Admin/Maintenance/GenSizeVariants.php new file mode 100644 index 00000000000..225711d34c8 --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/GenSizeVariants.php @@ -0,0 +1,76 @@ +where('type', 'like', 'image/%') + ->with('size_variants') + ->whereDoesntHave('size_variants', function (Builder $query) use ($request) { + $query->where('type', '=', $request->kind()); + }) + ->take(100) + ->get(); + + $generated = 0; + /** @var Photo $photo */ + foreach ($photos as $photo) { + // @codeCoverageIgnoreStart + $sizeVariantFactory->init($photo); + $sizeVariant = $sizeVariantFactory->createSizeVariantCond($request->kind()); + if ($sizeVariant !== null) { + $generated++; + Log::notice($request->kind()->value . ' (' . $sizeVariant->width . 'x' . $sizeVariant->height . ') for ' . $photo->title . ' created.'); + } else { + Log::error('Did not create ' . $request->kind()->value . ' for ' . $photo->title . '.'); + } + // @codeCoverageIgnoreEnd + } + } + + /** + * Check how many images need to be created. + * + * @return int + */ + public function check(CreateThumbsRequest $request, SizeVariantDimensionHelpers $svHelpers): int + { + if (!$svHelpers->isEnabledByConfiguration($request->kind())) { + return 0; + } + + $numGenerated = SizeVariant::query()->where('type', '=', $request->kind())->count(); + + $totalToHave = SizeVariant::query()->where(fn ($q) => $q + ->when($svHelpers->getMaxWidth($request->kind()) !== 0, fn ($q1) => $q1->where('width', '>', $svHelpers->getMaxWidth($request->kind()))) + ->when($svHelpers->getMaxHeight($request->kind()) !== 0, fn ($q2) => $q2->orWhere('height', '>', $svHelpers->getMaxHeight($request->kind()))) + ) + ->where('type', '=', SizeVariantType::ORIGINAL) + ->count(); + + return $totalToHave - $numGenerated; + } +} diff --git a/app/Http/Controllers/Admin/Maintenance/MissingFileSizes.php b/app/Http/Controllers/Admin/Maintenance/MissingFileSizes.php new file mode 100644 index 00000000000..4ca226e6156 --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/MissingFileSizes.php @@ -0,0 +1,69 @@ +where('storage_disk', '=', StorageDiskType::LOCAL) + ->where('filesize', '=', 0) + ->orderBy('id'); + // Internally, only holds $limit entries at once + $variants = $variants_query->lazyById(500); + + $generated = 0; + + foreach ($variants as $variant) { + // @codeCoverageIgnoreStart + $variantFile = $variant->getFile(); + if ($variantFile->exists()) { + try { + $variant->filesize = $variantFile->getFilesize(); + if (!$variant->save()) { + Log::error('Failed to update filesize for ' . $variantFile->getRelativePath() . '.'); + } else { + $generated++; + } + } catch (UnableToRetrieveMetadata $e) { + Log::error($variant->id . ' : Failed to get filesize for ' . $variantFile->getRelativePath() . '.'); + } + } else { + Log::error($variant->id . ' : No file found at ' . $variantFile->getRelativePath() . '.'); + } + // @codeCoverageIgnoreEnd + } + } + + /** + * Check how many images have missing file sizes.. + * + * @return int + */ + public function check(MaintenanceRequest $request): int + { + return SizeVariant::query() + ->where('filesize', '=', 0) + // TODO: remove s3 support here. + ->count(); + } +} diff --git a/app/Http/Controllers/Admin/Maintenance/Model/Album.php b/app/Http/Controllers/Admin/Maintenance/Model/Album.php new file mode 100644 index 00000000000..f5af93a005b --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/Model/Album.php @@ -0,0 +1,20 @@ + + */ +class Album extends Model implements Node +{ + /** @phpstan-use NodeTrait */ + use NodeTrait; + public $timestamps = false; +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/Maintenance/Optimize.php b/app/Http/Controllers/Admin/Maintenance/Optimize.php new file mode 100644 index 00000000000..1fa90098926 --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/Optimize.php @@ -0,0 +1,28 @@ +do()) + ->merge(collect($optimizeTables->do())) + ->all(); + } +} diff --git a/app/Http/Controllers/Admin/Maintenance/RegisterController.php b/app/Http/Controllers/Admin/Maintenance/RegisterController.php new file mode 100644 index 00000000000..386d6da1e5f --- /dev/null +++ b/app/Http/Controllers/Admin/Maintenance/RegisterController.php @@ -0,0 +1,32 @@ +key()->getValue()); + $verify = resolve(Verify::class); + $is_supporter = $verify->is_supporter(); + if ($is_supporter) { + return new RegisterData(true); + } + + // Not valid, reset the key. + Configs::set('license_key', ''); + + return new RegisterData(false); + } +} diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php new file mode 100644 index 00000000000..fc11b0734d4 --- /dev/null +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -0,0 +1,95 @@ +when(!$request->is_se() && !Configs::getValueAsBool('enable_se_preview'), fn ($q) => $q->where('level', '=', 0)) + ->orderBy('cat', 'asc')->get(); + + return new ConfigCollectionResource($editable_configs); + } + + public function setConfigs(SetConfigsRequest $request): ConfigCollectionResource + { + $configs = $request->configs(); + $configs->each(function ($config) { + Configs::query()->where('key', $config->key)->update(['value' => $config->value ?? '']); + }); + + Configs::invalidateCache(); + + return new ConfigCollectionResource(Configs::orderBy('cat', 'asc')->get()); + } + + /** + * Give the list of available languages. + * + * @return string[] + */ + public function getLanguages(GetAllConfigsRequest $request): array + { + // @phpstan-ignore-next-line + return collect(config('app.supported_locale'))->filter(function ($value, $key) { + return !str_contains($value, 'json'); + })->values()->toArray(); + } + + /** + * Takes the js input text and puts it into `dist/custom.js`. + * This allows admins to actually execute custom js code on their + * Lychee-Laravel installation. + * + * @param SetJSSettingRequest $request + * + * @return void + * + * @throws InsufficientFilesystemPermissions + */ + public function setJS(SetJSSettingRequest $request): void + { + $js = $request->getJs(); + if (Storage::disk('dist')->put('custom.js', $js) === false) { + if (Storage::disk('dist')->get('custom.js') !== $js) { + throw new InsufficientFilesystemPermissions('Could not save JS'); + } + } + } + + /** + * Takes the css input text and put it into `dist/user.css`. + * This allows admins to actually personalize the look of their + * installation. + * + * @param SetCSSSettingRequest $request + * + * @return void + * + * @throws InsufficientFilesystemPermissions + */ + public function setCSS(SetCSSSettingRequest $request): void + { + $css = $request->getCss(); + if (Storage::disk('dist')->put('user.css', $css) === false) { + if (Storage::disk('dist')->get('user.css') !== $css) { + throw new InsufficientFilesystemPermissions('Could not save CSS'); + } + } + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/UpdateController.php b/app/Http/Controllers/Admin/UpdateController.php new file mode 100644 index 00000000000..59d893beb97 --- /dev/null +++ b/app/Http/Controllers/Admin/UpdateController.php @@ -0,0 +1,133 @@ +applyUpdate = $applyUpdate; + } + + public function get(UpdateRequest $request, VersionInfo $versionInfo): UpdateInfo + { + /** @var VersionChannelType $channelName */ + $channelName = $versionInfo->getChannelName(); + $info = $versionInfo->fileVersion->getVersion()->toString(); + $extra = ''; + + if ($channelName !== VersionChannelType::RELEASE) { + if ($versionInfo->gitHubFunctions->localHead !== null) { + $branch = $versionInfo->gitHubFunctions->localBranch ?? '??'; + $commit = $versionInfo->gitHubFunctions->localHead ?? '??'; + $info = sprintf('%s (%s)', $branch, $commit); + $extra = $versionInfo->gitHubFunctions->getBehindTest(); + } else { + // @codeCoverageIgnoreStart + $info = 'No git data found.'; + // @codeCoverageIgnoreEnd + } + } + + return new UpdateInfo($info, $extra, $channelName); + } + + /** + * Checking if any updates are available. + * + * @return UpdateCheckInfo + */ + public function check(UpdateRequest $request, GitHubVersion $gitHubFunctions, VersionInfo $versionInfo): UpdateCheckInfo + { + return new UpdateCheckInfo($gitHubFunctions->getBehindTest(), !$gitHubFunctions->isUpToDate() || !$versionInfo->fileVersion->isUpToDate()); + } + + /** + * Updates Lychee and returns the messages as a JSON object. + * + * The method requires PHP to have shell access. + * Except for the return type this method is identical to + * {@link UpdateController::view()}. + * + * @param UpdateRequest $request + * + * @return array{updateMsgs: array} + * + * @throws LycheeException + */ + public function apply(UpdateRequest $request): array + { + UpdatableCheck::assertUpdatability(); + + return ['updateMsgs' => $this->applyUpdate->run()]; + } + + /** + * Updates Lychee and returns the messages as an HTML view. + * + * The method requires PHP to have shell access. + * Except for the return type this method is identical to + * {@link UpdateController::apply()}. + * + * @param UpdateRequest $request + * + * @return View + * + * @throws LycheeException + */ + public function view(UpdateRequest $request): View + { + UpdatableCheck::assertUpdatability(); + + $output = $this->applyUpdate->run(); + + return view('update.results', ['code' => '200', 'message' => 'Upgrade results', 'output' => $output]); + } + + /** + * Migrates the Lychee DB and returns a HTML view. + * + * **TODO:** Consolidate with {@link \App\Http\Controllers\Install\MigrationController::view()}. + * + * **ATTENTION:** This method serves a somewhat similar purpose as + * `MigrationController::view()` except that the latter does not only + * trigger a migration, but also generates a new API key. + * Also note, that this method internally uses + * {@link ApplyUpdate::migrate()} while `MigrationController::view` + * uses {@link \App\Actions\InstallUpdate\ApplyMigration::migrate()}. + * However, both methods are very similar, too. + * The whole code around installation/upgrade/migration should be + * thoroughly revised and refactored. + * + * @param MigrateRequest $request + * + * @return View|Response + */ + public function migrate(MigrateRequest $request): View|Response + { + $output = []; + $output = $this->applyUpdate->run(); + + return view('update.results', ['code' => '200', 'message' => 'Migration results', 'output' => $output]); + } +} diff --git a/app/Http/Controllers/Admin/UserManagementController.php b/app/Http/Controllers/Admin/UserManagementController.php new file mode 100644 index 00000000000..5efa0de50c6 --- /dev/null +++ b/app/Http/Controllers/Admin/UserManagementController.php @@ -0,0 +1,102 @@ + + */ + public function list(ManagmentListUsersRequest $request, Spaces $spaces): Collection + { + $users = User::select(['id', 'username', 'may_administrate', 'may_upload', 'may_edit_own_settings', 'quota_kb', 'description', 'note'])->orderBy('id', 'asc')->get(); + $spacesPerUser = $spaces->getFullSpacePerUser(); + $zipped = $users->zip($spacesPerUser); + + return $zipped->map(fn ($item) => new UserManagementResource($item[0], $item[1], $request->is_se())); + } + + /** + * Save modification done to a user. + * Note that an admin can change the password of a user at will. + * + * @param SetUserSettingsRequest $request + * @param Save $save + * + * @return void + */ + public function save(SetUserSettingsRequest $request, Save $save): void + { + $save->do( + user: $request->user2(), + username: $request->username(), + password: $request->password(), + mayUpload: $request->mayUpload(), + mayEditOwnSettings: $request->mayEditOwnSettings(), + quota_kb: $request->quota_kb(), + note: $request->note() + ); + } + + /** + * Deletes a user. + * + * The albums and photos owned by the user are re-assigned to the + * admin user. + * + * @param DeleteUserRequest $request + * + * @return void + */ + public function delete(DeleteUserRequest $request): void + { + if ($request->user2()->id === Auth::id()) { + throw new UnauthorizedException('You are not allowed to delete yourself'); + } + $request->user2()->delete(); + } + + /** + * Create a new user. + * + * @param AddUserRequest $request + * @param Create $create + * + * @return UserManagementResource + */ + public function create(AddUserRequest $request, Create $create): UserManagementResource + { + $user = $create->do( + username: $request->username(), + password: $request->password(), + mayUpload: $request->mayUpload(), + mayEditOwnSettings: $request->mayEditOwnSettings(), + quota_kb: $request->quota_kb(), + note: $request->note() + ); + + return new UserManagementResource($user, ['id' => $user->id, 'size' => 0], $request->is_se()); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php new file mode 100644 index 00000000000..1ac12365506 --- /dev/null +++ b/app/Http/Controllers/AuthController.php @@ -0,0 +1,89 @@ + $request->username(), + 'password' => $request->password(), + ])) { + Log::channel('login')->notice(__METHOD__ . ':' . __LINE__ . ' -- User (' . $request->username() . ') has logged in from ' . $request->ip()); + + return; + } + + Log::channel('login')->error(__METHOD__ . ':' . __LINE__ . ' -- User (' . $request->username() . ') has tried to log in from ' . $request->ip()); + throw new UnauthenticatedException('Unknown user or invalid password'); + } + + /** + * Unsets the session values. + * + * @return void + */ + public function logout(): void + { + Auth::logout(); + Session::flush(); + } + + /** + * Get the global rights of the current user. + */ + public function getGlobalRights(): Data + { + return new GlobalRightsResource(); + } + + /** + * First function being called via AJAX. + * + * @return Data + */ + public function getCurrentUser(): Data + { + /** @var User|null $user */ + $user = Auth::user(); + + return new UserResource($user); + } + + /** + * Return the configuration for the authentication. + * + * @return Data + */ + public function getConfig(): Data + { + return new AuthConfig(); + } +} diff --git a/app/Http/Controllers/Gallery/AlbumController.php b/app/Http/Controllers/Gallery/AlbumController.php new file mode 100644 index 00000000000..ad52f7bcab2 --- /dev/null +++ b/app/Http/Controllers/Gallery/AlbumController.php @@ -0,0 +1,327 @@ +album()); + $albumResource = null; + + if ($config->is_accessible) { + $albumResource = match (true) { + $request->album() instanceof BaseSmartAlbum => new SmartAlbumResource($request->album()), + $request->album() instanceof TagAlbum => new TagAlbumResource($request->album()), + $request->album() instanceof Album => new AlbumResource($request->album()), + default => throw new LycheeLogicException('This should not happen'), + }; + } + + return new AbstractAlbumResource($config, $albumResource); + } + + public function createAlbum(AddAlbumRequest $request): string + { + /** @var int $ownerId */ + $ownerId = Auth::id() ?? throw new UnauthenticatedException(); + $create = new Create($ownerId); + + return $create->create($request->title(), $request->parent_album())->id; + } + + public function createTagAlbum(AddTagAlbumRequest $request, CreateTagAlbum $create): string + { + return $create->create($request->title(), $request->tags())->id; + } + + public function updateAlbum(UpdateAlbumRequest $request, SetHeader $setHeader): EditableBaseAlbumResource + { + $album = $request->album(); + if ($album === null) { + throw new LycheeLogicException('album is null'); + } + $album->title = $request->title(); + $album->description = $request->description(); + $album->license = $request->license(); + $album->album_thumb_aspect_ratio = $request->aspectRatio(); + $album->copyright = $request->copyright(); + $album->photo_sorting = $request->photoSortingCriterion(); + $album->album_sorting = $request->albumSortingCriterion(); + $album->photo_layout = $request->photoLayout(); + + $album = $setHeader->do( + album: $album, + is_compact: $request->is_compact(), + photo: $request->photo(), + shall_override: true); + + return EditableBaseAlbumResource::fromModel($album); + } + + public function updateTagAlbum(UpdateTagAlbumRequest $request): EditableBaseAlbumResource + { + $album = $request->album(); + if ($album === null) { + throw new LycheeLogicException('album is null'); + } + $album->title = $request->title(); + $album->description = $request->description(); + $album->show_tags = $request->tags(); + $album->copyright = $request->copyright(); + $album->photo_sorting = $request->photoSortingCriterion(); + $album->photo_layout = $request->photoLayout(); + $album->save(); + + return EditableBaseAlbumResource::fromModel($album); + } + + public function updateProtectionPolicy(SetAlbumProtectionPolicyRequest $request, + SetProtectionPolicy $setProtectionPolicy, + SetSmartProtectionPolicy $setSmartProtectionPolicy): AlbumProtectionPolicy + { + if ($request->album() instanceof BaseSmartAlbum) { + $setSmartProtectionPolicy->do( + $request->album(), + $request->albumProtectionPolicy()->is_public + ); + + return AlbumProtectionPolicy::ofSmartAlbum($request->album()); + } + + /** @var BaseAlbum $album */ + $album = $request->album(); + $setProtectionPolicy->do( + $album, + $request->albumProtectionPolicy(), + $request->isPasswordProvided(), + $request->password() + ); + + return AlbumProtectionPolicy::ofBaseAlbum($album->refresh()); + } + + /** + * Delete the album and all of its pictures. + * + * @param DeleteAlbumsRequest $request the request + * @param Delete $delete the delete action + * + * @return void + */ + public function delete(DeleteAlbumsRequest $request, Delete $delete): void + { + $fileDeleter = $delete->do($request->albumIds()); + App::terminating(fn () => $fileDeleter->do()); + } + + /** + * Get the list of albums. + * + * @param TargetListAlbumRequest $request + * @param ListAlbums $listAlbums + * + * @return array + */ + public function getTargetListAlbums(TargetListAlbumRequest $request, ListAlbums $listAlbums) + { + if ($request->album() instanceof Album) { + /** @var Album $album */ + $album = $request->album(); + + return TargetAlbumResource::collect($listAlbums->do($album->_lft, $album->_rgt, $album->parent_id)); + } + + return TargetAlbumResource::collect($listAlbums->do(null, null, null)); + } + + /** + * Merge albums. The first of the list is the destination of the merge. + * + * @param MergeAlbumsRequest $request + * @param Merge $merge + * + * @return void + */ + public function merge(MergeAlbumsRequest $request, Merge $merge): void + { + $merge->do($request->album(), $request->albums()); + } + + /** + * Move multiple albums into another album. + * + * @param MoveAlbumsRequest $request + * @param Move $move + * + * @return void + */ + public function move(MoveAlbumsRequest $request, Move $move): void + { + $move->do($request->album(), $request->albums()); + } + + /** + * @param TransferAlbumRequest $request + * @param Transfer $transfer + * + * @return void + */ + public function transfer(TransferAlbumRequest $request, Transfer $transfer): void + { + $transfer->do($request->album(), $request->user2()->id); + } + + /** + * @param SetAsCoverRequest $request + * + * @return void + */ + public function cover(SetAsCoverRequest $request): void + { + $album = $request->album(); + $album->cover_id = ($album->cover_id === $request->photo()->id) ? null : $request->photo()->id; + $album->save(); + } + + /** + * @param $request + * + * @return void + */ + public function header(SetAsHeaderRequest $request, SetHeader $setHeader): void + { + $setHeader->do($request->album(), $request->is_compact(), $request->photo()); + } + + /** + * Rename an album. + * + * @param RenameAlbumRequest $request + * + * @return void + */ + public function rename(RenameAlbumRequest $request): void + { + $album = $request->album(); + $album->title = $request->title(); + $album->save(); + } + + /** + * Return the archive of the pictures of the album and its sub-albums. + * + * @param ZipRequest $request + * @param AlbumArchive $album_archive + * @param PhotoArchive $photo_archive + * + * @return StreamedResponse + */ + public function getArchive(ZipRequest $request, AlbumArchive $album_archive, PhotoArchive $photo_archive): StreamedResponse + { + if ($request->albums()->count() > 0) { + return $album_archive->do($request->albums()); + } + + return $photo_archive->do($request->photos(), $request->sizeVariant()); + } + + /** + * Provided the albumID and password, return whether the album can be accessed or not. + * + * @param UnlockAlbumRequest $request + * @param Unlock $unlock + * + * @return void + */ + public function unlock(UnlockAlbumRequest $request, Unlock $unlock): void + { + $unlock->do($request->album(), $request->password()); + } + + /** + * Upload a track for the Album. + * + * @param SetAlbumTrackRequest $request + * + * @return void + */ + public function setTrack(SetAlbumTrackRequest $request): void + { + $request->album()->setTrack($request->file); + } + + /** + * Delete a track from the Album. + * + * @param DeleteTrackRequest $request + * + * @return void + */ + public function deleteTrack(DeleteTrackRequest $request): void + { + $request->album()->deleteTrack(); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/AlbumsController.php b/app/Http/Controllers/Gallery/AlbumsController.php new file mode 100644 index 00000000000..3120124848b --- /dev/null +++ b/app/Http/Controllers/Gallery/AlbumsController.php @@ -0,0 +1,22 @@ +get(), new RootConfig()); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/ConfigController.php b/app/Http/Controllers/Gallery/ConfigController.php new file mode 100644 index 00000000000..1d239623275 --- /dev/null +++ b/app/Http/Controllers/Gallery/ConfigController.php @@ -0,0 +1,54 @@ +photoQueryPolicy = resolve(PhotoQueryPolicy::class); + } + + /** + * Return an image and the timeout if the frame is supported. + * + * @param FrameRequest $request + * + * @return FrameData + */ + public function get(FrameRequest $request): FrameData + { + $timeout = Configs::getValueAsInt('mod_frame_refresh'); + $photo = $this->loadPhoto($request->album(), 5); + + if ($photo === null) { + return new FrameData($timeout, '', ''); + } + + $src = $photo->size_variants->getMedium()?->url ?? $photo->size_variants->getOriginal()?->url; + + if ($photo->size_variants->getMedium() !== null && $photo->size_variants->getMedium2x() !== null) { + $srcset = $photo->size_variants->getMedium()->url . ' ' . $photo->size_variants->getMedium()->width . 'w,'; + $srcset .= $photo->size_variants->getMedium2x()->url . ' ' . $photo->size_variants->getMedium2x()->width . 'w'; + } else { + $srcset = ''; + } + + return new FrameData($timeout, $src, $srcset); + } + + /** + * Return the full random image data instead of just the URLs. + * + * @param FrameRequest $request + * + * @return PhotoResource + */ + public function random(FrameRequest $request): PhotoResource + { + $photo = $this->loadPhoto($request->album(), 5); + + return PhotoResource::fromModel($photo); + } + + /** + * Recursively search for a photo to display. + * + * @param AbstractAlbum|null $album + * @param int $retries + * + * @return Photo|null + */ + private function loadPhoto(AbstractAlbum|null $album, int $retries = 5): ?Photo + { + // avoid infinite recursion + if ($retries === 0) { + return null; + } + + $query = null; + + // default query + if ($album === null) { + $query = $this->photoQueryPolicy->applySearchabilityFilter(Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links'])); + } else { + $query = $album->photos()->with(['album', 'size_variants', 'size_variants.sym_links']); + } + + /** @var ?Photo $photo */ + // PHPStan does not understand that `firstOrFail` returns `Photo`, but assumes that it returns `Model` + // @phpstan-ignore-next-line + $photo = $query->inRandomOrder()->first(); + if ($photo === null) { + $album === null ? throw new PhotoCollectionEmptyException() : throw new PhotoCollectionEmptyException('Photo collection of ' . $album->title . ' is empty'); + } + + // retry + if ($photo->isVideo()) { + return $this->loadPhoto($album, $retries - 1); + } + + return $photo; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/MapController.php b/app/Http/Controllers/Gallery/MapController.php new file mode 100644 index 00000000000..512d426a0dd --- /dev/null +++ b/app/Http/Controllers/Gallery/MapController.php @@ -0,0 +1,48 @@ +rootPositionData = resolve(RootPositionData::class); + $this->albumPositionData = resolve(AlbumPositionData::class); + } + + public function getProvider(): Data + { + return new MapProviderData(); + } + + /** + * Return an image and the timeout if the frame is supported.. + * + * @param MapDataRequest $request + * + * @return PositionDataResource + */ + public function getData(MapDataRequest $request): Data + { + $album = $request->album(); + + if ($album === null) { + return $this->rootPositionData->do(); + } + + $includeSubAlbums = Configs::getValueAsBool('map_include_subalbums'); + + return $this->albumPositionData->get($album, $includeSubAlbums); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/PhotoController.php b/app/Http/Controllers/Gallery/PhotoController.php new file mode 100644 index 00000000000..e3c71fea53a --- /dev/null +++ b/app/Http/Controllers/Gallery/PhotoController.php @@ -0,0 +1,230 @@ +meta(); + $file = new UploadedFile($request->uploaded_file_chunk()); + + // Set up meta data if not already present + $meta->extension ??= '.' . pathinfo($meta->file_name, PATHINFO_EXTENSION); + $meta->uuid_name ??= strtr(base64_encode(random_bytes(12)), '+/', '-_') . $meta->extension; + + $final = new NativeLocalFile(Storage::disk(self::DISK_NAME)->path($meta->uuid_name)); + $final->append($file->read()); + + if ($meta->chunk_number < $meta->total_chunks) { + // Not the last chunk + return $meta; + } + + // Last chunk + $meta->stage = FileStatus::PROCESSING; + + return $this->process($final, $request->album(), $request->file_last_modified_time(), $meta); + } + + private function process( + NativeLocalFile $final, + ?AbstractAlbum $album, + ?int $file_last_modified_time, + UploadMetaResource $meta): UploadMetaResource + { + $processableFile = new ProcessableJobFile( + $final->getOriginalExtension(), + $meta->file_name + ); + $processableFile->write($final->read()); + + $final->close(); + $final->delete(); + $processableFile->close(); + // End of work-around + + if (Configs::getValueAsBool('use_job_queues')) { + ProcessImageJob::dispatch($processableFile, $album, $file_last_modified_time); + $meta->stage = FileStatus::READY; + + return $meta; + } + + $job = new ProcessImageJob($processableFile, $album, $file_last_modified_time); + $job->handle(resolve(AlbumFactory::class)); + $meta->stage = FileStatus::DONE; + + return $meta; + } + + public function fromUrl(FromUrlRequest $request, FromUrl $fromUrl): string + { + /** @var int $userId */ + $userId = Auth::id(); + $fromUrl->do($request->urls(), $request->album(), $userId); + + return 'success'; + } + + public function update(EditPhotoRequest $request): PhotoResource + { + $photo = $request->photo(); + $photo->title = $request->title(); + $photo->description = $request->description(); + $photo->created_at = $request->uploadDate(); + $photo->tags = $request->tags(); + $photo->license = $request->license()->value; + $photo->save(); + + return PhotoResource::fromModel($photo); + } + + /** + * Set the is-starred attribute of the given photos. + * + * @param SetPhotosStarredRequest $request + * + * @return void + */ + public function star(SetPhotosStarredRequest $request): void + { + foreach ($request->photos() as $photo) { + $photo->is_starred = $request->isStarred(); + $photo->save(); + } + } + + /** + * Moves the photos to an album. + * + * @param MovePhotosRequest $request + * @param Move $move + * + * @return void + */ + public function move(MovePhotosRequest $request, Move $move): void + { + $move->do($request->photos(), $request->album()); + } + + /** + * Delete one or more photos. + * + * @param DeletePhotosRequest $request + * @param Delete $delete + * + * @return void + */ + public function delete(DeletePhotosRequest $request, Delete $delete): void + { + $fileDeleter = $delete->do($request->photoIds()); + App::terminating(fn () => $fileDeleter->do()); + } + + /** + * Given a photoID and a direction (+1: 90° clockwise, -1: 90° counterclockwise) rotate an image. + * + * @param RotatePhotoRequest $request + * + * @return PhotoResource + */ + public function rotate(RotatePhotoRequest $request): PhotoResource + { + if (!Configs::getValueAsBool('editor_enabled')) { + throw new ConfigurationException('support for rotation disabled by configuration'); + } + + $rotateStrategy = new Rotate($request->photo(), $request->direction()); + $photo = $rotateStrategy->do(); + + return PhotoResource::fromModel($photo); + } + + /** + * Copy a photos to an album. + * Only the SQL entry is duplicated for space reason. + * + * @param CopyPhotosRequest $request + * @param Duplicate $duplicate + * + * @return void + */ + public function copy(CopyPhotosRequest $request, Duplicate $duplicate): void + { + $duplicate->do($request->photos(), $request->album()); + } + + /** + * Rename a photo. + * + * @param RenamePhotoRequest $request + * + * @return void + */ + public function rename(RenamePhotoRequest $request): void + { + $photo = $request->photo(); + $photo->title = $request->title; + $photo->save(); + } + + /** + * Set the tags of a photo. + * + * @param SetPhotosTagsRequest $request + * + * @return void + */ + public function tags(SetPhotosTagsRequest $request): void + { + $tags = $request->tags(); + + /** @var Photo $photo */ + foreach ($request->photos() as $photo) { + if ($request->shallOverride) { + $photo->tags = $tags; + } else { + $photo->tags = array_unique(array_merge($photo->tags, $tags)); + } + $photo->save(); + } + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/SearchController.php b/app/Http/Controllers/Gallery/SearchController.php new file mode 100644 index 00000000000..88d9aecec3a --- /dev/null +++ b/app/Http/Controllers/Gallery/SearchController.php @@ -0,0 +1,66 @@ +terms(); + $album = $request->album(); + + if (!$album instanceof Album) { + $album = null; + } + + /** @var LengthAwarePaginator $photoResults */ + /** @disregard P1013 Undefined method withQueryString() (stupid intelephense) */ + $photoResults = $photoSearch + ->sqlQuery($terms, $album) + ->orderBy(ColumnSortingPhotoType::TAKEN_AT->value, OrderSortingType::ASC->value) + ->paginate(Configs::getValueAsInt('search_pagination_limit')); + + $albumResults = $albumSearch->queryAlbums($terms); + + return ResultsResource::fromData($albumResults, $photoResults); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/SharingController.php b/app/Http/Controllers/Gallery/SharingController.php new file mode 100644 index 00000000000..68590adfe22 --- /dev/null +++ b/app/Http/Controllers/Gallery/SharingController.php @@ -0,0 +1,117 @@ + + */ + public function create(AddSharingRequest $request, Share $share): array + { + // delete any already created. + AccessPermission::whereIn('user_id', $request->userIds()) + ->whereIn('base_album_id', $request->albumIds()) + ->delete(); + + $access_permissions = []; + // Not optimal, but this is barely used, so who cares. + // A better approach would be to do a massive insert in a single SQL query from the cross product. + foreach ($request->userIds() as $user_id) { + foreach ($request->albumIds() as $album_id) { + $access_permissions[] = $share->do($request->permResource(), $user_id, $album_id); + } + } + + return AccessPermissionResource::collect($access_permissions); + } + + /** + * Edit sharing permissions. + * + * @param EditSharingRequest $request + * + * @return AccessPermissionResource + */ + public function edit(EditSharingRequest $request): AccessPermissionResource + { + $perm = $request->perm(); + $perm->update([ + 'grants_full_photo_access' => $request->permResource()->grants_full_photo_access, + 'grants_download' => $request->permResource()->grants_download, + 'grants_upload' => $request->permResource()->grants_upload, + 'grants_edit' => $request->permResource()->grants_edit, + 'grants_delete' => $request->permResource()->grants_delete, + ]); + + return AccessPermissionResource::fromModel($perm); + } + + /** + * List sharing permissions. + * + * @param ListSharingRequest $request + * + * @return Collection + */ + public function list(ListSharingRequest $request): Collection + { + $query = AccessPermission::with(['album', 'user']); + $query = $query->whereNotNull(APC::USER_ID); + $query = $query->where(APC::BASE_ALBUM_ID, '=', $request->album()->id); + + return AccessPermissionResource::collect($query->get()); + } + + /** + * List all sharing permissions. + * + * @param ListAllSharingRequest $request + * + * @return Collection + */ + public function listAll(ListAllSharingRequest $request): Collection + { + $query = AccessPermission::with(['album', 'user']); + $query = $query->when( + !Auth::user()->may_administrate, + fn ($q) => $q->whereIn('base_album_id', BaseAlbumImpl::select('id') + ->where('owner_id', '=', Auth::id()))); + $query = $query->whereNotNull('user_id'); + $query = $query->orderBy('base_album_id', 'asc'); + + return AccessPermissionResource::collect($query->get()); + } + + /** + * Delete sharing permissions. + * + * @param DeleteSharingRequest $request + * + * @return void + */ + public function delete(DeleteSharingRequest $request): void + { + AccessPermission::query()->where('id', '=', $request->perm()->id)->delete(); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Install/EnvController.php b/app/Http/Controllers/Install/EnvController.php index 6cc703c2db9..75d4de41619 100644 --- a/app/Http/Controllers/Install/EnvController.php +++ b/app/Http/Controllers/Install/EnvController.php @@ -3,8 +3,6 @@ namespace App\Http\Controllers\Install; use App\Exceptions\InstallationFailedException; -use App\Exceptions\Internal\FrameworkException; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; use Illuminate\Http\Request; use Illuminate\Routing\Controller; @@ -18,7 +16,6 @@ class EnvController extends Controller * * @return View * - * @throws FrameworkException * @throws InstallationFailedException */ public function view(Request $request): View @@ -45,8 +42,6 @@ public function view(Request $request): View } catch (\ErrorException $e) { // possibly thrown by low-level methods like `file_put_contents` throw new InstallationFailedException('I/O error for file `.env`', $e); - } catch (BindingResolutionException $e) { - throw new FrameworkException('Laravel\'s container component', $e); } } } diff --git a/app/Http/Controllers/Install/MigrationController.php b/app/Http/Controllers/Install/MigrationController.php index c4b84b1b1a5..e6b7b45c732 100644 --- a/app/Http/Controllers/Install/MigrationController.php +++ b/app/Http/Controllers/Install/MigrationController.php @@ -8,8 +8,6 @@ use App\Actions\InstallUpdate\Pipes\QueryExceptionChecker; use App\Actions\InstallUpdate\Pipes\Spacer; use App\Exceptions\InstallationFailedException; -use App\Exceptions\Internal\FrameworkException; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; use Illuminate\Pipeline\Pipeline; use Illuminate\Routing\Controller; @@ -23,8 +21,6 @@ class MigrationController extends Controller * Migrates the Lychee DB and generates a new API key. * * @return View - * - * @throws FrameworkException */ public function view(): View { @@ -46,15 +42,11 @@ public function view(): View $hasErrors = true; } - try { - return view('install.migrate', [ - 'title' => 'Lychee-installer', - 'step' => 4, - 'lines' => $output, - 'errors' => $hasErrors, - ]); - } catch (BindingResolutionException $e) { - throw new FrameworkException('Laravel\'s view component', $e); - } + return view('install.migrate', [ + 'title' => 'Lychee-installer', + 'step' => 4, + 'lines' => $output, + 'errors' => $hasErrors, + ]); } } diff --git a/app/Http/Controllers/Install/PermissionsController.php b/app/Http/Controllers/Install/PermissionsController.php index dc271372b8c..79eefc4ba32 100644 --- a/app/Http/Controllers/Install/PermissionsController.php +++ b/app/Http/Controllers/Install/PermissionsController.php @@ -4,8 +4,6 @@ use App\Actions\InstallUpdate\DefaultConfig; use App\Actions\InstallUpdate\PermissionsChecker; -use App\Exceptions\Internal\FrameworkException; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; use Illuminate\Routing\Controller; @@ -26,25 +24,19 @@ public function __construct(PermissionsChecker $checker, DefaultConfig $config) /** * @return View - * - * @throws FrameworkException */ public function view(): View { - try { - $perms = $this->permissions->check( - $this->config->get_permissions() - ); + $perms = $this->permissions->check( + $this->config->get_permissions() + ); - return view('install.permissions', [ - 'title' => 'Lychee-installer', - 'step' => 2, - 'permissions' => $perms['permissions'], - 'errors' => $perms['errors'], - 'windows' => $this->permissions->is_win(), - ]); - } catch (BindingResolutionException $e) { - throw new FrameworkException('Laravel\'s view component', $e); - } + return view('install.permissions', [ + 'title' => 'Lychee-installer', + 'step' => 2, + 'permissions' => $perms['permissions'], + 'errors' => $perms['errors'], + 'windows' => $this->permissions->is_win(), + ]); } } diff --git a/app/Http/Controllers/Install/RequirementsController.php b/app/Http/Controllers/Install/RequirementsController.php index 1d3fec7d7bd..b08fb1f51a6 100644 --- a/app/Http/Controllers/Install/RequirementsController.php +++ b/app/Http/Controllers/Install/RequirementsController.php @@ -4,8 +4,6 @@ use App\Actions\InstallUpdate\DefaultConfig; use App\Actions\InstallUpdate\RequirementsChecker; -use App\Exceptions\Internal\FrameworkException; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; use Illuminate\Routing\Controller; @@ -28,28 +26,22 @@ public function __construct(RequirementsChecker $checker, DefaultConfig $config) * Display the requirements page. * * @return View - * - * @throws FrameworkException */ public function view(): View { - try { - $phpSupportInfo = $this->requirements->checkPHPVersion( - $this->config->get_core()['minPhpVersion'] - ); - $reqs = $this->requirements->check( - $this->config->get_requirements() - ); + $phpSupportInfo = $this->requirements->checkPHPVersion( + $this->config->get_core()['minPhpVersion'] + ); + $reqs = $this->requirements->check( + $this->config->get_requirements() + ); - return view('install.requirements', [ - 'title' => 'Lychee-installer', - 'step' => 1, - 'phpSupportInfo' => $phpSupportInfo, - 'requirements' => $reqs['requirements'], - 'errors' => $reqs['errors'] ?? null, - ]); - } catch (BindingResolutionException $e) { - throw new FrameworkException('Laravel\'s view component', $e); - } + return view('install.requirements', [ + 'title' => 'Lychee-installer', + 'step' => 1, + 'phpSupportInfo' => $phpSupportInfo, + 'requirements' => $reqs['requirements'], + 'errors' => $reqs['errors'] ?? null, + ]); } } diff --git a/app/Http/Controllers/Install/SetUpAdminController.php b/app/Http/Controllers/Install/SetUpAdminController.php index 8076915d1a8..c1cc0232cbd 100644 --- a/app/Http/Controllers/Install/SetUpAdminController.php +++ b/app/Http/Controllers/Install/SetUpAdminController.php @@ -2,10 +2,8 @@ namespace App\Http\Controllers\Install; -use App\Exceptions\Internal\FrameworkException; use App\Http\Requests\Install\SetUpAdminRequest; use App\Models\User; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Hash; @@ -34,8 +32,6 @@ public function init(): View * Called on POST request. * * @return View - * - * @throws FrameworkException */ public function create(SetUpAdminRequest $request): View { @@ -53,21 +49,17 @@ public function create(SetUpAdminRequest $request): View $error .= '
' . $e->getPrevious()->getMessage(); } - try { - if ($error === '') { - return view('install.setup-success', [ - 'title' => 'Lychee-setup-admin', - 'step' => 5, - ]); - } - - return view('install.setup-admin', [ + if ($error === '') { + return view('install.setup-success', [ 'title' => 'Lychee-setup-admin', 'step' => 5, - 'error' => $error, ]); - } catch (BindingResolutionException $e) { - throw new FrameworkException('Laravel\'s view component', $e); } + + return view('install.setup-admin', [ + 'title' => 'Lychee-setup-admin', + 'step' => 5, + 'error' => $error, + ]); } } diff --git a/app/Http/Controllers/Install/WelcomeController.php b/app/Http/Controllers/Install/WelcomeController.php index 42128f3f0a8..5a28e6bb2a1 100644 --- a/app/Http/Controllers/Install/WelcomeController.php +++ b/app/Http/Controllers/Install/WelcomeController.php @@ -2,8 +2,6 @@ namespace App\Http\Controllers\Install; -use App\Exceptions\Internal\FrameworkException; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; use Illuminate\Routing\Controller; @@ -11,19 +9,13 @@ final class WelcomeController extends Controller { /** * @return View - * - * @throws FrameworkException */ public function view(): View { - try { - // Show separator - return view('install.welcome', [ - 'title' => 'Lychee-installer', - 'step' => 0, - ]); - } catch (BindingResolutionException $e) { - throw new FrameworkException('Laravel\'s view component', $e); - } + // Show separator + return view('install.welcome', [ + 'title' => 'Lychee-installer', + 'step' => 0, + ]); } } diff --git a/app/Http/Controllers/LandingPageController.php b/app/Http/Controllers/LandingPageController.php new file mode 100644 index 00000000000..629281b4e2d --- /dev/null +++ b/app/Http/Controllers/LandingPageController.php @@ -0,0 +1,18 @@ +oauth->validateProviderOrDie($provider); - - // We are already logged in: Registration operation - if (Auth::check()) { - $this->oauth->registerOrDie($providerEnum); - - return redirect(route('profile')); - } - - // Authentication operation - $this->oauth->authenticateOrDie($providerEnum); - - return redirect(route('livewire-gallery')); - } - - /** - * Function called to authenticate a user to an Oauth server. - * - * @param string $provider - * - * @return HttpFoundationRedirectResponse - */ - public function authenticate(string $provider) - { - if (Auth::check()) { - throw new UnauthorizedException('User already authenticated.'); - } - - $providerEnum = $this->oauth->validateProviderOrDie($provider); - - return Socialite::driver($providerEnum->value)->redirect(); - } - - /** - * Add some security on registration. - * - * @param string $provider - * - * @return HttpFoundationRedirectResponse - */ - public function register(string $provider) - { - Auth::user() ?? throw new UnauthenticatedException(); - if (!Request::hasValidSignature(false)) { - throw new UnauthorizedException('Registration attempted but not initialized.'); - } - - $providerEnum = $this->oauth->validateProviderOrDie($provider); - Session::put($providerEnum->value, OauthAction::OAUTH_REGISTER); - - return Socialite::driver($providerEnum->value)->redirect(); - } -} \ No newline at end of file diff --git a/app/Http/Controllers/OauthController.php b/app/Http/Controllers/OauthController.php new file mode 100644 index 00000000000..6176cef97fd --- /dev/null +++ b/app/Http/Controllers/OauthController.php @@ -0,0 +1,177 @@ +oauth->validateProviderOrDie($provider); + + // We are already logged in: Registration operation + if (Auth::check()) { + $this->oauth->registerOrDie($providerEnum); + + return redirect(route('profile')); + } + + // Authentication operation + $this->oauth->authenticateOrDie($providerEnum); + + return redirect(route('gallery')); + } + + /** + * Function called to authenticate a user to an Oauth server. + * + * @param string $provider + * + * @return HttpFoundationRedirectResponse + */ + public function authenticate(string $provider) + { + if (Auth::check()) { + throw new UnauthorizedException('User already authenticated.'); + } + + $providerEnum = $this->oauth->validateProviderOrDie($provider); + + return Socialite::driver($providerEnum->value)->redirect(); + } + + /** + * Add some security on registration. + * + * @param string $provider + * + * @return HttpFoundationRedirectResponse + */ + public function register(string $provider) + { + Auth::user() ?? throw new UnauthenticatedException(); + if (!Request::hasValidSignature(false)) { + throw new UnauthorizedException('Registration attempted but not initialized.'); + } + + $providerEnum = $this->oauth->validateProviderOrDie($provider); + Session::put($providerEnum->value, OauthAction::OAUTH_REGISTER); + + return Socialite::driver($providerEnum->value)->redirect(); + } + + /** + * List Oauth data. + * + * @return OauthRegistrationData[]|OauthProvidersType[] + */ + public function list(): array + { + if (Auth::check()) { + return $this->withUserData(); + } + + return $this->available(); + } + + /** + * Delete the Oauth registration for a user. + * + * @param ClearOauthRequest $request + * + * @return void + */ + public function clear(ClearOauthRequest $request): void + { + /** @var User $user */ + $user = Auth::user() ?? throw new UnauthenticatedException(); + $user->oauthCredentials()->where('provider', '=', $request->provider())->delete(); + } + + /** + * List available end points and registrations URLS. + * + * @return OauthRegistrationData[] + */ + private function withUserData(): array + { + $oauthData = []; + + /** @var User $user */ + $user = Auth::user() ?? throw new UnauthenticatedException(); + + $credentials = $user->oauthCredentials()->get(); + + foreach (OauthProvidersType::cases() as $provider) { + $client_id = config('services.' . $provider->value . '.client_id'); + if ($client_id === null || $client_id === '') { + continue; + } + + // We create a signed route for 5 minutes + $route = URL::signedRoute( + name: 'oauth-register', + parameters: ['provider' => $provider->value], + expiration: now()->addMinutes(5), + absolute: false); + + $oauthData[] = new OauthRegistrationData( + providerType: $provider, + isEnabled: $credentials->search(fn (OauthCredential $c) => $c->provider === $provider) !== false, + registrationRoute: $route, + ); + } + + return $oauthData; + } + + /** + * List available end points. + * + * @return OauthProvidersType[] + */ + private function available(): array + { + $oauthAvailable = []; + + foreach (OauthProvidersType::cases() as $oauthProvider) { + $client_id = config('services.' . $oauthProvider->value . '.client_id'); + if ($client_id === null || $client_id === '') { + continue; + } + + $oauthAvailable[] = $oauthProvider; + } + + return $oauthAvailable; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php new file mode 100644 index 00000000000..8135c978e2a --- /dev/null +++ b/app/Http/Controllers/ProfileController.php @@ -0,0 +1,87 @@ +username() !== null && + $request->username() !== '' && + Configs::getValueAsBool('allow_username_change')) { + $updateLogin->updateUsername($currentUser, $request->username(), $request->ip()); + } + + $currentUser = $updateLogin->updatePassword( + $currentUser, + $request->password() + ); + + $currentUser = $updateLogin->updateEmail( + $currentUser, + $request->email() + ); + + $currentUser->save(); + // Update the session with the new credentials of the user. + // Otherwise, the session is out-of-sync and falsely assumes the user + // to be unauthenticated upon the next request. + Auth::login($currentUser); + + return new UserResource($currentUser); + } + + /** + * Reset the token of the currently authenticated user. + * + * @return UserToken + * + * @throws UnauthenticatedException + * @throws ModelDBException + * @throws \Exception + */ + public function resetToken(ChangeTokenRequest $request, TokenReset $tokenReset): UserToken + { + $token = $tokenReset->do(); + + return new UserToken($token); + } + + /** + * Disable the token of the currently authenticated user. + * + * @return void + * + * @throws UnauthenticatedException + * @throws ModelDBException + */ + public function unsetToken(ChangeTokenRequest $request, TokenDisable $tokenDisable): void + { + $tokenDisable->do(); + } +} diff --git a/app/Http/Controllers/RSSController.php b/app/Http/Controllers/RSSController.php new file mode 100644 index 00000000000..482073df6b1 --- /dev/null +++ b/app/Http/Controllers/RSSController.php @@ -0,0 +1,30 @@ + + * + * @throws LycheeException + */ + public function getRSS(Generate $generate): Collection + { + if (!Configs::getValueAsBool('rss_enable')) { + throw new ConfigurationException('RSS is disabled by configuration'); + } + + return $generate->do(); + } +} diff --git a/app/Http/Controllers/StatisticsController.php b/app/Http/Controllers/StatisticsController.php new file mode 100644 index 00000000000..4fdabca7ea9 --- /dev/null +++ b/app/Http/Controllers/StatisticsController.php @@ -0,0 +1,97 @@ + + */ + public function getSpacePerUser(SpacePerUserRequest $request, Spaces $spaces): Collection + { + $spaceData = $spaces->getFullSpacePerUser( + owner_id: $request->ownerId() + ); + + return UserSpace::collect($spaceData); + } + + /** + * @param SpaceSizeVariantRequest $request + * @param Spaces $spaces + * + * @return Collection + */ + public function getSpacePerSizeVariantType(SpaceSizeVariantRequest $request, Spaces $spaces): Collection + { + $albumId = $request->album()?->id; + $ownerId = $albumId === null ? $request->ownerId() : null; + + $spaceData = $albumId === null + ? $spaces->getSpacePerSizeVariantTypePerUser(owner_id: $ownerId) + : $spaces->getSpacePerSizeVariantTypePerAlbum(album_id: $albumId); + + return Sizes::collect($spaceData); + } + + /** + * @param SpacePerAlbumRequest $request + * @param Spaces $spaces + * + * @return Collection + */ + public function getSpacePerAlbum(SpacePerAlbumRequest $request, Spaces $spaces): Collection + { + $albumId = $request->album()?->id; + $ownerId = $albumId === null ? $request->ownerId() : null; + $spaceData = $spaces->getSpacePerAlbum( + album_id: $albumId, + owner_id: $ownerId + ); + $countData = $spaces->getPhotoCountPerAlbum( + album_id: $albumId, + owner_id: $ownerId); + + $zipped = $spaceData->zip($countData); + + return $zipped->map(fn ($z) => new Album($z[0], $z[1])); + } + + /** + * ! Slow query. + * + * @param SpacePerAlbumRequest $request + * @param Spaces $spaces + * + * @return Collection + */ + public function getTotalSpacePerAlbum(SpacePerAlbumRequest $request, Spaces $spaces): Collection + { + $albumId = $request->album()?->id; + $ownerId = $albumId === null ? $request->ownerId() : null; + $spaceData = $spaces->getTotalSpacePerAlbum( + album_id: $albumId, + owner_id: $ownerId + ); + $countData = $spaces->getTotalPhotoCountPerAlbum( + album_id: $albumId, + owner_id: $ownerId); + + $zipped = $spaceData->zip($countData); + + return $zipped->map(fn ($z) => new Album($z[0], $z[1])); + } +} diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php new file mode 100644 index 00000000000..22d7a6b3f8f --- /dev/null +++ b/app/Http/Controllers/UsersController.php @@ -0,0 +1,34 @@ + + */ + public function list(ListUsersRequest $_request): Collection + { + return LightUserResource::collect(User::where('id', '!=', Auth::id())->orderBy('username')->get()); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/VersionController.php b/app/Http/Controllers/VersionController.php new file mode 100644 index 00000000000..347072fc2b3 --- /dev/null +++ b/app/Http/Controllers/VersionController.php @@ -0,0 +1,20 @@ +findAbstractAlbumOrFail($albumId, false); + Gate::authorize(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $album]); + session()->now('album', $album); + } + + if ($photoId !== null) { + $photo = Photo::findOrFail($photoId); + Gate::authorize(\PhotoPolicy::CAN_SEE, [Photo::class, $photo]); + session()->now('photo', $photo); + } + } catch (ModelNotFoundException) { + throw new NotFoundHttpException(); + } + + return view('vueapp'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/WebAuthn/WebAuthnManageController.php b/app/Http/Controllers/WebAuthn/WebAuthnManageController.php index c3e2055a0af..ce2941dbf3f 100644 --- a/app/Http/Controllers/WebAuthn/WebAuthnManageController.php +++ b/app/Http/Controllers/WebAuthn/WebAuthnManageController.php @@ -4,23 +4,29 @@ use App\Exceptions\UnauthenticatedException; use App\Http\Requests\WebAuthn\DeleteCredentialRequest; +use App\Http\Requests\WebAuthn\EditCredentialRequest; use App\Http\Requests\WebAuthn\ListCredentialsRequest; +use App\Http\Resources\Models\WebAuthnResource; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; class WebAuthnManageController { /** - * @throws UnauthenticatedException + * List all the WebAuthn users credentials. + * + * @param ListCredentialsRequest $request + * + * @return Collection * - * @phpstan-ignore-next-line unused... + * @throws UnauthenticatedException */ public function list(ListCredentialsRequest $request): Collection { /** @var \App\Models\User $user */ $user = Auth::user() ?? throw new UnauthenticatedException(); - return $user->webAuthnCredentials; + return WebAuthnResource::collect($user->webAuthnCredentials); } /** @@ -31,6 +37,20 @@ public function delete(DeleteCredentialRequest $request): void /** @var \App\Models\User $user */ $user = Auth::user() ?? throw new UnauthenticatedException(); - $user->webAuthnCredentials()->where('id', $request->id)->delete(); + $user->webAuthnCredentials()->where('id', $request->getId())->delete(); + } + + /** + * Edit credential. + * + * @param EditCredentialRequest $request + * + * @return void + */ + public function edit(EditCredentialRequest $request): void + { + $credential = $request->getCredential(); + $credential->alias = $request->getAlias(); + $credential->save(); } } diff --git a/app/Http/Controllers/WebAuthn/WebAuthnRegisterController.php b/app/Http/Controllers/WebAuthn/WebAuthnRegisterController.php index 1ef23567250..3c0fd45be45 100644 --- a/app/Http/Controllers/WebAuthn/WebAuthnRegisterController.php +++ b/app/Http/Controllers/WebAuthn/WebAuthnRegisterController.php @@ -19,6 +19,7 @@ class WebAuthnRegisterController */ public function options(AttestationRequest $request): Responsable { + /** @disregard P1014 */ $request->user = Auth::user() ?? throw new UnauthenticatedException(); return $request @@ -35,6 +36,7 @@ public function options(AttestationRequest $request): Responsable */ public function register(AttestedRequest $request): void { + /** @disregard P1014 */ $request->user = Auth::user() ?? throw new UnauthenticatedException(); $request->save(); } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 0e13dd4ac56..46c53d769e5 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -43,20 +43,6 @@ class Kernel extends HttpKernel \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\DisableCSP::class, - \App\Http\Middleware\QueryStringFixer::class, - ], - - 'web-livewire' => [ - 'accept_content_type:html', - \Illuminate\Cookie\Middleware\EncryptCookies::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, - \Illuminate\Session\Middleware\StartSession::class, - \Illuminate\Session\Middleware\AuthenticateSession::class, - \Illuminate\View\Middleware\ShareErrorsFromSession::class, - \App\Http\Middleware\VerifyCsrfToken::class, - \Illuminate\Routing\Middleware\SubstituteBindings::class, - \App\Http\Middleware\DisableCSP::class, - \App\Http\Middleware\QueryStringFixer::class, ], 'web-admin' => [ @@ -103,6 +89,9 @@ class Kernel extends HttpKernel 'content_type' => \App\Http\Middleware\ContentType::class, 'accept_content_type' => \App\Http\Middleware\AcceptContentType::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'login_required_v1' => \App\Legacy\V1\Middleware\LoginRequiredV1::class, // remove me in non-legacy build 'login_required' => \App\Http\Middleware\LoginRequired::class, + 'cache_control' => \App\Http\Middleware\CacheControl::class, + 'support' => \LycheeVerify\Http\Middleware\VerifySupporterStatus::class, ]; } diff --git a/app/Http/Middleware/AcceptContentType.php b/app/Http/Middleware/AcceptContentType.php index 2b8809f9b6f..b4f7b3f7918 100644 --- a/app/Http/Middleware/AcceptContentType.php +++ b/app/Http/Middleware/AcceptContentType.php @@ -25,7 +25,6 @@ class AcceptContentType * @var array */ protected $except = [ - 'livewire/upload-file', ]; /** diff --git a/app/Http/Middleware/CacheControl.php b/app/Http/Middleware/CacheControl.php new file mode 100644 index 00000000000..637ad170b6b --- /dev/null +++ b/app/Http/Middleware/CacheControl.php @@ -0,0 +1,27 @@ +headers->set('Cache-Control', 'private;max_age=' . $age); + + return $response; + } +} \ No newline at end of file diff --git a/app/Http/Middleware/Checks/HasAdminUser.php b/app/Http/Middleware/Checks/HasAdminUser.php index cd6e3fcd27f..d802107bdff 100644 --- a/app/Http/Middleware/Checks/HasAdminUser.php +++ b/app/Http/Middleware/Checks/HasAdminUser.php @@ -4,12 +4,8 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\Contracts\Http\MiddlewareCheck; -use App\Exceptions\Internal\FrameworkException; use App\Models\User; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Support\Facades\Schema; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; class HasAdminUser implements MiddlewareCheck { @@ -22,11 +18,7 @@ public function assert(): bool // In such case the tables already exist so the IsInstalled will return true. // However this middleware will throw an error because may_administrate does not exist yet. if (Schema::hasColumn('users', 'may_administrate')) { - try { - return User::query()->where('may_administrate', '=', true)->count() > 0; - } catch (BindingResolutionException|NotFoundExceptionInterface|ContainerExceptionInterface $e) { - throw new FrameworkException('Laravel\'s container component', $e); - } + return User::query()->where('may_administrate', '=', true)->count() > 0; } else { // If the column does not exist yet but we are executing this script // it means that there exists already an admin user (with ID = 0). diff --git a/app/Http/Middleware/Checks/IsInstalled.php b/app/Http/Middleware/Checks/IsInstalled.php index d5550eac88d..95b3fbb05b5 100644 --- a/app/Http/Middleware/Checks/IsInstalled.php +++ b/app/Http/Middleware/Checks/IsInstalled.php @@ -16,6 +16,8 @@ class IsInstalled implements MiddlewareCheck { /** * @throws InternalLycheeException + * + * @codeCoverageIgnore */ public function assert(): bool { @@ -39,11 +41,9 @@ public function assert(): bool return false; } // Not coverable by tests unless we actually remove the php dependencies... - // @codeCoverageIgnoreStart if (Str::contains($e->getMessage(), 'could not find driver')) { return false; } - // @codeCoverageIgnoreEnd throw $e; } catch (BindingResolutionException|NotFoundExceptionInterface|ContainerExceptionInterface $e) { throw new FrameworkException('Laravel\'s container component', $e); diff --git a/app/Http/Middleware/DisableCSP.php b/app/Http/Middleware/DisableCSP.php index 57201390160..1e6e5a63af0 100644 --- a/app/Http/Middleware/DisableCSP.php +++ b/app/Http/Middleware/DisableCSP.php @@ -7,7 +7,6 @@ use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Http\Request; use Illuminate\Support\Facades\File; -use Illuminate\Support\Str; /** * Class DisableCSP. @@ -34,7 +33,8 @@ public function handle(Request $request, \Closure $next): mixed $dir_url = config('app.dir_url'); if ( config('debugbar.enabled', false) === true || - $request->getRequestUri() === $dir_url . '/docs/api' + $request->getRequestUri() === $dir_url . '/docs/api' || + $request->getRequestUri() === $dir_url . '/request-docs' ) { config(['secure-headers.csp.enable' => false]); } @@ -49,22 +49,22 @@ public function handle(Request $request, \Closure $next): mixed config(['secure-headers.csp.script-src.hashes.sha256' => []]); } - // disable unsafe-eval if we are on a Livewire page - if (Features::active('livewire') || Str::startsWith($request->getRequestUri(), $dir_url . '/livewire/')) { - $this->handleLivewire(); + // disable unsafe-eval if we are on a VueJS page + if (Features::active('vuejs')) { + $this->handleVueJS(); } return $next($request); } /** - * Disabling rules because of poor decision from the designer of Livewire. + * Disabling rules because ... VueJS. * * @return void * * @throws BindingResolutionException */ - private function handleLivewire() + private function handleVueJS() { // We have to disable unsafe-eval because Livewire requires it... // So stupid.... diff --git a/app/Http/Middleware/LoginRequired.php b/app/Http/Middleware/LoginRequired.php index 83a72f7b51c..eff990bae1b 100644 --- a/app/Http/Middleware/LoginRequired.php +++ b/app/Http/Middleware/LoginRequired.php @@ -2,16 +2,13 @@ namespace App\Http\Middleware; -use App\Assets\Features; use App\Exceptions\ConfigurationException; -use App\Exceptions\ConfigurationKeyMissingException; use App\Exceptions\Internal\FrameworkException; -use App\Exceptions\Internal\LycheeLogicException; +use App\Exceptions\Internal\LycheeInvalidArgumentException; +use App\Exceptions\UnauthenticatedException; use App\Models\Configs; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Log; -use Illuminate\Support\Str; /** * Class LoginRequired. @@ -38,35 +35,24 @@ class LoginRequired */ public function handle(Request $request, \Closure $next, string $requiredStatus): mixed { + if (in_array($requiredStatus, [self::ALBUM, self::ROOT], true) === false) { + throw new LycheeInvalidArgumentException($requiredStatus . ' is not a valid login requirement.'); + } + // We are logged in. Proceed. if (Auth::user() !== null) { return $next($request); } - $dir_url = config('app.dir_url'); - if (Features::inactive('livewire') && !Str::startsWith($request->getRequestUri(), $dir_url . '/livewire/')) { + if (!Configs::getValueAsBool('login_required')) { + // Login is not required. Proceed. return $next($request); } - if ($requiredStatus !== self::ALBUM && $requiredStatus !== self::ROOT) { - throw new LycheeLogicException($requiredStatus . ' is not a valid login requirement.'); - } - - try { - if (!Configs::getValueAsBool('login_required')) { - // Login is not required. Proceed. - return $next($request); - } - - if ($requiredStatus === self::ALBUM && Configs::getValueAsBool('login_required_root_only')) { - return $next($request); - } - - return redirect()->route('login'); - } catch (ConfigurationKeyMissingException $e) { - Log::warning(__METHOD__ . ':' . __LINE__ . ' ' . $e->getMessage()); - + if ($requiredStatus === self::ALBUM && Configs::getValueAsBool('login_required_root_only')) { return $next($request); } + + throw new UnauthenticatedException('Login required.'); } } diff --git a/app/Http/Middleware/QueryStringFixer.php b/app/Http/Middleware/QueryStringFixer.php deleted file mode 100644 index f7d7fc448d1..00000000000 --- a/app/Http/Middleware/QueryStringFixer.php +++ /dev/null @@ -1,42 +0,0 @@ -server->set('QUERY_STRING', $_SERVER['QUERY_STRING']); - } - - return $next($request); - } -} diff --git a/app/Http/Requests/Album/AddAlbumRequest.php b/app/Http/Requests/Album/AddAlbumRequest.php new file mode 100644 index 00000000000..a658e097fe4 --- /dev/null +++ b/app/Http/Requests/Album/AddAlbumRequest.php @@ -0,0 +1,54 @@ +parentAlbum]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::PARENT_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null */ + $parentAlbumID = $values[RequestAttribute::PARENT_ID_ATTRIBUTE]; + $this->parent_album = $parentAlbumID === null ? + null : + Album::query()->findOrFail($parentAlbumID); + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Album/AddTagAlbumRequest.php b/app/Http/Requests/Album/AddTagAlbumRequest.php new file mode 100644 index 00000000000..4b858104ef8 --- /dev/null +++ b/app/Http/Requests/Album/AddTagAlbumRequest.php @@ -0,0 +1,52 @@ + ['required', new TitleRule()], + RequestAttribute::TAGS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::TAGS_ATTRIBUTE . '.*' => 'required|string|min:1', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + $this->tags = $values[RequestAttribute::TAGS_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Album/DeleteAlbumsRequest.php b/app/Http/Requests/Album/DeleteAlbumsRequest.php new file mode 100644 index 00000000000..e15bc6036d8 --- /dev/null +++ b/app/Http/Requests/Album/DeleteAlbumsRequest.php @@ -0,0 +1,50 @@ +albumIds()]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::ALBUM_IDS_ATTRIBUTE . '.*' => ['required', new AlbumIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + // As we are going to delete the albums anyway, we don't load the + // models for efficiency reasons. + // Instead, we use mass deletion via low-level SQL queries later. + $this->albumIds = $values[RequestAttribute::ALBUM_IDS_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Album/DeleteTrackRequest.php b/app/Http/Requests/Album/DeleteTrackRequest.php new file mode 100644 index 00000000000..3c2ea8d28da --- /dev/null +++ b/app/Http/Requests/Album/DeleteTrackRequest.php @@ -0,0 +1,37 @@ + ['required', new AlbumIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null */ + $albumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + $this->album = Album::query()->findOrFail($albumID); + } +} diff --git a/app/Http/Requests/Album/GetAlbumRequest.php b/app/Http/Requests/Album/GetAlbumRequest.php new file mode 100644 index 00000000000..ad85f437e99 --- /dev/null +++ b/app/Http/Requests/Album/GetAlbumRequest.php @@ -0,0 +1,59 @@ +album]); + + // In case of a password protected album, we must throw an exception + // with a special error message ("Password required") such that the + // front-end shows the password dialog if a password is set, but + // does not show the dialog otherwise. + if ( + !$result && + $this->album instanceof BaseAlbum && + $this->album->public_permissions()?->password !== null + ) { + throw new PasswordRequiredException(); + } + + return $result; + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new AlbumIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = $this->albumFactory->findAbstractAlbumOrFail($values[RequestAttribute::ALBUM_ID_ATTRIBUTE]); + } +} diff --git a/app/Http/Requests/Album/MergeAlbumsRequest.php b/app/Http/Requests/Album/MergeAlbumsRequest.php new file mode 100644 index 00000000000..eaf68b791a9 --- /dev/null +++ b/app/Http/Requests/Album/MergeAlbumsRequest.php @@ -0,0 +1,53 @@ + + */ +class MergeAlbumsRequest extends BaseApiRequest implements HasAlbum, HasAlbums +{ + use HasAlbumTrait; + /** @phpstan-use HasAlbumsTrait */ + use HasAlbumsTrait; + use AuthorizeCanEditAlbumAlbumsTrait; + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + RequestAttribute::ALBUM_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::ALBUM_IDS_ATTRIBUTE . '.*' => ['required', new AlbumIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string $id */ + $id = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + /** @var array $ids */ + $ids = $values[RequestAttribute::ALBUM_IDS_ATTRIBUTE]; + $this->album = Album::query()->findOrFail($id); + // @phpstan-ignore-next-line + $this->albums = Album::query() + ->with(['children']) + ->findOrFail($ids); + } +} diff --git a/app/Http/Requests/Album/MoveAlbumsRequest.php b/app/Http/Requests/Album/MoveAlbumsRequest.php new file mode 100644 index 00000000000..3a4262ceed0 --- /dev/null +++ b/app/Http/Requests/Album/MoveAlbumsRequest.php @@ -0,0 +1,53 @@ + + */ +class MoveAlbumsRequest extends BaseApiRequest implements HasAlbum, HasAlbums +{ + use HasAlbumTrait; + /** @phpstan-use HasAlbumsTrait */ + use HasAlbumsTrait; + use AuthorizeCanEditAlbumAlbumsTrait; + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + RequestAttribute::ALBUM_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::ALBUM_IDS_ATTRIBUTE . '.*' => ['required', new AlbumIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null $id */ + $id = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + /** @var array $ids */ + $ids = $values[RequestAttribute::ALBUM_IDS_ATTRIBUTE]; + $this->album = $id === null ? + null : + Album::findOrFail($id); + /** @phpstan-ignore-next-line */ + $this->albums = Album::findOrFail($ids); + } +} diff --git a/app/Http/Requests/Album/RenameAlbumRequest.php b/app/Http/Requests/Album/RenameAlbumRequest.php new file mode 100644 index 00000000000..24b4a44e8a5 --- /dev/null +++ b/app/Http/Requests/Album/RenameAlbumRequest.php @@ -0,0 +1,49 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(true)], + RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = $this->albumFactory->findBaseAlbumOrFail($values[RequestAttribute::ALBUM_ID_ATTRIBUTE]); + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Album/SetAlbumProtectionPolicyRequest.php b/app/Http/Requests/Album/SetAlbumProtectionPolicyRequest.php new file mode 100644 index 00000000000..6182cda2320 --- /dev/null +++ b/app/Http/Requests/Album/SetAlbumProtectionPolicyRequest.php @@ -0,0 +1,87 @@ +album instanceof BaseSmartAlbum) { + return Auth::user()?->may_administrate === true; + } + + return Gate::check(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $this->album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new AlbumIDRule(false)], + RequestAttribute::PASSWORD_ATTRIBUTE => ['sometimes', new PasswordRule(true)], + RequestAttribute::IS_PUBLIC_ATTRIBUTE => 'required|boolean', + RequestAttribute::IS_LINK_REQUIRED_ATTRIBUTE => 'required|boolean', + RequestAttribute::IS_NSFW_ATTRIBUTE => 'required|boolean', + RequestAttribute::GRANTS_DOWNLOAD_ATTRIBUTE => 'required|boolean', + RequestAttribute::GRANTS_FULL_PHOTO_ACCESS_ATTRIBUTE => 'required|boolean', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = $this->albumFactory->findAbstractAlbumOrFail( + $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] + ); + $this->albumProtectionPolicy = new AlbumProtectionPolicy( + is_public: static::toBoolean($values[RequestAttribute::IS_PUBLIC_ATTRIBUTE]), + is_link_required: static::toBoolean($values[RequestAttribute::IS_LINK_REQUIRED_ATTRIBUTE]), + is_nsfw: static::toBoolean($values[RequestAttribute::IS_NSFW_ATTRIBUTE]), + grants_full_photo_access: static::toBoolean($values[RequestAttribute::GRANTS_FULL_PHOTO_ACCESS_ATTRIBUTE]), + grants_download: static::toBoolean($values[RequestAttribute::GRANTS_DOWNLOAD_ATTRIBUTE]), + ); + $this->isPasswordProvided = array_key_exists(RequestAttribute::PASSWORD_ATTRIBUTE, $values); + $this->password = $this->isPasswordProvided ? $values[RequestAttribute::PASSWORD_ATTRIBUTE] : null; + } + + /** + * @return AlbumProtectionPolicy + */ + public function albumProtectionPolicy(): AlbumProtectionPolicy + { + return $this->albumProtectionPolicy; + } + + public function isPasswordProvided(): bool + { + return $this->isPasswordProvided; + } +} diff --git a/app/Http/Requests/Album/SetAlbumTrackRequest.php b/app/Http/Requests/Album/SetAlbumTrackRequest.php new file mode 100644 index 00000000000..a9f60f6be81 --- /dev/null +++ b/app/Http/Requests/Album/SetAlbumTrackRequest.php @@ -0,0 +1,48 @@ + ['required', new AlbumIDRule(false)], + self::FILE_ATTRIBUTE => 'required|file', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null */ + $albumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + $this->album = Album::query()->findOrFail($albumID); + $this->file = $files[self::FILE_ATTRIBUTE]; + } + + public function uploadedFile(): UploadedFile + { + return $this->file; + } +} diff --git a/app/Http/Requests/Album/SetAsCoverRequest.php b/app/Http/Requests/Album/SetAsCoverRequest.php new file mode 100644 index 00000000000..9f0e4e42866 --- /dev/null +++ b/app/Http/Requests/Album/SetAsCoverRequest.php @@ -0,0 +1,61 @@ +album]) && + Gate::check(PhotoPolicy::CAN_EDIT, [Photo::class, $this->photo]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + RequestAttribute::PHOTO_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $album = $this->albumFactory->findBaseAlbumOrFail( + $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] + ); + + if (!$album instanceof Album) { + throw ValidationException::withMessages([RequestAttribute::ALBUM_ID_ATTRIBUTE => 'album type not supported.']); + } + + $this->album = $album; + /** @var string $photoId */ + $photoId = $values[RequestAttribute::PHOTO_ID_ATTRIBUTE]; + $this->photo = Photo::query()->findOrFail($photoId); + } +} diff --git a/app/Http/Requests/Album/SetAsHeaderRequest.php b/app/Http/Requests/Album/SetAsHeaderRequest.php new file mode 100644 index 00000000000..d661e4ec65c --- /dev/null +++ b/app/Http/Requests/Album/SetAsHeaderRequest.php @@ -0,0 +1,69 @@ +album]) && + ($this->is_compact || ($this->photo->album_id === $this->album->id)); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + RequestAttribute::HEADER_ID_ATTRIBUTE => ['required', new RandomIDRule(true)], + RequestAttribute::IS_COMPACT_ATTRIBUTE => ['required', 'boolean'], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $album = $this->albumFactory->findBaseAlbumOrFail( + $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] + ); + + if (!$album instanceof Album) { + throw ValidationException::withMessages([RequestAttribute::ALBUM_ID_ATTRIBUTE => 'album type not supported.']); + } + + $this->album = $album; + $this->is_compact = static::toBoolean($values[RequestAttribute::IS_COMPACT_ATTRIBUTE]); + + if ($this->is_compact) { + return; + } + + /** @var string $photoId */ + $photoId = $values[RequestAttribute::HEADER_ID_ATTRIBUTE]; + $this->photo = Photo::query()->findOrFail($photoId); + } +} diff --git a/app/Http/Requests/Album/TargetListAlbumRequest.php b/app/Http/Requests/Album/TargetListAlbumRequest.php new file mode 100644 index 00000000000..55f41e04db3 --- /dev/null +++ b/app/Http/Requests/Album/TargetListAlbumRequest.php @@ -0,0 +1,60 @@ +album]); + + // In case of a password protected album, we must throw an exception + // with a special error message ("Password required") such that the + // front-end shows the password dialog if a password is set, but + // does not show the dialog otherwise. + if ( + !$result && + $this->album instanceof BaseAlbum && + $this->album->public_permissions()?->password !== null + ) { + throw new PasswordRequiredException(); + } + + return $result; + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new AlbumIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $album_id = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($album_id); + } +} diff --git a/app/Http/Requests/Album/TransferAlbumRequest.php b/app/Http/Requests/Album/TransferAlbumRequest.php new file mode 100644 index 00000000000..6a6573f1c87 --- /dev/null +++ b/app/Http/Requests/Album/TransferAlbumRequest.php @@ -0,0 +1,55 @@ +album()]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new AlbumIDRule(false)], + RequestAttribute::USER_ID_ATTRIBUTE => ['required', new IntegerIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var int $user_id */ + $user_id = $values[RequestAttribute::USER_ID_ATTRIBUTE]; + $this->user2 = User::findOrFail($user_id); + // We don't need the full albums, just the IDs, so we don't load the + // models for efficiency reasons. + // Instead, we use mass deletion via low-level SQL queries later. + $this->album = $this->albumFactory->findBaseAlbumOrFail($values[RequestAttribute::ALBUM_ID_ATTRIBUTE]); + } +} diff --git a/app/Http/Requests/Album/UnlockAlbumRequest.php b/app/Http/Requests/Album/UnlockAlbumRequest.php new file mode 100644 index 00000000000..ad364048a0f --- /dev/null +++ b/app/Http/Requests/Album/UnlockAlbumRequest.php @@ -0,0 +1,48 @@ + ['required', new RandomIDRule(false)], + RequestAttribute::PASSWORD_ATTRIBUTE => ['required', new PasswordRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = $this->albumFactory->findBaseAlbumOrFail( + $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] + ); + $this->password = $values[RequestAttribute::PASSWORD_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Album/UpdateAlbumRequest.php b/app/Http/Requests/Album/UpdateAlbumRequest.php new file mode 100644 index 00000000000..1a559356c2d --- /dev/null +++ b/app/Http/Requests/Album/UpdateAlbumRequest.php @@ -0,0 +1,144 @@ +album]) && + ($this->is_compact || + $this->photo === null || + $this->photo->album_id === $this->album->id); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], + RequestAttribute::LICENSE_ATTRIBUTE => ['required', new Enum(LicenseType::class)], + RequestAttribute::DESCRIPTION_ATTRIBUTE => ['present', new DescriptionRule()], + RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE => ['present', 'nullable', new Enum(ColumnSortingPhotoType::class)], + RequestAttribute::PHOTO_SORTING_ORDER_ATTRIBUTE => [ + 'required_with:' . RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE, + 'nullable', new Enum(OrderSortingType::class), + ], + RequestAttribute::ALBUM_SORTING_COLUMN_ATTRIBUTE => ['present', 'nullable', new Enum(ColumnSortingAlbumType::class)], + RequestAttribute::ALBUM_SORTING_ORDER_ATTRIBUTE => [ + 'required_with:' . RequestAttribute::ALBUM_SORTING_COLUMN_ATTRIBUTE, + 'nullable', new Enum(OrderSortingType::class), + ], + RequestAttribute::ALBUM_ASPECT_RATIO_ATTRIBUTE => ['present', 'nullable', new Enum(AspectRatioType::class)], + RequestAttribute::ALBUM_PHOTO_LAYOUT => ['present', 'nullable', new Enum(PhotoLayoutType::class)], + RequestAttribute::COPYRIGHT_ATTRIBUTE => ['present', 'nullable', new CopyrightRule()], + RequestAttribute::IS_COMPACT_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::HEADER_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $album = $this->albumFactory->findBaseAlbumOrFail( + $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] + ); + + if (!$album instanceof Album) { + throw ValidationException::withMessages([RequestAttribute::ALBUM_ID_ATTRIBUTE => 'album type not supported.']); + } + + $this->album = $album; + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + $this->description = $values[RequestAttribute::DESCRIPTION_ATTRIBUTE]; + $this->license = LicenseType::tryFrom($values[RequestAttribute::LICENSE_ATTRIBUTE]); + + $photoColumn = ColumnSortingPhotoType::tryFrom($values[RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE]); + $photoOrder = OrderSortingType::tryFrom($values[RequestAttribute::PHOTO_SORTING_ORDER_ATTRIBUTE]); + + $this->photoSortingCriterion = $photoColumn === null ? + null : + new PhotoSortingCriterion($photoColumn->toColumnSortingType(), $photoOrder); + + $albumColumn = ColumnSortingPhotoType::tryFrom($values[RequestAttribute::ALBUM_SORTING_COLUMN_ATTRIBUTE]); + $albumOrder = OrderSortingType::tryFrom($values[RequestAttribute::ALBUM_SORTING_ORDER_ATTRIBUTE]); + + $this->albumSortingCriterion = $albumColumn === null ? + null : + new AlbumSortingCriterion($albumColumn->toColumnSortingType(), $albumOrder); + + $this->aspectRatio = AspectRatioType::tryFrom($values[RequestAttribute::ALBUM_ASPECT_RATIO_ATTRIBUTE]); + $this->photoLayout = PhotoLayoutType::tryFrom($values[RequestAttribute::ALBUM_PHOTO_LAYOUT]); + $this->copyright = $values[RequestAttribute::COPYRIGHT_ATTRIBUTE]; + + $this->is_compact = static::toBoolean($values[RequestAttribute::IS_COMPACT_ATTRIBUTE]); + + if ($this->is_compact) { + return; + } + + /** @var string|null $photoId */ + $photoId = $values[RequestAttribute::HEADER_ID_ATTRIBUTE]; + $this->photo = $photoId !== null ? Photo::query()->findOrFail($photoId) : null; + } +} diff --git a/app/Http/Requests/Album/UpdateTagAlbumRequest.php b/app/Http/Requests/Album/UpdateTagAlbumRequest.php new file mode 100644 index 00000000000..99a07ca451d --- /dev/null +++ b/app/Http/Requests/Album/UpdateTagAlbumRequest.php @@ -0,0 +1,94 @@ + ['required', new RandomIDRule(false)], + RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], + RequestAttribute::DESCRIPTION_ATTRIBUTE => ['present', new DescriptionRule()], + RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE => ['present', 'nullable', new Enum(ColumnSortingPhotoType::class)], + RequestAttribute::PHOTO_SORTING_ORDER_ATTRIBUTE => [ + 'required_with:' . RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE, + 'nullable', new Enum(OrderSortingType::class), + ], + RequestAttribute::TAGS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::TAGS_ATTRIBUTE . '.*' => 'required|string|min:1', + RequestAttribute::COPYRIGHT_ATTRIBUTE => ['present', 'nullable', new CopyrightRule()], + RequestAttribute::ALBUM_PHOTO_LAYOUT => ['present', 'nullable', new Enum(PhotoLayoutType::class)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $album = $this->albumFactory->findBaseAlbumOrFail( + $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] + ); + + if (!$album instanceof TagAlbum) { + throw ValidationException::withMessages([RequestAttribute::ALBUM_ID_ATTRIBUTE => 'album type not supported.']); + } + + $this->album = $album; + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + $this->description = $values[RequestAttribute::DESCRIPTION_ATTRIBUTE]; + + $photoColumn = ColumnSortingPhotoType::tryFrom($values[RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE]); + $photoOrder = OrderSortingType::tryFrom($values[RequestAttribute::PHOTO_SORTING_ORDER_ATTRIBUTE]); + + $this->photoSortingCriterion = $photoColumn === null ? + null : + new PhotoSortingCriterion($photoColumn->toColumnSortingType(), $photoOrder); + + $this->photoLayout = PhotoLayoutType::tryFrom($values[RequestAttribute::ALBUM_PHOTO_LAYOUT]); + $this->copyright = $values[RequestAttribute::COPYRIGHT_ATTRIBUTE]; + $this->tags = $values[RequestAttribute::TAGS_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Album/ZipRequest.php b/app/Http/Requests/Album/ZipRequest.php new file mode 100644 index 00000000000..c13ee55144b --- /dev/null +++ b/app/Http/Requests/Album/ZipRequest.php @@ -0,0 +1,136 @@ + + */ +class ZipRequest extends BaseApiRequest implements HasAlbums, HasPhotos, HasSizeVariant +{ + /** @use HasAlbumsTrait */ + use HasAlbumsTrait; + use HasPhotosTrait; + use HasSizeVariantTrait; + + /** + * {@inheritDoc} + */ + public function authorize(): bool + { + /** @var AbstractAlbum $album */ + foreach ($this->albums as $album) { + if (!Gate::check(AlbumPolicy::CAN_DOWNLOAD, $album)) { + return false; + } + } + + /** @var Photo $photo */ + foreach ($this->photos as $photo) { + if (!Gate::check(PhotoPolicy::CAN_DOWNLOAD, $photo)) { + return false; + } + } + + return true; + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_IDS_ATTRIBUTE => ['sometimes', new AlbumIDListRule()], + RequestAttribute::PHOTO_IDS_ATTRIBUTE => ['sometimes', new RandomIDListRule()], + RequestAttribute::SIZE_VARIANT_ATTRIBUTE => ['required_if_accepted:photos_ids', new Enum(DownloadVariantType::class)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $album_ids = $values[RequestAttribute::ALBUM_IDS_ATTRIBUTE] ?? null; + $album_ids = $album_ids === null ? [] : explode(',', $album_ids); + $this->processAlbums($album_ids); + + // only interesting if we have no albums + $this->sizeVariant = DownloadVariantType::tryFrom($values[RequestAttribute::SIZE_VARIANT_ATTRIBUTE] ?? ''); + + $photo_ids = $values[RequestAttribute::PHOTO_IDS_ATTRIBUTE] ?? null; + $photo_ids = $photo_ids === null ? [] : explode(',', $photo_ids); + $this->processPhotos($photo_ids); + } + + /** + * Process albums. Set to empty collection if no albums are requested. + * + * @param string[] $album_ids + * + * @return void + */ + private function processAlbums(array $album_ids): void + { + if (count($album_ids) === 0) { + $this->albums = collect(); + + return; + } + + // TODO: `App\Actions\Album\Archive::compressAlbum` iterates over the original size variant of each photo in the album; we should eagerly load them for higher efficiency. + $this->albums = $this->albumFactory->findAbstractAlbumsOrFail($album_ids); + } + + /** + * Process photos. Set to empty collection if no photos are requested. + * + * @param string[] $photo_ids + * + * @return void + */ + private function processPhotos(array $photo_ids): void + { + if (count($photo_ids) === 0) { + $this->photos = collect(); + + return; + } + + $photoQuery = Photo::query()->with(['album']); + // The condition is required, because Lychee also supports to archive + // the "live video" as a size variant which is not a proper size variant + $variant = $this->sizeVariant->getSizeVariantType(); + if ($variant !== null) { // NOT LIVE PHOTO + // If a proper size variant is requested, eagerly load the size + // variants but only the requested type due to efficiency reasons + $photoQuery = $photoQuery->with([ + 'size_variants' => fn ($r) => $r->where('type', '=', $variant), + ]); + } + + // `findOrFail` returns the union `Photo|Collection` + // which is not assignable to `Collection`; but as we query + // with an array of IDs we never get a single entity (even if the + // array only contains a single ID). + $this->photos = $photoQuery->findOrFail($photo_ids); + } +} diff --git a/app/Http/Requests/BaseApiRequest.php b/app/Http/Requests/BaseApiRequest.php index eb1fbb0ffbe..59a6479bddd 100644 --- a/app/Http/Requests/BaseApiRequest.php +++ b/app/Http/Requests/BaseApiRequest.php @@ -15,11 +15,14 @@ use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Auth; use Illuminate\Validation\ValidationException; +use LycheeVerify\Contract\VerifyInterface; +use LycheeVerify\Verify; use Symfony\Component\HttpFoundation\Exception\BadRequestException; abstract class BaseApiRequest extends FormRequest { protected AlbumFactory $albumFactory; + protected VerifyInterface $verify; /** * @throws FrameworkException @@ -33,10 +36,11 @@ public function __construct( array $cookies = [], array $files = [], array $server = [], - $content = null + $content = null, ) { try { $this->albumFactory = resolve(AlbumFactory::class); + $this->verify = resolve(Verify::class); parent::__construct($query, $request, $attributes, $cookies, $files, $server, $content); } catch (BindingResolutionException $e) { throw new FrameworkException('Laravel\'s provider component', $e); diff --git a/app/Http/Requests/Diagnostics/DiagnosticsRequest.php b/app/Http/Requests/Diagnostics/DiagnosticsRequest.php new file mode 100644 index 00000000000..dca1e754138 --- /dev/null +++ b/app/Http/Requests/Diagnostics/DiagnosticsRequest.php @@ -0,0 +1,22 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + if (!Configs::getValueAsBool('mod_frame_enabled')) { + throw new UnauthorizedException(); + } + + $randomAlbumId = Configs::getValueAsString('random_album_id'); + $albumId = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? (($randomAlbumId !== '') ? $randomAlbumId : null); + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumId); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Install/SetUpAdminRequest.php b/app/Http/Requests/Install/SetUpAdminRequest.php index 088a1acf707..32ce5c0aadf 100644 --- a/app/Http/Requests/Install/SetUpAdminRequest.php +++ b/app/Http/Requests/Install/SetUpAdminRequest.php @@ -2,11 +2,11 @@ namespace App\Http\Requests\Install; -use App\Legacy\V1\Contracts\Http\Requests\HasPassword; -use App\Legacy\V1\Contracts\Http\Requests\HasUsername; -use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; -use App\Legacy\V1\Requests\Traits\HasPasswordTrait; -use App\Legacy\V1\Requests\Traits\HasUsernameTrait; +use App\Contracts\Http\Requests\HasPassword; +use App\Contracts\Http\Requests\HasUsername; +use App\Contracts\Http\Requests\RequestAttribute; +use App\Http\Requests\Traits\HasPasswordTrait; +use App\Http\Requests\Traits\HasUsernameTrait; use App\Rules\PasswordRule; use App\Rules\UsernameRule; use Illuminate\Foundation\Http\FormRequest; diff --git a/app/Http/Requests/Jobs/ShowJobsRequest.php b/app/Http/Requests/Jobs/ShowJobsRequest.php new file mode 100644 index 00000000000..92bc31db8ef --- /dev/null +++ b/app/Http/Requests/Jobs/ShowJobsRequest.php @@ -0,0 +1,19 @@ + [ + 'required', + 'string', + Rule::in([ + 'filesystems.disks.extract-jobs.root', + 'filesystems.disks.image-jobs.root', + 'filesystems.disks.image-upload.root']), + ], + ]; + } + + protected function processValidatedValues(array $values, array $files): void + { + $this->path = config($values[RequestAttribute::SINGLE_PATH_ATTRIBUTE]); + } + + /** + * {@inheritDoc} + */ + public function authorize(): bool + { + return Gate::check(SettingsPolicy::CAN_EDIT, Configs::class); + } + + public function path(): string + { + return $this->path; + } +} diff --git a/app/Http/Requests/Maintenance/CreateThumbsRequest.php b/app/Http/Requests/Maintenance/CreateThumbsRequest.php new file mode 100644 index 00000000000..82b78316668 --- /dev/null +++ b/app/Http/Requests/Maintenance/CreateThumbsRequest.php @@ -0,0 +1,48 @@ + [ + 'required', + Rule::in([ + SizeVariantType::SMALL->value, + SizeVariantType::SMALL2X->value, + SizeVariantType::MEDIUM->value, + SizeVariantType::MEDIUM2X->value]), + ], + ]; + } + + protected function processValidatedValues(array $values, array $files): void + { + $this->kind = SizeVariantType::from($values[RequestAttribute::SIZE_VARIANT_ATTRIBUTE]); + } + + /** + * {@inheritDoc} + */ + public function authorize(): bool + { + return Gate::check(SettingsPolicy::CAN_EDIT, Configs::class); + } + + public function kind(): SizeVariantType + { + return $this->kind; + } +} diff --git a/app/Http/Requests/Maintenance/MaintenanceRequest.php b/app/Http/Requests/Maintenance/MaintenanceRequest.php new file mode 100644 index 00000000000..2c6837bc982 --- /dev/null +++ b/app/Http/Requests/Maintenance/MaintenanceRequest.php @@ -0,0 +1,19 @@ + $this->username(), 'password' => $this->password()]); + + // Check if logged in AND is admin + return $isLoggedIn && Gate::check(SettingsPolicy::CAN_UPDATE, Configs::class); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::USERNAME_ATTRIBUTE => ['sometimes', new UsernameRule()], + RequestAttribute::PASSWORD_ATTRIBUTE => ['sometimes', new PasswordRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->username = $values[RequestAttribute::USERNAME_ATTRIBUTE] ?? ''; + $this->password = $values[RequestAttribute::PASSWORD_ATTRIBUTE] ?? ''; + } + + /** + * {@inheritDoc} + */ + protected function failedAuthorization(): void + { + throw new HttpResponseException(response()->view('update.error', ['code' => '403', 'message' => 'Incorrect username or password'], 403)); + } +} diff --git a/app/Http/Requests/Maintenance/RegisterRequest.php b/app/Http/Requests/Maintenance/RegisterRequest.php new file mode 100644 index 00000000000..919c50ab810 --- /dev/null +++ b/app/Http/Requests/Maintenance/RegisterRequest.php @@ -0,0 +1,41 @@ + ['required', 'string', 'max:255'], + ]; + } + + protected function processValidatedValues( + #[\SensitiveParameter] + array $values, + array $files): void + { + $this->key = new \SensitiveParameterValue($values['key']); + } + + /** + * {@inheritDoc} + */ + public function authorize(): bool + { + return Gate::check(SettingsPolicy::CAN_EDIT, Configs::class); + } + + public function key(): \SensitiveParameterValue + { + return $this->key; + } +} diff --git a/app/Http/Requests/Maintenance/UpdateRequest.php b/app/Http/Requests/Maintenance/UpdateRequest.php new file mode 100644 index 00000000000..4f5eb720700 --- /dev/null +++ b/app/Http/Requests/Maintenance/UpdateRequest.php @@ -0,0 +1,19 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null $albumId */ + $albumId = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumId); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Photo/CopyPhotosRequest.php b/app/Http/Requests/Photo/CopyPhotosRequest.php new file mode 100644 index 00000000000..c48290a7f10 --- /dev/null +++ b/app/Http/Requests/Photo/CopyPhotosRequest.php @@ -0,0 +1,50 @@ + 'required|array|min:1', + RequestAttribute::PHOTO_IDS_ATTRIBUTE . '.*' => ['required', new RandomIDRule(false)], + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var array $photosIDs */ + $photosIDs = $values[RequestAttribute::PHOTO_IDS_ATTRIBUTE]; + $this->photos = Photo::query() + ->with(['size_variants']) + ->findOrFail($photosIDs); + /** @var string|null */ + $targetAlbumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + $this->album = $targetAlbumID === null ? + null : + Album::query()->findOrFail($targetAlbumID); + } +} diff --git a/app/Http/Requests/Photo/DeletePhotosRequest.php b/app/Http/Requests/Photo/DeletePhotosRequest.php new file mode 100644 index 00000000000..028f1ba1f4f --- /dev/null +++ b/app/Http/Requests/Photo/DeletePhotosRequest.php @@ -0,0 +1,47 @@ +photoIds()]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::PHOTO_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::PHOTO_IDS_ATTRIBUTE . '.*' => ['required', new RandomIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + // As we are going to delete the photos anyway, we don't load the + // models for efficiency reasons. + // Instead, we use mass deletion via low-level SQL queries later. + $this->photoIds = $values[RequestAttribute::PHOTO_IDS_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Photo/EditPhotoRequest.php b/app/Http/Requests/Photo/EditPhotoRequest.php new file mode 100644 index 00000000000..647258aa4e3 --- /dev/null +++ b/app/Http/Requests/Photo/EditPhotoRequest.php @@ -0,0 +1,80 @@ +photo); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::PHOTO_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], + RequestAttribute::DESCRIPTION_ATTRIBUTE => ['present', new DescriptionRule()], + RequestAttribute::TAGS_ATTRIBUTE => ['present', 'array'], + RequestAttribute::TAGS_ATTRIBUTE . '.*' => ['required', 'string', 'min:1'], + RequestAttribute::LICENSE_ATTRIBUTE => ['required', new Enum(LicenseType::class)], + RequestAttribute::UPLOAD_DATE_ATTRIBUTE => ['required', 'date'], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string $photoID */ + $photoID = $values[RequestAttribute::PHOTO_ID_ATTRIBUTE]; + + $this->photo = Photo::query() + ->with(['size_variants', 'size_variants.sym_links']) + ->findOrFail($photoID); + + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + $this->description = $values[RequestAttribute::DESCRIPTION_ATTRIBUTE]; + $this->tags = $values[RequestAttribute::TAGS_ATTRIBUTE]; + $this->upload_date = Carbon::parse($values[RequestAttribute::UPLOAD_DATE_ATTRIBUTE]); + $this->license = LicenseType::tryFrom($values[RequestAttribute::LICENSE_ATTRIBUTE]); + } +} diff --git a/app/Http/Requests/Photo/FromUrlRequest.php b/app/Http/Requests/Photo/FromUrlRequest.php new file mode 100644 index 00000000000..c8e8da11bc9 --- /dev/null +++ b/app/Http/Requests/Photo/FromUrlRequest.php @@ -0,0 +1,77 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + RequestAttribute::URLS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::URLS_ATTRIBUTE . '.*' => 'required|string', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = null; + /** @var string|null $id */ + $id = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + if ($id !== null) { + $this->album = Album::query()->findOrFail($id); + } + $this->urls = $values[RequestAttribute::URLS_ATTRIBUTE]; + + // The replacement below looks suspicious. + // If it was really necessary, then there would be much more special + // characters (for example umlauts in international domain names) + // which would require replacement by their corresponding %-encoding. + // However, I assume that the PHP method `fopen` is happily fine with + // any character and internally handles special characters itself. + // Hence, either use a proper encoding method here instead of our + // home-brewed, poor-man replacement or drop it entirely. + // TODO: Find out what is needed and proceed accordingly. + // ? We can't use URL encode because we need to preserve :// and ? + $this->urls = str_replace(' ', '%20', $this->urls); + } + + /** + * @return string[] + */ + public function urls(): array + { + return $this->urls; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Photo/MovePhotosRequest.php b/app/Http/Requests/Photo/MovePhotosRequest.php new file mode 100644 index 00000000000..a2488cf5402 --- /dev/null +++ b/app/Http/Requests/Photo/MovePhotosRequest.php @@ -0,0 +1,47 @@ + 'required|array|min:1', + RequestAttribute::PHOTO_IDS_ATTRIBUTE . '.*' => ['required', new RandomIDRule(false)], + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var array $photosIss */ + $photosIss = $values[RequestAttribute::PHOTO_IDS_ATTRIBUTE]; + $this->photos = Photo::query() + ->findOrFail($photosIss); + /** @var string|null */ + $targetAlbumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE]; + $this->album = $targetAlbumID === null ? null : Album::query()->findOrFail($targetAlbumID); + } +} diff --git a/app/Http/Requests/Photo/RenamePhotoRequest.php b/app/Http/Requests/Photo/RenamePhotoRequest.php new file mode 100644 index 00000000000..28ac75270a1 --- /dev/null +++ b/app/Http/Requests/Photo/RenamePhotoRequest.php @@ -0,0 +1,51 @@ +photo); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::PHOTO_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string $photoID */ + $photoID = $values[RequestAttribute::PHOTO_ID_ATTRIBUTE]; + $this->photo = Photo::query()->findOrFail($photoID); + $this->title = $values[RequestAttribute::TITLE_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Photo/RotatePhotoRequest.php b/app/Http/Requests/Photo/RotatePhotoRequest.php new file mode 100644 index 00000000000..3e3eb7e6726 --- /dev/null +++ b/app/Http/Requests/Photo/RotatePhotoRequest.php @@ -0,0 +1,49 @@ + ['required', new RandomIDRule(false)], + RequestAttribute::DIRECTION_ATTRIBUTE => ['required', Rule::in([-1, 1])], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var ?string $photoID */ + $photoID = $values[RequestAttribute::PHOTO_ID_ATTRIBUTE]; + $this->photo = Photo::query() + ->with(['size_variants']) + ->findOrFail($photoID); + $this->direction = intval($values[RequestAttribute::DIRECTION_ATTRIBUTE]); + } + + public function direction(): int + { + return $this->direction; + } +} diff --git a/app/Http/Requests/Photo/SetPhotosStarredRequest.php b/app/Http/Requests/Photo/SetPhotosStarredRequest.php new file mode 100644 index 00000000000..9fefad14885 --- /dev/null +++ b/app/Http/Requests/Photo/SetPhotosStarredRequest.php @@ -0,0 +1,52 @@ + 'required|array|min:1', + RequestAttribute::PHOTO_IDS_ATTRIBUTE . '.*' => ['required', new RandomIDRule(false)], + RequestAttribute::IS_STARRED_ATTRIBUTE => 'required|boolean', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var array $photosIDs */ + $photosIDs = $values[RequestAttribute::PHOTO_IDS_ATTRIBUTE]; + $this->photos = Photo::query()->findOrFail($photosIDs); + $this->isStarred = static::toBoolean($values[RequestAttribute::IS_STARRED_ATTRIBUTE]); + } + + public function isStarred(): bool + { + return $this->isStarred; + } +} diff --git a/app/Http/Requests/Photo/SetPhotosTagsRequest.php b/app/Http/Requests/Photo/SetPhotosTagsRequest.php new file mode 100644 index 00000000000..aa7a1976c8f --- /dev/null +++ b/app/Http/Requests/Photo/SetPhotosTagsRequest.php @@ -0,0 +1,48 @@ + 'required|boolean', + RequestAttribute::PHOTO_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::PHOTO_IDS_ATTRIBUTE . '.*' => ['required', new RandomIDRule(false)], + RequestAttribute::TAGS_ATTRIBUTE => 'present|array', + RequestAttribute::TAGS_ATTRIBUTE . '.*' => 'required|string|min:1', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var array $photosIDs */ + $photosIDs = $values[RequestAttribute::PHOTO_IDS_ATTRIBUTE]; + $this->photos = Photo::query()->findOrFail($photosIDs); + $this->tags = $values[RequestAttribute::TAGS_ATTRIBUTE]; + $this->shallOverride = $values[RequestAttribute::SHALL_OVERRIDE_ATTRIBUTE]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Photo/UploadPhotoRequest.php b/app/Http/Requests/Photo/UploadPhotoRequest.php new file mode 100644 index 00000000000..79bd5e95cf5 --- /dev/null +++ b/app/Http/Requests/Photo/UploadPhotoRequest.php @@ -0,0 +1,93 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new AlbumIDRule(true)], + RequestAttribute::FILE_LAST_MODIFIED_TIME => 'sometimes|nullable|numeric', + RequestAttribute::FILE_ATTRIBUTE => ['required', 'file'], + 'file_name' => 'required|string', + 'uuid_name' => ['present', new FileUuidRule()], + 'extension' => ['present', new ExtensionRule()], + 'chunk_number' => 'required|integer|min:1', + 'total_chunks' => 'required|integer|gte:chunk_number', + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($values[RequestAttribute::ALBUM_ID_ATTRIBUTE]); + // Convert the File Last Modified to seconds instead of milliseconds + $val = $values[RequestAttribute::FILE_LAST_MODIFIED_TIME] ?? null; + $this->file_last_modified_time = $val !== null ? intval($val) : null; + $this->file_chunk = $files[RequestAttribute::FILE_ATTRIBUTE]; + $this->meta = new UploadMetaResource( + file_name: $values['file_name'], + extension: $values['extension'] ?? null, + uuid_name: $values['uuid_name'] ?? null, + stage: FileStatus::UPLOADING, + chunk_number: $values['chunk_number'], + total_chunks: $values['total_chunks'], + ); + } + + public function uploaded_file_chunk(): UploadedFile + { + return $this->file_chunk; + } + + public function file_last_modified_time(): ?int + { + return $this->file_last_modified_time !== null ? intval($this->file_last_modified_time / 1000) : null; + } + + public function meta(): UploadMetaResource + { + return $this->meta; + } +} diff --git a/app/Legacy/V1/Requests/User/U2FRequest.php b/app/Http/Requests/Profile/ChangeTokenRequest.php similarity index 65% rename from app/Legacy/V1/Requests/User/U2FRequest.php rename to app/Http/Requests/Profile/ChangeTokenRequest.php index 7df053432dc..e7ea50d4fc9 100644 --- a/app/Legacy/V1/Requests/User/U2FRequest.php +++ b/app/Http/Requests/Profile/ChangeTokenRequest.php @@ -1,17 +1,13 @@ ['required', 'string', new Enum(OauthProvidersType::class)], + ]; + } + + protected function processValidatedValues(array $values, array $files): void + { + $this->provider = OauthProvidersType::from($values[RequestAttribute::PROVIDER_ATTRIBUTE]); + } + + public function provider(): OauthProvidersType + { + return $this->provider; + } +} diff --git a/app/Http/Requests/Profile/UpdateProfileRequest.php b/app/Http/Requests/Profile/UpdateProfileRequest.php new file mode 100644 index 00000000000..04861af5536 --- /dev/null +++ b/app/Http/Requests/Profile/UpdateProfileRequest.php @@ -0,0 +1,88 @@ + ['required', new UsernameRule(true)], + RequestAttribute::PASSWORD_ATTRIBUTE => ['sometimes', 'confirmed', new PasswordRule(false)], + RequestAttribute::OLD_PASSWORD_ATTRIBUTE => ['required', new PasswordRule(false), new CurrentPasswordRule()], + RequestAttribute::EMAIL_ATTRIBUTE => ['present', 'nullable', 'email:rfc,dns', 'max:100'], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->password = $values[RequestAttribute::PASSWORD_ATTRIBUTE] ?? null; + $this->oldPassword = $values[RequestAttribute::OLD_PASSWORD_ATTRIBUTE]; + + $this->username = trim($values[RequestAttribute::USERNAME_ATTRIBUTE]); + $this->username = $this->username === '' ? null : $this->username; + + $this->email = trim($values[RequestAttribute::EMAIL_ATTRIBUTE] ?? ''); + $this->email = $this->email === '' ? null : $this->email; + } + + /** + * Returns the previous password. + * + * See {@link HasPasswordTrait::password()} for an explanation of the + * semantic difference between the return values `null` and `''`. + * + * @return string|null + */ + public function oldPassword(): ?string + { + return $this->oldPassword; + } + + /** + * Return the new username chosen. + * if Username is null, this means that the user does not want to update it. + * + * @return ?string + */ + public function username(): ?string + { + return $this->username; + } + + public function email(): ?string + { + return $this->email; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Search/GetSearchRequest.php b/app/Http/Requests/Search/GetSearchRequest.php new file mode 100644 index 00000000000..1fa44b092ba --- /dev/null +++ b/app/Http/Requests/Search/GetSearchRequest.php @@ -0,0 +1,62 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::TERM_ATTRIBUTE => ['required', 'string'], + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $albumId = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumId); + + // Escape special characters for a LIKE query + $this->terms = explode(' ', str_replace( + ['\\', '%', '_'], + ['\\\\', '\\%', '\\_'], + base64_decode($values[RequestAttribute::TERM_ATTRIBUTE], true) + )); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Search/InitSearchRequest.php b/app/Http/Requests/Search/InitSearchRequest.php new file mode 100644 index 00000000000..7aa449d0fbc --- /dev/null +++ b/app/Http/Requests/Search/InitSearchRequest.php @@ -0,0 +1,50 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $albumId = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumId); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Session/LoginRequest.php b/app/Http/Requests/Session/LoginRequest.php index 453b157f7b8..eba9a516ff6 100644 --- a/app/Http/Requests/Session/LoginRequest.php +++ b/app/Http/Requests/Session/LoginRequest.php @@ -2,13 +2,14 @@ namespace App\Http\Requests\Session; +use App\Contracts\Http\Requests\HasPassword; +use App\Contracts\Http\Requests\HasUsername; +use App\Contracts\Http\Requests\RequestAttribute; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Session\LoginRuleSet; -use App\Legacy\V1\Contracts\Http\Requests\HasPassword; -use App\Legacy\V1\Contracts\Http\Requests\HasUsername; -use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; -use App\Legacy\V1\Requests\Traits\HasPasswordTrait; -use App\Legacy\V1\Requests\Traits\HasUsernameTrait; +use App\Http\Requests\Traits\HasPasswordTrait; +use App\Http\Requests\Traits\HasUsernameTrait; +use App\Rules\PasswordRule; +use App\Rules\UsernameRule; class LoginRequest extends BaseApiRequest implements HasUsername, HasPassword { @@ -28,7 +29,10 @@ public function authorize(): bool */ public function rules(): array { - return LoginRuleSet::rules(); + return [ + RequestAttribute::USERNAME_ATTRIBUTE => ['required', new UsernameRule()], + RequestAttribute::PASSWORD_ATTRIBUTE => ['required', new PasswordRule(false)], + ]; } /** diff --git a/app/Http/Requests/Settings/GetAllConfigsRequest.php b/app/Http/Requests/Settings/GetAllConfigsRequest.php new file mode 100644 index 00000000000..c05e6c085b1 --- /dev/null +++ b/app/Http/Requests/Settings/GetAllConfigsRequest.php @@ -0,0 +1,23 @@ +css; + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [self::ATTRIBUTE => 'present|nullable|string']; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->css = $values[self::ATTRIBUTE] ?? ''; + } +} diff --git a/app/Http/Requests/Settings/SetConfigsRequest.php b/app/Http/Requests/Settings/SetConfigsRequest.php new file mode 100644 index 00000000000..475eb0d4d25 --- /dev/null +++ b/app/Http/Requests/Settings/SetConfigsRequest.php @@ -0,0 +1,59 @@ + ['required'], + RequestAttribute::CONFIGS_ARRAY_KEY_ATTRIBUTE => ['required', new ConfigKeyRule(), new ConfigKeyRequireSupportRule($this->verify)], + RequestAttribute::CONFIGS_ARRAY_VALUE_ATTRIBUTE => ['present', new ConfigValueRule()], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $editableConfigs = []; + foreach ($values[RequestAttribute::CONFIGS_ATTRIBUTE] as $config) { + $editableConfigs[] = new EditableConfigResource($config[RequestAttribute::CONFIGS_KEY_ATTRIBUTE], $config[RequestAttribute::CONFIGS_VALUE_ATTRIBUTE]); + } + $this->configs = collect($editableConfigs); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Settings/SetJSSettingRequest.php b/app/Http/Requests/Settings/SetJSSettingRequest.php new file mode 100644 index 00000000000..9a17cdd70f4 --- /dev/null +++ b/app/Http/Requests/Settings/SetJSSettingRequest.php @@ -0,0 +1,43 @@ +js; + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [self::ATTRIBUTE => 'present|nullable|string']; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->js = $values[self::ATTRIBUTE] ?? ''; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Sharing/AddSharingRequest.php b/app/Http/Requests/Sharing/AddSharingRequest.php new file mode 100644 index 00000000000..348d9d7d7de --- /dev/null +++ b/app/Http/Requests/Sharing/AddSharingRequest.php @@ -0,0 +1,72 @@ +albumIds]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::ALBUM_IDS_ATTRIBUTE . '.*' => ['required', new RandomIDRule(false)], + RequestAttribute::USER_IDS_ATTRIBUTE => 'required|array|min:1', + RequestAttribute::USER_IDS_ATTRIBUTE . '.*' => ['required', new IntegerIDRule(false)], + RequestAttribute::GRANTS_DOWNLOAD_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_FULL_PHOTO_ACCESS_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_UPLOAD_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_EDIT_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_DELETE_ATTRIBUTE => ['required', 'boolean'], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->albumIds = $values[RequestAttribute::ALBUM_IDS_ATTRIBUTE]; + $this->userIds = $values[RequestAttribute::USER_IDS_ATTRIBUTE]; + $this->permResource = new AccessPermissionResource( + grants_edit: static::toBoolean($values[RequestAttribute::GRANTS_EDIT_ATTRIBUTE]), + grants_delete: static::toBoolean($values[RequestAttribute::GRANTS_DELETE_ATTRIBUTE]), + grants_download: static::toBoolean($values[RequestAttribute::GRANTS_DOWNLOAD_ATTRIBUTE]), + grants_full_photo_access: static::toBoolean($values[RequestAttribute::GRANTS_FULL_PHOTO_ACCESS_ATTRIBUTE]), + grants_upload: static::toBoolean($values[RequestAttribute::GRANTS_UPLOAD_ATTRIBUTE]), + ); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Sharing/DeleteSharingRequest.php b/app/Http/Requests/Sharing/DeleteSharingRequest.php new file mode 100644 index 00000000000..44db202f924 --- /dev/null +++ b/app/Http/Requests/Sharing/DeleteSharingRequest.php @@ -0,0 +1,57 @@ +perm->album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::PERMISSION_ID => ['required', new IntegerIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var int $id */ + $id = $values[RequestAttribute::PERMISSION_ID]; + $this->perm = AccessPermission::with(['album', 'user'])->findOrFail($id); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Sharing/EditSharingRequest.php b/app/Http/Requests/Sharing/EditSharingRequest.php new file mode 100644 index 00000000000..c6163a1de79 --- /dev/null +++ b/app/Http/Requests/Sharing/EditSharingRequest.php @@ -0,0 +1,71 @@ +perm->album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::PERMISSION_ID => ['required', new IntegerIDRule(false)], + RequestAttribute::GRANTS_DOWNLOAD_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_FULL_PHOTO_ACCESS_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_UPLOAD_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_EDIT_ATTRIBUTE => ['required', 'boolean'], + RequestAttribute::GRANTS_DELETE_ATTRIBUTE => ['required', 'boolean'], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var int $id */ + $id = $values[RequestAttribute::PERMISSION_ID]; + $this->perm = AccessPermission::with(['album', 'user'])->findOrFail($id); + + $this->permResource = new AccessPermissionResource( + grants_edit: static::toBoolean($values[RequestAttribute::GRANTS_EDIT_ATTRIBUTE]), + grants_delete: static::toBoolean($values[RequestAttribute::GRANTS_DELETE_ATTRIBUTE]), + grants_download: static::toBoolean($values[RequestAttribute::GRANTS_DOWNLOAD_ATTRIBUTE]), + grants_full_photo_access: static::toBoolean($values[RequestAttribute::GRANTS_FULL_PHOTO_ACCESS_ATTRIBUTE]), + grants_upload: static::toBoolean($values[RequestAttribute::GRANTS_UPLOAD_ATTRIBUTE]), + ); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Sharing/ListAllSharingRequest.php b/app/Http/Requests/Sharing/ListAllSharingRequest.php new file mode 100644 index 00000000000..ccde4c1aeab --- /dev/null +++ b/app/Http/Requests/Sharing/ListAllSharingRequest.php @@ -0,0 +1,24 @@ +album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->album = $this->albumFactory->findBaseAlbumOrFail($values[RequestAttribute::ALBUM_ID_ATTRIBUTE]); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Statistics/SpacePerAlbumRequest.php b/app/Http/Requests/Statistics/SpacePerAlbumRequest.php new file mode 100644 index 00000000000..b24802f9a79 --- /dev/null +++ b/app/Http/Requests/Statistics/SpacePerAlbumRequest.php @@ -0,0 +1,60 @@ +album === null) { + return Gate::check(SettingsPolicy::CAN_SEE_STATISTICS, [Configs::class]); + } + + return Auth::check() && Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $this->album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null */ + $albumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumID); + + // Filter only to user if user is not admin + if (Auth::check() && Auth::user()?->may_administrate !== true) { + $this->owner_id = intval(Auth::id()); + } + } +} diff --git a/app/Http/Requests/Statistics/SpacePerUserRequest.php b/app/Http/Requests/Statistics/SpacePerUserRequest.php new file mode 100644 index 00000000000..fcf2f65ec8e --- /dev/null +++ b/app/Http/Requests/Statistics/SpacePerUserRequest.php @@ -0,0 +1,35 @@ +may_administrate !== true) { + $this->owner_id = intval(Auth::id()); + } + } +} diff --git a/app/Http/Requests/Statistics/SpaceSizeVariantRequest.php b/app/Http/Requests/Statistics/SpaceSizeVariantRequest.php new file mode 100644 index 00000000000..30918f4d6fc --- /dev/null +++ b/app/Http/Requests/Statistics/SpaceSizeVariantRequest.php @@ -0,0 +1,60 @@ +album === null) { + return Gate::check(UserPolicy::CAN_EDIT, [User::class]); + } + + return Auth::check() && Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $this->album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null */ + $albumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumID); + + // Filter only to user if user is not admin + if (Auth::check() && Auth::user()?->may_administrate !== true) { + $this->owner_id = intval(Auth::id()); + } + } +} diff --git a/app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumAlbumsTrait.php b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumAlbumsTrait.php new file mode 100644 index 00000000000..58c68516e4f --- /dev/null +++ b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumAlbumsTrait.php @@ -0,0 +1,29 @@ +album])) { + return false; + } + + /** @var AbstractAlbum $album */ + foreach ($this->albums as $album) { + if (!Gate::check(AlbumPolicy::CAN_EDIT, $album)) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumTrait.php b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumTrait.php new file mode 100644 index 00000000000..804dd74b6c6 --- /dev/null +++ b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditAlbumTrait.php @@ -0,0 +1,22 @@ +album]); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotoTrait.php b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotoTrait.php new file mode 100644 index 00000000000..3e67b8a302d --- /dev/null +++ b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotoTrait.php @@ -0,0 +1,22 @@ +photo]); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosAlbumTrait.php b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosAlbumTrait.php new file mode 100644 index 00000000000..15d8f55f7c8 --- /dev/null +++ b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosAlbumTrait.php @@ -0,0 +1,34 @@ +album])) { + return false; + } + + /** @var Photo $photo */ + foreach ($this->photos as $photo) { + if (!Gate::check(PhotoPolicy::CAN_EDIT, $photo)) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosTrait.php b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosTrait.php new file mode 100644 index 00000000000..2c440285faf --- /dev/null +++ b/app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosTrait.php @@ -0,0 +1,28 @@ +photos as $photo) { + if (!Gate::check(PhotoPolicy::CAN_EDIT, $photo)) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/HasAbstractAlbumTrait.php b/app/Http/Requests/Traits/HasAbstractAlbumTrait.php new file mode 100644 index 00000000000..27f3e1772fa --- /dev/null +++ b/app/Http/Requests/Traits/HasAbstractAlbumTrait.php @@ -0,0 +1,18 @@ +album; + } +} diff --git a/app/Http/Requests/Traits/HasAccessPermissionResourceTrait.php b/app/Http/Requests/Traits/HasAccessPermissionResourceTrait.php new file mode 100644 index 00000000000..d04f5ebf850 --- /dev/null +++ b/app/Http/Requests/Traits/HasAccessPermissionResourceTrait.php @@ -0,0 +1,18 @@ +permResource; + } +} diff --git a/app/Http/Requests/Traits/HasAccessPermissionTrait.php b/app/Http/Requests/Traits/HasAccessPermissionTrait.php new file mode 100644 index 00000000000..53ac1b21966 --- /dev/null +++ b/app/Http/Requests/Traits/HasAccessPermissionTrait.php @@ -0,0 +1,18 @@ +perm; + } +} diff --git a/app/Http/Requests/Traits/HasAlbumIdTrait.php b/app/Http/Requests/Traits/HasAlbumIdTrait.php new file mode 100644 index 00000000000..12a4a4d09db --- /dev/null +++ b/app/Http/Requests/Traits/HasAlbumIdTrait.php @@ -0,0 +1,16 @@ +albumId; + } +} diff --git a/app/Http/Requests/Traits/HasAlbumIdsTrait.php b/app/Http/Requests/Traits/HasAlbumIdsTrait.php new file mode 100644 index 00000000000..faf2cc44869 --- /dev/null +++ b/app/Http/Requests/Traits/HasAlbumIdsTrait.php @@ -0,0 +1,19 @@ +albumIds; + } +} diff --git a/app/Http/Requests/Traits/HasAlbumSortingCriterionTrait.php b/app/Http/Requests/Traits/HasAlbumSortingCriterionTrait.php new file mode 100644 index 00000000000..bebe5742e19 --- /dev/null +++ b/app/Http/Requests/Traits/HasAlbumSortingCriterionTrait.php @@ -0,0 +1,18 @@ +albumSortingCriterion; + } +} diff --git a/app/Http/Requests/Traits/HasAlbumTrait.php b/app/Http/Requests/Traits/HasAlbumTrait.php new file mode 100644 index 00000000000..ca2a83f680b --- /dev/null +++ b/app/Http/Requests/Traits/HasAlbumTrait.php @@ -0,0 +1,18 @@ +album; + } +} diff --git a/app/Http/Requests/Traits/HasAlbumsTrait.php b/app/Http/Requests/Traits/HasAlbumsTrait.php new file mode 100644 index 00000000000..2d72661af3c --- /dev/null +++ b/app/Http/Requests/Traits/HasAlbumsTrait.php @@ -0,0 +1,24 @@ + + */ + protected Collection $albums; + + /** + * @return Collection + */ + public function albums(): Collection + { + return $this->albums; + } +} diff --git a/app/Http/Requests/Traits/HasAspectRatioTrait.php b/app/Http/Requests/Traits/HasAspectRatioTrait.php new file mode 100644 index 00000000000..2fbc3978ee8 --- /dev/null +++ b/app/Http/Requests/Traits/HasAspectRatioTrait.php @@ -0,0 +1,18 @@ +aspectRatio; + } +} diff --git a/app/Http/Requests/Traits/HasBaseAlbumTrait.php b/app/Http/Requests/Traits/HasBaseAlbumTrait.php new file mode 100644 index 00000000000..eec39cd182f --- /dev/null +++ b/app/Http/Requests/Traits/HasBaseAlbumTrait.php @@ -0,0 +1,18 @@ +album; + } +} diff --git a/app/Http/Requests/Traits/HasCompactBooleanTrait.php b/app/Http/Requests/Traits/HasCompactBooleanTrait.php new file mode 100644 index 00000000000..32e10a97b5a --- /dev/null +++ b/app/Http/Requests/Traits/HasCompactBooleanTrait.php @@ -0,0 +1,13 @@ +is_compact; + } +} diff --git a/app/Http/Requests/Traits/HasConfigsTrait.php b/app/Http/Requests/Traits/HasConfigsTrait.php new file mode 100644 index 00000000000..61689853aff --- /dev/null +++ b/app/Http/Requests/Traits/HasConfigsTrait.php @@ -0,0 +1,20 @@ + */ + protected Collection $configs; + + /** + * @return Collection + */ + public function configs(): Collection + { + return $this->configs; + } +} diff --git a/app/Http/Requests/Traits/HasCopyrightTrait.php b/app/Http/Requests/Traits/HasCopyrightTrait.php new file mode 100644 index 00000000000..ab903ed3441 --- /dev/null +++ b/app/Http/Requests/Traits/HasCopyrightTrait.php @@ -0,0 +1,16 @@ +copyright; + } +} diff --git a/app/Http/Requests/Traits/HasDescriptionTrait.php b/app/Http/Requests/Traits/HasDescriptionTrait.php new file mode 100644 index 00000000000..3d510d74df2 --- /dev/null +++ b/app/Http/Requests/Traits/HasDescriptionTrait.php @@ -0,0 +1,16 @@ +description; + } +} diff --git a/app/Http/Requests/Traits/HasLicenseTrait.php b/app/Http/Requests/Traits/HasLicenseTrait.php new file mode 100644 index 00000000000..7936924f992 --- /dev/null +++ b/app/Http/Requests/Traits/HasLicenseTrait.php @@ -0,0 +1,18 @@ +license; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/HasNoteTrait.php b/app/Http/Requests/Traits/HasNoteTrait.php new file mode 100644 index 00000000000..0c570709b5f --- /dev/null +++ b/app/Http/Requests/Traits/HasNoteTrait.php @@ -0,0 +1,16 @@ +note; + } +} diff --git a/app/Http/Requests/Traits/HasOwnerIdTrait.php b/app/Http/Requests/Traits/HasOwnerIdTrait.php new file mode 100644 index 00000000000..318fac0eeec --- /dev/null +++ b/app/Http/Requests/Traits/HasOwnerIdTrait.php @@ -0,0 +1,16 @@ +owner_id; + } +} diff --git a/app/Http/Requests/Traits/HasParentAlbumTrait.php b/app/Http/Requests/Traits/HasParentAlbumTrait.php new file mode 100644 index 00000000000..fe7be9cb360 --- /dev/null +++ b/app/Http/Requests/Traits/HasParentAlbumTrait.php @@ -0,0 +1,18 @@ +parent_album; + } +} diff --git a/app/Http/Requests/Traits/HasPasswordTrait.php b/app/Http/Requests/Traits/HasPasswordTrait.php new file mode 100644 index 00000000000..9e991730d2c --- /dev/null +++ b/app/Http/Requests/Traits/HasPasswordTrait.php @@ -0,0 +1,31 @@ +password; + } +} diff --git a/app/Http/Requests/Traits/HasPhotoIdsTrait.php b/app/Http/Requests/Traits/HasPhotoIdsTrait.php new file mode 100644 index 00000000000..6ba6851b08f --- /dev/null +++ b/app/Http/Requests/Traits/HasPhotoIdsTrait.php @@ -0,0 +1,19 @@ +photoIds; + } +} diff --git a/app/Http/Requests/Traits/HasPhotoLayoutTrait.php b/app/Http/Requests/Traits/HasPhotoLayoutTrait.php new file mode 100644 index 00000000000..131a78d9ce0 --- /dev/null +++ b/app/Http/Requests/Traits/HasPhotoLayoutTrait.php @@ -0,0 +1,18 @@ +photoLayout; + } +} diff --git a/app/Http/Requests/Traits/HasPhotoSortingCriterionTrait.php b/app/Http/Requests/Traits/HasPhotoSortingCriterionTrait.php new file mode 100644 index 00000000000..3e1e0988cbe --- /dev/null +++ b/app/Http/Requests/Traits/HasPhotoSortingCriterionTrait.php @@ -0,0 +1,18 @@ +photoSortingCriterion; + } +} diff --git a/app/Http/Requests/Traits/HasPhotoTrait.php b/app/Http/Requests/Traits/HasPhotoTrait.php new file mode 100644 index 00000000000..6943610c539 --- /dev/null +++ b/app/Http/Requests/Traits/HasPhotoTrait.php @@ -0,0 +1,18 @@ +photo; + } +} diff --git a/app/Http/Requests/Traits/HasPhotosTrait.php b/app/Http/Requests/Traits/HasPhotosTrait.php new file mode 100644 index 00000000000..9ab310560da --- /dev/null +++ b/app/Http/Requests/Traits/HasPhotosTrait.php @@ -0,0 +1,22 @@ + + */ + protected Collection $photos; + + /** + * @return Collection + */ + public function photos(): Collection + { + return $this->photos; + } +} diff --git a/app/Http/Requests/Traits/HasQuotaKBTrait.php b/app/Http/Requests/Traits/HasQuotaKBTrait.php new file mode 100644 index 00000000000..bd4663803af --- /dev/null +++ b/app/Http/Requests/Traits/HasQuotaKBTrait.php @@ -0,0 +1,19 @@ +quota_kb; + } +} diff --git a/app/Http/Requests/Traits/HasSeStatusBooleanTrait.php b/app/Http/Requests/Traits/HasSeStatusBooleanTrait.php new file mode 100644 index 00000000000..1ac8d1ef9aa --- /dev/null +++ b/app/Http/Requests/Traits/HasSeStatusBooleanTrait.php @@ -0,0 +1,22 @@ +is_se === null) { + $this->is_se = $this->verify->validate() && $this->verify->is_supporter(); + } + + return $this->is_se; + } +} diff --git a/app/Http/Requests/Traits/HasSizeVariantTrait.php b/app/Http/Requests/Traits/HasSizeVariantTrait.php new file mode 100644 index 00000000000..43435a32aa1 --- /dev/null +++ b/app/Http/Requests/Traits/HasSizeVariantTrait.php @@ -0,0 +1,18 @@ +sizeVariant; + } +} diff --git a/app/Http/Requests/Traits/HasTagAlbumTrait.php b/app/Http/Requests/Traits/HasTagAlbumTrait.php new file mode 100644 index 00000000000..9a01803f893 --- /dev/null +++ b/app/Http/Requests/Traits/HasTagAlbumTrait.php @@ -0,0 +1,18 @@ +album; + } +} diff --git a/app/Http/Requests/Traits/HasTagsTrait.php b/app/Http/Requests/Traits/HasTagsTrait.php new file mode 100644 index 00000000000..4a5552771eb --- /dev/null +++ b/app/Http/Requests/Traits/HasTagsTrait.php @@ -0,0 +1,19 @@ +tags; + } +} diff --git a/app/Http/Requests/Traits/HasTermsTrait.php b/app/Http/Requests/Traits/HasTermsTrait.php new file mode 100644 index 00000000000..fa28a16a54b --- /dev/null +++ b/app/Http/Requests/Traits/HasTermsTrait.php @@ -0,0 +1,19 @@ +terms; + } +} diff --git a/app/Http/Requests/Traits/HasTitleTrait.php b/app/Http/Requests/Traits/HasTitleTrait.php new file mode 100644 index 00000000000..3e81dce8010 --- /dev/null +++ b/app/Http/Requests/Traits/HasTitleTrait.php @@ -0,0 +1,16 @@ +title; + } +} diff --git a/app/Http/Requests/Traits/HasUploadDateTrait.php b/app/Http/Requests/Traits/HasUploadDateTrait.php new file mode 100644 index 00000000000..48c25281417 --- /dev/null +++ b/app/Http/Requests/Traits/HasUploadDateTrait.php @@ -0,0 +1,18 @@ +upload_date; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/HasUserIdTrait.php b/app/Http/Requests/Traits/HasUserIdTrait.php new file mode 100644 index 00000000000..2d8e201fd60 --- /dev/null +++ b/app/Http/Requests/Traits/HasUserIdTrait.php @@ -0,0 +1,19 @@ +userId; + } +} diff --git a/app/Http/Requests/Traits/HasUserIdsTrait.php b/app/Http/Requests/Traits/HasUserIdsTrait.php new file mode 100644 index 00000000000..d0f901800f5 --- /dev/null +++ b/app/Http/Requests/Traits/HasUserIdsTrait.php @@ -0,0 +1,19 @@ + + */ + protected array $userIds = []; + + /** + * @return array + */ + public function userIds(): array + { + return $this->userIds; + } +} diff --git a/app/Http/Requests/Traits/HasUserTrait.php b/app/Http/Requests/Traits/HasUserTrait.php new file mode 100644 index 00000000000..a7974f7ab78 --- /dev/null +++ b/app/Http/Requests/Traits/HasUserTrait.php @@ -0,0 +1,29 @@ +user2; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Traits/HasUsernameTrait.php b/app/Http/Requests/Traits/HasUsernameTrait.php new file mode 100644 index 00000000000..faa58360463 --- /dev/null +++ b/app/Http/Requests/Traits/HasUsernameTrait.php @@ -0,0 +1,16 @@ +username; + } +} diff --git a/app/Http/Requests/UserManagement/AddUserRequest.php b/app/Http/Requests/UserManagement/AddUserRequest.php new file mode 100644 index 00000000000..2a2e0a71292 --- /dev/null +++ b/app/Http/Requests/UserManagement/AddUserRequest.php @@ -0,0 +1,84 @@ + ['required', new UsernameRule()], + RequestAttribute::PASSWORD_ATTRIBUTE => ['required', new PasswordRule(false)], + RequestAttribute::MAY_UPLOAD_ATTRIBUTE => 'present|boolean', + RequestAttribute::MAY_EDIT_OWN_SETTINGS_ATTRIBUTE => 'present|boolean', + RequestAttribute::HAS_QUOTA_ATTRIBUTE => ['sometimes', 'boolean', new BooleanRequireSupportRule(false, $this->verify)], + RequestAttribute::QUOTA_ATTRIBUTE => ['sometimes', 'int', new IntegerRequireSupportRule(0, $this->verify)], + RequestAttribute::NOTE_ATTRIBUTE => ['sometimes', 'string', new StringRequireSupportRule('', $this->verify)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->username = $values[RequestAttribute::USERNAME_ATTRIBUTE]; + $this->password = $values[RequestAttribute::PASSWORD_ATTRIBUTE]; + $this->mayUpload = static::toBoolean($values[RequestAttribute::MAY_UPLOAD_ATTRIBUTE]); + $this->mayEditOwnSettings = static::toBoolean($values[RequestAttribute::MAY_EDIT_OWN_SETTINGS_ATTRIBUTE]); + $has_quota = static::toBoolean($values[RequestAttribute::HAS_QUOTA_ATTRIBUTE] ?? false); + $this->quota_kb = $has_quota ? intval($values[RequestAttribute::QUOTA_ATTRIBUTE]) : null; + $this->note = $values[RequestAttribute::NOTE_ATTRIBUTE] ?? ''; + } + + public function mayUpload(): bool + { + return $this->mayUpload; + } + + public function mayEditOwnSettings(): bool + { + return $this->mayEditOwnSettings; + } +} diff --git a/app/Http/Requests/UserManagement/DeleteUserRequest.php b/app/Http/Requests/UserManagement/DeleteUserRequest.php new file mode 100644 index 00000000000..752e24b7088 --- /dev/null +++ b/app/Http/Requests/UserManagement/DeleteUserRequest.php @@ -0,0 +1,45 @@ + ['required', new IntegerIDRule(false)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var int $userID */ + $userID = $values[RequestAttribute::ID_ATTRIBUTE]; + $this->user2 = User::query()->findOrFail($userID); + } +} diff --git a/app/Http/Requests/UserManagement/ManagmentListUsersRequest.php b/app/Http/Requests/UserManagement/ManagmentListUsersRequest.php new file mode 100644 index 00000000000..f9ee4080d43 --- /dev/null +++ b/app/Http/Requests/UserManagement/ManagmentListUsersRequest.php @@ -0,0 +1,23 @@ + ['required', new IntegerIDRule(false)], + RequestAttribute::USERNAME_ATTRIBUTE => ['required', new UsernameRule(), 'min:1'], + RequestAttribute::PASSWORD_ATTRIBUTE => ['sometimes', new PasswordRule(false)], + RequestAttribute::MAY_UPLOAD_ATTRIBUTE => 'present|boolean', + RequestAttribute::MAY_EDIT_OWN_SETTINGS_ATTRIBUTE => 'present|boolean', + RequestAttribute::HAS_QUOTA_ATTRIBUTE => ['sometimes', 'boolean', new BooleanRequireSupportRule(false, $this->verify)], + RequestAttribute::QUOTA_ATTRIBUTE => ['sometimes', 'int', new IntegerRequireSupportRule(0, $this->verify)], + RequestAttribute::NOTE_ATTRIBUTE => ['sometimes', 'nullable', 'string', new StringRequireSupportRule('', $this->verify)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->username = $values[RequestAttribute::USERNAME_ATTRIBUTE]; + if (array_key_exists(RequestAttribute::PASSWORD_ATTRIBUTE, $values)) { + // See {@link HasPasswordTrait::password()} for an explanation + // of the semantic difference between `null` and `''`. + $this->password = $values[RequestAttribute::PASSWORD_ATTRIBUTE] ?? ''; + } else { + $this->password = null; + } + $this->mayUpload = static::toBoolean($values[RequestAttribute::MAY_UPLOAD_ATTRIBUTE]); + $this->mayEditOwnSettings = static::toBoolean($values[RequestAttribute::MAY_EDIT_OWN_SETTINGS_ATTRIBUTE]); + /** @var int $userID */ + $userID = $values[RequestAttribute::ID_ATTRIBUTE]; + $this->user2 = User::query()->findOrFail($userID); + $has_quota = static::toBoolean($values[RequestAttribute::HAS_QUOTA_ATTRIBUTE] ?? false); + $this->quota_kb = $has_quota ? intval($values[RequestAttribute::QUOTA_ATTRIBUTE]) : null; + $this->note = $values[RequestAttribute::NOTE_ATTRIBUTE] ?? ''; + } + + public function mayUpload(): bool + { + return $this->mayUpload; + } + + public function mayEditOwnSettings(): bool + { + return $this->mayEditOwnSettings; + } +} diff --git a/app/Http/Requests/Users/ListUsersRequest.php b/app/Http/Requests/Users/ListUsersRequest.php new file mode 100644 index 00000000000..df9e1338bb8 --- /dev/null +++ b/app/Http/Requests/Users/ListUsersRequest.php @@ -0,0 +1,19 @@ + 'required|string', + ]; } protected function processValidatedValues(array $values, array $files): void diff --git a/app/Http/Requests/WebAuthn/EditCredentialRequest.php b/app/Http/Requests/WebAuthn/EditCredentialRequest.php new file mode 100644 index 00000000000..60b3aec501d --- /dev/null +++ b/app/Http/Requests/WebAuthn/EditCredentialRequest.php @@ -0,0 +1,50 @@ + 'required|string', + RequestAttribute::ALIAS_ATTRIBUTE => 'required|string|min:5|max:255', + ]; + } + + protected function processValidatedValues(array $values, array $files): void + { + /** @var string $id */ + $id = $values[RequestAttribute::ID_ATTRIBUTE]; + $this->credential = WebAuthnCredential::query()->findOrFail($id); + $this->alias = $values[RequestAttribute::ALIAS_ATTRIBUTE]; + } + + public function getCredential(): WebAuthnCredential + { + return $this->credential; + } + + public function getAlias(): string + { + return $this->alias; + } +} diff --git a/app/Http/Resources/Collections/ConfigCollectionResource.php b/app/Http/Resources/Collections/ConfigCollectionResource.php new file mode 100644 index 00000000000..0b07a18a47b --- /dev/null +++ b/app/Http/Resources/Collections/ConfigCollectionResource.php @@ -0,0 +1,36 @@ + */ + public array $configs; + + /** + * @param Collection $configs + * + * @return void + */ + public function __construct(Collection $configs) + { + $configs + // Group by category + ->chunkWhile(fn (Configs $value, int $key, Collection $chunk) => $value->cat === $chunk->last()->cat) + // For each category, map the configs to ConfigResource + ->each(function (Collection $chunk) { + $configs_data = ConfigResource::collect($chunk->all()); + $this->configs[$chunk->first()->cat] = $configs_data; + }); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Collections/PositionDataResource.php b/app/Http/Resources/Collections/PositionDataResource.php new file mode 100644 index 00000000000..5d9bbf6bef7 --- /dev/null +++ b/app/Http/Resources/Collections/PositionDataResource.php @@ -0,0 +1,41 @@ + */ + #[LiteralTypeScriptType('App.Http.Resources.Models.PhotoResource[]')] + public ?Collection $photos; + + /** + * @param string|null $id the ID of the album; `null` for root album + * @param string|null $title the title of the album; `null` if untitled + * @param Collection $photos the collection of photos with position data to be shown on map + * @param string|null $track_url the URL of the album's track + */ + public function __construct( + ?string $id, + ?string $title, + Collection $photos, + ?string $track_url, + ) { + $this->id = $id; + $this->title = $title; + $this->track_url = $track_url; + $this->photos = PhotoResource::collect($photos); + } +} diff --git a/app/Http/Resources/Collections/RootAlbumResource.php b/app/Http/Resources/Collections/RootAlbumResource.php new file mode 100644 index 00000000000..14499ccaf74 --- /dev/null +++ b/app/Http/Resources/Collections/RootAlbumResource.php @@ -0,0 +1,73 @@ + */ + public Collection $smart_albums; + /** @var Collection */ + public Collection $tag_albums; + /** @var Collection */ + public Collection $albums; + /** @var Collection */ + public Collection $shared_albums; + public RootConfig $config; + public RootAlbumRightsResource $rights; + + /** + * @param Collection $smart_albums + * @param Collection $tag_albums + * @param Collection $albums + * @param Collection $shared_albums + * @param RootConfig $config + * + * @return void + */ + public function __construct( + Collection $smart_albums, + Collection $tag_albums, + Collection $albums, + Collection $shared_albums, + RootConfig $config, + RootAlbumRightsResource $rights, + ) { + $this->smart_albums = $smart_albums; + $this->tag_albums = $tag_albums; + $this->albums = $albums; + $this->shared_albums = $shared_albums; + $this->config = $config; + $this->rights = $rights; + } + + public static function fromDTO(TopAlbumDTO $dto, RootConfig $config): self + { + return new self( + smart_albums: ThumbAlbumResource::collect($dto->smart_albums->values()), + tag_albums: ThumbAlbumResource::collect($dto->tag_albums), + albums: ThumbAlbumResource::collect($dto->albums), + shared_albums: $dto->shared_albums !== null ? ThumbAlbumResource::collect($dto->shared_albums) : collect([]), + config: $config, + rights: new RootAlbumRightsResource() + ); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Diagnostics/CleaningState.php b/app/Http/Resources/Diagnostics/CleaningState.php new file mode 100644 index 00000000000..716d5cdaf29 --- /dev/null +++ b/app/Http/Resources/Diagnostics/CleaningState.php @@ -0,0 +1,23 @@ +path = str_replace(storage_path() . '/', '', $path); + $this->base = str_replace(base_path() . '/', '', $path); + $this->is_not_empty = $is_not_empty; + } +} diff --git a/app/Http/Resources/Diagnostics/ErrorLine.php b/app/Http/Resources/Diagnostics/ErrorLine.php new file mode 100644 index 00000000000..19531984137 --- /dev/null +++ b/app/Http/Resources/Diagnostics/ErrorLine.php @@ -0,0 +1,40 @@ +type = self::TYPE_WARNING; + $this->line = \Str::substr($line, 9); + } + + if (\Str::startsWith($line, 'Info: ')) { + $this->type = self::TYPE_INFO; + $this->line = \Str::substr($line, 6); + } + + if (\Str::startsWith($line, 'Error: ')) { + $this->type = self::TYPE_ERROR; + $this->line = \Str::substr($line, 7); + } + } + + public static function fromString(string $line): ErrorLine + { + return new self($line); + } +} diff --git a/app/Http/Resources/Diagnostics/Permissions.php b/app/Http/Resources/Diagnostics/Permissions.php new file mode 100644 index 00000000000..d62c547f2a5 --- /dev/null +++ b/app/Http/Resources/Diagnostics/Permissions.php @@ -0,0 +1,16 @@ +id = $album->id; + $this->title = $album->title; + $this->description = $album->description; + $this->copyright = $album->copyright; + $this->photo_sorting = $album->photo_sorting; + $this->is_model_album = false; + $this->license = null; + $this->album_sorting = null; + $this->header_id = null; + $this->cover_id = null; + $this->photo_layout = $album->photo_layout; + + if ($album instanceof Album) { + $this->is_model_album = true; + $this->license = $album->license; + $this->album_sorting = $album->album_sorting; + $this->header_id = $album->header_id; + $this->cover_id = $album->cover_id; + $this->aspect_ratio = $album->album_thumb_aspect_ratio; + } + + if ($album instanceof TagAlbum) { + $this->tags = $album->show_tags; + } + } + + public static function fromModel(Album|TagAlbum $album): EditableBaseAlbumResource + { + return new self($album); + } +} diff --git a/app/Http/Resources/Editable/EditableConfigResource.php b/app/Http/Resources/Editable/EditableConfigResource.php new file mode 100644 index 00000000000..9b8a8fb9f64 --- /dev/null +++ b/app/Http/Resources/Editable/EditableConfigResource.php @@ -0,0 +1,19 @@ +key = $key; + $this->value = $value; + } +} diff --git a/app/Http/Resources/Editable/UploadMetaResource.php b/app/Http/Resources/Editable/UploadMetaResource.php new file mode 100644 index 00000000000..1d8502fa4e3 --- /dev/null +++ b/app/Http/Resources/Editable/UploadMetaResource.php @@ -0,0 +1,21 @@ +public_permissions(); + + $this->is_accessible = $is_accessible; + $this->is_base_album = $album instanceof BaseAlbum; + $this->is_model_album = $album instanceof Album; + $this->is_password_protected = !$is_accessible && $public_perm?->password !== null; + $this->is_nsfw_warning_visible = + $album instanceof BaseAlbum && + $album->is_nsfw && + (Auth::check() ? Configs::getValueAsBool('nsfw_warning_admin') : Configs::getValueAsBool('nsfw_warning')); + + $this->setIsMapAccessible(); + $this->setIsSearchAccessible($this->is_base_album); + $this->is_mod_frame_enabled = Configs::getValueAsBool('mod_frame_enabled') && $album->photos->count() > 0; + if ($album instanceof Album && $album->album_thumb_aspect_ratio !== null) { + $this->album_thumb_css_aspect_ratio = $album->album_thumb_aspect_ratio->css(); + } else { + $this->album_thumb_css_aspect_ratio = Configs::getValueAsEnum('default_album_thumb_aspect_ratio', AspectRatioType::class)->css(); + } + + $this->photo_layout = (($album instanceof BaseAlbum) ? $album->photo_layout : null) ?? Configs::getValueAsEnum('layout', PhotoLayoutType::class); + } + + public function setIsMapAccessible(): void + { + $map_display = Configs::getValueAsBool('map_display'); + $public_display = Auth::check() || Configs::getValueAsBool('map_display_public'); + $this->is_map_accessible = $map_display && $public_display; + } + + public function setIsSearchAccessible(bool $is_base_album): void + { + $this->is_search_accessible = (Auth::check() || Configs::getValueAsBool('search_public')) && $is_base_album; + } +} \ No newline at end of file diff --git a/app/Http/Resources/GalleryConfigs/FooterConfig.php b/app/Http/Resources/GalleryConfigs/FooterConfig.php new file mode 100644 index 00000000000..d17fdd1fec3 --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/FooterConfig.php @@ -0,0 +1,43 @@ +footer_additional_text = Configs::getValueAsString('footer_additional_text'); + $this->footer_show_copyright = Configs::getValueAsBool('footer_show_copyright'); + $this->footer_show_social_media = Configs::getValueAsBool('footer_show_social_media'); + $site_copyright_begin = Configs::getValueAsString('site_copyright_begin'); + $site_copyright_end = Configs::getValueAsString('site_copyright_end'); + $site_owner = Configs::getValueAsString('site_owner'); + $this->sm_facebook_url = Configs::getValueAsString('sm_facebook_url'); + $this->sm_flickr_url = Configs::getValueAsString('sm_flickr_url'); + $this->sm_instagram_url = Configs::getValueAsString('sm_instagram_url'); + $this->sm_twitter_url = Configs::getValueAsString('sm_twitter_url'); + $this->sm_youtube_url = Configs::getValueAsString('sm_youtube_url'); + + $copy_right_year = $site_copyright_begin; + if ($site_copyright_begin !== $site_copyright_end) { + $copy_right_year = $copy_right_year . '-' . $site_copyright_end; + } + + $this->copyright = $copy_right_year !== '' ? sprintf(__('lychee.FOOTER_COPYRIGHT'), $site_owner, $copy_right_year) : ''; + } +} diff --git a/app/Http/Resources/GalleryConfigs/InitConfig.php b/app/Http/Resources/GalleryConfigs/InitConfig.php new file mode 100644 index 00000000000..164fbab4290 --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/InitConfig.php @@ -0,0 +1,94 @@ +is_debug_enabled = config('app.debug'); + $this->are_nsfw_visible = Configs::getValueAsBool('nsfw_visible'); + $this->is_nsfw_background_blurred = Configs::getValueAsBool('nsfw_blur'); + $this->nsfw_banner_override = Configs::getValueAsString('nsfw_banner_override'); + $this->is_nsfw_banner_backdrop_blurred = Configs::getValueAsBool('nsfw_banner_blur_backdrop'); + $this->image_overlay_type = Configs::getValueAsEnum('image_overlay_type', ImageOverlayType::class); + $this->display_thumb_album_overlay = Configs::getValueAsEnum('display_thumb_album_overlay', ThumbOverlayVisibilityType::class); + $this->display_thumb_photo_overlay = Configs::getValueAsEnum('display_thumb_photo_overlay', ThumbOverlayVisibilityType::class); + $this->show_keybinding_help_popup = Configs::getValueAsBool('show_keybinding_help_popup'); + $this->clockwork_url = $this->has_clockwork_in_menu(); + + $this->album_subtitle_type = Configs::getValueAsEnum('album_subtitle_type', ThumbAlbumSubtitleType::class); + $this->can_rotate = Configs::getValueAsBool('editor_enabled'); + $this->can_autoplay = Configs::getValueAsBool('autoplay_enabled'); + $this->slideshow_timeout = Configs::getValueAsInt('slideshow_timeout'); + + $this->album_decoration = Configs::getValueAsEnum('album_decoration', AlbumDecorationType::class); + $this->album_decoration_orientation = Configs::getValueAsEnum('album_decoration_orientation', AlbumDecorationOrientation::class); + + $this->title = Configs::getValueAsString('site_title'); + + $verify = resolve(Verify::class); + $is_supporter = $verify->is_supporter(); + $this->is_se_enabled = $verify->validate() && $is_supporter; + $this->is_se_preview_enabled = !$is_supporter && Configs::getValueAsBool('enable_se_preview'); + $this->is_se_info_hidden = $is_supporter || Configs::getValueAsBool('disable_se_call_for_actions'); + + $this->dropbox_api_key = Auth::user()?->may_administrate === true ? Configs::getValueAsString('dropbox_key') : 'disabled'; + } + + private function has_clockwork_in_menu(): string|null + { + // Defining clockwork URL + $clockWorkEnabled = config('clockwork.enable') === true || (config('app.debug') === true && config('clockwork.enable') === null); + $clockWorkWeb = config('clockwork.web'); + if ($clockWorkEnabled && $clockWorkWeb === true) { + return URL::asset('clockwork/app'); + } + if (is_string($clockWorkWeb)) { + return $clockWorkWeb . '/app'; + } + + return null; + } +} \ No newline at end of file diff --git a/app/Http/Resources/GalleryConfigs/LandingPageResource.php b/app/Http/Resources/GalleryConfigs/LandingPageResource.php new file mode 100644 index 00000000000..0972182fd92 --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/LandingPageResource.php @@ -0,0 +1,30 @@ +footer = new FooterConfig(); + $this->landing_page_enable = Configs::getValueAsBool('landing_page_enable'); + $this->landing_background = Configs::getValueAsString('landing_background'); + $this->landing_subtitle = Configs::getValueAsString('landing_subtitle'); + $this->landing_title = Configs::getValueAsString('landing_title'); + $this->site_owner = Configs::getValueAsString('site_owner'); + $this->site_title = Configs::getValueAsString('site_title'); + } +} diff --git a/app/Http/Resources/GalleryConfigs/MapProviderData.php b/app/Http/Resources/GalleryConfigs/MapProviderData.php new file mode 100644 index 00000000000..66ea04404b6 --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/MapProviderData.php @@ -0,0 +1,22 @@ +attribution = $map_providers->getAtributionHtml(); + $this->layer = $map_providers->getLayer(); + } +} \ No newline at end of file diff --git a/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php b/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php new file mode 100644 index 00000000000..264171335b2 --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php @@ -0,0 +1,26 @@ +photo_layout_justified_row_height = Configs::getValueAsInt('photo_layout_justified_row_height'); + $this->photo_layout_masonry_column_width = Configs::getValueAsInt('photo_layout_masonry_column_width'); + $this->photo_layout_grid_column_width = Configs::getValueAsInt('photo_layout_grid_column_width'); + $this->photo_layout_square_column_width = Configs::getValueAsInt('photo_layout_square_column_width'); + $this->photo_layout_gap = Configs::getValueAsInt('photo_layout_gap'); + } +} diff --git a/app/Http/Resources/GalleryConfigs/RegisterData.php b/app/Http/Resources/GalleryConfigs/RegisterData.php new file mode 100644 index 00000000000..f79d98bf89d --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/RegisterData.php @@ -0,0 +1,14 @@ +whereNotNull('longitude')->count() > 0; + $map_display = Configs::getValueAsBool('map_display'); + $public_display = Auth::check() || Configs::getValueAsBool('map_display_public'); + $this->is_map_accessible = $count_locations && $map_display && $public_display; + $this->is_mod_frame_enabled = $this->checkModFrameEnabled(); + $this->is_search_accessible = Auth::check() || Configs::getValueAsBool('search_public'); + $this->album_thumb_css_aspect_ratio = Configs::getValueAsEnum('default_album_thumb_aspect_ratio', AspectRatioType::class)->css(); + $this->show_keybinding_help_button = Configs::getValueAsBool('show_keybinding_help_button'); + $this->login_button_position = Configs::getValueAsString('login_button_position'); + $this->back_button_enabled = Configs::getValueAsBool('back_button_enabled'); + $this->back_button_text = Configs::getValueAsString('back_button_text'); + $this->back_button_url = Configs::getValueAsString('back_button_url'); + } + + private function checkModFrameEnabled(): bool + { + if (!Configs::getValueAsBool('mod_frame_enabled')) { + return false; + } + + $factory = resolve(AlbumFactory::class); + try { + $album = $factory->findAbstractAlbumOrFail(Configs::getValueAsString('random_album_id')); + + return Gate::check(\AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $album]); + } catch (\Throwable) { + Log::critical('Could not find random album for frame with ID:' . Configs::getValueAsString('random_album_id')); + + return false; + } + } +} + diff --git a/app/Http/Resources/GalleryConfigs/UploadConfig.php b/app/Http/Resources/GalleryConfigs/UploadConfig.php new file mode 100644 index 00000000000..cdb200a00a0 --- /dev/null +++ b/app/Http/Resources/GalleryConfigs/UploadConfig.php @@ -0,0 +1,41 @@ +upload_processing_limit = max(1, Configs::getValueAsInt('upload_processing_limit')); + $this->upload_chunk_size = self::getUploadLimit(); + } + + public static function getUploadLimit(): int + { + $size = Configs::getValueAsInt('upload_chunk_size'); + if ($size === 0) { + try { + $size = (int) min( + Helpers::convertSize(ini_get('upload_max_filesize')), + Helpers::convertSize(ini_get('post_max_size')), + Helpers::convertSize(ini_get('memory_limit')) / 10 + ); + } catch (InfoException $e) { + return 1024 * 1024; + } + } + + return $size; + } +} diff --git a/app/Http/Resources/Models/AbstractAlbumResource.php b/app/Http/Resources/Models/AbstractAlbumResource.php new file mode 100644 index 00000000000..e62cd5ebc81 --- /dev/null +++ b/app/Http/Resources/Models/AbstractAlbumResource.php @@ -0,0 +1,20 @@ +config = $config; + $this->resource = $resource; + } +} diff --git a/app/Http/Resources/Models/AccessPermissionResource.php b/app/Http/Resources/Models/AccessPermissionResource.php new file mode 100644 index 00000000000..105135c0a8e --- /dev/null +++ b/app/Http/Resources/Models/AccessPermissionResource.php @@ -0,0 +1,39 @@ +id, + user_id: $accessPermission->user_id, + username: $accessPermission->user->name, + album_title: $accessPermission->album->title, + grants_full_photo_access: $accessPermission->grants_full_photo_access, + grants_download: $accessPermission->grants_download, + grants_upload: $accessPermission->grants_upload, + grants_edit: $accessPermission->grants_edit, + grants_delete: $accessPermission->grants_delete + ); + } +} diff --git a/app/Http/Resources/Models/AlbumResource.php b/app/Http/Resources/Models/AlbumResource.php new file mode 100644 index 00000000000..9224a93f51c --- /dev/null +++ b/app/Http/Resources/Models/AlbumResource.php @@ -0,0 +1,95 @@ + */ + #[LiteralTypeScriptType('App.Http.Resources.Models.ThumbAlbumResource[]')] + public ?Collection $albums; + /** @var ?Collection */ + #[LiteralTypeScriptType('App.Http.Resources.Models.PhotoResource[]')] + public ?Collection $photos; + + // thumb + public ?string $cover_id; + public ?ThumbResource $thumb; + + // security + public AlbumProtectionPolicy $policy; + public AlbumRightsResource $rights; + public PreFormattedAlbumData $preFormattedData; + public ?EditableBaseAlbumResource $editable; + + public function __construct(Album $album) + { + $this->id = $album->id; + $this->title = $album->title; + $this->description = $album->description; + $this->owner_name = Auth::check() ? $album->owner->name : null; + $this->copyright = $album->copyright; + + // attributes + $this->track_url = $album->track_url; + $this->license = $album->license->localization(); + // TODO: Investigate later why this string is 24 characters long. + $this->header_id = trim($album->header_id); + + // children + $this->parent_id = $album->parent_id; + $this->has_albums = !$album->isLeaf(); + $this->albums = $album->relationLoaded('children') ? ThumbAlbumResource::collect($album->children) : null; + $this->photos = $album->relationLoaded('photos') ? PhotoResource::collect($album->photos) : null; + $this->prepPhotosCollection(); + + // thumb + $this->cover_id = $album->cover_id; + $this->thumb = ThumbResource::make($album->thumb?->id, $album->thumb?->type, $album->thumb?->thumbUrl, $album->thumb?->thumb2xUrl); + + // security + $this->policy = AlbumProtectionPolicy::ofBaseAlbum($album); + $this->rights = new AlbumRightsResource($album); + $url = $this->getHeaderUrl($album); + $this->preFormattedData = new PreFormattedAlbumData($album, $url); + + if ($this->rights->can_edit) { + $this->editable = EditableBaseAlbumResource::fromModel($album); + } + } + + public static function fromModel(Album $album): AlbumResource + { + return new self($album); + } +} diff --git a/app/Http/Resources/Models/ConfigResource.php b/app/Http/Resources/Models/ConfigResource.php new file mode 100644 index 00000000000..b484e7803bb --- /dev/null +++ b/app/Http/Resources/Models/ConfigResource.php @@ -0,0 +1,34 @@ +key = $c->key; + $this->type = ConfigType::tryFrom($c->type_range) ?? $c->type_range; + $this->value = $c->value; + $this->documentation = $c->description; + $this->details = $c->details; + $this->require_se = $c->level > 0; + } + + public static function fromModel(Configs $c): ConfigResource + { + return new self($c); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Models/JobHistoryResource.php b/app/Http/Resources/Models/JobHistoryResource.php new file mode 100644 index 00000000000..90c93becb50 --- /dev/null +++ b/app/Http/Resources/Models/JobHistoryResource.php @@ -0,0 +1,33 @@ +username = $jobHistory->owner->username; + $this->status = $jobHistory->status->name(); + $this->created_at = $jobHistory->created_at->toIso8601String(); + $this->updated_at = $jobHistory->updated_at->toIso8601String(); + $this->job = $jobHistory->job; + } + + public static function fromModel(JobHistory $jobHistory): JobHistoryResource + { + return new self($jobHistory); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Models/LightUserResource.php b/app/Http/Resources/Models/LightUserResource.php new file mode 100644 index 00000000000..c077d10fbb2 --- /dev/null +++ b/app/Http/Resources/Models/LightUserResource.php @@ -0,0 +1,25 @@ +id = $user->id; + $this->username = $user->username; + } + + public static function fromModel(User $c): LightUserResource + { + return new self($c); + } +} diff --git a/app/Http/Resources/Models/PhotoResource.php b/app/Http/Resources/Models/PhotoResource.php new file mode 100644 index 00000000000..086656b9780 --- /dev/null +++ b/app/Http/Resources/Models/PhotoResource.php @@ -0,0 +1,102 @@ +id = $photo->id; + $this->album_id = $photo->album_id; + $this->altitude = $photo->altitude; + $this->aperture = $photo->aperture; + $this->checksum = $photo->checksum; + $this->created_at = $photo->created_at->toIso8601String(); + $this->description = $photo->description ?? ''; + $this->focal = $photo->focal; + $this->is_starred = $photo->is_starred; + $this->iso = $photo->iso; + $this->latitude = $photo->latitude; + $this->lens = $photo->lens; + $this->license = $photo->license; + $this->live_photo_checksum = $photo->live_photo_checksum; + $this->live_photo_content_id = $photo->live_photo_content_id; + $this->live_photo_url = $photo->live_photo_url; + $this->setLocation($photo); + $this->longitude = $photo->longitude; + $this->make = $photo->make; + $this->model = $photo->model; + $this->original_checksum = $photo->original_checksum; + $this->shutter = $photo->shutter; + $this->size_variants = new SizeVariantsResouce($photo); + $this->tags = $photo->tags; + $this->taken_at = $photo->taken_at?->toIso8601String(); + $this->taken_at_orig_tz = $photo->taken_at_orig_tz; + $this->title = $photo->title; + $this->type = $photo->type; + $this->updated_at = $photo->updated_at->toIso8601String(); + $this->rights = new PhotoRightsResource($photo); + $this->next_photo_id = null; + $this->previous_photo_id = null; + $this->preformatted = new PreformattedPhotoData($photo, $this->size_variants->original); + $this->precomputed = new PreComputedPhotoData($photo); + } + + public static function fromModel(Photo $photo): PhotoResource + { + return new self($photo); + } + + private function setLocation(Photo $photo): void + { + $showLocation = Configs::getValueAsBool('location_show') && (Auth::check() || Configs::getValueAsBool('location_show_public')); + $this->location = $showLocation ? $photo->location : null; + } +} diff --git a/app/Http/Resources/Models/SizeVariantResource.php b/app/Http/Resources/Models/SizeVariantResource.php new file mode 100644 index 00000000000..d3050d1efaa --- /dev/null +++ b/app/Http/Resources/Models/SizeVariantResource.php @@ -0,0 +1,30 @@ +type = $sizeVariant->type; + $this->locale = $sizeVariant->type->localization(); + $this->filesize = Helpers::getSymbolByQuantity(floatval($sizeVariant->filesize)); + $this->height = $sizeVariant->height; + $this->width = $sizeVariant->width; + $this->url = !$noUrl ? $sizeVariant->url : null; + } +} diff --git a/app/Http/Resources/Models/SizeVariantsResouce.php b/app/Http/Resources/Models/SizeVariantsResouce.php new file mode 100644 index 00000000000..a0f3247cdb4 --- /dev/null +++ b/app/Http/Resources/Models/SizeVariantsResouce.php @@ -0,0 +1,46 @@ +relationLoaded('size_variants') ? $photo->size_variants : null; + $downgrade = !Gate::check(PhotoPolicy::CAN_ACCESS_FULL_PHOTO, [Photo::class, $photo]) && + !$photo->isVideo() && + $size_variants?->hasMedium() === true; + + $original = $size_variants?->getSizeVariant(SizeVariantType::ORIGINAL); + $medium = $size_variants?->getSizeVariant(SizeVariantType::MEDIUM); + $medium2x = $size_variants?->getSizeVariant(SizeVariantType::MEDIUM2X); + $small = $size_variants?->getSizeVariant(SizeVariantType::SMALL); + $small2x = $size_variants?->getSizeVariant(SizeVariantType::SMALL2X); + $thumb = $size_variants?->getSizeVariant(SizeVariantType::THUMB); + $thumb2x = $size_variants?->getSizeVariant(SizeVariantType::THUMB2X); + + $this->medium = $medium?->toResource(); + $this->medium2x = $medium2x?->toResource(); + $this->original = $original?->toResource($downgrade); + $this->small = $small?->toResource(); + $this->small2x = $small2x?->toResource(); + $this->thumb = $thumb?->toResource(); + $this->thumb2x = $thumb2x?->toResource(); + } +} diff --git a/app/Http/Resources/Models/SmartAlbumResource.php b/app/Http/Resources/Models/SmartAlbumResource.php new file mode 100644 index 00000000000..b879513a486 --- /dev/null +++ b/app/Http/Resources/Models/SmartAlbumResource.php @@ -0,0 +1,51 @@ + */ + #[LiteralTypeScriptType('App.Http.Resources.Models.PhotoResource[]')] + public ?Collection $photos; + public ?ThumbResource $thumb; + public AlbumProtectionPolicy $policy; + public AlbumRightsResource $rights; + public PreFormattedAlbumData $preFormattedData; + + public function __construct(BaseSmartAlbum $smartAlbum) + { + $this->id = $smartAlbum->id; + $this->title = $smartAlbum->title; + /** @phpstan-ignore-next-line */ + $this->photos = $smartAlbum->relationLoaded('photos') ? PhotoResource::collect($smartAlbum->getPhotos()) : null; + $this->prepPhotosCollection(); + + $this->thumb = ThumbResource::make($smartAlbum->thumb?->id, $smartAlbum->thumb?->type, $smartAlbum->thumb?->thumbUrl, $smartAlbum->thumb?->thumb2xUrl); + $this->policy = AlbumProtectionPolicy::ofSmartAlbum($smartAlbum); + $this->rights = new AlbumRightsResource($smartAlbum); + $url = $this->getHeaderUrl($smartAlbum); + $this->preFormattedData = new PreFormattedAlbumData($smartAlbum, $url); + } + + public static function fromModel(BaseSmartAlbum $smartAlbum): SmartAlbumResource + { + return new self($smartAlbum); + } +} diff --git a/app/Http/Resources/Models/TagAlbumResource.php b/app/Http/Resources/Models/TagAlbumResource.php new file mode 100644 index 00000000000..4894da27bc1 --- /dev/null +++ b/app/Http/Resources/Models/TagAlbumResource.php @@ -0,0 +1,78 @@ + */ + #[LiteralTypeScriptType('App.Http.Resources.Models.PhotoResource[]')] + public ?Collection $photos; + + // thumb + public ThumbResource|null $thumb; + + // security + public AlbumProtectionPolicy $policy; + public AlbumRightsResource $rights; + public PreFormattedAlbumData $preFormattedData; + public ?EditableBaseAlbumResource $editable; + + public function __construct(TagAlbum $tagAlbum) + { + // basic + $this->id = $tagAlbum->id; + $this->title = $tagAlbum->title; + $this->owner_name = Auth::check() ? $tagAlbum->owner->name : null; + $this->is_tag_album = true; + $this->show_tags = $tagAlbum->show_tags; + $this->copyright = $tagAlbum->copyright; + + // children + $this->photos = $tagAlbum->relationLoaded('photos') ? PhotoResource::collect($tagAlbum->photos) : null; + $this->prepPhotosCollection(); + + // thumb + $this->thumb = ThumbResource::make($tagAlbum->thumb?->id, $tagAlbum->thumb?->type, $tagAlbum->thumb?->thumbUrl, $tagAlbum->thumb?->thumb2xUrl); + + // security + $this->policy = AlbumProtectionPolicy::ofBaseAlbum($tagAlbum); + $this->rights = new AlbumRightsResource($tagAlbum); + $url = $this->getHeaderUrl($tagAlbum); + $this->preFormattedData = new PreFormattedAlbumData($tagAlbum, $url); + + if ($this->rights->can_edit) { + $this->editable = EditableBaseAlbumResource::fromModel($tagAlbum); + } + } + + public static function fromModel(TagAlbum $tagAlbum): TagAlbumResource + { + return new self($tagAlbum); + } +} diff --git a/app/Http/Resources/Models/TargetAlbumResource.php b/app/Http/Resources/Models/TargetAlbumResource.php new file mode 100644 index 00000000000..6c8af3442fa --- /dev/null +++ b/app/Http/Resources/Models/TargetAlbumResource.php @@ -0,0 +1,43 @@ +id = $values['id']; + $this->title = $values['title']; + $this->original = $values['original']; + $this->short_title = $values['short_title']; + $this->thumb = $values['thumb']; + } + + /** + * @param TAlbumSaved $a + * + * @return TargetAlbumResource + */ + public static function fromArray(array $a): TargetAlbumResource + { + return new self($a); + } +} diff --git a/app/Http/Resources/Models/ThumbAlbumResource.php b/app/Http/Resources/Models/ThumbAlbumResource.php new file mode 100644 index 00000000000..0c12a1da0a5 --- /dev/null +++ b/app/Http/Resources/Models/ThumbAlbumResource.php @@ -0,0 +1,106 @@ +id = $data->id; + $this->thumb = $data->thumb === null ? null : new ThumbResource($data->thumb->id, $data->thumb->type, $data->thumb->thumbUrl, $data->thumb->thumb2xUrl); + $this->title = $data->title; + + if ($data instanceof BaseSmartAlbum) { + $policy = AlbumProtectionPolicy::ofSmartAlbum($data); + } else { + /** @var BaseAlbum $data */ + $this->max_taken_at = $data->max_taken_at?->format($date_format); + $this->min_taken_at = $data->min_taken_at?->format($date_format); + + $this->formatMinMaxDate(); + + $this->created_at = $data->created_at->format($date_format); + $policy = AlbumProtectionPolicy::ofBaseAlbum($data); + $this->description = Str::limit($data->description, 100); + $this->owner = $data->owner->username; + } + + if ($data instanceof Album) { + $this->num_photos = $data->num_photos; + $this->num_subalbums = $data->num_children; + } + + $this->is_nsfw = $policy->is_nsfw; + $this->is_public = $policy->is_public; + $this->is_link_required = $policy->is_link_required; + $this->is_password_required = $policy->is_password_required; + + $this->is_tag_album = $data instanceof TagAlbum; + // This aims to indicate whether the current thumb is used to determine the parent. + $this->has_subalbum = $data instanceof Album && !$data->isLeaf(); + + $this->rights = new AlbumRightsResource($data); + } + + public static function fromModel(AbstractAlbum $album): ThumbAlbumResource + { + return new self($album); + } + + private function formatMinMaxDate(): void + { + if ($this->max_taken_at === null || $this->min_taken_at === null) { + return; + } + if ($this->max_taken_at === $this->min_taken_at) { + $this->formatted_min_max = $this->max_taken_at; + + return; + } + + if (Configs::getValueAsEnum('thumb_min_max_order', DateOrderingType::class) === DateOrderingType::YOUNGER_OLDER) { + $this->formatted_min_max = $this->max_taken_at . ' - ' . $this->min_taken_at; + } else { + $this->formatted_min_max = $this->min_taken_at . ' - ' . $this->max_taken_at; + } + } +} diff --git a/app/Http/Resources/Models/ThumbResource.php b/app/Http/Resources/Models/ThumbResource.php new file mode 100644 index 00000000000..ed516706867 --- /dev/null +++ b/app/Http/Resources/Models/ThumbResource.php @@ -0,0 +1,43 @@ +id = $id; + $this->type = $type; + $this->thumb = $thumbUrl; + $this->thumb2x = $thumb2xUrl; + } + + /** + * @param string|null $id + * @param string|null $type + * @param string|null $thumbUrl + * @param string|null $thumb2xUrl + * + * @return ($id is null ? null : ThumbResource) + */ + public static function make(?string $id, ?string $type, ?string $thumbUrl, ?string $thumb2xUrl = null): ?self + { + if ($id === null) { + return null; + } + + /** @var string $id */ + /** @var string $type */ + /** @var string $thumbUrl */ + return new self($id, $type, $thumbUrl, $thumb2xUrl); + } +} diff --git a/app/Http/Resources/Models/UserManagementResource.php b/app/Http/Resources/Models/UserManagementResource.php new file mode 100644 index 00000000000..0a660d45ee6 --- /dev/null +++ b/app/Http/Resources/Models/UserManagementResource.php @@ -0,0 +1,47 @@ +id = $user->id; + $this->username = $user->username; + $this->may_administrate = $user->may_administrate; + $this->may_upload = $user->may_upload || $user->may_administrate; + $this->may_edit_own_settings = $user->may_edit_own_settings || $user->may_administrate; + if ($is_se) { + $this->quota_kb = $user->quota_kb; + $this->description = $user->description; + $this->note = $user->note; + $this->space = $space['size']; + } + if ($user->id !== $space['id']) { + throw new \RuntimeException('User and space id do not match'); + } + } +} diff --git a/app/Http/Resources/Models/UserResource.php b/app/Http/Resources/Models/UserResource.php new file mode 100644 index 00000000000..88b81782e11 --- /dev/null +++ b/app/Http/Resources/Models/UserResource.php @@ -0,0 +1,24 @@ +id = $user?->id; + $this->has_token = $user?->token !== null; + $this->username = $user?->username; + $this->email = $user?->email; + } +} diff --git a/app/DTO/AlbumProtectionPolicy.php b/app/Http/Resources/Models/Utils/AlbumProtectionPolicy.php similarity index 92% rename from app/DTO/AlbumProtectionPolicy.php rename to app/Http/Resources/Models/Utils/AlbumProtectionPolicy.php index 5faee05ea8c..8b314d2f941 100644 --- a/app/DTO/AlbumProtectionPolicy.php +++ b/app/Http/Resources/Models/Utils/AlbumProtectionPolicy.php @@ -1,9 +1,11 @@ is_video = $photo->isVideo(); + $this->is_raw = $photo->isRaw(); + $this->is_livephoto = $photo->live_photo_url !== null; + $this->is_camera_date = $photo->taken_at !== null; + $this->has_exif = $this->genExifHash($photo) !== ''; + $this->has_location = $this->has_location($photo); + } + + private function has_location(Photo $photo): bool + { + return $photo->longitude !== null && + $photo->latitude !== null && + $photo->altitude !== null; + } + + private function genExifHash(Photo $photo): string + { + $exifHash = $photo->make; + $exifHash .= $photo->model; + $exifHash .= $photo->shutter; + if (!$photo->isVideo()) { + $exifHash .= $photo->aperture; + $exifHash .= $photo->focal; + } + $exifHash .= $photo->iso; + + return $exifHash; + } +} diff --git a/app/Livewire/DTO/AlbumFormatted.php b/app/Http/Resources/Models/Utils/PreFormattedAlbumData.php similarity index 54% rename from app/Livewire/DTO/AlbumFormatted.php rename to app/Http/Resources/Models/Utils/PreFormattedAlbumData.php index c8f7152ed5c..d12c43d266b 100644 --- a/app/Livewire/DTO/AlbumFormatted.php +++ b/app/Http/Resources/Models/Utils/PreFormattedAlbumData.php @@ -1,24 +1,29 @@ min_taken_at = $album->min_taken_at?->format($min_max_date_format); $this->max_taken_at = $album->max_taken_at?->format($min_max_date_format); + $this->formatMinMaxDate(); $this->created_at = $album->created_at->format($create_date_format); - $this->description = trim($album->description ?? ''); + $this->description = Markdown::convert(trim($album->description ?? ''))->getContent(); $this->copyright = $album->copyright; } if ($album instanceof Album) { @@ -42,4 +48,22 @@ public function __construct(AbstractAlbum $album, ?string $url) $this->license = $album->license === LicenseType::NONE ? '' : $album->license->localization(); } } -} \ No newline at end of file + + private function formatMinMaxDate(): void + { + if ($this->max_taken_at === null || $this->min_taken_at === null) { + return; + } + if ($this->max_taken_at === $this->min_taken_at) { + $this->min_max_text = $this->max_taken_at; + + return; + } + + if (Configs::getValueAsEnum('header_min_max_order', DateOrderingType::class) === DateOrderingType::YOUNGER_OLDER) { + $this->min_max_text = $this->max_taken_at . ' - ' . $this->min_taken_at; + } else { + $this->min_max_text = $this->min_taken_at . ' - ' . $this->max_taken_at; + } + } +} diff --git a/app/Http/Resources/Models/Utils/PreformattedPhotoData.php b/app/Http/Resources/Models/Utils/PreformattedPhotoData.php new file mode 100644 index 00000000000..3899b3a1143 --- /dev/null +++ b/app/Http/Resources/Models/Utils/PreformattedPhotoData.php @@ -0,0 +1,60 @@ +created_at = $photo->created_at->format($date_format_uploaded); + $this->taken_at = $photo->taken_at?->format($date_format_taken_at); + $this->date_overlay = ($photo->taken_at ?? $photo->created_at)->format($overlay_date_format) ?? ''; + + $this->shutter = str_replace('s', 'sec', $photo->shutter ?? ''); + $this->aperture = str_replace('f/', '', $photo->aperture ?? ''); + $this->iso = sprintf(__('lychee.PHOTO_ISO'), $photo->iso); + $this->lens = ($photo->lens === '' || $photo->lens === null) ? '' : sprintf('(%s)', $photo->lens); + + $this->duration = Helpers::secondsToHMS(intval($photo->aperture)); + $this->fps = $photo->focal === null ? $photo->focal . ' fps' : ''; + + $this->filesize = $original?->filesize ?? '0'; + $this->resolution = $original?->width . ' x ' . $original?->height; + $this->latitude = Helpers::decimalToDegreeMinutesSeconds($photo->latitude, true); + $this->longitude = Helpers::decimalToDegreeMinutesSeconds($photo->longitude, false); + $this->altitude = $photo->altitude !== null ? round($photo->altitude, 1) . 'm' : null; + $this->license = $photo->license !== LicenseType::NONE ? $photo->license->localization() : ''; + $this->description = ($photo->description ?? '') === '' ? '' : Markdown::convert($photo->description)->getContent(); + } +} diff --git a/app/Http/Resources/Models/Utils/UserToken.php b/app/Http/Resources/Models/Utils/UserToken.php new file mode 100644 index 00000000000..b7b1ec1e67a --- /dev/null +++ b/app/Http/Resources/Models/Utils/UserToken.php @@ -0,0 +1,15 @@ +id = $credential->id; + $this->alias = $credential->alias; + $this->created_at = $credential->created_at->toIso8601String(); + } + + public static function fromModel(WebAuthnCredential $credential): WebAuthnResource + { + return new self($credential); + } +} diff --git a/app/Http/Resources/Oauth/OauthRegistrationData.php b/app/Http/Resources/Oauth/OauthRegistrationData.php new file mode 100644 index 00000000000..24948a757ee --- /dev/null +++ b/app/Http/Resources/Oauth/OauthRegistrationData.php @@ -0,0 +1,18 @@ +can_edit = Gate::check(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $abstractAlbum]); + $this->can_share = Gate::check(AlbumPolicy::CAN_SHARE, [AbstractAlbum::class, $abstractAlbum]); + $this->can_share_with_users = Gate::check(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $abstractAlbum]); + $this->can_download = Gate::check(AlbumPolicy::CAN_DOWNLOAD, [AbstractAlbum::class, $abstractAlbum]); + $this->can_upload = Gate::check(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, $abstractAlbum]); + $this->can_move = Gate::check(AlbumPolicy::CAN_DELETE, [AbstractAlbum::class, $abstractAlbum]) && $abstractAlbum instanceof Album; + $this->can_delete = Gate::check(AlbumPolicy::CAN_DELETE, [AbstractAlbum::class, $abstractAlbum]); + $this->can_transfer = Gate::check(AlbumPolicy::CAN_TRANSFER, [AbstractAlbum::class, $abstractAlbum]); + $this->can_access_original = Gate::check(AlbumPolicy::CAN_ACCESS_FULL_PHOTO, [AbstractAlbum::class, $abstractAlbum]); + } +} diff --git a/app/Http/Resources/Rights/GlobalRightsResource.php b/app/Http/Resources/Rights/GlobalRightsResource.php new file mode 100644 index 00000000000..d821deab51d --- /dev/null +++ b/app/Http/Resources/Rights/GlobalRightsResource.php @@ -0,0 +1,23 @@ +root_album = new RootAlbumRightsResource(); + $this->settings = new SettingsRightsResource(); + $this->user_management = new UserManagementRightsResource(); + $this->user = new UserRightsResource(); + } +} diff --git a/app/Http/Resources/Rights/PhotoRightsResource.php b/app/Http/Resources/Rights/PhotoRightsResource.php new file mode 100644 index 00000000000..d209c7ae2a2 --- /dev/null +++ b/app/Http/Resources/Rights/PhotoRightsResource.php @@ -0,0 +1,31 @@ +can_edit = Gate::check(PhotoPolicy::CAN_EDIT, [Photo::class, $photo]); + $this->can_download = Gate::check(PhotoPolicy::CAN_DOWNLOAD, [Photo::class, $photo]); + $this->can_access_full_photo = Gate::check(PhotoPolicy::CAN_ACCESS_FULL_PHOTO, [Photo::class, $photo]); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Rights/RootAlbumRightsResource.php b/app/Http/Resources/Rights/RootAlbumRightsResource.php new file mode 100644 index 00000000000..6cad814f8cd --- /dev/null +++ b/app/Http/Resources/Rights/RootAlbumRightsResource.php @@ -0,0 +1,22 @@ +can_edit = Gate::check(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, null]); + $this->can_upload = Gate::check(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, null]); + } +} diff --git a/app/Http/Resources/Rights/SettingsRightsResource.php b/app/Http/Resources/Rights/SettingsRightsResource.php new file mode 100644 index 00000000000..5c9e98215f3 --- /dev/null +++ b/app/Http/Resources/Rights/SettingsRightsResource.php @@ -0,0 +1,30 @@ +can_edit = Gate::check(SettingsPolicy::CAN_EDIT, [Configs::class]); + $this->can_see_logs = Gate::check(SettingsPolicy::CAN_SEE_LOGS, [Configs::class]); + $this->can_clear_logs = Gate::check(SettingsPolicy::CAN_CLEAR_LOGS, [Configs::class]); + $this->can_see_diagnostics = Gate::check(SettingsPolicy::CAN_SEE_DIAGNOSTICS, [Configs::class]); + $this->can_update = Gate::check(SettingsPolicy::CAN_UPDATE, [Configs::class]); + $this->can_access_dev_tools = Gate::check(SettingsPolicy::CAN_ACCESS_DEV_TOOLS, [Configs::class]); + } +} diff --git a/app/Http/Resources/Rights/UserManagementRightsResource.php b/app/Http/Resources/Rights/UserManagementRightsResource.php new file mode 100644 index 00000000000..941c1e920c7 --- /dev/null +++ b/app/Http/Resources/Rights/UserManagementRightsResource.php @@ -0,0 +1,26 @@ +can_create = Gate::check(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, [User::class]); + $this->can_list = Gate::check(UserPolicy::CAN_LIST, [User::class]); + $this->can_edit = Gate::check(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, [User::class]); + $this->can_delete = Gate::check(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, [User::class]); + } +} diff --git a/app/Http/Resources/Rights/UserRightsResource.php b/app/Http/Resources/Rights/UserRightsResource.php new file mode 100644 index 00000000000..d94505b7201 --- /dev/null +++ b/app/Http/Resources/Rights/UserRightsResource.php @@ -0,0 +1,20 @@ +can_edit = Gate::check(UserPolicy::CAN_EDIT, [User::class]); + } +} diff --git a/app/Http/Resources/Root/AuthConfig.php b/app/Http/Resources/Root/AuthConfig.php new file mode 100644 index 00000000000..647d81f7289 --- /dev/null +++ b/app/Http/Resources/Root/AuthConfig.php @@ -0,0 +1,30 @@ + */ + public readonly array $oauthProviders; + public readonly bool $u2f_enabled; + + public function __construct() + { + $providers = []; + foreach (OauthProvidersType::cases() as $oauth) { + $client_id = config('services.' . $oauth->value . '.client_id'); + if ($client_id === null || $client_id === '') { + continue; + } + $providers[] = $oauth; + } + $this->oauthProviders = $providers; + $this->u2f_enabled = WebAuthnCredential::query()->whereNull('disabled_at')->count() > 0; + } +} \ No newline at end of file diff --git a/app/Http/Resources/Root/VersionResource.php b/app/Http/Resources/Root/VersionResource.php new file mode 100644 index 00000000000..48437452ff9 --- /dev/null +++ b/app/Http/Resources/Root/VersionResource.php @@ -0,0 +1,38 @@ +version = resolve(InstalledVersion::class)->getVersion()->toString(); + } + + $fileVersion = resolve(FileVersion::class); + $gitHubVersion = resolve(GitHubVersion::class); + + if (Configs::getValueAsBool('check_for_updates')) { + // @codeCoverageIgnoreStart + $fileVersion->hydrate(); + $gitHubVersion->hydrate(); + // @codeCoverageIgnoreEnd + } + + $this->is_new_release_available = !$fileVersion->isUpToDate(); + $this->is_git_update_available = !$gitHubVersion->isUpToDate(); + } +} diff --git a/app/Http/Resources/Search/InitResource.php b/app/Http/Resources/Search/InitResource.php new file mode 100644 index 00000000000..685165efee9 --- /dev/null +++ b/app/Http/Resources/Search/InitResource.php @@ -0,0 +1,21 @@ +search_minimum_length = Configs::getValueAsInt('search_minimum_length_required'); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Search/ResultsResource.php b/app/Http/Resources/Search/ResultsResource.php new file mode 100644 index 00000000000..4a41325fd6b --- /dev/null +++ b/app/Http/Resources/Search/ResultsResource.php @@ -0,0 +1,75 @@ + */ + #[LiteralTypeScriptType('App.Http.Resources.Models.ThumbAlbumResource[]')] + public Collection $albums; + + /** @var Collection */ + #[LiteralTypeScriptType('App.Http.Resources.Models.PhotoResource[]')] + public Collection $photos; + + public int $current_page; + public int $from; + public int $last_page; + public int $per_page; + public int $to; + public int $total; + + /** + * @param Collection $albums + * @param LengthAwarePaginator&Paginator $photos + * + * @return void + */ + public function __construct( + Collection $albums, + LengthAwarePaginator $photos, + ) { + $this->albums = $albums; + $this->photos = collect($photos->items()); + $this->current_page = $photos->currentPage(); + $this->from = $photos->firstItem() ?? 0; + $this->last_page = $photos->lastPage(); + $this->per_page = $photos->perPage(); + $this->to = $photos->lastItem() ?? 0; + $this->total = $photos->total(); + + $this->prepPhotosCollection(); + } + + /** + * @param Collection $albums + * @param LengthAwarePaginator $photos + * + * @return ResultsResource + */ + public static function fromData(Collection $albums, LengthAwarePaginator $photos): self + { + return new self( + albums: ThumbAlbumResource::collect($albums), + photos: PhotoResource::collect($photos), // @phpstan-ignore-line + ); + } +} \ No newline at end of file diff --git a/app/Http/Resources/Sharing/ListedAlbumsResource.php b/app/Http/Resources/Sharing/ListedAlbumsResource.php new file mode 100644 index 00000000000..946783374ba --- /dev/null +++ b/app/Http/Resources/Sharing/ListedAlbumsResource.php @@ -0,0 +1,22 @@ +id = $albumListed->id; + $this->title = $albumListed->title; + } +} diff --git a/app/Http/Resources/Sharing/SharedAlbumResource.php b/app/Http/Resources/Sharing/SharedAlbumResource.php new file mode 100644 index 00000000000..b7259a8f13a --- /dev/null +++ b/app/Http/Resources/Sharing/SharedAlbumResource.php @@ -0,0 +1,30 @@ +id = $albumShared->id; + $this->user_id = $albumShared->user_id; + $this->album_id = $albumShared->album_id; + $this->username = $albumShared->username; + $this->title = $albumShared->title; + } +} diff --git a/app/Http/Resources/Sharing/SharesResource.php b/app/Http/Resources/Sharing/SharesResource.php new file mode 100644 index 00000000000..cda664b899e --- /dev/null +++ b/app/Http/Resources/Sharing/SharesResource.php @@ -0,0 +1,40 @@ + */ + #[LiteralTypeScriptType('App.Http.Resources.Sharing.SharedAlbumResource[]')] + public Collection $shared; + /** @var Collection */ + #[LiteralTypeScriptType('App.Http.Resources.Sharing.ListedAlbumsResource[]')] + public Collection $albums; + /** @var Collection */ + #[LiteralTypeScriptType('App.Http.Resources.Sharing.UserSharedResource[]')] + public Collection $users; + + /** + * @param Collection $shared + * @param Collection $albums + * @param Collection $users + * + * @return void + */ + public function __construct( + Collection $shared, + Collection $albums, + Collection $users) + { + $this->shared = $shared->map(fn ($s) => new SharedAlbumResource($s)); + $this->albums = $albums->map(fn ($a) => new ListedAlbumsResource($a)); + $this->users = $users->map(fn ($u) => new UserSharedResource($u)); + } +} diff --git a/app/Http/Resources/Sharing/UserSharedResource.php b/app/Http/Resources/Sharing/UserSharedResource.php new file mode 100644 index 00000000000..67ef9e90d42 --- /dev/null +++ b/app/Http/Resources/Sharing/UserSharedResource.php @@ -0,0 +1,20 @@ +id = $user->id; + $this->username = $user->username; + } +} diff --git a/app/Http/Resources/Statistics/Album.php b/app/Http/Resources/Statistics/Album.php new file mode 100644 index 00000000000..0eb148fbe0e --- /dev/null +++ b/app/Http/Resources/Statistics/Album.php @@ -0,0 +1,37 @@ +username = $count_data['username']; + $this->title = $count_data['title']; + $this->is_nsfw = $count_data['is_nsfw']; + $this->left = $count_data['left']; + $this->right = $count_data['right']; + $this->num_photos = $count_data['num_photos']; + $this->num_descendants = $count_data['num_descendants']; + $this->size = $space_data['size']; + } +} diff --git a/app/Http/Resources/Statistics/Sizes.php b/app/Http/Resources/Statistics/Sizes.php new file mode 100644 index 00000000000..f8f89fe62fb --- /dev/null +++ b/app/Http/Resources/Statistics/Sizes.php @@ -0,0 +1,37 @@ +type = $sizes['type']; + $this->label = $sizes['type']->localization(); + $this->size = $sizes['size']; + } + + /** + * @param array{type:SizeVariantType,size:int} $sizes + * + * @return Sizes + */ + public static function fromArray(array $sizes): self + { + return new self($sizes); + } +} diff --git a/app/Http/Resources/Statistics/UserSpace.php b/app/Http/Resources/Statistics/UserSpace.php new file mode 100644 index 00000000000..6ad8b3585b4 --- /dev/null +++ b/app/Http/Resources/Statistics/UserSpace.php @@ -0,0 +1,36 @@ +id = $user_data['id']; + $this->username = $user_data['username']; + $this->size = $user_data['size']; + } + + /** + * @param array{id:int,username:string,size:int} $user_data + * + * @return UserSpace + */ + public static function fromArray(array $user_data): self + { + return new self($user_data); + } +} diff --git a/app/Http/Resources/Traits/HasHeaderUrl.php b/app/Http/Resources/Traits/HasHeaderUrl.php new file mode 100644 index 00000000000..ee0984d9a35 --- /dev/null +++ b/app/Http/Resources/Traits/HasHeaderUrl.php @@ -0,0 +1,72 @@ +header_id === AlbumController::COMPACT_HEADER) { + return null; + } + + if ($album->photos->isEmpty()) { + return null; + } + + // TODO : already use the prefetched data for photos instead of 2 extra queries? + + return $this->getByQuery($album); + } + + private function getByQuery(AbstractAlbum $album): ?string + { + $headerSizeVariant = null; + + if ($album instanceof Album && $album->header_id !== null) { + $headerSizeVariant = SizeVariant::query() + ->where('photo_id', '=', $album->header_id) + ->whereIn('type', [SizeVariantType::MEDIUM, SizeVariantType::SMALL2X, SizeVariantType::SMALL]) + ->orderBy('type', 'asc') + ->first(); + } + + if ($headerSizeVariant !== null) { + return $headerSizeVariant->url; + } + + $query_ratio = SizeVariant::query() + ->select('photo_id') + ->whereBelongsTo($album->photos) + ->where('ratio', '>', 1) // ! we prefer landscape first. + ->whereIn('type', [SizeVariantType::MEDIUM, SizeVariantType::SMALL2X, SizeVariantType::SMALL]); + $num = $query_ratio->count() - 1; + $photo = $query_ratio->skip(rand(0, $num))->first(); + + if ($photo === null) { + $query = SizeVariant::query() + ->select('photo_id') + ->whereBelongsTo($album->photos) + ->whereIn('type', [SizeVariantType::MEDIUM, SizeVariantType::SMALL2X, SizeVariantType::SMALL]); + $num = $query->count() - 1; + $photo = $query->skip(rand(0, $num))->first(); + } + + return $photo === null ? null : SizeVariant::query() + ->where('photo_id', '=', $photo->photo_id) + ->where('type', '>', 1) + ->orderBy('type', 'asc') + ->first()?->url; + } +} \ No newline at end of file diff --git a/app/Http/Resources/Traits/HasPrepPhotoCollection.php b/app/Http/Resources/Traits/HasPrepPhotoCollection.php new file mode 100644 index 00000000000..376aab4c7f6 --- /dev/null +++ b/app/Http/Resources/Traits/HasPrepPhotoCollection.php @@ -0,0 +1,34 @@ + $photos + */ +trait HasPrepPhotoCollection +{ + private function prepPhotosCollection(): void + { + if ($this->photos === null) { + return; + } + + $previous_photo = null; + $this->photos->each(function (PhotoResource &$photo) use (&$previous_photo) { + if ($previous_photo !== null) { + $previous_photo->next_photo_id = $photo->id; + } + $photo->previous_photo_id = $previous_photo?->id; + $previous_photo = $photo; + }); + + if ($this->photos->count() > 1 && Configs::getValueAsBool('photos_wraparound')) { + $this->photos->first()->previous_photo_id = $this->photos->last()->id; + $this->photos->last()->next_photo_id = $this->photos->first()->id; + } + } +} \ No newline at end of file diff --git a/app/Http/RuleSets/Album/ArchiveAlbumRuleSet.php b/app/Http/RuleSets/Album/ArchiveAlbumRuleSet.php deleted file mode 100644 index d5cba9f530b..00000000000 --- a/app/Http/RuleSets/Album/ArchiveAlbumRuleSet.php +++ /dev/null @@ -1,23 +0,0 @@ - ['required', new AlbumIDListRule()], - ]; - } -} diff --git a/app/Http/RuleSets/Album/SetAlbumDescriptionRuleSet.php b/app/Http/RuleSets/Album/SetAlbumDescriptionRuleSet.php deleted file mode 100644 index 48e55b2a9c0..00000000000 --- a/app/Http/RuleSets/Album/SetAlbumDescriptionRuleSet.php +++ /dev/null @@ -1,25 +0,0 @@ - ['required', new RandomIDRule(false)], - RequestAttribute::DESCRIPTION_ATTRIBUTE => ['present', new DescriptionRule()], - ]; - } -} diff --git a/app/Http/RuleSets/Album/SetAlbumLicenseRuleSet.php b/app/Http/RuleSets/Album/SetAlbumLicenseRuleSet.php deleted file mode 100644 index c8f92b16100..00000000000 --- a/app/Http/RuleSets/Album/SetAlbumLicenseRuleSet.php +++ /dev/null @@ -1,26 +0,0 @@ - ['required', new RandomIDRule(false)], - RequestAttribute::LICENSE_ATTRIBUTE => ['required', new Enum(LicenseType::class)], - ]; - } -} diff --git a/app/Http/RuleSets/Album/SetAlbumNSFWRuleSet.php b/app/Http/RuleSets/Album/SetAlbumNSFWRuleSet.php deleted file mode 100644 index 8b8e875c7fc..00000000000 --- a/app/Http/RuleSets/Album/SetAlbumNSFWRuleSet.php +++ /dev/null @@ -1,24 +0,0 @@ - ['required', new RandomIDRule(false)], - RequestAttribute::IS_NSFW_ATTRIBUTE => 'required|boolean', - ]; - } -} diff --git a/app/Http/RuleSets/Album/SetAlbumSortingRuleSetLegacy.php b/app/Http/RuleSets/Album/SetAlbumSortingRuleSetLegacy.php deleted file mode 100644 index 3e897c611cb..00000000000 --- a/app/Http/RuleSets/Album/SetAlbumSortingRuleSetLegacy.php +++ /dev/null @@ -1,28 +0,0 @@ - ['required', new RandomIDRule(false)], - RequestAttribute::SORTING_COLUMN_ATTRIBUTE => ['present', 'nullable', new Enum(ColumnSortingPhotoType::class)], - RequestAttribute::SORTING_ORDER_ATTRIBUTE => [ - 'required_with:' . RequestAttribute::SORTING_COLUMN_ATTRIBUTE, - 'nullable', new Enum(OrderSortingType::class), - ], - ]; - } -} diff --git a/app/Http/RuleSets/Album/SetPhotoSortingRuleSet.php b/app/Http/RuleSets/Album/SetPhotoSortingRuleSet.php deleted file mode 100644 index e9fb885c26f..00000000000 --- a/app/Http/RuleSets/Album/SetPhotoSortingRuleSet.php +++ /dev/null @@ -1,28 +0,0 @@ - ['required', new RandomIDRule(false)], - RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE => ['present', 'nullable', new Enum(ColumnSortingPhotoType::class)], - RequestAttribute::PHOTO_SORTING_ORDER_ATTRIBUTE => [ - 'required_with:' . RequestAttribute::PHOTO_SORTING_COLUMN_ATTRIBUTE, - 'nullable', new Enum(OrderSortingType::class), - ], - ]; - } -} diff --git a/app/Image/Handlers/GdHandler.php b/app/Image/Handlers/GdHandler.php index 9feb0adf1b4..e0eb4b8117b 100644 --- a/app/Image/Handlers/GdHandler.php +++ b/app/Image/Handlers/GdHandler.php @@ -268,14 +268,14 @@ private function autoRotate(int $orientation): void 3 => -180, 5, 6 => -90, 7, 8 => 90, - default => throw new ImageProcessingException('Image orientation out of range') + default => throw new ImageProcessingException('Image orientation out of range'), }; $flip = match ($orientation) { 0, 1, 3, 6, 8 => 0, 2, 7, 5 => IMG_FLIP_HORIZONTAL, 4 => IMG_FLIP_VERTICAL, - default => throw new ImageProcessingException('Image orientation out of range') + default => throw new ImageProcessingException('Image orientation out of range'), }; if ($angle !== 0) { @@ -423,7 +423,7 @@ private function fastImageCopyResampled( int $dst_h, int $src_w, int $src_h, - int $quality = 4 + int $quality = 4, ): void { try { if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) { diff --git a/app/Image/Handlers/ImagickHandler.php b/app/Image/Handlers/ImagickHandler.php index 5a05e5bc0e6..23840a4e08d 100644 --- a/app/Image/Handlers/ImagickHandler.php +++ b/app/Image/Handlers/ImagickHandler.php @@ -115,14 +115,14 @@ private function autoRotate(): void $needsFlop = match ($orientation) { \Imagick::ORIENTATION_TOPRIGHT, \Imagick::ORIENTATION_BOTTOMLEFT, \Imagick::ORIENTATION_LEFTTOP, \Imagick::ORIENTATION_RIGHTBOTTOM => true, - \Imagick::ORIENTATION_TOPLEFT, \Imagick::ORIENTATION_BOTTOMRIGHT, \Imagick::ORIENTATION_RIGHTTOP, \Imagick::ORIENTATION_LEFTBOTTOM, \Imagick::ORIENTATION_UNDEFINED => false + \Imagick::ORIENTATION_TOPLEFT, \Imagick::ORIENTATION_BOTTOMRIGHT, \Imagick::ORIENTATION_RIGHTTOP, \Imagick::ORIENTATION_LEFTBOTTOM, \Imagick::ORIENTATION_UNDEFINED => false, }; $angle = match ($orientation) { \Imagick::ORIENTATION_TOPLEFT, \Imagick::ORIENTATION_TOPRIGHT, \Imagick::ORIENTATION_UNDEFINED => 0, \Imagick::ORIENTATION_BOTTOMRIGHT, \Imagick::ORIENTATION_BOTTOMLEFT => 180, \Imagick::ORIENTATION_LEFTTOP, \Imagick::ORIENTATION_LEFTBOTTOM => -90, - \Imagick::ORIENTATION_RIGHTTOP, \Imagick::ORIENTATION_RIGHTBOTTOM => 90 + \Imagick::ORIENTATION_RIGHTTOP, \Imagick::ORIENTATION_RIGHTBOTTOM => 90, }; if ($needsFlop && !$this->imImage->flopImage()) { diff --git a/app/Image/SizeVariantDefaultFactory.php b/app/Image/SizeVariantDefaultFactory.php index ee8cbbf7ec2..ee47242a3d6 100644 --- a/app/Image/SizeVariantDefaultFactory.php +++ b/app/Image/SizeVariantDefaultFactory.php @@ -177,7 +177,7 @@ private function createSizeVariantInternal(SizeVariantType $sizeVariant, ImageDi { $svImage = match ($sizeVariant) { SizeVariantType::THUMB, SizeVariantType::THUMB2X => $this->referenceImage->cloneAndCrop($maxDim), - default => $this->referenceImage->cloneAndScale($maxDim) + default => $this->referenceImage->cloneAndScale($maxDim), }; $svFile = $this->namingStrategy->createFile($sizeVariant); diff --git a/app/Image/SizeVariantDimensionHelpers.php b/app/Image/SizeVariantDimensionHelpers.php index 367bd7bea62..78017fcf015 100644 --- a/app/Image/SizeVariantDimensionHelpers.php +++ b/app/Image/SizeVariantDimensionHelpers.php @@ -80,7 +80,7 @@ public function isLargeEnough(ImageDimension $realDim, ImageDimension $maxDim, S return match ($sizeVariant) { SizeVariantType::THUMB => true, SizeVariantType::THUMB2X => $realDim->width >= $maxDim->width && $realDim->height >= $maxDim->height, - default => ($realDim->width >= $maxDim->width && $maxDim->width !== 0) || ($realDim->height >= $maxDim->height && $maxDim->height !== 0) + default => ($realDim->width >= $maxDim->width && $maxDim->width !== 0) || ($realDim->height >= $maxDim->height && $maxDim->height !== 0), }; } diff --git a/app/Legacy/Actions/Photo/Create.php b/app/Legacy/Actions/Photo/Create.php index befd54cdb23..f025f8b01a6 100644 --- a/app/Legacy/Actions/Photo/Create.php +++ b/app/Legacy/Actions/Photo/Create.php @@ -161,7 +161,7 @@ protected function loadFileMetadata(NativeLocalFile $sourceFile, int $fileLastMo protected function findLivePartner( ?string $contentID, string $mimeType, - ?Album $album + ?Album $album, ): ?Photo { try { $livePartner = null; diff --git a/app/Legacy/Actions/Photo/Strategies/AbstractAddStrategy.php b/app/Legacy/Actions/Photo/Strategies/AbstractAddStrategy.php index 2ca699e029c..206d9bdd915 100644 --- a/app/Legacy/Actions/Photo/Strategies/AbstractAddStrategy.php +++ b/app/Legacy/Actions/Photo/Strategies/AbstractAddStrategy.php @@ -12,7 +12,7 @@ abstract class AbstractAddStrategy { protected function __construct( protected ImportParam $parameters, - protected Photo $photo + protected Photo $photo, ) { } diff --git a/app/Actions/Settings/UpdateLogin.php b/app/Legacy/Actions/Settings/UpdateLogin.php similarity index 98% rename from app/Actions/Settings/UpdateLogin.php rename to app/Legacy/Actions/Settings/UpdateLogin.php index 740317f20a8..2add429908f 100644 --- a/app/Actions/Settings/UpdateLogin.php +++ b/app/Legacy/Actions/Settings/UpdateLogin.php @@ -1,6 +1,6 @@ toInteger() <= 40008) { + // @codeCoverageIgnoreStart return self::logAsAdminFromConfig($username, $password, $ip); + // @codeCoverageIgnoreEnd } // For version up to 4.6.3 diff --git a/app/Legacy/BaseConfigMigration.php b/app/Legacy/BaseConfigMigration.php index b5ba9a2338d..d614cae61ee 100644 --- a/app/Legacy/BaseConfigMigration.php +++ b/app/Legacy/BaseConfigMigration.php @@ -16,6 +16,8 @@ abstract class BaseConfigMigration extends Migration /** * @return array + * + * @codeCoverageIgnore */ abstract public function getConfigs(): array; @@ -29,6 +31,8 @@ final public function up(): void /** * Reverse the migrations. + * + * @codeCoverageIgnore */ final public function down(): void { diff --git a/app/Actions/Albums/Tree.php b/app/Legacy/V1/Actions/Albums/Tree.php similarity index 92% rename from app/Actions/Albums/Tree.php rename to app/Legacy/V1/Actions/Albums/Tree.php index 508073798d2..3478d911b74 100644 --- a/app/Actions/Albums/Tree.php +++ b/app/Legacy/V1/Actions/Albums/Tree.php @@ -1,6 +1,6 @@ orderBy($this->sorting->column, $this->sorting->order); - /** @var NsCollection $albums */ + /** @var NsCollection $albums */ $albums = $query->get(); - /** @var ?NsCollection $sharedAlbums */ + /** @var ?NsCollection $sharedAlbums */ $sharedAlbums = null; $userID = Auth::id(); if ($userID !== null) { @@ -75,8 +75,8 @@ public function get(): AlbumForestResource // (sub)-tree and then `toTree` will return garbage as it does // not find connected paths within `$albums` or `$sharedAlbums`, // resp. - /** @var NsCollection $albums */ - /** @var ?NsCollection $sharedAlbums */ + /** @var NsCollection $albums */ + /** @var ?NsCollection $sharedAlbums */ list($albums, $sharedAlbums) = $albums->partition(fn (Album $album) => $album->owner_id === $userID); } diff --git a/app/Legacy/V1/Contracts/Http/Requests/HasAlbumSortingCriterion.php b/app/Legacy/V1/Contracts/Http/Requests/HasAlbumSortingCriterion.php new file mode 100644 index 00000000000..62c23122aa7 --- /dev/null +++ b/app/Legacy/V1/Contracts/Http/Requests/HasAlbumSortingCriterion.php @@ -0,0 +1,13 @@ +orderBy('cat') ->orderBy('id') + // Only display settings which are not part of SE + ->where('level', '=', 0) + ->whereNotIn('key', ['email']) ->get(); } @@ -419,7 +423,16 @@ public function getAll(GetSetAllSettingsRequest $request): Collection public function saveAll(GetSetAllSettingsRequest $request): void { $lastException = null; - foreach ($request->except(['_token', 'function', '/api/Settings::saveAll']) as $key => $value) { + // Select all the SE settings. + $except = DB::table('configs') + ->select('key') + ->where('level', '=', '1') + ->pluck('key') + // Concat bunch of things coming from the POST request. + ->concat(['_token', 'function', '/api/Settings::saveAll']) + // Convert to array. + ->all(); + foreach ($request->except($except) as $key => $value) { $value ??= ''; try { Configs::set($key, $value); diff --git a/app/Legacy/V1/Controllers/Administration/SharingController.php b/app/Legacy/V1/Controllers/Administration/SharingController.php index 0e0259fcdbb..beacade2cb5 100644 --- a/app/Legacy/V1/Controllers/Administration/SharingController.php +++ b/app/Legacy/V1/Controllers/Administration/SharingController.php @@ -5,11 +5,11 @@ use App\Actions\Sharing\ListShare; use App\Constants\AccessPermissionConstants as APC; use App\Exceptions\Internal\QueryBuilderException; +use App\Http\Resources\Sharing\SharesResource; use App\Legacy\V1\Requests\Sharing\AddSharesRequest; use App\Legacy\V1\Requests\Sharing\DeleteSharingRequest; use App\Legacy\V1\Requests\Sharing\ListSharingRequest; use App\Legacy\V1\Requests\Sharing\SetSharesByAlbumRequest; -use App\Legacy\V1\Resources\Sharing\SharesResource; use App\Models\Configs; use App\Models\User; use Illuminate\Database\Eloquent\Collection; diff --git a/app/Legacy/V1/Controllers/Administration/UserController.php b/app/Legacy/V1/Controllers/Administration/UserController.php index 10c63f2a0fb..c3868519050 100644 --- a/app/Legacy/V1/Controllers/Administration/UserController.php +++ b/app/Legacy/V1/Controllers/Administration/UserController.php @@ -2,13 +2,13 @@ namespace App\Legacy\V1\Controllers\Administration; -use App\Actions\Settings\UpdateLogin; use App\Actions\User\TokenDisable; use App\Actions\User\TokenReset; use App\Contracts\Exceptions\InternalLycheeException; use App\Exceptions\Internal\FrameworkException; use App\Exceptions\ModelDBException; use App\Exceptions\UnauthenticatedException; +use App\Legacy\Actions\Settings\UpdateLogin; use App\Legacy\V1\Requests\User\ChangeLoginRequest; use App\Legacy\V1\Requests\User\ChangeTokenRequest; use App\Legacy\V1\Requests\User\SetEmailRequest; diff --git a/app/Legacy/V1/Controllers/AlbumController.php b/app/Legacy/V1/Controllers/AlbumController.php index 62a3042f666..2d8673cf35f 100644 --- a/app/Legacy/V1/Controllers/AlbumController.php +++ b/app/Legacy/V1/Controllers/AlbumController.php @@ -16,6 +16,7 @@ use App\Exceptions\MediaFileOperationException; use App\Exceptions\ModelDBException; use App\Exceptions\UnauthenticatedException; +use App\Http\Resources\Collections\PositionDataResource; use App\Legacy\V1\Requests\Album\AddAlbumRequest; use App\Legacy\V1\Requests\Album\AddTagAlbumRequest; use App\Legacy\V1\Requests\Album\ArchiveAlbumsRequest; @@ -37,7 +38,6 @@ use App\Legacy\V1\Requests\Album\SetAlbumTagsRequest; use App\Legacy\V1\Requests\Album\SetAlbumTrackRequest; use App\Legacy\V1\Requests\Album\UnlockAlbumRequest; -use App\Legacy\V1\Resources\Collections\PositionDataResource; use App\Legacy\V1\Resources\Models\AlbumResource; use App\Legacy\V1\Resources\Models\SmartAlbumResource; use App\Legacy\V1\Resources\Models\TagAlbumResource; @@ -103,7 +103,7 @@ public function get(GetAlbumRequest $request): AlbumResource|TagAlbumResource|Sm $request->album() instanceof BaseSmartAlbum => SmartAlbumResource::make($request->album()), $request->album() instanceof TagAlbum => TagAlbumResource::make($request->album()), $request->album() instanceof Album => AlbumResource::make($request->album()), - default => throw new LycheeLogicException('This should not happen') + default => throw new LycheeLogicException('This should not happen'), }; } diff --git a/app/Legacy/V1/Controllers/AlbumsController.php b/app/Legacy/V1/Controllers/AlbumsController.php index dc6e3fff3e6..dcdb017ba8e 100644 --- a/app/Legacy/V1/Controllers/AlbumsController.php +++ b/app/Legacy/V1/Controllers/AlbumsController.php @@ -4,11 +4,11 @@ use App\Actions\Albums\PositionData; use App\Actions\Albums\Top; -use App\Actions\Albums\Tree; use App\Contracts\Exceptions\LycheeException; use App\DTO\TopAlbumDTO; +use App\Http\Resources\Collections\PositionDataResource; +use App\Legacy\V1\Actions\Albums\Tree; use App\Legacy\V1\Resources\Collections\AlbumForestResource; -use App\Legacy\V1\Resources\Collections\PositionDataResource; use App\Legacy\V1\Resources\Collections\TopAlbumsResource; use App\Models\Configs; use Illuminate\Routing\Controller; diff --git a/app/Legacy/V1/Controllers/IndexController.php b/app/Legacy/V1/Controllers/IndexController.php index b01a408d818..bc9d9048ace 100644 --- a/app/Legacy/V1/Controllers/IndexController.php +++ b/app/Legacy/V1/Controllers/IndexController.php @@ -89,15 +89,15 @@ public function show(): View * Cannot be tested. * * @return void + * + * @codeCoverageIgnore */ - // @codeCoverageIgnoreStart public function phpinfo(): void { Gate::authorize(SettingsPolicy::CAN_SEE_DIAGNOSTICS, Configs::class); phpinfo(); } - // @codeCoverageIgnoreEnd /** * Returns the frontend in "gallery mode". diff --git a/app/Legacy/V1/Controllers/LegacyController.php b/app/Legacy/V1/Controllers/LegacyController.php index 5f11abf0596..9e305d2ed59 100644 --- a/app/Legacy/V1/Controllers/LegacyController.php +++ b/app/Legacy/V1/Controllers/LegacyController.php @@ -4,8 +4,8 @@ use App\Exceptions\ConfigurationException; use App\Exceptions\Internal\QueryBuilderException; -use App\Http\Requests\Legacy\TranslateIDRequest; use App\Legacy\Legacy; +use App\Legacy\V1\Requests\Legacy\TranslateIDRequest; use Illuminate\Routing\Controller; /** diff --git a/app/Legacy/V1/Controllers/PhotoController.php b/app/Legacy/V1/Controllers/PhotoController.php index 5804bc04eb7..0b335dcb72f 100644 --- a/app/Legacy/V1/Controllers/PhotoController.php +++ b/app/Legacy/V1/Controllers/PhotoController.php @@ -46,7 +46,7 @@ class PhotoController extends Controller */ public function __construct( private SymLinkFunctions $symLinkFunctions, - private AlbumFactory $albumFactory + private AlbumFactory $albumFactory, ) { } @@ -173,8 +173,6 @@ public function setTitle(SetPhotosTitleRequest $request): void * @param SetPhotosStarredRequest $request * * @return void - * - * @throws LycheeException */ public function setStar(SetPhotosStarredRequest $request): void { @@ -191,8 +189,6 @@ public function setStar(SetPhotosStarredRequest $request): void * @param SetPhotoDescriptionRequest $request * * @return void - * - * @throws LycheeException */ public function setDescription(SetPhotoDescriptionRequest $request): void { @@ -206,8 +202,6 @@ public function setDescription(SetPhotoDescriptionRequest $request): void * @param SetPhotosTagsRequest $request * * @return void - * - * @throws LycheeException */ public function setTags(SetPhotosTagsRequest $request): void { diff --git a/app/Legacy/V1/Controllers/RedirectController.php b/app/Legacy/V1/Controllers/RedirectController.php index 5178727e0af..7952d969101 100644 --- a/app/Legacy/V1/Controllers/RedirectController.php +++ b/app/Legacy/V1/Controllers/RedirectController.php @@ -75,11 +75,11 @@ public function photo(Request $request, string $albumID, ?string $photoID): Symf $this->unlock->do($album, $request['password']); } - // If we are using livewire by default, we redirect to Livewire url intead. - if (Features::active('livewire')) { + // If we are using vuejs by default, we redirect to vuejs url intead. + if (Features::active('vuejs')) { return $photoID === null ? - redirect(route('livewire-gallery-album', ['albumId' => $albumID])) : - redirect(route('livewire-gallery-photo', ['albumId' => $albumID, 'photoId' => $photoID])); + redirect(route('gallery-album', ['albumId' => $albumID])) : + redirect(route('gallery-photo', ['albumId' => $albumID, 'photoId' => $photoID])); } return $photoID === null ? @@ -98,13 +98,13 @@ public function photo(Request $request, string $albumID, ?string $photoID): Symf */ public function view(): View|SymfonyResponse { - $base_route = Configs::getValueAsBool('landing_page_enable') ? route('landing') : route('livewire-gallery'); + $base_route = Configs::getValueAsBool('landing_page_enable') ? route('landing') : route('gallery'); if (Features::active('legacy_v4_redirect') === false) { return redirect($base_route); } return view('hook-redirection', [ - 'gallery' => route('livewire-gallery'), + 'gallery' => route('gallery'), 'base' => $base_route, ]); } diff --git a/app/DTO/DiagnosticInfo.php b/app/Legacy/V1/DTO/DiagnosticInfo.php similarity index 83% rename from app/DTO/DiagnosticInfo.php rename to app/Legacy/V1/DTO/DiagnosticInfo.php index 76618636a10..e84db3759c2 100644 --- a/app/DTO/DiagnosticInfo.php +++ b/app/Legacy/V1/DTO/DiagnosticInfo.php @@ -1,7 +1,8 @@ getRequestUri(), $dir_url . '/livewire/')) { - return $next($request); - } - if ($requiredStatus !== self::ALBUM && $requiredStatus !== self::ROOT) { throw new LycheeLogicException($requiredStatus . ' is not a valid login requirement.'); } diff --git a/app/Legacy/V1/Requests/Album/AddAlbumRequest.php b/app/Legacy/V1/Requests/Album/AddAlbumRequest.php index e7044036cc1..ebe4c20511b 100644 --- a/app/Legacy/V1/Requests/Album/AddAlbumRequest.php +++ b/app/Legacy/V1/Requests/Album/AddAlbumRequest.php @@ -4,12 +4,12 @@ use App\Contracts\Models\AbstractAlbum; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\AddAlbumRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasParentAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasTitle; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasParentAlbumTrait; use App\Legacy\V1\Requests\Traits\HasTitleTrait; +use App\Legacy\V1\RuleSets\Album\AddAlbumRuleSet; use App\Models\Album; use App\Policies\AlbumPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Album/AddTagAlbumRequest.php b/app/Legacy/V1/Requests/Album/AddTagAlbumRequest.php index 099d2277ffd..f1a665ee605 100644 --- a/app/Legacy/V1/Requests/Album/AddTagAlbumRequest.php +++ b/app/Legacy/V1/Requests/Album/AddTagAlbumRequest.php @@ -4,12 +4,12 @@ use App\Contracts\Models\AbstractAlbum; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\AddTagAlbumRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasTags; use App\Legacy\V1\Contracts\Http\Requests\HasTitle; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasTagsTrait; use App\Legacy\V1\Requests\Traits\HasTitleTrait; +use App\Legacy\V1\RuleSets\Album\AddTagAlbumRuleSet; use App\Policies\AlbumPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Album/DeleteAlbumsRequest.php b/app/Legacy/V1/Requests/Album/DeleteAlbumsRequest.php index dde7ce1859a..d44824505cf 100644 --- a/app/Legacy/V1/Requests/Album/DeleteAlbumsRequest.php +++ b/app/Legacy/V1/Requests/Album/DeleteAlbumsRequest.php @@ -3,10 +3,10 @@ namespace App\Legacy\V1\Requests\Album; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\DeleteAlbumsRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbumIDs; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasAlbumIDsTrait; +use App\Legacy\V1\RuleSets\Album\DeleteAlbumsRuleSet; use App\Models\Album; use App\Policies\AlbumPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Album/DeleteTrackRequest.php b/app/Legacy/V1/Requests/Album/DeleteTrackRequest.php index ecb6c62edbb..fa86f172e44 100644 --- a/app/Legacy/V1/Requests/Album/DeleteTrackRequest.php +++ b/app/Legacy/V1/Requests/Album/DeleteTrackRequest.php @@ -3,11 +3,11 @@ namespace App\Legacy\V1\Requests\Album; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\BasicAlbumIdRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditAlbumTrait; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; +use App\Legacy\V1\RuleSets\Album\BasicAlbumIdRuleSet; use App\Models\Album; class DeleteTrackRequest extends BaseApiRequest implements HasAlbum diff --git a/app/Legacy/V1/Requests/Album/GetAlbumRequest.php b/app/Legacy/V1/Requests/Album/GetAlbumRequest.php index 85fb2705ed0..7020c32434e 100644 --- a/app/Legacy/V1/Requests/Album/GetAlbumRequest.php +++ b/app/Legacy/V1/Requests/Album/GetAlbumRequest.php @@ -5,10 +5,10 @@ use App\Contracts\Models\AbstractAlbum; use App\Exceptions\PasswordRequiredException; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\BasicAlbumIdRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAbstractAlbum; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasAbstractAlbumTrait; +use App\Legacy\V1\RuleSets\Album\BasicAlbumIdRuleSet; use App\Models\Extensions\BaseAlbum; use App\Policies\AlbumPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Album/MergeAlbumsRequest.php b/app/Legacy/V1/Requests/Album/MergeAlbumsRequest.php index 0382cd6d6a9..53f91113900 100644 --- a/app/Legacy/V1/Requests/Album/MergeAlbumsRequest.php +++ b/app/Legacy/V1/Requests/Album/MergeAlbumsRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Album; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\MergeAlbumsRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasAlbums; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditAlbumAlbumsTrait; use App\Legacy\V1\Requests\Traits\HasAlbumsTrait; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; +use App\Legacy\V1\RuleSets\Album\MergeAlbumsRuleSet; use App\Models\Album; /** diff --git a/app/Legacy/V1/Requests/Album/MoveAlbumsRequest.php b/app/Legacy/V1/Requests/Album/MoveAlbumsRequest.php index 5579fca981d..d3b9e3e7bad 100644 --- a/app/Legacy/V1/Requests/Album/MoveAlbumsRequest.php +++ b/app/Legacy/V1/Requests/Album/MoveAlbumsRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Album; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\MoveAlbumsRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasAlbums; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditAlbumAlbumsTrait; use App\Legacy\V1\Requests\Traits\HasAlbumsTrait; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; +use App\Legacy\V1\RuleSets\Album\MoveAlbumsRuleSet; use App\Models\Album; /** diff --git a/app/Legacy/V1/Requests/Album/SetAlbumCoverRequest.php b/app/Legacy/V1/Requests/Album/SetAlbumCoverRequest.php index b1c69132975..6630270fd11 100644 --- a/app/Legacy/V1/Requests/Album/SetAlbumCoverRequest.php +++ b/app/Legacy/V1/Requests/Album/SetAlbumCoverRequest.php @@ -4,12 +4,12 @@ use App\Contracts\Models\AbstractAlbum; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\SetAlbumCoverRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Album\SetAlbumCoverRuleSet; use App\Models\Album; use App\Models\Photo; use App\Policies\AlbumPolicy; diff --git a/app/Legacy/V1/Requests/Album/SetAlbumHeaderRequest.php b/app/Legacy/V1/Requests/Album/SetAlbumHeaderRequest.php index 458c6a9b136..f210b331231 100644 --- a/app/Legacy/V1/Requests/Album/SetAlbumHeaderRequest.php +++ b/app/Legacy/V1/Requests/Album/SetAlbumHeaderRequest.php @@ -4,12 +4,12 @@ use App\Contracts\Models\AbstractAlbum; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\SetAlbumHeaderRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Album\SetAlbumHeaderRuleSet; use App\Models\Album; use App\Models\Photo; use App\Policies\AlbumPolicy; diff --git a/app/Legacy/V1/Requests/Album/SetAlbumProtectionPolicyRequest.php b/app/Legacy/V1/Requests/Album/SetAlbumProtectionPolicyRequest.php index 762e6e285be..7f0bd1fd3ed 100644 --- a/app/Legacy/V1/Requests/Album/SetAlbumProtectionPolicyRequest.php +++ b/app/Legacy/V1/Requests/Album/SetAlbumProtectionPolicyRequest.php @@ -2,8 +2,8 @@ namespace App\Legacy\V1\Requests\Album; -use App\DTO\AlbumProtectionPolicy; use App\Http\Requests\BaseApiRequest; +use App\Http\Resources\Models\Utils\AlbumProtectionPolicy; use App\Legacy\V1\Contracts\Http\Requests\HasBaseAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasPassword; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; diff --git a/app/Legacy/V1/Requests/Album/SetAlbumTagsRequest.php b/app/Legacy/V1/Requests/Album/SetAlbumTagsRequest.php index e44acd3c027..f5692679a15 100644 --- a/app/Legacy/V1/Requests/Album/SetAlbumTagsRequest.php +++ b/app/Legacy/V1/Requests/Album/SetAlbumTagsRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Album; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\SetAlbumTagRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasTagAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasTags; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditAlbumTrait; use App\Legacy\V1\Requests\Traits\HasTagAlbumTrait; use App\Legacy\V1\Requests\Traits\HasTagsTrait; +use App\Legacy\V1\RuleSets\Album\SetAlbumTagRuleSet; use App\Models\TagAlbum; class SetAlbumTagsRequest extends BaseApiRequest implements HasTagAlbum, HasTags diff --git a/app/Legacy/V1/Requests/Album/SetAlbumsTitleRequest.php b/app/Legacy/V1/Requests/Album/SetAlbumsTitleRequest.php index c7a2f734659..4fba0b7470c 100644 --- a/app/Legacy/V1/Requests/Album/SetAlbumsTitleRequest.php +++ b/app/Legacy/V1/Requests/Album/SetAlbumsTitleRequest.php @@ -4,12 +4,12 @@ use App\Contracts\Models\AbstractAlbum; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\SetAlbumsTitleRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbums; use App\Legacy\V1\Contracts\Http\Requests\HasTitle; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasAlbumsTrait; use App\Legacy\V1\Requests\Traits\HasTitleTrait; +use App\Legacy\V1\RuleSets\Album\SetAlbumsTitleRuleSet; use App\Policies\AlbumPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Album/UnlockAlbumRequest.php b/app/Legacy/V1/Requests/Album/UnlockAlbumRequest.php index c0ae5a70b53..29846fdba1b 100644 --- a/app/Legacy/V1/Requests/Album/UnlockAlbumRequest.php +++ b/app/Legacy/V1/Requests/Album/UnlockAlbumRequest.php @@ -3,12 +3,12 @@ namespace App\Legacy\V1\Requests\Album; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Album\UnlockAlbumRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasBaseAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasPassword; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasBaseAlbumTrait; use App\Legacy\V1\Requests\Traits\HasPasswordTrait; +use App\Legacy\V1\RuleSets\Album\UnlockAlbumRuleSet; class UnlockAlbumRequest extends BaseApiRequest implements HasBaseAlbum, HasPassword { diff --git a/app/Legacy/V1/Requests/Import/ImportFromUrlRequest.php b/app/Legacy/V1/Requests/Import/ImportFromUrlRequest.php index ec299967932..cfdd0ef1425 100644 --- a/app/Legacy/V1/Requests/Import/ImportFromUrlRequest.php +++ b/app/Legacy/V1/Requests/Import/ImportFromUrlRequest.php @@ -3,11 +3,11 @@ namespace App\Legacy\V1\Requests\Import; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Import\ImportFromUrlRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditAlbumTrait; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; +use App\Legacy\V1\RuleSets\Import\ImportFromUrlRuleSet; use App\Models\Album; class ImportFromUrlRequest extends BaseApiRequest implements HasAlbum diff --git a/app/Legacy/V1/Requests/Import/ImportServerRequest.php b/app/Legacy/V1/Requests/Import/ImportServerRequest.php index b742445a62b..7f3cfe93579 100644 --- a/app/Legacy/V1/Requests/Import/ImportServerRequest.php +++ b/app/Legacy/V1/Requests/Import/ImportServerRequest.php @@ -5,10 +5,10 @@ use App\Contracts\Models\AbstractAlbum; use App\DTO\ImportMode; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Import\ImportServerRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; +use App\Legacy\V1\RuleSets\Import\ImportServerRuleSet; use App\Models\Album; use App\Models\Configs; use App\Policies\AlbumPolicy; diff --git a/app/Http/Requests/Legacy/TranslateIDRequest.php b/app/Legacy/V1/Requests/Legacy/TranslateIDRequest.php similarity index 96% rename from app/Http/Requests/Legacy/TranslateIDRequest.php rename to app/Legacy/V1/Requests/Legacy/TranslateIDRequest.php index 7823d800890..aedcb9f226c 100644 --- a/app/Http/Requests/Legacy/TranslateIDRequest.php +++ b/app/Legacy/V1/Requests/Legacy/TranslateIDRequest.php @@ -1,6 +1,6 @@ with([ - 'size_variants' => fn (HasMany $r) => $r->where('type', '=', $variant), + 'size_variants' => fn ($r) => $r->where('type', '=', $variant), ]); } // `findOrFail` returns the union `Photo|Collection` diff --git a/app/Legacy/V1/Requests/Photo/DeletePhotosRequest.php b/app/Legacy/V1/Requests/Photo/DeletePhotosRequest.php index aa456337649..fa86c4afeaa 100644 --- a/app/Legacy/V1/Requests/Photo/DeletePhotosRequest.php +++ b/app/Legacy/V1/Requests/Photo/DeletePhotosRequest.php @@ -3,10 +3,10 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\DeletePhotosRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPhotoIDs; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasPhotoIDsTrait; +use App\Legacy\V1\RuleSets\Photo\DeletePhotosRuleSet; use App\Models\Photo; use App\Policies\PhotoPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Photo/DuplicatePhotosRequest.php b/app/Legacy/V1/Requests/Photo/DuplicatePhotosRequest.php index 1f3cfd21414..b7fa565b0f3 100644 --- a/app/Legacy/V1/Requests/Photo/DuplicatePhotosRequest.php +++ b/app/Legacy/V1/Requests/Photo/DuplicatePhotosRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\DuplicatePhotosRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasPhotos; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotosAlbumTrait; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; use App\Legacy\V1\Requests\Traits\HasPhotosTrait; +use App\Legacy\V1\RuleSets\Photo\DuplicatePhotosRuleSet; use App\Models\Album; use App\Models\Photo; diff --git a/app/Legacy/V1/Requests/Photo/GetPhotoRequest.php b/app/Legacy/V1/Requests/Photo/GetPhotoRequest.php index 8f3b6810883..8777951ddb7 100644 --- a/app/Legacy/V1/Requests/Photo/GetPhotoRequest.php +++ b/app/Legacy/V1/Requests/Photo/GetPhotoRequest.php @@ -3,10 +3,10 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\GetPhotoRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Photo\GetPhotoRuleSet; use App\Models\Photo; use App\Policies\PhotoPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Photo/MovePhotosRequest.php b/app/Legacy/V1/Requests/Photo/MovePhotosRequest.php index 83c05dd5fa6..e76926235c9 100644 --- a/app/Legacy/V1/Requests/Photo/MovePhotosRequest.php +++ b/app/Legacy/V1/Requests/Photo/MovePhotosRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\MovePhotosRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasAlbum; use App\Legacy\V1\Contracts\Http\Requests\HasPhotos; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotosAlbumTrait; use App\Legacy\V1\Requests\Traits\HasAlbumTrait; use App\Legacy\V1\Requests\Traits\HasPhotosTrait; +use App\Legacy\V1\RuleSets\Photo\MovePhotosRuleSet; use App\Models\Album; use App\Models\Photo; diff --git a/app/Legacy/V1/Requests/Photo/RotatePhotoRequest.php b/app/Legacy/V1/Requests/Photo/RotatePhotoRequest.php index 5a435095022..6e30b8d245a 100644 --- a/app/Legacy/V1/Requests/Photo/RotatePhotoRequest.php +++ b/app/Legacy/V1/Requests/Photo/RotatePhotoRequest.php @@ -3,11 +3,11 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\RotatePhotoRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotoTrait; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Photo\RotatePhotoRuleSet; use App\Models\Photo; class RotatePhotoRequest extends BaseApiRequest implements HasPhoto diff --git a/app/Legacy/V1/Requests/Photo/SetPhotoDescriptionRequest.php b/app/Legacy/V1/Requests/Photo/SetPhotoDescriptionRequest.php index a7a4e3b6934..e81360b7af6 100644 --- a/app/Legacy/V1/Requests/Photo/SetPhotoDescriptionRequest.php +++ b/app/Legacy/V1/Requests/Photo/SetPhotoDescriptionRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\SetPhotoDescriptionRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasDescription; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotoTrait; use App\Legacy\V1\Requests\Traits\HasDescriptionTrait; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Photo\SetPhotoDescriptionRuleSet; use App\Models\Photo; class SetPhotoDescriptionRequest extends BaseApiRequest implements HasPhoto, HasDescription diff --git a/app/Legacy/V1/Requests/Photo/SetPhotoLicenseRequest.php b/app/Legacy/V1/Requests/Photo/SetPhotoLicenseRequest.php index 0fc74fe88f5..42245dad197 100644 --- a/app/Legacy/V1/Requests/Photo/SetPhotoLicenseRequest.php +++ b/app/Legacy/V1/Requests/Photo/SetPhotoLicenseRequest.php @@ -4,13 +4,13 @@ use App\Enum\LicenseType; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\SetPhotoLicenseRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasLicense; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotoTrait; use App\Legacy\V1\Requests\Traits\HasLicenseTrait; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Photo\SetPhotoLicenseRuleSet; use App\Models\Photo; class SetPhotoLicenseRequest extends BaseApiRequest implements HasPhoto, HasLicense diff --git a/app/Legacy/V1/Requests/Photo/SetPhotoUploadDateRequest.php b/app/Legacy/V1/Requests/Photo/SetPhotoUploadDateRequest.php index f57a634856c..fa6541c49e5 100644 --- a/app/Legacy/V1/Requests/Photo/SetPhotoUploadDateRequest.php +++ b/app/Legacy/V1/Requests/Photo/SetPhotoUploadDateRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\SetPhotoUploadDateRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasDate; use App\Legacy\V1\Contracts\Http\Requests\HasPhoto; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotoTrait; use App\Legacy\V1\Requests\Traits\HasDateTrait; use App\Legacy\V1\Requests\Traits\HasPhotoTrait; +use App\Legacy\V1\RuleSets\Photo\SetPhotoUploadDateRuleSet; use App\Models\Photo; use Illuminate\Support\Carbon; diff --git a/app/Legacy/V1/Requests/Photo/SetPhotosStarredRequest.php b/app/Legacy/V1/Requests/Photo/SetPhotosStarredRequest.php index 0d13e9d740f..0e057cd49b6 100644 --- a/app/Legacy/V1/Requests/Photo/SetPhotosStarredRequest.php +++ b/app/Legacy/V1/Requests/Photo/SetPhotosStarredRequest.php @@ -3,11 +3,11 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\SetPhotosStarredRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPhotos; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotosTrait; use App\Legacy\V1\Requests\Traits\HasPhotosTrait; +use App\Legacy\V1\RuleSets\Photo\SetPhotosStarredRuleSet; use App\Models\Photo; /** diff --git a/app/Legacy/V1/Requests/Photo/SetPhotosTagsRequest.php b/app/Legacy/V1/Requests/Photo/SetPhotosTagsRequest.php index 023a45baefd..55a69e17b03 100644 --- a/app/Legacy/V1/Requests/Photo/SetPhotosTagsRequest.php +++ b/app/Legacy/V1/Requests/Photo/SetPhotosTagsRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\SetPhotosTagsRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPhotos; use App\Legacy\V1\Contracts\Http\Requests\HasTags; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotosTrait; use App\Legacy\V1\Requests\Traits\HasPhotosTrait; use App\Legacy\V1\Requests\Traits\HasTagsTrait; +use App\Legacy\V1\RuleSets\Photo\SetPhotosTagsRuleSet; use App\Models\Photo; class SetPhotosTagsRequest extends BaseApiRequest implements HasPhotos, HasTags diff --git a/app/Legacy/V1/Requests/Photo/SetPhotosTitleRequest.php b/app/Legacy/V1/Requests/Photo/SetPhotosTitleRequest.php index 77459e2c02e..f331ee4413d 100644 --- a/app/Legacy/V1/Requests/Photo/SetPhotosTitleRequest.php +++ b/app/Legacy/V1/Requests/Photo/SetPhotosTitleRequest.php @@ -3,13 +3,13 @@ namespace App\Legacy\V1\Requests\Photo; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Photo\SetPhotosTitleRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPhotos; use App\Legacy\V1\Contracts\Http\Requests\HasTitle; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\Authorize\AuthorizeCanEditPhotosTrait; use App\Legacy\V1\Requests\Traits\HasPhotosTrait; use App\Legacy\V1\Requests\Traits\HasTitleTrait; +use App\Legacy\V1\RuleSets\Photo\SetPhotosTitleRuleSet; use App\Models\Photo; class SetPhotosTitleRequest extends BaseApiRequest implements HasPhotos, HasTitle diff --git a/app/Legacy/V1/Requests/User/ChangeLoginRequest.php b/app/Legacy/V1/Requests/User/ChangeLoginRequest.php index 41963775df3..ddfbc80ad23 100644 --- a/app/Legacy/V1/Requests/User/ChangeLoginRequest.php +++ b/app/Legacy/V1/Requests/User/ChangeLoginRequest.php @@ -3,10 +3,10 @@ namespace App\Legacy\V1\Requests\User; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\User\ChangeLoginRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPassword; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasPasswordTrait; +use App\Legacy\V1\RuleSets\User\ChangeLoginRuleSet; use App\Models\User; use App\Policies\UserPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/User/SetEmailRequest.php b/app/Legacy/V1/Requests/User/SetEmailRequest.php index 6fda4d957fd..27abba39fde 100644 --- a/app/Legacy/V1/Requests/User/SetEmailRequest.php +++ b/app/Legacy/V1/Requests/User/SetEmailRequest.php @@ -3,8 +3,8 @@ namespace App\Legacy\V1\Requests\User; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\User\SetEmailRuleSet; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; +use App\Legacy\V1\RuleSets\User\SetEmailRuleSet; use App\Models\User; use App\Policies\UserPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Users/AddUserRequest.php b/app/Legacy/V1/Requests/Users/AddUserRequest.php index 4ecc19654f0..c2e2f2f8b69 100644 --- a/app/Legacy/V1/Requests/Users/AddUserRequest.php +++ b/app/Legacy/V1/Requests/Users/AddUserRequest.php @@ -3,12 +3,12 @@ namespace App\Legacy\V1\Requests\Users; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Users\AddUserRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPassword; use App\Legacy\V1\Contracts\Http\Requests\HasUsername; use App\Legacy\V1\Contracts\Http\Requests\RequestAttribute; use App\Legacy\V1\Requests\Traits\HasPasswordTrait; use App\Legacy\V1\Requests\Traits\HasUsernameTrait; +use App\Legacy\V1\RuleSets\Users\AddUserRuleSet; use App\Models\User; use App\Policies\UserPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Requests/Users/SetUserSettingsRequest.php b/app/Legacy/V1/Requests/Users/SetUserSettingsRequest.php index 627ec8d2877..df1ea6c0842 100644 --- a/app/Legacy/V1/Requests/Users/SetUserSettingsRequest.php +++ b/app/Legacy/V1/Requests/Users/SetUserSettingsRequest.php @@ -3,7 +3,6 @@ namespace App\Legacy\V1\Requests\Users; use App\Http\Requests\BaseApiRequest; -use App\Http\RuleSets\Users\SetUserSettingsRuleSet; use App\Legacy\V1\Contracts\Http\Requests\HasPassword; use App\Legacy\V1\Contracts\Http\Requests\HasUser; use App\Legacy\V1\Contracts\Http\Requests\HasUsername; @@ -11,6 +10,7 @@ use App\Legacy\V1\Requests\Traits\HasPasswordTrait; use App\Legacy\V1\Requests\Traits\HasUsernameTrait; use App\Legacy\V1\Requests\Traits\HasUserTrait; +use App\Legacy\V1\RuleSets\Users\SetUserSettingsRuleSet; use App\Models\User; use App\Policies\UserPolicy; use Illuminate\Support\Facades\Gate; diff --git a/app/Legacy/V1/Resources/Collections/AlbumForestResource.php b/app/Legacy/V1/Resources/Collections/AlbumForestResource.php index 69273af4b21..ad6c7cf6d6a 100644 --- a/app/Legacy/V1/Resources/Collections/AlbumForestResource.php +++ b/app/Legacy/V1/Resources/Collections/AlbumForestResource.php @@ -19,7 +19,7 @@ class AlbumForestResource extends JsonResource */ public function __construct( public Collection $albums, - public ?Collection $sharedAlbums = null + public ?Collection $sharedAlbums = null, ) { // Laravel applies a shortcut when this value === null but not when it is something else. parent::__construct('must_not_be_null'); diff --git a/app/Legacy/V1/Resources/Collections/PositionDataResource.php b/app/Legacy/V1/Resources/Collections/PositionDataResource.php index 6ccb727a8d5..71649a77e18 100644 --- a/app/Legacy/V1/Resources/Collections/PositionDataResource.php +++ b/app/Legacy/V1/Resources/Collections/PositionDataResource.php @@ -25,7 +25,7 @@ public function __construct( ?string $id, ?string $title, Collection $photos, - ?string $track_url + ?string $track_url, ) { parent::__construct($photos); $this->id = $id; diff --git a/app/Legacy/V1/Resources/Collections/TopAlbumsResource.php b/app/Legacy/V1/Resources/Collections/TopAlbumsResource.php index 7c0313f3684..5b2683891bb 100644 --- a/app/Legacy/V1/Resources/Collections/TopAlbumsResource.php +++ b/app/Legacy/V1/Resources/Collections/TopAlbumsResource.php @@ -32,7 +32,7 @@ public function __construct( public Collection $smart_albums, public Collection $tag_albums, public Collection $albums, - public ?Collection $shared_albums = null + public ?Collection $shared_albums = null, ) { // Laravel applies a shortcut when this value === null but not when it is something else. parent::__construct('must_not_be_null'); diff --git a/app/Legacy/V1/Resources/Models/AlbumResource.php b/app/Legacy/V1/Resources/Models/AlbumResource.php index a0e480f4ccb..074436d299f 100644 --- a/app/Legacy/V1/Resources/Models/AlbumResource.php +++ b/app/Legacy/V1/Resources/Models/AlbumResource.php @@ -2,7 +2,7 @@ namespace App\Legacy\V1\Resources\Models; -use App\DTO\AlbumProtectionPolicy; +use App\Http\Resources\Models\Utils\AlbumProtectionPolicy; use App\Legacy\V1\Resources\Collections\AlbumCollectionResource; use App\Legacy\V1\Resources\Collections\PhotoCollectionResource; use App\Legacy\V1\Resources\Rights\AlbumRightsResource; diff --git a/app/Legacy/V1/Resources/Models/SmartAlbumResource.php b/app/Legacy/V1/Resources/Models/SmartAlbumResource.php index 6ae7aeb4f9c..428c519d3a5 100644 --- a/app/Legacy/V1/Resources/Models/SmartAlbumResource.php +++ b/app/Legacy/V1/Resources/Models/SmartAlbumResource.php @@ -2,7 +2,7 @@ namespace App\Legacy\V1\Resources\Models; -use App\DTO\AlbumProtectionPolicy; +use App\Http\Resources\Models\Utils\AlbumProtectionPolicy; use App\Legacy\V1\Resources\Collections\PhotoCollectionResource; use App\Legacy\V1\Resources\Rights\AlbumRightsResource; use App\SmartAlbums\BaseSmartAlbum; diff --git a/app/Legacy/V1/Resources/Models/TagAlbumResource.php b/app/Legacy/V1/Resources/Models/TagAlbumResource.php index cd6f9193f37..14d71d40fa2 100644 --- a/app/Legacy/V1/Resources/Models/TagAlbumResource.php +++ b/app/Legacy/V1/Resources/Models/TagAlbumResource.php @@ -2,7 +2,7 @@ namespace App\Legacy\V1\Resources\Models; -use App\DTO\AlbumProtectionPolicy; +use App\Http\Resources\Models\Utils\AlbumProtectionPolicy; use App\Legacy\V1\Resources\Collections\PhotoCollectionResource; use App\Legacy\V1\Resources\Rights\AlbumRightsResource; use App\Legacy\V1\Resources\Traits\WithStatus; diff --git a/app/Legacy/V1/Resources/Sharing/ListedAlbumsResource.php b/app/Legacy/V1/Resources/Sharing/ListedAlbumsResource.php deleted file mode 100644 index 40c0d9cdbc1..00000000000 --- a/app/Legacy/V1/Resources/Sharing/ListedAlbumsResource.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function toArray($request): array - { - return [ - 'id' => $this->resource->id, - 'title' => $this->resource->title, - ]; - } -} diff --git a/app/Legacy/V1/Resources/Sharing/SharedAlbumResource.php b/app/Legacy/V1/Resources/Sharing/SharedAlbumResource.php deleted file mode 100644 index bd6982253bc..00000000000 --- a/app/Legacy/V1/Resources/Sharing/SharedAlbumResource.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ - public function toArray($request): array - { - return [ - 'id' => $this->resource->id, - 'user_id' => $this->resource->user_id, - 'album_id' => $this->resource->album_id, - 'username' => $this->resource->username, - 'title' => $this->resource->title, - ]; - } -} diff --git a/app/Legacy/V1/Resources/Sharing/SharesResource.php b/app/Legacy/V1/Resources/Sharing/SharesResource.php deleted file mode 100644 index e7570c2cef1..00000000000 --- a/app/Legacy/V1/Resources/Sharing/SharesResource.php +++ /dev/null @@ -1,44 +0,0 @@ - $shared - * @param Collection $albums - * @param Collection $users - * - * @return void - */ - public function __construct( - public Collection $shared, - public Collection $albums, - public Collection $users) - { - // Laravel applies a shortcut when this value === null but not when it is something else. - parent::__construct('must_not_be_null'); - } - - /** - * Transform the resource into an array. - * - * @param \Illuminate\Http\Request $request - * - * @return array - */ - public function toArray($request): array - { - return [ - 'shared' => SharedAlbumResource::collection($this->shared), - 'albums' => ListedAlbumsResource::collection($this->albums), - 'users' => UserSharedResource::collection($this->users), - ]; - } -} diff --git a/app/Legacy/V1/Resources/Sharing/UserSharedResource.php b/app/Legacy/V1/Resources/Sharing/UserSharedResource.php deleted file mode 100644 index 76a46579159..00000000000 --- a/app/Legacy/V1/Resources/Sharing/UserSharedResource.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function toArray($request): array - { - return [ - 'id' => $this->resource->id, - 'username' => $this->resource->username, - ]; - } -} diff --git a/app/Http/RuleSets/AddAlbumRuleSet.php b/app/Legacy/V1/RuleSets/AddAlbumRuleSet.php similarity index 92% rename from app/Http/RuleSets/AddAlbumRuleSet.php rename to app/Legacy/V1/RuleSets/AddAlbumRuleSet.php index 1847098604d..1c3aa98cec8 100644 --- a/app/Http/RuleSets/AddAlbumRuleSet.php +++ b/app/Legacy/V1/RuleSets/AddAlbumRuleSet.php @@ -1,6 +1,6 @@ defines the arguments to be passed to the - * Livewire component loaded inside the ContextMenu - */ - #[Locked] - public array $params = []; - - /** - * Open the Context Menu. - * - * @param string $type defines the Component loaded inside the modal - * @param array $params Arguments to pass to the modal - * - * @return void - */ - #[On('openContextMenu')] - public function openContextMenu(string $type, array $params = [], string $style = 'left: 30px; top: 30px;'): void - { - $this->type = $type; - $this->params = $params; - $this->style = $style; - $this->open(); - } - - /** - * Close the ContextMenu component. - * - * @return void - */ - #[On('closeContextMenu')] - public function closeContextMenu(): void - { - $this->close(); - } - - /** - * Rendering of the Component. - * - * @return View - */ - public function render(): View - { - return view('livewire.components.context-menu'); - } -} diff --git a/app/Livewire/Components/Base/Modal.php b/app/Livewire/Components/Base/Modal.php deleted file mode 100644 index ab00e93d814..00000000000 --- a/app/Livewire/Components/Base/Modal.php +++ /dev/null @@ -1,88 +0,0 @@ - no close button - * any other string correspond to the LANG text. - * - * @var string - */ - public string $close_text = ''; - - /** - * @var array defines the arguments to be passed to the - * Livewire component loaded inside the Modal - */ - public array $params = []; - - /** - * Css properties for the modal. - * - * @var string - */ - public string $modalSize = 'md:max-w-xl'; - - /** - * Open a Modal. - * - * @param string $type defines the Component loaded inside the modal - * @param string $close_text text to put if we use a close button - * @param array $params Arguments to pass to the modal - * - * @return void - */ - #[On('openModal')] - public function openModal(string $type, string $close_text = '', array $params = []): void - { - $this->open(); - $this->type = $type; - $this->close_text = $close_text; - $this->params = $params; - } - - /** - * Close the Modal component. - * - * @return void - */ - #[On('closeModal')] - public function closeModal(): void - { - $this->close(); - } - - /** - * Rendering of the Component. - * - * @return View - */ - public function render(): View - { - return view('livewire.components.modal'); - } -} diff --git a/app/Livewire/Components/Forms/Add/ImportFromDropbox.php b/app/Livewire/Components/Forms/Add/ImportFromDropbox.php deleted file mode 100644 index fb6422423bf..00000000000 --- a/app/Livewire/Components/Forms/Add/ImportFromDropbox.php +++ /dev/null @@ -1,44 +0,0 @@ - null]): void - { - Gate::authorize(AlbumPolicy::CAN_IMPORT_FROM_SERVER, AbstractAlbum::class); - } - - /** - * Call the parametrized rendering. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.add.import-from-server'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Add/ImportFromUrl.php b/app/Livewire/Components/Forms/Add/ImportFromUrl.php deleted file mode 100644 index 6f92b9ea282..00000000000 --- a/app/Livewire/Components/Forms/Add/ImportFromUrl.php +++ /dev/null @@ -1,113 +0,0 @@ -fromUrl = resolve(FromUrl::class); - } - - public ImportFromUrlForm $form; - - /** - * We load the parameters. - * - * @param array{parentID:?string} $params set of parameters of the form - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $albumId = $params[Params::PARENT_ID] ?? null; - - // remove smart albums => if we are in one: upload to unsorted (i.e. albumId = null) - if (SmartAlbumType::tryFrom($albumId) !== null) { - $albumId = null; - } - - /** @var Album $album */ - $album = $albumId === null ? null : Album::query()->findOrFail($albumId); - - Gate::authorize(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, $album]); - - $this->form->init($albumId); - } - - /** - * Call the parametrized rendering. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.add.import-from-url'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } - - /** - * A form has a Submit method. - * - * @return void - */ - public function submit(): void - { - // Reset error bag - $this->resetErrorBag(); - - $this->form->prepare(); - $this->form->validate(); - - Gate::authorize(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, $this->form->getAlbum()]); - - /** @var int $userId */ - $userId = Auth::id(); - - try { - $this->fromUrl->do($this->form->urls, $this->form->getAlbum(), $userId); - $this->notify(__('lychee.UPLOAD_IMPORT_COMPLETE')); - } catch (MassImportException $e) { - $this->notify($e->getMessage()); - } - // Do we want refresh or direcly open newly created Album ? - $this->dispatch('reloadPage')->to(PageGalleryAlbum::class); - $this->close(); - } -} diff --git a/app/Livewire/Components/Forms/Add/Upload.php b/app/Livewire/Components/Forms/Add/Upload.php deleted file mode 100644 index eeefd7107d7..00000000000 --- a/app/Livewire/Components/Forms/Add/Upload.php +++ /dev/null @@ -1,177 +0,0 @@ - */ - public array $uploads = []; - - public int $chunkSize; - public int $parallelism; - - /** - * Mount the component. - * - * @param array{parentID:?string} $params - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $this->albumId = $params[Params::PARENT_ID] ?? null; - - // remove smart albums => if we are in one: upload to unsorted (i.e. albumId = null) - if (SmartAlbumType::tryFrom($this->albumId) !== null) { - $this->albumId = null; - } - - $album = $this->albumId === null ? null : Album::findOrFail($this->albumId); - Gate::authorize(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, $album]); - - $this->chunkSize = self::getUploadLimit(); - $this->parallelism = Configs::getValueAsInt('upload_processing_limit'); - } - - public function render(): View - { - return view('livewire.forms.add.upload'); - } - - /** - * @param TemporaryUploadedFile $value - * @param string $key - * - * @return void - */ - public function updatedUploads($value, string $key): void - { - $keys = explode('.', $key); - $index = intval($keys[0]); - $attribute = $keys[1] ?? null; - - $fileDetails = $this->uploads[$index]; - // Initialize data if not existing. - $fileDetails['extension'] ??= '.' . pathinfo($fileDetails['fileName'], PATHINFO_EXTENSION); - $fileDetails['uuidName'] ??= strtr(base64_encode(random_bytes(12)), '+/', '-_') . $fileDetails['extension']; - - // Ensure data are set - $this->uploads[$index]['extension'] = $fileDetails['extension']; - $this->uploads[$index]['uuidName'] = $fileDetails['uuidName']; - $this->uploads[$index]['stage'] = $fileDetails['stage'] ?? FileStatus::UPLOADING->value; - $this->uploads[$index]['progress'] = $fileDetails['progress'] ?? 0; - - if ($attribute === 'fileChunk') { - $fileDetails = $this->uploads[$index]; - /** @var TemporaryUploadedFile $chunkFile */ - $chunkFile = $fileDetails['fileChunk']; - $final = new NativeLocalFile(Storage::disk(self::DISK_NAME)->path($fileDetails['uuidName'])); - $final->append($chunkFile->readStream()); - $chunkFile->delete(); - - $curSize = $final->getFilesize(); - - $this->uploads[$index]['progress'] = intval($curSize / $fileDetails['fileSize'] * 100); - if ($this->uploads[$index]['progress'] === 100) { - $this->uploads[$index]['stage'] = FileStatus::READY->value; - } - } - - $this->triggerProcessing(); - } - - public function triggerProcessing(): void - { - foreach ($this->uploads as $idx => $fileData) { - if ($fileData['stage'] === FileStatus::READY->value) { - $uploadedFile = new NativeLocalFile(Storage::disk(self::DISK_NAME)->path($fileData['uuidName'])); - $processableFile = new ProcessableJobFile( - $fileData['extension'], - $fileData['fileName'] - ); - $processableFile->write($uploadedFile->read()); - $uploadedFile->close(); - $uploadedFile->delete(); - $processableFile->close(); - // End of work-around - - try { - $this->uploads[$idx]['stage'] = FileStatus::PROCESSING->value; - - if (Configs::getValueAsBool('use_job_queues')) { - ProcessImageJob::dispatch($processableFile, $this->albumId, $fileData['lastModified']); - } else { - ProcessImageJob::dispatchSync($processableFile, $this->albumId, $fileData['lastModified']); - } - $this->uploads[$idx]['stage'] = FileStatus::DONE->value; - } catch (PhotoSkippedException $e) { - $this->uploads[$idx]['stage'] = FileStatus::SKIPPED->value; - } - } - } - } - - public static function getUploadLimit(): int - { - $size = Configs::getValueAsInt('upload_chunk_size'); - if ($size === 0) { - $size = (int) min( - Helpers::convertSize(ini_get('upload_max_filesize')), - Helpers::convertSize(ini_get('post_max_size')), - Helpers::convertSize(ini_get('memory_limit')) / 10 - ); - } - - /** @var string[] $rules */ - $rules = FileUploadConfiguration::rules(); - $sizeRule = collect($rules)->first(fn ($rule) => Str::startsWith($rule, 'max:'), 'max:12288'); - $LivewireSizeLimit = intval(Str::substr($sizeRule, 4)) * 1024; - - return min($size, $LivewireSizeLimit); - } - - /** - * Close the modal containing the Upload panel. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/AddTrack.php b/app/Livewire/Components/Forms/Album/AddTrack.php deleted file mode 100644 index 80e062e7da3..00000000000 --- a/app/Livewire/Components/Forms/Album/AddTrack.php +++ /dev/null @@ -1,105 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - } - - /** - * @return array> - */ - public function rules(): array - { - return [ - RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new AlbumIDRule(false)], - 'file' => 'required|file', - ]; - } - - /** - * Mount the component. - * - * @param array{parentID:?string} $params - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $this->albumID = $params[Params::PARENT_ID] ?? null; - - if ($this->albumID === null) { - throw new LycheeLogicException('parentID is null'); - } - - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumID, false); - if (!$album instanceof Album) { - throw new LycheeDomainException('This functionality is not available for tag albums.'); - } - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - } - - public function render(): View - { - return view('livewire.forms.album.add-track'); - } - - public function submit(): void - { - $this->validate(); - /** @var Album $album */ - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumID, false); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - $album->setTrack($this->file); - $this->notify(__('lychee.SUCCESS')); - $this->closeModal(); - } - - /** - * Close the modal containing the Upload panel. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/Create.php b/app/Livewire/Components/Forms/Album/Create.php deleted file mode 100644 index f7e7785a51c..00000000000 --- a/app/Livewire/Components/Forms/Album/Create.php +++ /dev/null @@ -1,102 +0,0 @@ -> - */ - protected function rules(): array - { - return AddAlbumRuleSet::rules(); - } - - /** - * Mount the component. - * - * @param array{parentID:string|null} $params - * - * @return void - */ - public function mount(array $params = [Params::PARENT_ID => null]): void - { - $this->parent_id = $params[Params::PARENT_ID]; - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, [$this->parent_id]]); - } - - /** - * Call the parametrized rendering. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.add.create'); - } - - /** - * A form has a Submit method. - * - * @return void - */ - public function submit(): void - { - // Reset error bag - $this->resetErrorBag(); - - // Validate - $this->validate(); - - /** @var Album|null $parentAlbum */ - $parentAlbum = $this->parent_id === null ? null : Album::query()->findOrFail($this->parent_id); - - // Authorize - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $parentAlbum]); - - /** @var int $ownerId */ - $ownerId = Auth::id() ?? throw new UnauthenticatedException(); - $create = new AlbumCreate($ownerId); - $new_album = $create->create($this->title, $parentAlbum); - - $this->redirect(route('livewire-gallery-album', ['albumId' => $new_album->id]), false); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/CreateTag.php b/app/Livewire/Components/Forms/Album/CreateTag.php deleted file mode 100644 index 8a52a34e4b1..00000000000 --- a/app/Livewire/Components/Forms/Album/CreateTag.php +++ /dev/null @@ -1,104 +0,0 @@ -create = resolve(CreateTagAlbum::class); - } - - /** - * This defines the set of validation rules to be applied on the input. - * It would be a good idea to unify (namely reuse) the rules from the JSON api. - * - * @return array> - */ - protected function rules(): array - { - return AddTagAlbumRuleSet::rules(); - } - - /** - * Mount the component. - * - * @param array $params - * - * @return void - */ - public function mount(array $params = []): void - { - Gate::authorize(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, null]); - } - - /** - * Call the parametrized rendering. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.add.create-tag'); - } - - /** - * A form has a Submit method. - * - * @return void - */ - public function submit(): void - { - // Reset error bag - $this->resetErrorBag(); - - $this->tags = explode(',', $this->tag); - - // Validate - $this->validate(); - - // Authorize - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, null]); - - // Create - $new_album = $this->create->create($this->title, $this->tags); - - // Do we want refresh or direcly open newly created Album ? - $this->close(); - $this->redirect(route('livewire-gallery-album', ['albumId' => $new_album->id]), true); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/Delete.php b/app/Livewire/Components/Forms/Album/Delete.php deleted file mode 100644 index 174791d71c0..00000000000 --- a/app/Livewire/Components/Forms/Album/Delete.php +++ /dev/null @@ -1,101 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - $this->deleteAction = resolve(DeleteAction::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param array{albumID?:string,albumIDs?:string[],parentID:?string} $params to delete - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $id = $params[Params::ALBUM_ID] ?? null; - $this->albumIDs = $id !== null ? [$id] : $params[Params::ALBUM_IDS] ?? []; - $this->num = count($this->albumIDs); - - if ($this->num === 1) { - $this->title = $this->albumFactory->findBaseAlbumOrFail($this->albumIDs[0])->title; - } - - Gate::authorize(AlbumPolicy::CAN_DELETE_ID, [AbstractAlbum::class, $this->albumIDs]); - $this->parent_id = $params[Params::PARENT_ID] ?? SmartAlbumType::UNSORTED->value; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.delete'); - } - - /** - * Execute deletion. - * - * @return void - */ - public function delete(): void - { - $this->validate(DeleteAlbumsRuleSet::rules()); - - Gate::authorize(AlbumPolicy::CAN_DELETE_ID, [AbstractAlbum::class, $this->albumIDs]); - - $fileDeleter = $this->deleteAction->do($this->albumIDs); - App::terminating(fn () => $fileDeleter->do()); - - if ($this->parent_id === SmartAlbumType::UNSORTED->value) { - $this->redirect(route('livewire-gallery'), true); - } else { - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->parent_id]), true); - } - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/DeletePanel.php b/app/Livewire/Components/Forms/Album/DeletePanel.php deleted file mode 100644 index 67e808a5322..00000000000 --- a/app/Livewire/Components/Forms/Album/DeletePanel.php +++ /dev/null @@ -1,89 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - $this->deleteAction = resolve(DeleteAction::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param BaseAlbum $album to update the attributes of - * - * @return void - */ - public function mount(BaseAlbum $album): void - { - Gate::authorize(AlbumPolicy::CAN_DELETE, [AbstractAlbum::class, $album]); - - $this->albumIDs = [$album->id]; - $this->title = $album->title; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.delete-panel'); - } - - /** - * Execute deletion. - * - * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse - */ - public function delete(): \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse - { - $this->validate(DeleteAlbumsRuleSet::rules()); - - $baseAlbum = $this->albumFactory->findBaseAlbumOrFail($this->albumIDs[0], false); - - Gate::authorize(AlbumPolicy::CAN_DELETE, $baseAlbum); - - $parent_id = ($baseAlbum instanceof Album) ? $baseAlbum->parent_id : null; - - $fileDeleter = $this->deleteAction->do([$baseAlbum->id]); - App::terminating(fn () => $fileDeleter->do()); - - if ($parent_id !== null) { - return redirect()->to(route('livewire-gallery-album', ['albumId' => $parent_id])); - } - - return redirect()->to(route('livewire-gallery')); - } -} diff --git a/app/Livewire/Components/Forms/Album/DeleteTrack.php b/app/Livewire/Components/Forms/Album/DeleteTrack.php deleted file mode 100644 index 2328c688c06..00000000000 --- a/app/Livewire/Components/Forms/Album/DeleteTrack.php +++ /dev/null @@ -1,88 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - } - - /** - * Mount the component. - * - * @param array{parentID:?string} $params - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $this->albumID = $params[Params::PARENT_ID] ?? null; - - if ($this->albumID === null) { - throw new LycheeLogicException('parentID is null'); - } - - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumID, false); - if (!$album instanceof Album) { - throw new LycheeDomainException('This functionality is not available for tag albums.'); - } - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - } - - public function render(): View - { - return view('livewire.forms.album.delete-track'); - } - - public function submit(): void - { - /** @var Album $album */ - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumID, false); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - $album->deleteTrack(); - $this->notify(__('lychee.SUCCESS')); - $this->closeModal(); - } - - /** - * Close the modal containing the Upload panel. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/Merge.php b/app/Livewire/Components/Forms/Album/Merge.php deleted file mode 100644 index 02244f4c4fb..00000000000 --- a/app/Livewire/Components/Forms/Album/Merge.php +++ /dev/null @@ -1,134 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - $this->mergeAlbums = resolve(AlbumMerge::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param array{albumID?:string,albumIDs?:string[],parentID:?string} $params to move - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $id = $params[Params::ALBUM_ID] ?? null; - $this->albumIDs = $id !== null ? [$id] : $params[Params::ALBUM_IDS] ?? []; - $this->num = count($this->albumIDs); - - if ($this->num === 1) { - /** @var Album $album */ - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumIDs[0], false); - $this->lft = $album->_lft; - $this->rgt = $album->_rgt; - } elseif ($this->num > 1) { - $this->albumID = array_shift($this->albumIDs); - $this->title = $this->albumFactory->findBaseAlbumOrFail($this->albumID, false)->title; - } - - if (count($this->albumIDs) === 1) { - $this->titleMoved = $this->albumFactory->findBaseAlbumOrFail($this->albumIDs[0], false)->title; - } - - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - $this->parent_id = $params[Params::PARENT_ID] ?? null; - } - - /** - * Prepare confirmation step. - * - * @param string $id - * @param string $title - * - * @return void - */ - public function setAlbum(string $id, string $title): void - { - $this->albumID = $id; - $this->title = $title; - } - - public function submit(): void - { - $this->albumID = $this->albumID === '' ? null : $this->albumID; - - $this->validate(MergeAlbumsRuleSet::rules()); - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - - /** @var ?Album $album */ - $album = $this->albumID === null ? null : Album::query()->findOrFail($this->albumID); - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - - // `findOrFail` returns a union type, but we know that it returns the - // correct collection in this case - /** @var Collection $albums */ - $albums = Album::query()->findOrFail($this->albumIDs); - - $this->mergeAlbums->do($album, $albums); - - if ($this->parent_id !== null) { - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->parent_id]), true); - } else { - $this->redirect(route('livewire-gallery'), true); - } - $this->close(); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.merge'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/Move.php b/app/Livewire/Components/Forms/Album/Move.php deleted file mode 100644 index 5d2a1b25226..00000000000 --- a/app/Livewire/Components/Forms/Album/Move.php +++ /dev/null @@ -1,127 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - $this->moveAlbums = resolve(AlbumMove::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param array{albumID?:string,albumIDs?:string[],parentID:?string} $params to move - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $id = $params[Params::ALBUM_ID] ?? null; - $this->albumIDs = $id !== null ? [$id] : $params[Params::ALBUM_IDS] ?? []; - $this->num = count($this->albumIDs); - - if ($this->num === 1) { - /** @var Album $album */ - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumIDs[0], false); - $this->titleMoved = $album->title; - $this->lft = $album->_lft; - $this->rgt = $album->_rgt; - } - - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - $this->parent_id = $params[Params::PARENT_ID] ?? null; - } - - /** - * Prepare confirmation step. - * - * @param string $id - * @param string $title - * - * @return void - */ - public function setAlbum(string $id, string $title): void - { - $this->albumID = $id; - $this->title = $title; - } - - public function submit(): void - { - $this->albumID = $this->albumID === '' ? null : $this->albumID; - - $this->validate(MoveAlbumsRuleSet::rules()); - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - - /** @var ?Album $album */ - $album = $this->albumID === null ? null : Album::query()->findOrFail($this->albumID); - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - - // `findOrFail` returns a union type, but we know that it returns the - // correct collection in this case - /** @var Collection $albums */ - $albums = Album::query()->findOrFail($this->albumIDs); - $this->moveAlbums->do($album, $albums); - - if ($this->parent_id !== null) { - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->parent_id]), true); - } else { - $this->redirect(route('livewire-gallery'), true); - } - $this->close(); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.move'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/MovePanel.php b/app/Livewire/Components/Forms/Album/MovePanel.php deleted file mode 100644 index 146d2f7ad22..00000000000 --- a/app/Livewire/Components/Forms/Album/MovePanel.php +++ /dev/null @@ -1,111 +0,0 @@ -moveAlbums = resolve(AlbumMove::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param Album $album to update the attributes of - * - * @return void - */ - public function mount(Album $album): void - { - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - - $this->albumIDs = [$album->id]; - $this->titleMoved = $album->title; - $this->lft = $album->_lft; - $this->rgt = $album->_rgt; - $this->parent_id = $album->parent_id; - } - - /** - * Prepare confirmation step. - * - * @param string $id - * @param string $title - * - * @return void - */ - public function setAlbum(string $id, string $title) - { - $this->albumID = $id; - $this->title = $title; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.move-panel'); - } - - /** - * Execute transfer of ownership. - */ - public function move(): void - { - $this->areValid(MoveAlbumsRuleSet::rules()); - - // set default for root. - $this->albumID = $this->albumID === '' ? null : $this->albumID; - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - - /** @var ?Album $album */ - $album = $this->albumID === null ? null : Album::query()->findOrFail($this->albumID); - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - - // `findOrFail` returns a union type, but we know that it returns the - // correct collection in this case - /** @var Collection $albums */ - $albums = Album::query()->findOrFail($this->albumIDs); - $this->moveAlbums->do($album, $albums); - - if ($this->parent_id !== null) { - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->parent_id]), true); - } else { - $this->redirect(route('livewire-gallery'), true); - } - } -} diff --git a/app/Livewire/Components/Forms/Album/Properties.php b/app/Livewire/Components/Forms/Album/Properties.php deleted file mode 100644 index 9adfaf09d38..00000000000 --- a/app/Livewire/Components/Forms/Album/Properties.php +++ /dev/null @@ -1,207 +0,0 @@ -is_model_album = $album instanceof ModelsAlbum; - $this->is_tag_album = $album instanceof TagAlbum; - - $this->albumID = $album->id; - $this->title = $album->title; - $this->description = $album->description ?? ''; - $this->photo_sorting_column = $album->photo_sorting?->column->value ?? ''; - $this->photo_sorting_order = $album->photo_sorting?->order->value ?? ''; - $this->copyright = $album->copyright ?? ''; - if ($this->is_model_album) { - /** @var ModelsAlbum $album */ - $this->license = $album->license->value; - $this->album_sorting_column = $album->album_sorting?->column->value ?? ''; - $this->album_sorting_order = $album->album_sorting?->order->value ?? ''; - $this->album_aspect_ratio = $album->album_thumb_aspect_ratio?->value ?? ''; - } - if ($this->is_tag_album) { - /** @var TagAlbum $album */ - $this->tag = implode(', ', $album->show_tags); - } - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.properties'); - } - - /** - * Update Username & Password of current user. - */ - public function submit(AlbumFactory $albumFactory): void - { - $rules = [ - RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], - RequestAttribute::LICENSE_ATTRIBUTE => ['required', new Enum(LicenseType::class)], - ...SetAlbumDescriptionRuleSet::rules(), - ...SetPhotoSortingRuleSet::rules(), - ...SetAlbumSortingRuleSet::rules(), - RequestAttribute::ALBUM_ASPECT_RATIO_ATTRIBUTE => ['present', 'nullable', new Enum(AspectRatioType::class)], - RequestAttribute::COPYRIGHT_ATTRIBUTE => ['present', 'nullable', new CopyrightRule()], - ]; - - if (!$this->areValid($rules)) { - return; - } - - $baseAlbum = $albumFactory->findBaseAlbumOrFail($this->albumID, false); - Gate::authorize(AlbumPolicy::CAN_EDIT, $baseAlbum); - - $baseAlbum->title = $this->title; - $baseAlbum->description = $this->description; - - $this->copyright = trim($this->copyright); - - // Not super pretty but whatever. - $column = ColumnSortingPhotoType::tryFrom($this->photo_sorting_column); - $order = OrderSortingType::tryFrom($this->photo_sorting_order); - $photoSortingCriterion = $column === null ? null : new PhotoSortingCriterion($column->toColumnSortingType(), $order); - $baseAlbum->photo_sorting = $photoSortingCriterion; - - // If left empty, we set to null - $baseAlbum->copyright = $this->copyright === '' ? null : $this->copyright; - - if ($this->is_model_album) { - /** @var ModelsAlbum $baseAlbum */ - $baseAlbum->license = LicenseType::from($this->license); - - $column = ColumnSortingAlbumType::tryFrom($this->album_sorting_column); - $order = OrderSortingType::tryFrom($this->album_sorting_order); - $albumSortingCriterion = $column === null ? null : new AlbumSortingCriterion($column->toColumnSortingType(), $order); - $baseAlbum->album_sorting = $albumSortingCriterion; - $baseAlbum->album_thumb_aspect_ratio = AspectRatioType::tryFrom($this->album_aspect_ratio); - } - if ($this->is_tag_album) { - /** @var TagAlbum $baseAlbum */ - $baseAlbum->show_tags = collect(explode(',', $this->tag))->map(fn ($v) => trim($v))->filter(fn ($v) => $v !== '')->all(); - } - - $this->notify(__('lychee.CHANGE_SUCCESS')); - $baseAlbum->save(); - } - - /** - * Return computed property so that it does not stay in memory. - * - * @return array column sorting - */ - final public function getPhotoSortingColumnsProperty(): array - { - // ? Dark magic: The ... will expand the array. - return ['' => '-', ...ColumnSortingPhotoType::localized()]; - } - - /** - * Return computed property so that it does not stay in memory. - * - * @return array column sorting - */ - final public function getAlbumSortingColumnsProperty(): array - { - // ? Dark magic: The ... will expand the array. - return ['' => '-', ...ColumnSortingAlbumType::localized()]; - } - - /** - * Return computed property so that it does not stay in memory. - * - * @return array order - */ - final public function getSortingOrdersProperty(): array - { - // ? Dark magic: The ... will expand the array. - return ['' => '-', ...OrderSortingType::localized()]; - } - - /** - * Return computed property so that it does not stay in memory. - * - * @return array order - */ - final public function getAspectRatiosProperty(): array - { - // ? Dark magic: The ... will expand the array. - return ['' => '-', ...AspectRatioType::localized()]; - } - - /** - * Return the list of license localized. - * - * @return array - * - * @throws BindingResolutionException - */ - final public function getLicensesProperty(): array - { - return LicenseType::localized(); - } -} diff --git a/app/Livewire/Components/Forms/Album/Rename.php b/app/Livewire/Components/Forms/Album/Rename.php deleted file mode 100644 index 6da62cc299e..00000000000 --- a/app/Livewire/Components/Forms/Album/Rename.php +++ /dev/null @@ -1,93 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param array{albumID?:string,albumIDs?:string[],parentID:?string} $params to move - * - * @return void - */ - public function mount(array $params = ['parentID' => null]): void - { - $id = $params[Params::ALBUM_ID] ?? null; - $this->albumIDs = $id !== null ? [$id] : $params[Params::ALBUM_IDS] ?? []; - $this->num = count($this->albumIDs); - - if ($this->num === 1) { - $this->title = $this->albumFactory->findBaseAlbumOrFail($this->albumIDs[0], false)->title; - } - - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - $this->parent_id = $params[Params::PARENT_ID] ?? SmartAlbumType::UNSORTED->value; - } - - /** - * Rename. - * - * @return void - */ - public function submit(): void - { - $this->validate(SetAlbumsTitleRuleSet::rules()); - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->albumIDs]); - BaseAlbumImpl::query()->whereIn('id', $this->albumIDs)->update(['title' => $this->title]); - - $this->close(); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.rename'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Album/SetHeader.php b/app/Livewire/Components/Forms/Album/SetHeader.php deleted file mode 100644 index 563c554deb8..00000000000 --- a/app/Livewire/Components/Forms/Album/SetHeader.php +++ /dev/null @@ -1,99 +0,0 @@ - */ - #[Locked] public array $photoListSaved; - public ?string $header_id; - public ?string $title; - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param string $album_id to update the attributes of - * - * @return void - */ - public function mount(string $album_id): void - { - /** @var Album $album */ - $album = Album::with(['header'])->findOrFail($album_id); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - - $this->albumID = $album_id; - - $this->photoListSaved = Photo::with('size_variants')->where('album_id', '=', $album_id)->get()->map(fn (Photo $photo) => [ - 'id' => $photo->id, - 'title' => $photo->title, - 'thumb' => $photo->size_variants->getThumb()?->url ?? URL::asset('img/no_images.svg'), - ])->all(); - - $this->header_id = $album->header_id; - $this->title = $album->header?->title; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.set-header'); - } - - /** - * Give the tree of albums owned by the user. - * - * @return array - */ - public function getPhotoListProperty(): array - { - $filtered = collect($this->photoListSaved); - if ($this->search !== null && trim($this->search) !== '') { - return $filtered->filter(function (array $photo) { - return Str::contains($photo['title'], ltrim($this->search), true); - })->all(); - } - - return $filtered->all(); - } - - public function select(?string $photoId, ?string $title): void - { - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, [$this->albumID]]); - - Album::where('id', '=', $this->albumID)->update(['header_id' => $photoId]); - $this->header_id = $photoId; - $this->title = $title; - } - - public function clearHeaderId(): void - { - $this->select(null, null); - } -} diff --git a/app/Livewire/Components/Forms/Album/ShareWith.php b/app/Livewire/Components/Forms/Album/ShareWith.php deleted file mode 100644 index 0465c20f522..00000000000 --- a/app/Livewire/Components/Forms/Album/ShareWith.php +++ /dev/null @@ -1,159 +0,0 @@ -album = $album; - Gate::authorize(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $this->album]); - $this->resetData(); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.share-with'); - } - - /** - * Return the list of users to share with. - * This is basically: - * - Not the current user. - * - Not the owner of the album (just to be sure) - * - Not the admins (they already have all access) - * - Not users which have already been shared. - * - * @return TUser[] - * - * @throws UnauthorizedException - * @throws QueryBuilderException - */ - public function getUserListProperty(): array - { - $alreadySelected = collect($this->perms) - ->map(fn (AccessPermission $perm) => $perm->user_id) - ->all(); - - $id = Auth::id() ?? throw new UnauthorizedException(); - $filtered = User::query() - ->where('id', '<>', $id) - ->where('id', '<>', $this->album->owner_id) - ->where('may_administrate', '<>', true) - ->whereNotIn('id', $alreadySelected) - ->orderBy('username', 'ASC') - ->get() - ->map(fn (User $usr) => ['id' => $usr->id, 'username' => $usr->username]); - - if ($this->search !== null && trim($this->search) !== '') { - return $filtered->filter(function (array $album) { - return Str::contains($album['username'], ltrim($this->search), true); - })->all(); - } - - return $filtered->all(); - } - - public function add(): void - { - Gate::authorize(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $this->album]); - - $perm = new AccessPermission(); - $perm->user_id = $this->userID; - $perm->base_album_id = $this->album->id; - $perm->grants_full_photo_access = $this->grants_full_photo_access; - $perm->grants_download = $this->grants_download; - $perm->grants_upload = $this->grants_upload; - $perm->grants_edit = $this->grants_edit; - $perm->grants_delete = $this->grants_delete; - $perm->save(); - - $this->resetData(); - } - - public function select(int $userID, string $username): void - { - $this->userID = $userID; - $this->username = $username; - } - - public function clearUsername(): void - { - $this->userID = null; - $this->username = null; - } - - private function resetData(): void - { - $this->perms = $this->album->access_permissions()->with(['user', 'album'])->whereNotNull('user_id')->get()->all(); - $this->grants_download = Configs::getValueAsBool('grants_download'); - $this->grants_full_photo_access = Configs::getValueAsBool('grants_full_photo_access'); - $this->grants_upload = false; - $this->grants_edit = false; - $this->grants_delete = false; - $this->search = null; - $this->userID = null; - $this->username = null; - } - - public function delete(int $id): void - { - $perm = AccessPermission::with('album')->findOrFail($id); - Gate::authorize(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $perm->album]); - - AccessPermission::query()->where('id', '=', $id)->delete(); - $this->resetData(); - } -} diff --git a/app/Livewire/Components/Forms/Album/ShareWithLine.php b/app/Livewire/Components/Forms/Album/ShareWithLine.php deleted file mode 100644 index e42d1483d67..00000000000 --- a/app/Livewire/Components/Forms/Album/ShareWithLine.php +++ /dev/null @@ -1,83 +0,0 @@ -album]); - - $this->album_title = $album_title; - $this->perm = $perm; - $this->username = $perm->user->username; - $this->grants_full_photo_access = $perm->grants_full_photo_access; - $this->grants_download = $perm->grants_download; - $this->grants_upload = $perm->grants_upload; - $this->grants_edit = $perm->grants_edit; - $this->grants_delete = $perm->grants_delete; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.share-with-line'); - } - - /** - * This runs after a wired property is updated. - * - * @param mixed $field - * @param mixed $value - * - * @return void - */ - public function updated($field, $value): void - { - Gate::authorize(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $this->perm->album]); - - $this->perm->grants_full_photo_access = $this->grants_full_photo_access; - $this->perm->grants_download = $this->grants_download; - $this->perm->grants_upload = $this->grants_upload; - $this->perm->grants_edit = $this->grants_edit; - $this->perm->grants_delete = $this->grants_delete; - $this->perm->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } -} diff --git a/app/Livewire/Components/Forms/Album/Transfer.php b/app/Livewire/Components/Forms/Album/Transfer.php deleted file mode 100644 index 697644fc2b2..00000000000 --- a/app/Livewire/Components/Forms/Album/Transfer.php +++ /dev/null @@ -1,121 +0,0 @@ -albumID = $album->id; - $this->title = $album->title; - $this->current_owner = $album->owner_id; - $this->username = $this->getUsersProperty()[0]; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.transfer'); - } - - /** - * Return a table with the user_id and associated username. - * - * @return string[] list of usernames - */ - public function getUsersProperty(): array - { - return User::query() - ->select('username') - ->where('id', '<>', $this->current_owner) - ->orderBy('id', 'ASC') - ->pluck('username') - ->all(); - } - - /** - * Execute transfer of ownership. - * - * @param AlbumFactory $albumFactory - * - * @return RedirectResponse|View - */ - public function transfer(AlbumFactory $albumFactory) - { - $this->areValid([ - 'albumID' => ['required', new AlbumIDRule(false)], - 'username' => ['required', new UsernameRule()], - ]); - - $baseAlbum = $albumFactory->findBaseAlbumOrFail($this->albumID, false); - - // We use CAN DELETE because it is pretty much the same. Only the owner and admin can transfer ownership - Gate::authorize(AlbumPolicy::CAN_DELETE, $baseAlbum); - - $userId = User::query() - ->select(['id']) - ->where('username', '=', $this->username) - ->firstOrFail(['id'])->id; - - $baseAlbum->owner_id = $userId; - $baseAlbum->save(); - - // If this is an Album, we also need to fix the children and photos ownership - if ($baseAlbum instanceof Album) { - $baseAlbum->makeRoot(); - $baseAlbum->save(); - $baseAlbum->fixOwnershipOfChildren(); - } - - // If we are not an administrator, this mean we no longer have access. - if (Auth::user()->may_administrate !== true) { - return redirect()->to(route('livewire-gallery')); - } - - // Remount the component and re-render. - $this->mount($baseAlbum); - $this->notify('Transfer successful!'); - - return $this->render(); - } -} diff --git a/app/Livewire/Components/Forms/Album/UnlockAlbum.php b/app/Livewire/Components/Forms/Album/UnlockAlbum.php deleted file mode 100644 index a8cb45021e8..00000000000 --- a/app/Livewire/Components/Forms/Album/UnlockAlbum.php +++ /dev/null @@ -1,84 +0,0 @@ -unlock = resolve(Unlock::class); - $this->albumFactory = resolve(AlbumFactory::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param $albumID album to unlock - * @param $back where we go back to - * - * @return void - */ - public function mount(string $albumID, string $back): void - { - $this->albumID = $albumID; - $this->back = $back; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.unlock-album'); - } - - /** - * Method called from the front-end to unlock the album when given a password. - * This will throw an exception on failure! - * - * @return void - */ - public function submit(): void - { - if (!$this->areValid(UnlockAlbumRuleSet::rules())) { - return; - } - - $album = $this->albumFactory->findBaseAlbumOrFail($this->albumID); - try { - $this->unlock->do($album, $this->password); - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->albumID])); - } catch (UnauthorizedException $e) { - $this->addError('password', 'Wrong password'); - } - } -} diff --git a/app/Livewire/Components/Forms/Album/Visibility.php b/app/Livewire/Components/Forms/Album/Visibility.php deleted file mode 100644 index 70dcab2b291..00000000000 --- a/app/Livewire/Components/Forms/Album/Visibility.php +++ /dev/null @@ -1,188 +0,0 @@ -albumID = $album->id; - $this->is_base_album = $album instanceof BaseAlbum; - $this->is_nsfw = $this->is_base_album ? $album->is_nsfw : false; - - /** @var AccessPermission $perm */ - $perm = $album->public_permissions(); - - $this->is_public = $perm !== null; - if ($this->is_public) { - $this->setPublic($perm); - } - } - - /** - * When we initialize, we also need to update the public attributes of the components. - * - * @param AccessPermission $perm - * - * @return void - */ - private function setPublic(AccessPermission $perm): void - { - $this->grants_full_photo_access = $perm->grants_full_photo_access; - $this->is_link_required = $perm->is_link_required; - $this->grants_download = $perm->grants_download; - $this->is_password_required = $perm->password !== null; - // ! We do NOT load the password as we do not want to expose it. - } - - /** - * When we set to Private, we automatically reset the all the attributes to false. - * The AccessPermission object associated will be destroyed later, as such it is better to reset the data. - * - * @return void - */ - private function setPrivate(): void - { - $this->grants_full_photo_access = false; - $this->is_link_required = false; - $this->is_password_required = false; - $this->grants_download = false; - $this->password = null; - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.album.visibility'); - } - - /** - * If any attributes are changed, we call this. - * - * @return void - */ - public function updated() - { - if ($this->is_base_album) { - $this->updatedAsBaseAlbum(); - } else { - $this->updatedAsSmartAlbum(); - } - } - - /** - * Update the policy for a base album. - * - * @return void - */ - private function updatedAsBaseAlbum() - { - $albumFactory = resolve(AlbumFactory::class); - $baseAlbum = $albumFactory->findBaseAlbumOrFail($this->albumID, false); - - $this->validate(SetAlbumProtectionPolicyRuleSet::rules()); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $baseAlbum]); - - if (!$this->is_public) { - $this->setPrivate(); - } - - $albumProtectionPolicy = new AlbumProtectionPolicy( - is_public: $this->is_public, - is_link_required: $this->is_link_required, - is_nsfw: $this->is_nsfw, - grants_full_photo_access: $this->grants_full_photo_access, - grants_download: $this->grants_download, - ); - - // No empty string. - if ($this->password === '') { - $this->password = null; - } - - // If password is required but password is empty this means that we do not want to change current password. - $passwordUpdateRequested = $this->is_password_required && $this->password !== null; - - // Override password if it is no longer required - if (!$this->is_password_required) { - $this->password = null; - $passwordUpdateRequested = true; - } - - $setProtectionPolicy = resolve(SetProtectionPolicy::class); - $setProtectionPolicy->do( - $baseAlbum, - $albumProtectionPolicy, - $passwordUpdateRequested, - $this->password - ); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } - - /** - * Update policy for a smart album. - * - * @return void - */ - private function updatedAsSmartAlbum(): void - { - $albumFactory = resolve(AlbumFactory::class); - /** @var \App\SmartAlbums\BaseSmartAlbum */ - $smartAlbum = $albumFactory->findAbstractAlbumOrFail($this->albumID, false); - - $this->validate([ - RequestAttribute::IS_PUBLIC_ATTRIBUTE => 'required|boolean', - ]); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $smartAlbum]); - - if ($this->is_public) { - $smartAlbum->setPublic(); - } else { - $smartAlbum->setPrivate(); - } - } -} diff --git a/app/Livewire/Components/Forms/Confirms/SaveAll.php b/app/Livewire/Components/Forms/Confirms/SaveAll.php deleted file mode 100644 index c3dc041d90c..00000000000 --- a/app/Livewire/Components/Forms/Confirms/SaveAll.php +++ /dev/null @@ -1,47 +0,0 @@ -closeModal(); - $this->dispatch('saveAll')->to(AllSettings::class); - } - - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Photo/CopyTo.php b/app/Livewire/Components/Forms/Photo/CopyTo.php deleted file mode 100644 index 6f1699c688e..00000000000 --- a/app/Livewire/Components/Forms/Photo/CopyTo.php +++ /dev/null @@ -1,124 +0,0 @@ -duplicate = resolve(Duplicate::class); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param array{photoID?:string,photoIDs?:string[],albumID:?string} $params to move - * - * @return void - */ - public function mount(array $params = ['albumID' => null]): void - { - $id = $params[Params::PHOTO_ID] ?? null; - $this->photoIDs = $id !== null ? [$id] : $params[Params::PHOTO_IDS] ?? []; - $this->num = count($this->photoIDs); - - if ($this->num === 1) { - /** @var Photo $photo */ - $photo = Photo::query()->findOrFail($this->photoIDs[0]); - $this->title = $photo->title; - } - - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - $this->parent_id = $params[Params::ALBUM_ID] ?? SmartAlbumType::UNSORTED->value; - } - - /** - * Prepare confirmation step. - * - * @param string $id - * @param string $title - * - * @return void - */ - public function setAlbum(string $id, string $title): void - { - $this->albumID = $id; - $this->title = $title; - - $this->validate(DuplicatePhotosRuleSet::rules()); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - - $this->albumID = $this->albumID === '' ? null : $this->albumID; - - /** @var ?Album $album */ - $album = $this->albumID === null ? null : Album::query()->findOrFail($this->albumID); - Gate::authorize(AlbumPolicy::CAN_EDIT, [Album::class, $album]); - - $photos = Photo::query()->with(['size_variants'])->findOrFail($this->photoIDs); - - $copiedPhotos = $this->duplicate->do($photos, $album); - - $notify = new UserNotify(); - - $copiedPhotos->each(fn ($photo, $k) => $notify->do($photo)); - - // We stay in current album. - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->parent_id]), true); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.photo.copyTo'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Photo/Delete.php b/app/Livewire/Components/Forms/Photo/Delete.php deleted file mode 100644 index 61b612db617..00000000000 --- a/app/Livewire/Components/Forms/Photo/Delete.php +++ /dev/null @@ -1,95 +0,0 @@ - null]): void - { - $id = $params[Params::PHOTO_ID] ?? null; - $this->photoIDs = $id !== null ? [$id] : $params[Params::PHOTO_IDS] ?? []; - - Gate::authorize(PhotoPolicy::CAN_DELETE_BY_ID, [Photo::class, $this->photoIDs]); - - $this->num = count($this->photoIDs); - - if ($this->num === 1) { - /** @var Photo $photo */ - $photo = Photo::query()->findOrFail($this->photoIDs[0]); - $this->title = $photo->title; - } - - $this->albumId = $params[Params::ALBUM_ID] ?? null; - $this->num = count($this->photoIDs); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.photo.delete'); - } - - /** - * Execute deletion. - * - * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse - */ - public function submit(DeleteAction $delete): \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse - { - $this->validate(DeletePhotosRuleSet::rules()); - - Gate::authorize(PhotoPolicy::CAN_DELETE_BY_ID, [Photo::class, $this->photoIDs]); - - $fileDeleter = $delete->do($this->photoIDs); - App::terminating(fn () => $fileDeleter->do()); - - return redirect()->to(route('livewire-gallery-album', ['albumId' => $this->albumId ?? SmartAlbumType::UNSORTED->value])); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Photo/Download.php b/app/Livewire/Components/Forms/Photo/Download.php deleted file mode 100644 index fdb7d82da77..00000000000 --- a/app/Livewire/Components/Forms/Photo/Download.php +++ /dev/null @@ -1,69 +0,0 @@ - null]): void - { - $id = $params[Params::PHOTO_ID] ?? null; - $this->photoIDs = $id !== null ? [$id] : $params[Params::PHOTO_IDS] ?? []; - $num = count($this->photoIDs); - - if ($num === 1) { - $this->photo = Photo::query()->findOrFail($this->photoIDs[0]); - Gate::authorize(PhotoPolicy::CAN_DOWNLOAD, [Photo::class, $this->photo]); - } else { - $this->redirect(route('photo_download', ['kind' => DownloadVariantType::ORIGINAL->value]) . '&photoIDs=' . implode(',', $this->photoIDs)); - } - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.photo.download'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Photo/Move.php b/app/Livewire/Components/Forms/Photo/Move.php deleted file mode 100644 index ce086eefb03..00000000000 --- a/app/Livewire/Components/Forms/Photo/Move.php +++ /dev/null @@ -1,116 +0,0 @@ -move = new PhotoMove(); - } - - /** - * This is the equivalent of the constructor for Livewire Components. - * - * @param array{photoID?:string,photoIDs?:string[],albumID:?string} $params to move - * - * @return void - */ - public function mount(array $params = ['albumID' => null]): void - { - $id = $params[Params::PHOTO_ID] ?? null; - $this->photoIDs = $id !== null ? [$id] : $params[Params::PHOTO_IDS] ?? []; - $this->num = count($this->photoIDs); - - if ($this->num === 1) { - /** @var Photo $photo */ - $photo = Photo::query()->findOrFail($this->photoIDs[0]); - $this->title = $photo->title; - } - - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - $this->parent_id = $params[Params::ALBUM_ID] ?? SmartAlbumType::UNSORTED->value; - } - - /** - * Prepare confirmation step. - * - * @param string $id - * @param string $title - * - * @return void - */ - public function setAlbum(string $id, string $title): void - { - $this->albumID = $id; - $this->title = $title; - - $this->validate(MovePhotosRuleSet::rules()); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - - $this->albumID = $this->albumID === '' ? null : $this->albumID; - - /** @var ?Album $album */ - $album = $this->albumID === null ? null : Album::query()->findOrFail($this->albumID); - Gate::authorize(AlbumPolicy::CAN_EDIT, [Album::class, $album]); - - $photos = Photo::query()->findOrFail($this->photoIDs); - - $this->move->do($photos, $album); - - // We stay in current album. - $this->redirect(route('livewire-gallery-album', ['albumId' => $this->parent_id]), true); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.photo.move'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Photo/Rename.php b/app/Livewire/Components/Forms/Photo/Rename.php deleted file mode 100644 index 04e82defe15..00000000000 --- a/app/Livewire/Components/Forms/Photo/Rename.php +++ /dev/null @@ -1,83 +0,0 @@ - null]): void - { - $id = $params[Params::PHOTO_ID] ?? null; - $this->photoIDs = $id !== null ? [$id] : $params[Params::PHOTO_IDS] ?? []; - $this->num = count($this->photoIDs); - - if ($this->num === 1) { - /** @var Photo $photo */ - $photo = Photo::query()->findOrFail($this->photoIDs[0]); - $this->title = $photo->title; - } - - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - } - - /** - * Rename. - * - * @return void - */ - public function submit(): void - { - $this->validate(SetPhotosTitleRuleSet::rules()); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - Photo::query()->whereIn('id', $this->photoIDs)->update(['title' => $this->title]); - - $this->close(); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.photo.rename'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Photo/Tag.php b/app/Livewire/Components/Forms/Photo/Tag.php deleted file mode 100644 index 4cd88800194..00000000000 --- a/app/Livewire/Components/Forms/Photo/Tag.php +++ /dev/null @@ -1,95 +0,0 @@ - null]): void - { - $id = $params[Params::PHOTO_ID] ?? null; - $this->photoIDs = $id !== null ? [$id] : $params[Params::PHOTO_IDS] ?? []; - $this->num = count($this->photoIDs); - - if ($this->num === 1) { - /** @var Photo $photo */ - $photo = Photo::query()->findOrFail($this->photoIDs[0]); - $this->tag = implode(', ', $photo->tags); - } - - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - } - - /** - * Tag. - * - * @return void - */ - public function submit(): void - { - $this->tags = collect(explode(',', $this->tag))->map(fn ($v) => trim($v))->filter(fn ($v) => $v !== '')->all(); - - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->photoIDs]); - - $photos = Photo::query()->whereIn('id', $this->photoIDs)->get(); - foreach ($photos as $photo) { - if ($this->shall_override) { - $photo->tags = $this->tags; - } else { - $photo->tags = array_unique(array_merge($photo->tags, $this->tags)); - } - $photo->save(); - } - - $this->close(); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.photo.tag'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } -} diff --git a/app/Livewire/Components/Forms/Profile/GetApiToken.php b/app/Livewire/Components/Forms/Profile/GetApiToken.php deleted file mode 100644 index 7f9e528942e..00000000000 --- a/app/Livewire/Components/Forms/Profile/GetApiToken.php +++ /dev/null @@ -1,111 +0,0 @@ -tokenReset = resolve(TokenReset::class); - $this->tokenDisable = resolve(TokenDisable::class); - } - - /** - * Mount the current data of the user. - * $token is kept empty in order to avoid revealing the data. - * - * @return void - */ - public function mount(): void - { - $user = Auth::user() ?? throw new UnauthenticatedException(); - - $this->token = __('lychee.TOKEN_NOT_AVAILABLE'); - $this->isDisabled = true; - - if ($user->token === null) { - $this->token = __('lychee.DISABLED_TOKEN_STATUS_MSG'); - } - } - - /** - * Renders the modal content. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.profile.get-api-token'); - } - - /** - * Add an handle to close the modal form from a user-land call. - * - * @return void - */ - public function close(): void - { - $this->closeModal(); - } - - /** - * Method call from front-end to reset the Token. - * We generate a new one on the fly and display it. - * - * @return void - */ - public function resetToken(): void - { - /** - * Authorize the request. - */ - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - - $this->token = $this->tokenReset->do(); - $this->isDisabled = false; - } - - /** - * Method call from front-end to disable the token. - * We simply erase the current one. - * - * @return void - */ - public function disableToken(): void - { - /** - * Authorize the request. - */ - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - - $this->tokenDisable->do(); - $this->token = __('lychee.DISABLED_TOKEN_STATUS_MSG'); - $this->isDisabled = true; - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Profile/ManageSecondFactor.php b/app/Livewire/Components/Forms/Profile/ManageSecondFactor.php deleted file mode 100644 index db947577e54..00000000000 --- a/app/Livewire/Components/Forms/Profile/ManageSecondFactor.php +++ /dev/null @@ -1,92 +0,0 @@ -> - */ - public function rules(): array - { - return ['alias' => 'required|string|min:5|max:255']; - } - - /** - * Just mount the component with the required WebAuthn Credentials. - * - * @param WebAuthnCredential $credential - * - * @return void - */ - public function mount(WebAuthnCredential $credential): void - { - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - - if ($credential->authenticatable_id !== (Auth::id() ?? throw new UnauthenticatedException())) { - throw new UnauthorizedException(); - } - - $this->credential = $credential; - $this->alias = $credential->alias ?? Str::substr($credential->id, 0, 30); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.profile.manage-second-factor'); - } - - /** - * This runs after a wired property is updated. - * - * @param mixed $field - * @param mixed $value - * - * @return void - */ - public function updated($field, $value): void - { - if (!$this->areValid($this->rules())) { - $this->has_error = true; - - return; - } - - $this->has_error = false; - $this->credential->alias = $this->alias; - $this->credential->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } -} diff --git a/app/Livewire/Components/Forms/Profile/Oauth.php b/app/Livewire/Components/Forms/Profile/Oauth.php deleted file mode 100644 index 268deddfc8f..00000000000 --- a/app/Livewire/Components/Forms/Profile/Oauth.php +++ /dev/null @@ -1,80 +0,0 @@ -authorize(UserPolicy::CAN_EDIT, [User::class]); - - return view('livewire.forms.profile.oauth'); - } - - public function clear(string $provider): void - { - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - $providerEnum = OauthProvidersType::from($provider); - - /** @var User $user */ - $user = Auth::user() ?? throw new UnauthenticatedException(); - $user->oauthCredentials()->where('provider', '=', $providerEnum)->delete(); - } - - /** - * Return computed property for OauthData. - * - * @return array - */ - public function getOauthDataProperty(): array - { - $oauthData = []; - - /** @var User $user */ - $user = Auth::user() ?? throw new UnauthenticatedException(); - - $credentials = $user->oauthCredentials()->get(); - - foreach (OauthProvidersType::cases() as $provider) { - $client_id = config('services.' . $provider->value . '.client_id'); - if ($client_id === null || $client_id === '') { - continue; - } - - // We create a signed route for 5 minutes - $route = URL::signedRoute( - name: 'oauth-register', - parameters: ['provider' => $provider->value], - expiration: now()->addMinutes(5), - absolute: false); - - $oauthData[$provider->value] = new OauthData( - providerType: $provider->value, - isEnabled: $credentials->search(fn (OauthCredential $c) => $c->provider === $provider) !== false, - registrationRoute: $route, - ); - } - - return $oauthData; - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Profile/SecondFactor.php b/app/Livewire/Components/Forms/Profile/SecondFactor.php deleted file mode 100644 index c1f96d18c47..00000000000 --- a/app/Livewire/Components/Forms/Profile/SecondFactor.php +++ /dev/null @@ -1,65 +0,0 @@ -authorize(UserPolicy::CAN_EDIT, [User::class]); - - return view('livewire.modules.profile.second-factor'); - } - - /** - * Return the list of credentials associated to the current logged in user. - * - * @return Collection - * - * @throws UnauthenticatedException - */ - public function getCredentialsProperty(): Collection - { - /** @var \App\Models\User $user */ - $user = Auth::user() ?? throw new UnauthenticatedException(); - - return $user->webAuthnCredentials; - } - - /** - * Delete an existing credential. - * - * @param string $id - * - * @return void - * - * @throws \InvalidArgumentException - */ - public function delete(string $id): void - { - /** @var User $user */ - $user = Auth::user() ?? throw new UnauthenticatedException(); - - $user->webAuthnCredentials()->where('id', '=', $id)->delete(); - $this->notify(__('lychee.U2F_CREDENTIALS_DELETED')); - } -} diff --git a/app/Livewire/Components/Forms/Profile/SetEmail.php b/app/Livewire/Components/Forms/Profile/SetEmail.php deleted file mode 100644 index 709945e6803..00000000000 --- a/app/Livewire/Components/Forms/Profile/SetEmail.php +++ /dev/null @@ -1,67 +0,0 @@ -authorize(UserPolicy::CAN_EDIT, [User::class]); - - /** @var User $user */ - $user = Auth::user(); - $this->value = $user->email; - $this->description = __('lychee.ENTER_EMAIL'); - $this->action = __('lychee.SAVE'); - } - - /** - * Render the component with the email form. - * - * @return View - * - * @throws UnauthenticatedException - */ - public function render(): View - { - return view('livewire.forms.settings.input'); - } - - /** - * Save the email address entered. - * - * @return void - * - * @throws UnauthenticatedException - */ - public function save(): void - { - $this->validate(['value' => 'required|email']); - - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - - /** @var User $user */ - $user = Auth::user() ?? throw new UnauthenticatedException(); - $user->email = $this->value; - $user->save(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Profile/SetLogin.php b/app/Livewire/Components/Forms/Profile/SetLogin.php deleted file mode 100644 index 489ddd0a459..00000000000 --- a/app/Livewire/Components/Forms/Profile/SetLogin.php +++ /dev/null @@ -1,92 +0,0 @@ -updateLogin = resolve(UpdateLogin::class); - } - - public function mount(): void - { - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - } - - /** - * Simply render the form. - * - * @return View - */ - public function render(): View - { - return view('livewire.forms.profile.set-login'); - } - - /** - * Update Username & Password of current user. - */ - public function submit(): void - { - $this->validate(ChangeLoginRuleSet::rules()); - $this->validate(['oldPassword' => new CurrentPasswordRule()]); - - $this->authorize(UserPolicy::CAN_EDIT, [User::class]); - - $currentUser = $this->updateLogin->do( - $this->username, - $this->password, - $this->oldPassword, - request()->ip() - ); - - // Update the session with the new credentials of the user. - // Otherwise, the session is out-of-sync and falsely assumes the user - // to be unauthenticated upon the next request. - Auth::login($currentUser); - $this->notify(__('lychee.CHANGE_SUCCESS')); - - $this->oldPassword = ''; - $this->username = ''; - $this->password = ''; - $this->password_confirmation = ''; - } - - /** - * Open a login modal box. - * - * @return void - */ - public function openApiTokenModal(): void - { - $this->openClosableModal('forms.profile.get-api-token', __('lychee.CLOSE')); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/Base/BaseConfigDoubleDropDown.php b/app/Livewire/Components/Forms/Settings/Base/BaseConfigDoubleDropDown.php deleted file mode 100644 index 2dbe0c40afa..00000000000 --- a/app/Livewire/Components/Forms/Settings/Base/BaseConfigDoubleDropDown.php +++ /dev/null @@ -1,95 +0,0 @@ -value1 = $this->config1->value; - $this->value2 = $this->config2->value; - - return view('livewire.forms.settings.double-drop-down'); - } - - /** - * This runs before a wired property is updated. - * - * @param mixed $field - * @param mixed $value - * - * @return void - * - * @throws InvalidCastException - * @throws JsonEncodingException - * @throws \RuntimeException - */ - public function updated($field, $value) - { - Gate::authorize(SettingsPolicy::CAN_EDIT, [Configs::class]); - $error_msg = $this->config1->sanity($this->value1); - if ($error_msg !== '') { - $this->notify($error_msg, NotificationType::ERROR); - - return; - } - $error_msg = $this->config2->sanity($this->value2); - if ($error_msg !== '') { - $this->notify($error_msg, NotificationType::ERROR); - - return; - } - - $this->config1->value = $this->value1; - $this->config1->save(); - $this->config2->value = $this->value2; - $this->config2->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } - - /** - * Defines accessor for the drop down options1. - * - * @return array - */ - abstract public function getOptions1Property(): array; - - /** - * Defines accessor for the drop down options2. - * - * @return array - */ - abstract public function getOptions2Property(): array; -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/Base/BaseConfigDropDown.php b/app/Livewire/Components/Forms/Settings/Base/BaseConfigDropDown.php deleted file mode 100644 index 0e3d11f6b8e..00000000000 --- a/app/Livewire/Components/Forms/Settings/Base/BaseConfigDropDown.php +++ /dev/null @@ -1,69 +0,0 @@ -value = $this->config->value; - - return view('livewire.forms.settings.drop-down'); - } - - /** - * This runs before a wired property is updated. - * - * @param mixed $field - * @param mixed $value - * - * @return void - */ - public function updating($field, $value): void - { - Gate::authorize(SettingsPolicy::CAN_EDIT, [Configs::class]); - $error_msg = $this->config->sanity($value); - if ($error_msg !== '') { - $this->notify($error_msg, NotificationType::ERROR); - - return; - } - - $this->config->value = $value; - $this->config->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } - - /** - * Defines accessor for the drop down options1. - * - * @return array - */ - abstract public function getOptionsProperty(): array; -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/Base/BooleanSetting.php b/app/Livewire/Components/Forms/Settings/Base/BooleanSetting.php deleted file mode 100644 index 694c3d8a379..00000000000 --- a/app/Livewire/Components/Forms/Settings/Base/BooleanSetting.php +++ /dev/null @@ -1,77 +0,0 @@ -description = __('lychee.' . $description); - $this->footer = $footer !== '' ? __('lychee.' . $footer) : ''; - $this->config = Configs::where('key', '=', $name)->firstOrFail(); - } - - /** - * Render the toggle element. - * - * @return View - */ - public function render(): View - { - $this->flag = $this->config->value === '1'; - - return view('livewire.forms.settings.toggle'); - } - - /** - * This runs before a wired property is updated. - * - * @param mixed $field - * @param mixed $value - * - * @return void - * - * @throws InvalidCastException - * @throws JsonEncodingException - * @throws \RuntimeException - */ - public function updating($field, $value) - { - Gate::authorize(SettingsPolicy::CAN_EDIT, [Configs::class]); - - $this->config->value = $value === true ? '1' : '0'; - $this->config->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/Base/PasswordSetting.php b/app/Livewire/Components/Forms/Settings/Base/PasswordSetting.php deleted file mode 100644 index bf07966dc57..00000000000 --- a/app/Livewire/Components/Forms/Settings/Base/PasswordSetting.php +++ /dev/null @@ -1,24 +0,0 @@ -value = $this->config->value; - - return view('livewire.forms.settings.password'); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/Base/StringSetting.php b/app/Livewire/Components/Forms/Settings/Base/StringSetting.php deleted file mode 100644 index d64f7b399ce..00000000000 --- a/app/Livewire/Components/Forms/Settings/Base/StringSetting.php +++ /dev/null @@ -1,76 +0,0 @@ -description = __('lychee.' . $description); - $this->action = __('lychee.' . $action); - $this->placeholder = __('lychee.' . $placeholder); - $this->config = Configs::where('key', '=', $name)->firstOrFail(); - } - - /** - * Renders the input form. - * - * @return View - */ - public function render(): View - { - $this->value = $this->config->value; - - return view('livewire.forms.settings.input'); - } - - /** - * Validation call to persist the data (as opposed to drop down menu and toggle which are instant). - * - * @return void - */ - public function save(): void - { - Gate::authorize(SettingsPolicy::CAN_EDIT, [Configs::class]); - $error_msg = $this->config->sanity($this->value); - if ($error_msg !== '') { - $this->notify($error_msg, NotificationType::ERROR); - $this->value = $this->config->value; - - return; - } - - $this->config->value = $this->value; - $this->config->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetAlbumDecorationOrientationSetting.php b/app/Livewire/Components/Forms/Settings/SetAlbumDecorationOrientationSetting.php deleted file mode 100644 index 0155d9da0b0..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetAlbumDecorationOrientationSetting.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return AlbumDecorationOrientation::localized(); - } - - /** - * Set the required strings. - * - * @return void - */ - public function mount(): void - { - $this->description = __('lychee.ALBUM_DECORATION_ORIENTATION'); - $this->config = Configs::where('key', '=', 'album_decoration_orientation')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetAlbumDecorationSetting.php b/app/Livewire/Components/Forms/Settings/SetAlbumDecorationSetting.php deleted file mode 100644 index eb7c3a14171..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetAlbumDecorationSetting.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return AlbumDecorationType::localized(); - } - - /** - * Set up the translations. - * - * @return void - */ - public function mount() - { - $this->description = __('lychee.ALBUM_DECORATION'); - $this->config = Configs::where('key', '=', 'album_decoration')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetAlbumSortingSetting.php b/app/Livewire/Components/Forms/Settings/SetAlbumSortingSetting.php deleted file mode 100644 index b3ea1da8092..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetAlbumSortingSetting.php +++ /dev/null @@ -1,56 +0,0 @@ -begin = $matches[1]; - $this->middle = $matches[2]; - $this->end = $matches[3]; - - $this->config1 = Configs::where('key', '=', 'sorting_albums_col')->firstOrFail(); - $this->config2 = Configs::where('key', '=', 'sorting_albums_order')->firstOrFail(); - } - - /** - * Give the options on the column. - * - * @return array - */ - public function getOptions1Property(): array - { - return ColumnSortingAlbumType::localized(); - } - - /** - * Give the options on the ordering. - * - * @return array - */ - public function getOptions2Property(): array - { - return OrderSortingType::localized(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetLangSetting.php b/app/Livewire/Components/Forms/Settings/SetLangSetting.php deleted file mode 100644 index 37adec9a151..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetLangSetting.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return config('app.supported_locale'); - } - - /** - * Set up the texts. - * - * @return void - */ - public function mount() - { - $this->description = __('lychee.LANG_TEXT'); - // We do not use Lang::get_code() because we want to be able to modify it. - // We are interested in the setting itself. - $this->config = Configs::where('key', '=', 'lang')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetLayoutSetting.php b/app/Livewire/Components/Forms/Settings/SetLayoutSetting.php deleted file mode 100644 index b10291fed53..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetLayoutSetting.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return PhotoLayoutType::localized(); - } - - /** - * Mount the texts. - * - * @return void - */ - public function mount() - { - $this->description = __('lychee.LAYOUT_TYPE'); - $this->config = Configs::where('key', '=', 'layout')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetLicenseDefaultSetting.php b/app/Livewire/Components/Forms/Settings/SetLicenseDefaultSetting.php deleted file mode 100644 index eefa0930a81..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetLicenseDefaultSetting.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return LicenseType::localized(); - } - - /** - * Set up the drop down menu. - * - * @return void - */ - public function mount(): void - { - $this->description = __('lychee.DEFAULT_LICENSE'); - $this->config = Configs::where('key', '=', 'default_license')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetMapProviderSetting.php b/app/Livewire/Components/Forms/Settings/SetMapProviderSetting.php deleted file mode 100644 index af08060d022..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetMapProviderSetting.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return [ - 'Wikimedia' => __('lychee.MAP_PROVIDER_WIKIMEDIA'), - 'OpenStreetMap.org' => __('lychee.MAP_PROVIDER_OSM_ORG'), - 'OpenStreetMap.de' => __('lychee.MAP_PROVIDER_OSM_DE'), - 'OpenStreetMap.fr' => __('lychee.MAP_PROVIDER_OSM_FR'), - 'RRZE' => __('lychee.MAP_PROVIDER_RRZE'), - ]; - } - - /** - * Mount the config. - * - * @return void - */ - public function mount() - { - $this->description = __('lychee.MAP_PROVIDER'); - $this->config = Configs::where('key', '=', 'map_provider')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetPhotoOverlaySetting.php b/app/Livewire/Components/Forms/Settings/SetPhotoOverlaySetting.php deleted file mode 100644 index 7cd5557eaa1..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetPhotoOverlaySetting.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function getOptionsProperty(): array - { - return ImageOverlayType::localized(); - } - - /** - * Set up the drop down menu. - * - * @return void - */ - public function mount(): void - { - $this->description = __('lychee.OVERLAY_TYPE'); - $this->config = Configs::where('key', '=', 'image_overlay_type')->firstOrFail(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Forms/Settings/SetPhotoSortingSetting.php b/app/Livewire/Components/Forms/Settings/SetPhotoSortingSetting.php deleted file mode 100644 index c0faf4ca53d..00000000000 --- a/app/Livewire/Components/Forms/Settings/SetPhotoSortingSetting.php +++ /dev/null @@ -1,56 +0,0 @@ -begin = $matches[1]; - $this->middle = $matches[2]; - $this->end = $matches[3]; - - $this->config1 = Configs::where('key', '=', 'sorting_photos_col')->firstOrFail(); - $this->config2 = Configs::where('key', '=', 'sorting_photos_order')->firstOrFail(); - } - - /** - * Give the columns options. - * - * @return array - */ - public function getOptions1Property(): array - { - return ColumnSortingPhotoType::localized(); - } - - /** - * Ordering ascending or descending. - * - * @return array - */ - public function getOptions2Property(): array - { - return OrderSortingType::localized(); - } -} \ No newline at end of file diff --git a/app/Livewire/Components/Menus/AlbumAdd.php b/app/Livewire/Components/Menus/AlbumAdd.php deleted file mode 100644 index 57439f168b8..00000000000 --- a/app/Livewire/Components/Menus/AlbumAdd.php +++ /dev/null @@ -1,127 +0,0 @@ -closeContextMenu(); - $this->openModal('forms.album.create', $this->params); - } - - /** - * Open Create Tag Album modal. - * - * @return void - */ - public function openTagAlbumCreateModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.create-tag', $this->params); - } - - public function openImportFromServerModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.add.import-from-server', $this->params); - } - - public function openImportFromUrlModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.add.import-from-url', $this->params); - } - - public function openUploadModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.add.upload', $this->params); - } - - public function openImportFromDropboxModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.add.import-from-dropbox', $this->params); - } - - public function openAddTrackModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.add-track', $this->params); - } - - public function openDeleteTrackModal(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.delete-track', $this->params); - } - - public function getHasParentProperty(): bool - { - return $this->getParentAlbum() !== null; - } - - public function getCanAddTrackProperty(): bool - { - return $this->getParentAlbum() !== null; - } - - public function getHasTrackProperty(): bool - { - return $this->getParentAlbum()?->track_short_path !== null; - } - - public function getParentAlbum(): Album|null - { - $id = $this->params[Params::PARENT_ID]; - if ($id === null) { - return null; - } - - if ($this->album !== null) { - return $this->album; - } - - $album_candidate = resolve(AlbumFactory::class)->findAbstractAlbumOrFail($id); - if ($album_candidate instanceof Album) { - $this->album = $album_candidate; - } - - return $this->album; - } -} diff --git a/app/Livewire/Components/Menus/AlbumDropdown.php b/app/Livewire/Components/Menus/AlbumDropdown.php deleted file mode 100644 index 3e7333ec57e..00000000000 --- a/app/Livewire/Components/Menus/AlbumDropdown.php +++ /dev/null @@ -1,68 +0,0 @@ -closeContextMenu(); - $this->openModal('forms.album.rename', [Params::ALBUM_ID => $this->params[Params::ALBUM_ID], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function merge(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.merge', [Params::ALBUM_ID => $this->params[Params::ALBUM_ID], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function move(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.move', [Params::ALBUM_ID => $this->params[Params::ALBUM_ID], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function delete(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.delete', [Params::ALBUM_ID => $this->params[Params::ALBUM_ID], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function download(): void - { - $this->closeContextMenu(); - $this->redirect(route('download', ['albumIDs' => $this->params[Params::ALBUM_ID]])); - } - - public function setAsCover(): void - { - $this->closeContextMenu(); - $this->dispatch('setAsCover', $this->params[Params::ALBUM_ID])->to(Album::class); - } -} diff --git a/app/Livewire/Components/Menus/AlbumsDropdown.php b/app/Livewire/Components/Menus/AlbumsDropdown.php deleted file mode 100644 index 78f16eca367..00000000000 --- a/app/Livewire/Components/Menus/AlbumsDropdown.php +++ /dev/null @@ -1,61 +0,0 @@ -closeContextMenu(); - $this->openModal('forms.album.rename', [Params::ALBUM_IDS => $this->params[Params::ALBUM_IDS], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function mergeAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.merge', [Params::ALBUM_IDS => $this->params[Params::ALBUM_IDS], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function moveAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.move', [Params::ALBUM_IDS => $this->params[Params::ALBUM_IDS], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function deleteAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.album.delete', [Params::ALBUM_IDS => $this->params[Params::ALBUM_IDS], Params::PARENT_ID => $this->params[Params::PARENT_ID]]); - } - - public function downloadAll(): void - { - $this->redirect(route('download') . '?albumIDs=' . implode(',', $this->params[Params::ALBUM_IDS])); - $this->closeContextMenu(); - } -} diff --git a/app/Livewire/Components/Menus/LeftMenu.php b/app/Livewire/Components/Menus/LeftMenu.php deleted file mode 100644 index e916d6a5b4e..00000000000 --- a/app/Livewire/Components/Menus/LeftMenu.php +++ /dev/null @@ -1,137 +0,0 @@ -loadDevMenu(); - - return view('livewire.components.left-menu'); - } - - /** - * Open the Context Menu. - * - * @return void - */ - #[On('openLeftMenu')] - public function openLeftMenu(): void - { - $this->open(); - } - - /** - * Close the LeftMenu component. - * - * @return void - */ - #[On('closeLeftMenu')] - public function closeLeftMenu(): void - { - $this->close(); - } - - /** - * Toggle the LeftMenu component. - * - * @return void - */ - #[On('toggleLeftMenu')] - public function toggleLeftMenu(): void - { - $this->toggle(); - } - - /** - * Open a about modal box. - * TODO Consider moving this directly to Blade. - * - * @return void - */ - public function openAboutModal(): void - { - $this->openClosableModal('modals.about', __('lychee.CLOSE')); - } - - /** - * We load some data about debuging tools section. - * - * @return void - */ - private function loadDevMenu(): void - { - $this->has_dev_tools = Gate::check(SettingsPolicy::CAN_ACCESS_DEV_TOOLS, [Configs::class]); - if (!$this->has_dev_tools) { - return; - } - - // Defining clockwork URL - $clockWorkEnabled = config('clockwork.enable') === true || (config('app.debug') === true && config('clockwork.enable') === null); - $clockWorkWeb = config('clockwork.web'); - if ($clockWorkEnabled && $clockWorkWeb === true || is_string($clockWorkWeb)) { - $this->clockwork_url = $clockWorkWeb === true ? URL::asset('clockwork/app') : $clockWorkWeb . '/app'; - } - - // API documentation - $this->doc_api_url = Route::has('scramble.docs.api') ? route('scramble.docs.api') : null; - - // Double check to avoid showing an empty section. - $this->has_dev_tools = $this->doc_api_url !== null || $this->clockwork_url !== null; - } -} diff --git a/app/Livewire/Components/Menus/PhotoDropdown.php b/app/Livewire/Components/Menus/PhotoDropdown.php deleted file mode 100644 index 9b404c38df0..00000000000 --- a/app/Livewire/Components/Menus/PhotoDropdown.php +++ /dev/null @@ -1,139 +0,0 @@ -find($params[Params::ALBUM_ID]); - - $this->params = $params; - $this->is_starred = Photo::query()->findOrFail($params[Params::PHOTO_ID])->is_starred; - $this->is_model_album = $album instanceof Album; - if ($album !== null) { - $this->is_header = $album->header_id === $params[Params::PHOTO_ID]; - } - } - - /** - * Renders the Add menu in the top right. - * - * @return View - */ - public function render(): View - { - return view('livewire.context-menus.photo-dropdown'); - } - - public function star(): void - { - $this->closeContextMenu(); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, [$this->params[Params::PHOTO_ID]]]); - Photo::where('id', '=', $this->params[Params::PHOTO_ID])->update(['is_starred' => true]); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - public function unstar(): void - { - $this->closeContextMenu(); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, [$this->params[Params::PHOTO_ID]]]); - Photo::where('id', '=', $this->params[Params::PHOTO_ID])->update(['is_starred' => false]); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - public function tag(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.tag', [Params::PHOTO_ID => $this->params[Params::PHOTO_ID], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function setAsCover(): void - { - /** @var Album $album */ - $album = Album::query()->findOrFail($this->params[Params::ALBUM_ID]); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - $album->cover_id = $album->cover_id === $this->params[Params::PHOTO_ID] ? null : $this->params[Params::PHOTO_ID]; - $album->save(); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - $this->closeContextMenu(); - } - - public function setAsHeader(): void - { - /** @var Album $album */ - $album = Album::query()->findOrFail($this->params[Params::ALBUM_ID]); - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $album]); - $album->header_id = $album->header_id === $this->params[Params::PHOTO_ID] ? null : $this->params[Params::PHOTO_ID]; - $album->save(); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - $this->closeContextMenu(); - } - - public function rename(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.rename', [Params::PHOTO_ID => $this->params[Params::PHOTO_ID], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function copyTo(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.copy-to', [Params::PHOTO_ID => $this->params[Params::PHOTO_ID], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function move(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.move', [Params::PHOTO_ID => $this->params[Params::PHOTO_ID], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function delete(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.delete', [Params::PHOTO_ID => $this->params[Params::PHOTO_ID], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function download(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.download', [Params::PHOTO_ID => $this->params[Params::PHOTO_ID], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } -} diff --git a/app/Livewire/Components/Menus/PhotosDropdown.php b/app/Livewire/Components/Menus/PhotosDropdown.php deleted file mode 100644 index 869b5e6cc96..00000000000 --- a/app/Livewire/Components/Menus/PhotosDropdown.php +++ /dev/null @@ -1,102 +0,0 @@ -params = $params; - $this->are_starred = count($params[Params::PHOTO_IDS]) === - Photo::query()->whereIn('id', $params[Params::PHOTO_IDS])->where('is_starred', '=', true)->count(); - } - - /** - * Renders the Add menu in the top right. - * - * @return View - */ - public function render(): View - { - return view('livewire.context-menus.photos-dropdown'); - } - - public function starAll(): void - { - $this->closeContextMenu(); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->params[Params::PHOTO_IDS]]); - Photo::whereIn('id', $this->params[Params::PHOTO_IDS])->update(['is_starred' => true]); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - public function unstarAll(): void - { - $this->closeContextMenu(); - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $this->params[Params::PHOTO_IDS]]); - Photo::whereIn('id', $this->params[Params::PHOTO_IDS])->update(['is_starred' => false]); - $this->dispatch('reloadPage')->to(GalleryAlbum::class); - } - - public function tagAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.tag', [Params::PHOTO_IDS => $this->params[Params::PHOTO_IDS], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function renameAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.rename', [Params::PHOTO_IDS => $this->params[Params::PHOTO_IDS], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function copyAllTo(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.copy-to', [Params::PHOTO_IDS => $this->params[Params::PHOTO_IDS], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function moveAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.move', [Params::PHOTO_IDS => $this->params[Params::PHOTO_IDS], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function deleteAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.delete', [Params::PHOTO_IDS => $this->params[Params::PHOTO_IDS], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } - - public function downloadAll(): void - { - $this->closeContextMenu(); - $this->openModal('forms.photo.download', [Params::PHOTO_IDS => $this->params[Params::PHOTO_IDS], Params::ALBUM_ID => $this->params[Params::ALBUM_ID]]); - } -} diff --git a/app/Livewire/Components/Modals/About.php b/app/Livewire/Components/Modals/About.php deleted file mode 100644 index 33383e154e3..00000000000 --- a/app/Livewire/Components/Modals/About.php +++ /dev/null @@ -1,56 +0,0 @@ -version = resolve(InstalledVersion::class)->getVersion()->toString(); - } - - $fileVersion = resolve(FileVersion::class); - $gitHubVersion = resolve(GitHubVersion::class); - if (Configs::getValueAsBool('check_for_updates')) { - // @codeCoverageIgnoreStart - $fileVersion->hydrate(); - $gitHubVersion->hydrate(); - // @codeCoverageIgnoreEnd - } - $this->is_new_release_available = !$fileVersion->isUpToDate(); - $this->is_git_update_available = !$gitHubVersion->isUpToDate(); - } - - /** - * Renders the About component. - * - * @return View - */ - public function render(): View - { - return view('livewire.modals.about'); - } -} diff --git a/app/Livewire/Components/Modals/Login.php b/app/Livewire/Components/Modals/Login.php deleted file mode 100644 index 3b7b7252f0e..00000000000 --- a/app/Livewire/Components/Modals/Login.php +++ /dev/null @@ -1,129 +0,0 @@ -version = resolve(InstalledVersion::class)->getVersion()->toString(); - } - - $fileVersion = resolve(FileVersion::class); - $gitHubVersion = resolve(GitHubVersion::class); - if (Configs::getValueAsBool('check_for_updates')) { - // @codeCoverageIgnoreStart - $fileVersion->hydrate(); - $gitHubVersion->hydrate(); - // @codeCoverageIgnoreEnd - } - $this->is_new_release_available = !$fileVersion->isUpToDate(); - $this->is_git_update_available = !$gitHubVersion->isUpToDate(); - } - - /** - * Hook the submit button. - * - * @return void - * - * @throws \Throwable - * @throws ValidationException - * @throws BindingResolutionException - * @throws \InvalidArgumentException - * @throws QueryBuilderException - */ - public function submit(): void - { - // Empty error bag - $this->resetErrorBag(); - - // Call Livewire validation on the from - $data = $this->validate(LoginRuleSet::rules()); - - // apply login as admin and trigger a reload - if (Auth::attempt(['username' => $data['username'], 'password' => $data['password']])) { - Log::notice(__METHOD__ . ':' . __LINE__ . ' User (' . $data['username'] . ') has logged in from ' . request()->ip()); - $this->dispatch('login-close'); - $this->dispatch('reloadPage'); - - return; - } - - // Wrong login: stay on the modal and update the rendering. - $this->addError('wrongLogin', 'Wrong login or password.'); - Log::error(__METHOD__ . ':' . __LINE__ . ' User (' . $data['username'] . ') has tried to log in from ' . request()->ip()); - } - - /** - * Check whether any user has a 2FA credential set. - * - * @return bool - */ - public function getCanUse2faProperty(): bool - { - return WebAuthnCredential::query()->whereNull('disabled_at')->count() > 0; - } - - /** - * List the Oauth providers which are enabled. - * - * @return string[] - */ - public function getAvailableOauthProperty(): array - { - $oauthAvailable = []; - - foreach (OauthProvidersType::cases() as $oauthProvider) { - $client_id = config('services.' . $oauthProvider->value . '.client_id'); - if ($client_id === null || $client_id === '') { - continue; - } - - $oauthAvailable[] = $oauthProvider->value; - } - - return $oauthAvailable; - } -} diff --git a/app/Livewire/Components/Modules/Diagnostics/AbstractPreSection.php b/app/Livewire/Components/Modules/Diagnostics/AbstractPreSection.php deleted file mode 100644 index e490dfa8588..00000000000 --- a/app/Livewire/Components/Modules/Diagnostics/AbstractPreSection.php +++ /dev/null @@ -1,46 +0,0 @@ -can = Gate::check(SettingsPolicy::CAN_SEE_DIAGNOSTICS, Configs::class); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - final public function render(): View - { - return view('livewire.modules.diagnostics.pre'); - } - - /** - * Defined the data to be displayed. - * - * @return string[] - */ - abstract public function getDataProperty(): array; - - /** - * Defined the title to be displayed. - * - * @return string - */ - abstract public function getTitleProperty(): string; -} diff --git a/app/Livewire/Components/Modules/Diagnostics/Configurations.php b/app/Livewire/Components/Modules/Diagnostics/Configurations.php deleted file mode 100644 index ccde9c5517a..00000000000 --- a/app/Livewire/Components/Modules/Diagnostics/Configurations.php +++ /dev/null @@ -1,18 +0,0 @@ -can ? resolve(Configuration::class)->get() : []; - } -} diff --git a/app/Livewire/Components/Modules/Diagnostics/Errors.php b/app/Livewire/Components/Modules/Diagnostics/Errors.php deleted file mode 100644 index c7f29999e78..00000000000 --- a/app/Livewire/Components/Modules/Diagnostics/Errors.php +++ /dev/null @@ -1,73 +0,0 @@ -
-	Diagnostics
-	-----------
-	    ' . __('lychee.LOADING') . ' ...
-
-'; - } - - public function getTitleProperty(): string - { - return 'Diagnostics'; - } - - /** - * Computable property to access the errors. - * If we are not ready to load, we return an empty array. - * - * @return array - */ - public function getDataProperty(): array - { - return collect(resolve(DiagnosticsErrors::class)->get())->map(function ($line) { - $arr = ['color' => '', 'type' => '', 'line' => $line]; - - if (Str::startsWith($line, 'Warning: ')) { - $arr['color'] = 'text-warning-600'; - $arr['type'] = 'Warning:'; - $arr['line'] = Str::substr($line, 9); - } - - if (Str::startsWith($line, 'Info: ')) { - $arr['color'] = 'text-primary-400'; - $arr['type'] = 'Info:'; - $arr['line'] = Str::substr($line, 6); - } - - if (Str::startsWith($line, 'Error: ')) { - // @codeCoverageIgnoreStart - $arr['color'] = 'text-danger-600'; - $arr['type'] = 'Error:'; - $arr['line'] = Str::substr($line, 7); - // @codeCoverageIgnoreEnd - } - - return $arr; - })->all(); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - final public function render(): View - { - return view('livewire.modules.diagnostics.pre-colored'); - } -} diff --git a/app/Livewire/Components/Modules/Diagnostics/Infos.php b/app/Livewire/Components/Modules/Diagnostics/Infos.php deleted file mode 100644 index e49393c5c4e..00000000000 --- a/app/Livewire/Components/Modules/Diagnostics/Infos.php +++ /dev/null @@ -1,18 +0,0 @@ -can ? resolve(Info::class)->get() : []; - } -} diff --git a/app/Livewire/Components/Modules/Diagnostics/Space.php b/app/Livewire/Components/Modules/Diagnostics/Space.php deleted file mode 100644 index ed177ea0ba3..00000000000 --- a/app/Livewire/Components/Modules/Diagnostics/Space.php +++ /dev/null @@ -1,54 +0,0 @@ -diagnostics = resolve(DiagnosticsSpace::class); - $this->action = __('lychee.DIAGNOSTICS_GET_SIZE'); - $this->can = Gate::check(SettingsPolicy::CAN_SEE_DIAGNOSTICS, Configs::class); - } - - public function getTitleProperty(): string - { - return 'Space Usage'; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.modules.diagnostics.with-action-call'); - } - - /** - * Return the size used by Lychee. - * We now separate this from the initial get() call as this is quite time consuming. - * - * @return void - */ - public function do(): void - { - Gate::authorize(SettingsPolicy::CAN_SEE_DIAGNOSTICS, Configs::class); - $this->result = $this->diagnostics->get(); - } -} diff --git a/app/Livewire/Components/Modules/Jobs/Feedback.php b/app/Livewire/Components/Modules/Jobs/Feedback.php deleted file mode 100644 index 1b9819cc87b..00000000000 --- a/app/Livewire/Components/Modules/Jobs/Feedback.php +++ /dev/null @@ -1,86 +0,0 @@ -display = false; - - return; - } - - $this->open = Configs::getValueAsBool('current_job_processing_visible'); - $this->display = Configs::getValueAsBool('job_processing_queue_visible'); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.modules.jobs.feedback'); - } - - /** - * Return the list of current Jobs that will be created & possibly processed. - * - * @return Collection Jobs - */ - public function getJobHistoryProperty(): Collection - { - return JobHistory::query() - ->where('owner_id', '=', Auth::id()) - ->whereIn('status', [JobStatus::READY, JobStatus::STARTED]) - ->orderBy('status', OrderSortingType::DESC->value) - ->orderBy('created_at', OrderSortingType::ASC->value) - ->get(); - } - - /** - * Return the Number of jobs ready. - * - * @return int - */ - public function getNumReadyProperty(): int - { - return JobHistory::query() - ->where('owner_id', '=', Auth::id()) - ->where('status', '=', JobStatus::READY) - ->count(); - } - - /** - * Return the Number of jobs ready. - * - * @return int - */ - public function getNumStartedProperty(): int - { - return JobHistory::query() - ->where('owner_id', '=', Auth::id()) - ->where('status', '=', JobStatus::STARTED) - ->count(); - } -} diff --git a/app/Livewire/Components/Modules/Maintenance/Cleaning.php b/app/Livewire/Components/Modules/Maintenance/Cleaning.php deleted file mode 100644 index 5d756d1c7d8..00000000000 --- a/app/Livewire/Components/Modules/Maintenance/Cleaning.php +++ /dev/null @@ -1,116 +0,0 @@ -path = $path; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.modules.maintenance.cleaning'); - } - - /** - * Clean the path from all files excluding $this->skip. - * - * @return void - */ - public function do(): void - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - if ($this->getNoFileFoundProperty()) { - return; - } - - $dirs = []; - $files = []; - foreach (new \DirectoryIterator($this->path) as $fileInfo) { - if ($fileInfo->isDot()) { - continue; - } - if (in_array($fileInfo->getFilename(), $this->skip, true)) { - continue; - } - $this->result[] = sprintf(__('maintenance.cleaning.result'), $fileInfo->getFilename()); - - if ($fileInfo->isDir()) { - $dirs[] = $fileInfo->getRealPath(); - rmdir($fileInfo->getRealPath()); - continue; - } - $files[] = $fileInfo->getRealPath(); - unlink($fileInfo->getRealPath()); - } - } - - /** - * Check whether there are files to be removed. - * If not, we will not display the module to reduce complexity. - * - * @return bool - */ - public function getNoFileFoundProperty(): bool - { - if (!is_dir($this->path)) { - Log::warning('directory ' . $this->path . ' not found!'); - - return true; - } - - if (!(new \FilesystemIterator($this->path))->valid()) { - return true; - } - - $files_found = false; - foreach (new \DirectoryIterator($this->path) as $fileInfo) { - if ($fileInfo->isDot()) { - continue; - } - if (in_array($fileInfo->getFilename(), $this->skip, true)) { - continue; - } - $files_found = true; - } - - return $files_found === false; - } -} diff --git a/app/Livewire/Components/Modules/Maintenance/FixTree.php b/app/Livewire/Components/Modules/Maintenance/FixTree.php deleted file mode 100644 index 53a10dcb814..00000000000 --- a/app/Livewire/Components/Modules/Maintenance/FixTree.php +++ /dev/null @@ -1,62 +0,0 @@ - */ - #[Locked] public array $stats; - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - $query = Album::query(); - - $this->stats = $query->countErrors(); - - return view('livewire.modules.maintenance.fix-tree'); - } - - /** - * Clean the path from all files excluding $this->skip. - * - * @return void - */ - public function do(): void - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - $query = Album::query(); - $this->result = $query->fixTree(); - } - - /** - * Check whether there are files to be removed. - * If not, we will not display the module to reduce complexity. - * - * @return bool - */ - public function getNoErrorsFoundProperty(): bool - { - return 0 === ($this->stats['oddness'] ?? 0) + ($this->stats['duplicates'] ?? 0) + ($this->stats['wrong_parent'] ?? 0) + ($this->stats['missing_parent'] ?? 0); - } -} diff --git a/app/Livewire/Components/Modules/Maintenance/GenSizeVariants.php b/app/Livewire/Components/Modules/Maintenance/GenSizeVariants.php deleted file mode 100644 index 746bf7152b7..00000000000 --- a/app/Livewire/Components/Modules/Maintenance/GenSizeVariants.php +++ /dev/null @@ -1,137 +0,0 @@ -svHelpers = new SizeVariantDimensionHelpers(); - } - - /** - * Mount depending of the path. - * - * @param string $type to generate for - * - * @return void - */ - public function mount(string $type): void - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - $this->type = $type; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - return view('livewire.modules.maintenance.gen-sizevariants'); - } - - /** - * Generates missing size variants by chunk of 100. - * - * @return void - */ - public function do(): void - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - $photos = Photo::query() - ->where('type', 'like', 'image/%') - ->with('size_variants') - ->whereDoesntHave('size_variants', function (Builder $query) { - $query->where('type', '=', $this->getSvProperty()); - }) - ->take(100) - ->get(); - - // Initialize factory for size variants - $sizeVariantFactory = resolve(SizeVariantFactory::class); - - $generated = 0; - /** @var Photo $photo */ - foreach ($photos as $photo) { - $sizeVariantFactory->init($photo); - $sizeVariant = $sizeVariantFactory->createSizeVariantCond($this->getSvProperty()); - if ($sizeVariant !== null) { - $generated++; - Log::notice($this->type . ' (' . $sizeVariant->width . 'x' . $sizeVariant->height . ') for ' . $photo->title . ' created.'); - } else { - Log::error('Did not create ' . $this->type . ' for ' . $photo->title . '.'); - } - } - - $this->notify(sprintf(__('maintenance.gen-sizevariants.success'), $generated, $this->getSvProperty()->name())); - } - - /** - * Check how many images needs to be created. - * - * @return int - */ - public function getNumberOfSizeVariantsToGenerateProperty(): int - { - if (!$this->svHelpers->isEnabledByConfiguration($this->getSvProperty())) { - return 0; - } - - $numGenerated = SizeVariant::query()->where('type', '=', $this->getSvProperty())->count(); - - $totalToHave = SizeVariant::query()->where(fn ($q) => $q - ->when($this->svHelpers->getMaxWidth($this->getSvProperty()) !== 0, fn ($q1) => $q1->where('width', '>', $this->svHelpers->getMaxWidth($this->getSvProperty()))) - ->when($this->svHelpers->getMaxHeight($this->getSvProperty()) !== 0, fn ($q2) => $q2->orWhere('height', '>', $this->svHelpers->getMaxHeight($this->getSvProperty()))) - ) - ->where('type', '=', SizeVariantType::ORIGINAL) - ->count(); - - return $totalToHave - $numGenerated; - } - - /** - * Easy accessor for the Enum type. - * - * @return SizeVariantType - */ - public function getSvProperty(): SizeVariantType - { - return SizeVariantType::from($this->type); - } -} diff --git a/app/Livewire/Components/Modules/Maintenance/MissingFileSizes.php b/app/Livewire/Components/Modules/Maintenance/MissingFileSizes.php deleted file mode 100644 index e50431bb998..00000000000 --- a/app/Livewire/Components/Modules/Maintenance/MissingFileSizes.php +++ /dev/null @@ -1,93 +0,0 @@ -where('filesize', '=', 0) - // TODO: remove s3 support here. - ->orderBy('id'); - // Internally, only holds $limit entries at once - $variants = $variants_query->lazyById(500); - - $generated = 0; - - foreach ($variants as $variant) { - $variantFile = $variant->getFile(); - if ($variantFile->exists()) { - $variant->filesize = $variantFile->getFilesize(); - if (!$variant->save()) { - Log::error('Failed to update filesize for ' . $variantFile->getRelativePath() . '.'); - } else { - $generated++; - } - } else { - Log::error('No file found at ' . $variantFile->getRelativePath() . '.'); - } - } - - $this->notify(sprintf(__('maintenance.fill-filesize-sizevariants.success'), $generated)); - } - - /** - * Check how many images needs to be created. - * - * @return int - */ - public function getNumberOfMissingSizeProperty(): int - { - return SizeVariant::query() - ->where('filesize', '=', 0) - // TODO: remove s3 support here. - ->count(); - } -} diff --git a/app/Livewire/Components/Modules/Maintenance/Optimize.php b/app/Livewire/Components/Modules/Maintenance/Optimize.php deleted file mode 100644 index f347e1a83bf..00000000000 --- a/app/Livewire/Components/Modules/Maintenance/Optimize.php +++ /dev/null @@ -1,45 +0,0 @@ -result = collect(resolve(OptimizeDb::class)->do()) - ->merge(collect(resolve(OptimizeTables::class)->do())) - ->all(); - } -} diff --git a/app/Livewire/Components/Modules/Maintenance/Update.php b/app/Livewire/Components/Modules/Maintenance/Update.php deleted file mode 100644 index 9159e144d5a..00000000000 --- a/app/Livewire/Components/Modules/Maintenance/Update.php +++ /dev/null @@ -1,102 +0,0 @@ -versionInfo = resolve(VersionInfo::class); - } - - /** - * Mount the component for the first time and load the data. - */ - public function mount(): void - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - - $this->getData(); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.modules.maintenance.update'); - } - - /** - * Checking if any updates are available. - * - * @return void - */ - public function check(): void - { - Gate::authorize(SettingsPolicy::CAN_UPDATE, Configs::class); - $this->can_check = false; - - $gitHubFunctions = resolve(GitHubVersion::class); - $gitHubFunctions->hydrate(true, false); - $this->extra = $gitHubFunctions->getBehindTest(); - $this->can_update = !$gitHubFunctions->isUpToDate() || !$this->versionInfo->fileVersion->isUpToDate(); - } - - /** - * Fetching the data of the installation. - * - * @return void - */ - private function getData(): void - { - /** @var VersionChannelType $channelName */ - $channelName = $this->versionInfo->getChannelName(); - $this->info = $this->versionInfo->fileVersion->getVersion()->toString(); - - if ($channelName !== VersionChannelType::RELEASE) { - if ($this->versionInfo->gitHubFunctions->localHead !== null) { - $branch = $this->versionInfo->gitHubFunctions->localBranch ?? '??'; - $commit = $this->versionInfo->gitHubFunctions->localHead ?? '??'; - $this->info = sprintf('%s (%s)', $branch, $commit); - $this->extra = $this->versionInfo->gitHubFunctions->getBehindTest(); - } else { - // @codeCoverageIgnoreStart - $this->info = 'No git data found.'; - // @codeCoverageIgnoreEnd - } - } - - $this->channelName = $channelName->value; - } -} diff --git a/app/Livewire/Components/Modules/Users/UserLine.php b/app/Livewire/Components/Modules/Users/UserLine.php deleted file mode 100644 index f54912cc3b9..00000000000 --- a/app/Livewire/Components/Modules/Users/UserLine.php +++ /dev/null @@ -1,110 +0,0 @@ -save = resolve(Save::class); - } - - /** - * Given a user, load the properties. - * Note that password stays empty to ensure that we do not update it by mistake. - * - * @param User $user - * - * @return void - */ - public function mount(User $user): void - { - Gate::authorize(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, [User::class]); - - $this->user = $user; - $this->id = $user->id; - $this->username = $user->username; - $this->may_edit_own_settings = $user->may_edit_own_settings; - $this->may_upload = $user->may_upload; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.modules.users.user-line'); - } - - /** - * computed property to check if the state is dirty. - * TODO: See if the dirty state of Livewire is usable instead. - * - * @return bool - */ - public function getHasChangedProperty(): bool - { - return $this->user->username !== $this->username || - $this->user->may_upload !== $this->may_upload || - $this->user->may_edit_own_settings !== $this->may_edit_own_settings || - $this->password !== ''; - } - - /** - * Save modification done to a user. - * Note that an admin can change the password of a user at will. - * - * @return void - */ - public function save(): void - { - if (!$this->areValid(SetUserSettingsRuleSet::rules())) { - return; - } - - Gate::authorize(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, [User::class]); - - $this->save->do( - $this->user, - $this->username, - $this->password, - $this->may_upload, - $this->may_edit_own_settings - ); - $this->password = ''; // Reset - $this->notify(__('lychee.CHANGE_SUCCESS')); - } -} diff --git a/app/Livewire/Components/Pages/AllSettings.php b/app/Livewire/Components/Pages/AllSettings.php deleted file mode 100644 index 6429d9afbf4..00000000000 --- a/app/Livewire/Components/Pages/AllSettings.php +++ /dev/null @@ -1,75 +0,0 @@ -form->setConfigs(Configs::orderBy('cat', 'asc')->get()); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.all-settings'); - } - - /** - * Open Saving confirmation modal. - * - * @return void - */ - public function openConfirmSave(): void - { - $this->openModal('forms.confirms.save-all'); - } - - /** - * Save everything. - * - * @return void - */ - #[On('saveAll')] - public function saveAll(): void - { - Gate::authorize(SettingsPolicy::CAN_EDIT, [Configs::class]); - - $this->form->save(); - } - - public function back(): mixed - { - $this->dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('settings'), true); - } -} diff --git a/app/Livewire/Components/Pages/Diagnostics.php b/app/Livewire/Components/Pages/Diagnostics.php deleted file mode 100644 index a09e8ae2220..00000000000 --- a/app/Livewire/Components/Pages/Diagnostics.php +++ /dev/null @@ -1,34 +0,0 @@ -dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } - - #[On('reloadPage')] - public function reloadPage(): void - { - $this->render(); - } -} diff --git a/app/Livewire/Components/Pages/Frame.php b/app/Livewire/Components/Pages/Frame.php deleted file mode 100644 index ba6c3688476..00000000000 --- a/app/Livewire/Components/Pages/Frame.php +++ /dev/null @@ -1,128 +0,0 @@ -albumId = $albumId ?? (($randomAlbumId !== '') ? $randomAlbumId : null); - - $album = $this->albumId === null ? null : $this->albumFactory->findAbstractAlbumOrFail($this->albumId); - Gate::authorize(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $album]); - - $this->title = $album?->title; - $this->loadPhoto(); - $this->timeout = Configs::getValueAsInt('mod_frame_refresh'); - $this->back = $albumId !== null ? route('livewire-gallery-album', ['albumId' => $albumId]) : route('livewire-gallery'); - } - - /** - * @param int $retries - * - * @return array - * - * @throws InternalLycheeException - * @throws ModelNotFoundException - * @throws InvalidSmartIdException - * @throws PhotoCollectionEmptyException - * @throws IllegalOrderOfOperationException - */ - #[Renderless] - public function loadPhoto(int $retries = 5): array - { - // avoid infinite recursion - if ($retries === 0) { - $this->src = ''; - $this->srcset = ''; - - return ['src' => '', 'srcset' => '']; - } - - // default query - $query = $this->photoQueryPolicy->applySearchabilityFilter(Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links'])); - - if ($this->albumId !== null) { - $query = $this->albumFactory->findAbstractAlbumOrFail($this->albumId) - ->photos() - ->with(['album', 'size_variants', 'size_variants.sym_links']); - } - - /** @var ?Photo $photo */ - // PHPStan does not understand that `firstOrFail` returns `Photo`, but assumes that it returns `Model` - // @phpstan-ignore-next-line - $photo = $query->inRandomOrder()->first(); - if ($photo === null) { - $this->title === null ? - throw new PhotoCollectionEmptyException() : throw new PhotoCollectionEmptyException('Photo collection of ' . $this->title . ' is empty'); - } - - // retry - if ($photo->isVideo()) { - return $this->loadPhoto($retries - 1); - } - - $this->src = $photo->size_variants->getMedium()?->url ?? $photo->size_variants->getOriginal()?->url; - - if ($photo->size_variants->getMedium() !== null && $photo->size_variants->getMedium2x() !== null) { - $this->srcset = $photo->size_variants->getMedium()->url . ' ' . $photo->size_variants->getMedium()->width . 'w'; - $this->srcset .= $photo->size_variants->getMedium2x()->url . ' ' . $photo->size_variants->getMedium2x()->width . 'w'; - } else { - $this->srcset = ''; - } - - return ['src' => $this->src, 'srcset' => $this->srcset]; - } - - public function boot(): void - { - $this->albumFactory = resolve(AlbumFactory::class); - $this->photoQueryPolicy = resolve(PhotoQueryPolicy::class); - } -} diff --git a/app/Livewire/Components/Pages/Gallery/Album.php b/app/Livewire/Components/Pages/Gallery/Album.php deleted file mode 100644 index a96cd1b23c0..00000000000 --- a/app/Livewire/Components/Pages/Gallery/Album.php +++ /dev/null @@ -1,269 +0,0 @@ -albumFactory = resolve(AlbumFactory::class); - $this->layouts = new Layouts(); - $this->albumsCollection = new ProtectedCollection(type: 'album'); - $this->photosCollection = new ProtectedCollection(type: 'photo'); - } - - public function mount(string $albumId, string $photoId = ''): void - { - $this->albumId = $albumId; - $this->photoId = $photoId; - $this->flags = new AlbumFlags(); - - $this->reloadPage(); - } - - /** - * Rendering of the blade template. - * - * @return View - */ - final public function render(): View - { - $this->sessionFlags = SessionFlags::get(); - $this->rights = AlbumRights::make($this->album); - $this->num_albums = 0; - $this->num_albums = 0; - - if ($this->flags->is_accessible) { - $this->formatted = new AlbumFormatted($this->album, $this->fetchHeaderUrl()?->url); - $this->num_users = User::count(); - - $this->photosCollection->set($this->album->photos); - $this->num_photos = $this->photosCollection->get()->count(); - - // No photos, no frame - if ($this->num_photos === 0) { - $this->flags->is_mod_frame_enabled = false; - } - - if ($this->album instanceof ModelsAlbum) { - $this->albumsCollection->set($this->album->children()->getResults()); - $this->num_albums = $this->albumsCollection->get()->count(); - } else { - $this->albumsCollection->set(null); - } - - $is_latitude_longitude_found = false; - if ($this->album instanceof ModelsAlbum) { - $is_latitude_longitude_found = $this->album->all_photos()->whereNotNull('latitude')->whereNotNull('longitude')->count() > 0; - $aspectRatio = $this->album->album_thumb_aspect_ratio ?? Configs::getValueAsEnum('default_album_thumb_aspect_ratio', AspectRatioType::class); - $this->flags->album_thumb_css_aspect_ratio = $aspectRatio->css(); - $this->flags->cover_id = $this->album->cover_id; - } else { - $is_latitude_longitude_found = $this->album->photos()->whereNotNull('latitude')->whereNotNull('longitude')->count() > 0; - } - // Only display if there are actual data - $this->flags->is_map_accessible = $this->flags->is_map_accessible && $is_latitude_longitude_found; - - $this->photoFlags = new PhotoFlags( - can_autoplay: true, - can_rotate: Configs::getValueAsBool('editor_enabled'), - can_edit: $this->rights->can_edit, - ); - } else { - $this->albumsCollection->set(null); - $this->photosCollection->set(collect([])); - } - - return view('livewire.pages.gallery.album'); - } - - /** - * Reload the data. - * - * @return void - */ - #[On('reloadPage')] - public function reloadPage(): void - { - $this->album = $this->albumFactory->findAbstractAlbumOrFail($this->albumId); - $this->flags->is_base_album = $this->album instanceof BaseAlbum; - $this->flags->is_search_accessible = $this->flags->is_search_accessible && $this->album instanceof ModelsAlbum; - $this->flags->is_accessible = Gate::check(AlbumPolicy::CAN_ACCESS, [ModelsAlbum::class, $this->album]); - - if (!$this->flags->is_accessible) { - $this->flags->is_password_protected = - $this->album->public_permissions() !== null && - $this->album->public_permissions()->password !== null; - } - - if (Auth::check() && !$this->flags->is_accessible && !$this->flags->is_password_protected) { - $this->redirect(route('livewire-gallery')); - } - } - - /** - * Fetch the header url. - * - * @return SizeVariant|null - * - * @throws QueryBuilderException - * @throws RelationNotFoundException - */ - private function fetchHeaderUrl(): SizeVariant|null - { - $headerSizeVariant = null; - - if (Configs::getValueAsBool('use_album_compact_header')) { - return null; - } - - if ($this->album instanceof ModelsAlbum && $this->album->header_id === SetHeader::COMPACT_HEADER) { - return null; - } - - if ($this->album->photos->isEmpty()) { - return null; - } - - if ($this->album instanceof ModelsAlbum && $this->album->header_id !== null) { - $headerSizeVariant = SizeVariant::query() - ->where('photo_id', '=', $this->album->header_id) - ->whereIn('type', [SizeVariantType::MEDIUM, SizeVariantType::SMALL2X, SizeVariantType::SMALL]) - ->orderBy('type', 'asc') - ->first(); - } - - if ($headerSizeVariant !== null) { - return $headerSizeVariant; - } - - $query_ratio = SizeVariant::query() - ->select('photo_id') - ->whereBelongsTo($this->album->photos) - ->where('ratio', '>', 1) // ! we prefer landscape first. - ->whereIn('type', [SizeVariantType::MEDIUM, SizeVariantType::SMALL2X, SizeVariantType::SMALL]); - $num = $query_ratio->count() - 1; - $photo = $query_ratio->skip(rand(0, $num))->first(); - - if ($photo === null) { - $query = SizeVariant::query() - ->select('photo_id') - ->whereBelongsTo($this->album->photos) - ->whereIn('type', [SizeVariantType::MEDIUM, SizeVariantType::SMALL2X, SizeVariantType::SMALL]); - $num = $query->count() - 1; - $photo = $query->skip(rand(0, $num))->first(); - } - - return $photo === null ? null : SizeVariant::query() - ->where('photo_id', '=', $photo->photo_id) - ->where('type', '>', 1) - ->orderBy('type', 'asc') - ->first(); - } - - public function getBackProperty(): string - { - if ($this->album instanceof ModelsAlbum && $this->album->parent_id !== null) { - return route('livewire-gallery-album', ['albumId' => $this->album->parent_id]); - } - - return route('livewire-gallery'); - } - - public function getTitleProperty(): string - { - return $this->album->title; - } - - #[Renderless] - public function setCover(?string $photoID): void - { - if (!$this->album instanceof ModelsAlbum) { - return; - } - - Gate::authorize(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $this->album]); - - $photo = $photoID === null ? null : Photo::query()->findOrFail($photoID); - if ($photo !== null) { - Gate::authorize(PhotoPolicy::CAN_SEE, [Photo::class, $photo]); - } - - $this->album->cover_id = ($this->album->cover_id === $photo->id) ? null : $photo->id; - $this->album->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } - - #[Renderless] - #[On('setAsCover')] - public function setAsCover(string $albumID): void - { - if (!$this->album instanceof ModelsAlbum) { - return; - } - - Gate::authorize(AlbumPolicy::CAN_EDIT_ID, [AbstractAlbum::class, $this->album]); - // We are freezing this cover to the album and to the child. - - /** @var ModelsAlbum $child */ - $child = $this->albumFactory->findAbstractAlbumOrFail($albumID); - - $this->album->cover_id = ($this->album->cover_id === $child->thumb->id) ? null : $child->thumb->id; - $this->album->save(); - $this->notify(__('lychee.CHANGE_SUCCESS')); - } - - public function getAlbumFormattedProperty(): AlbumFormatted - { - return $this->formatted; - } - - public function getNoImagesAlbumsMessageProperty(): string - { - return 'Nothing to see here'; - } -} diff --git a/app/Livewire/Components/Pages/Gallery/Albums.php b/app/Livewire/Components/Pages/Gallery/Albums.php deleted file mode 100644 index 91524d6e9e6..00000000000 --- a/app/Livewire/Components/Pages/Gallery/Albums.php +++ /dev/null @@ -1,131 +0,0 @@ -flags = new AlbumsFlags(); - $this->rights = AlbumRights::make(null); - $this->checkFrameAccess(); - - return view('livewire.pages.gallery.albums'); - } - - public function mount(): void - { - $this->sessionFlags = SessionFlags::get(); - } - - #[On('reloadPage')] - public function reloadPage(): void - { - $this->topAlbums = resolve(Top::class)->get(); - } - - public function boot(): void - { - $this->topAlbums = resolve(Top::class)->get(); - $this->title = Configs::getValueAsString('site_title'); - } - - /** - * @return Collection - */ - public function getAlbumsProperty(): Collection - { - return $this->topAlbums->albums; - } - - /** - * @return Collection - */ - public function getSmartAlbumsProperty(): Collection - { - return $this->topAlbums->smart_albums - ->concat($this->topAlbums->tag_albums); - } - - /** - * @return Collection - */ - public function getSharedAlbumsProperty(): Collection - { - return $this->topAlbums?->shared_albums ?? collect([]); - } - - private function checkFrameAccess(): void - { - if ($this->flags->is_mod_frame_enabled !== true) { - return; - } - - $randomAlbumId = Configs::getValueAsString('random_album_id'); - $album = resolve(AlbumFactory::class)->findAbstractAlbumOrFail($randomAlbumId); - if (Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $album]) !== true) { - $this->flags->is_mod_frame_enabled = false; - - return; - } - - $this->flags->is_mod_frame_enabled = $album->photos->count() > 0; - } - - public function getIsLoginLeftProperty(): bool - { - return Configs::getValueAsString('login_button_position') === 'left'; - } - - /** - * Used in the JS front-end to manage the selected albums. - * - * @return string[] - */ - public function getAlbumIDsProperty(): array - { - return $this->topAlbums->albums->map(fn ($v, $k) => $v->id)->all(); - } -} diff --git a/app/Livewire/Components/Pages/Gallery/BaseAlbumComponent.php b/app/Livewire/Components/Pages/Gallery/BaseAlbumComponent.php deleted file mode 100644 index beb5a4e00e7..00000000000 --- a/app/Livewire/Components/Pages/Gallery/BaseAlbumComponent.php +++ /dev/null @@ -1,170 +0,0 @@ - */ - protected ?ProtectedCollection $albumsCollection; - - /** @var ProtectedCollection<\App\Models\Photo> */ - protected ?ProtectedCollection $photosCollection; - - #[Locked] public ?string $albumId = null; - #[Locked] public ?string $photoId = null; - #[Locked] public int $num_albums = 0; - #[Locked] public int $num_photos = 0; - #[Locked] public int $num_users = 0; - #[Locked] public PhotoFlags $photoFlags; - #[Locked] public AlbumFlags $flags; - #[Locked] public AlbumRights $rights; - public SessionFlags $sessionFlags; - - /** - * Rendering of the blade template. - * - * @return View - */ - abstract public function render(): View; - - /** - * Return the photoIDs (no need to wait to compute the geometry). - * - * @return PhotoCollectionResource - */ - final public function getPhotosResourceProperty(): PhotoCollectionResource - { - return PhotoCollectionResource::make($this->getPhotosProperty()); - } - - /** - * Return the photoIDs (no need to wait to compute the geometry). - * - * @return Collection|LengthAwarePaginator - */ - public function getPhotosProperty(): Collection|LengthAwarePaginator - { - return $this->photosCollection->get(); - } - - /** - * Return the albums. - * - * @return Collection|null - */ - final public function getAlbumsProperty(): Collection|null - { - return $this->albumsCollection->get(); - } - - /** - * Used in the JS front-end to manage the selected albums. - * - * @return string[] - */ - final public function getAlbumIDsProperty(): array - { - return $this->albumsCollection->get()?->map(fn ($v, $_k) => $v->id)?->all() ?? []; - } - - /** - * Back property used to retrieve the URL to step back and back arrow. - * - * @return string - */ - abstract public function getBackProperty(): string; - - /** - * Title property for the header. - * - * @return string - */ - abstract public function getTitleProperty(): string; - - /** - * Data for Details & Hero. - * - * @return AlbumFormatted|null - */ - abstract public function getAlbumFormattedProperty(): AlbumFormatted|null; - - /** - * Return the data used to generate the layout on the front-end. - * - * @return Layouts - */ - final public function getLayoutsProperty(): Layouts - { - return $this->layouts; - } - - /** - * Getter for the license types in the front-end. - * - * @return array associated array of license type and their localization - */ - final public function getLicensesProperty(): array - { - return LicenseType::localized(); - } - - /** - * Getter for the OverlayType displayed in photoView. - * - * @return string enum - */ - final public function getOverlayTypeProperty(): string - { - return Configs::getValueAsEnum('image_overlay_type', ImageOverlayType::class)->value; - } - - final public function getMapProviderProperty(): MapProviders - { - return Configs::getValueAsEnum('map_provider', MapProviders::class); - } - - /** - * Message displayed when no result or the page is empty. - * - * @return string - */ - abstract public function getNoImagesAlbumsMessageProperty(): string; -} diff --git a/app/Livewire/Components/Pages/Gallery/Search.php b/app/Livewire/Components/Pages/Gallery/Search.php deleted file mode 100644 index 39e9c78e904..00000000000 --- a/app/Livewire/Components/Pages/Gallery/Search.php +++ /dev/null @@ -1,173 +0,0 @@ - */ - private LengthAwarePaginator $photos; - - #[Locked] - #[Url(history: true)] - public string $urlQuery = ''; - public string $searchQuery = ''; // ! Wired - private AlbumFactory $albumFactory; - public ?ModelsAlbum $album = null; - - /** @var string[] */ - protected array $terms = []; - - #[Locked] - public int $search_minimum_length_required; - - public function boot(): void - { - $this->layouts = new Layouts(); - $this->albumSearch = resolve(AlbumSearch::class); - $this->photoSearch = resolve(PhotoSearch::class); - $this->albumsCollection = new ProtectedCollection(type: 'album', is_loaded: true, collection: collect([])); - $this->photosCollection = new ProtectedCollection(type: 'photo'); - $this->photos = new LengthAwarePaginator([], 0, 200); - $this->num_albums = 0; - $this->num_photos = 0; - $this->search_minimum_length_required = Configs::getValueAsInt('search_minimum_length_required'); - $this->albumFactory = resolve(AlbumFactory::class); - } - - public function mount(string $albumId = ''): void - { - if (!Auth::check() && !Configs::getValueAsBool('search_public')) { - redirect(route('livewire-gallery')); - } - - $this->rights = AlbumRights::make(null); - - $this->flags = new AlbumFlags(); - $this->photoFlags = new PhotoFlags( - can_autoplay: true, - can_rotate: Configs::getValueAsBool('editor_enabled'), - can_edit: false, - ); - $this->sessionFlags = SessionFlags::get(); - $this->flags->is_base_album = false; - $this->flags->is_accessible = true; - if ($albumId === '') { - $this->album = null; - } else { - $album = $this->albumFactory->findAbstractAlbumOrFail($albumId); - if ($album instanceof ModelsAlbum) { - $this->album = $album; - $this->flags->cover_id = $this->album->cover_id; - } else { - $this->album = null; - } - } - } - - /** - * Whenever searchQuery is updated, we recompute the urlQuery. - * - * @return void - */ - public function updatedSearchQuery(): void - { - $this->urlQuery = base64_encode($this->searchQuery); - } - - /** - * Render component. - * - * @return View - */ - public function render(): View - { - $this->searchQuery = base64_decode($this->urlQuery, true); - $this->terms = explode(' ', str_replace( - ['\\', '%', '_'], - ['\\\\', '\\%', '\\_'], - $this->searchQuery - )); - - if (strlen($this->searchQuery) >= $this->search_minimum_length_required) { - /** @var LengthAwarePaginator $photoResults */ - /** @disregard P1013 Undefined method withQueryString() (stupid intelephense) */ - $photoResults = $this->photoSearch - ->sqlQuery($this->terms, $this->album) - ->orderBy(ColumnSortingPhotoType::TAKEN_AT->value, OrderSortingType::ASC->value) - ->paginate(Configs::getValueAsInt('search_pagination_limit')) - ->withQueryString(); - $this->photos = $photoResults; - $albumResults = $this->albumSearch->queryAlbums($this->terms); - $this->albumsCollection->set($albumResults); - $this->num_albums = $this->albumsCollection->get()->count(); - $this->num_photos = $this->photos->count(); - $this->albumId = ''; - $this->photoId = ''; - } - /** @var Collection $albumResults */ - - return view('livewire.pages.gallery.search'); - } - - /** - * Return the photos. - * - * @return Collection - */ - public function getPhotosProperty(): Collection - { - return collect($this->photos->items()); - } - - // For now, simple - public function getBackProperty(): string - { - return route('livewire-gallery'); - } - - // For now, simple - public function getTitleProperty(): string - { - return __('lychee.SEARCH'); - } - - public function getAlbumFormattedProperty(): null - { - return null; - } - - public function getNoImagesAlbumsMessageProperty(): string - { - return strlen($this->searchQuery) < 3 ? '' : 'No results'; - } -} diff --git a/app/Livewire/Components/Pages/Gallery/SensitiveWarning.php b/app/Livewire/Components/Pages/Gallery/SensitiveWarning.php deleted file mode 100644 index 75fd651f999..00000000000 --- a/app/Livewire/Components/Pages/Gallery/SensitiveWarning.php +++ /dev/null @@ -1,60 +0,0 @@ -text = Configs::getValueAsString('nsfw_banner_override'); - $this->isBlurred = Configs::getValueAsBool('nsfw_banner_blur_backdrop'); - - // TODO: remember if was open or not. - - if ($album instanceof Album) { - $this->isOpen = $album->is_nsfw; - - if (Auth::user()?->may_administrate === true) { - $this->isOpen = $this->isOpen && Configs::getValueAsBool('nsfw_warning_admin'); - } else { - $this->isOpen = $this->isOpen && Configs::getValueAsBool('nsfw_warning'); - } - } - } - - /** - * Render the associated view. - * - * @return View - */ - public function render(): View - { - return view('livewire.modules.gallery.sensitive-warning'); - } -} diff --git a/app/Livewire/Components/Pages/Jobs.php b/app/Livewire/Components/Pages/Jobs.php deleted file mode 100644 index f19b67dfd62..00000000000 --- a/app/Livewire/Components/Pages/Jobs.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * @throws ConfigurationKeyMissingException - */ - public function getJobsProperty(): Collection - { - return JobHistory::query() - ->orderBy('id', 'desc') - ->limit(Configs::getValueAsInt('log_max_num_line')) - ->get(); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.jobs'); - } - - public function back(): mixed - { - $this->dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } -} diff --git a/app/Livewire/Components/Pages/Landing.php b/app/Livewire/Components/Pages/Landing.php deleted file mode 100644 index 7fee45e3b4d..00000000000 --- a/app/Livewire/Components/Pages/Landing.php +++ /dev/null @@ -1,43 +0,0 @@ -title = Configs::getValueAsString('landing_title'); - $this->subtitle = Configs::getValueAsString('landing_subtitle'); - $background = Configs::getValueAsString('landing_background'); - if (!Str::startsWith($background, 'http')) { - $background = URL::asset($background); - } - $this->background = $background; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.landing'); - } -} diff --git a/app/Livewire/Components/Pages/Login.php b/app/Livewire/Components/Pages/Login.php deleted file mode 100644 index 2d3d632d803..00000000000 --- a/app/Livewire/Components/Pages/Login.php +++ /dev/null @@ -1,52 +0,0 @@ -title = Configs::getValueAsString('site_title'); - $this->can_use_2fa = !Auth::check() && (WebAuthnCredential::query()->whereNull('disabled_at')->count() > 0); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.login'); - } - - public function getIsLoginLeftProperty(): bool - { - return Configs::getValueAsString('login_button_position') === 'left'; - } - - #[On('reloadPage')] - public function reloadPage(): void - { - redirect(route('livewire-gallery')); - } -} diff --git a/app/Livewire/Components/Pages/Maintenance.php b/app/Livewire/Components/Pages/Maintenance.php deleted file mode 100644 index 3c0a25e8394..00000000000 --- a/app/Livewire/Components/Pages/Maintenance.php +++ /dev/null @@ -1,35 +0,0 @@ -dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } -} diff --git a/app/Livewire/Components/Pages/Map.php b/app/Livewire/Components/Pages/Map.php deleted file mode 100644 index 62a4ddb0551..00000000000 --- a/app/Livewire/Components/Pages/Map.php +++ /dev/null @@ -1,91 +0,0 @@ -map_provider = Configs::getValueAsEnum('map_provider', MapProviders::class); - - return view('livewire.pages.gallery.map'); - } - - public function mount(?string $albumId = null): void - { - $this->albumId = $albumId; - - if ($albumId !== null) { - $this->album = $this->albumFactory->findAbstractAlbumOrFail($this->albumId); - $this->title = $this->album->title; - } - - Gate::authorize(AlbumPolicy::CAN_ACCESS_MAP, [AbstractAlbum::class, $this->album]); - } - - /** - * @return array - */ - public function getDataProperty(): array - { - if ($this->albumId === null) { - /** @var array $ret */ - $ret = $this->rootPositionData->do()->toArray(request()); - - return $ret; - } - - $includeSubAlbums = Configs::getValueAsBool('map_include_subalbums'); - - /** @var array $ret */ - $ret = $this->albumPositionData->get($this->album, $includeSubAlbums)->toArray(request()); - - return $ret; - } - - public function boot(): void - { - $this->albumFactory = resolve(AlbumFactory::class); - $this->rootPositionData = resolve(RootPositionData::class); - $this->albumPositionData = resolve(AlbumPositionData::class); - $this->title = Configs::getValueAsString('site_title'); - } - - public function back(): mixed - { - if ($this->albumId === null) { - return $this->redirect(route('livewire-gallery'), true); - } else { - return $this->redirect(route('livewire-gallery-album', ['albumId' => $this->albumId]), true); - } - } -} diff --git a/app/Livewire/Components/Pages/Profile.php b/app/Livewire/Components/Pages/Profile.php deleted file mode 100644 index 5c9f140a387..00000000000 --- a/app/Livewire/Components/Pages/Profile.php +++ /dev/null @@ -1,58 +0,0 @@ -are_notification_active = Configs::getValueAsBool('new_photos_notification'); - $this->is_token_auh_active = config('auth.guards.lychee.driver', 'session-or-token') === 'session-or-token'; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.profile'); - } - - public function back(): mixed - { - $this->dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } -} diff --git a/app/Livewire/Components/Pages/Settings.php b/app/Livewire/Components/Pages/Settings.php deleted file mode 100644 index 46ff7598e47..00000000000 --- a/app/Livewire/Components/Pages/Settings.php +++ /dev/null @@ -1,97 +0,0 @@ -css = Storage::disk('dist')->get('user.css') ?? ''; - $this->js = Storage::disk('dist')->get('custom.js') ?? ''; - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.settings'); - } - - public function back(): mixed - { - $this->dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } - - /** - * Takes the css input text and put it into `dist/user.css`. - * This allows admins to actually personalize the look of their - * installation. - * - * @return void - * - * @throws InsufficientFilesystemPermissions - */ - public function setCSS(): void - { - Gate::authorize(SettingsPolicy::CAN_EDIT, Configs::class); - - if (Storage::disk('dist')->put('user.css', $this->css) === false) { - if (Storage::disk('dist')->get('user.css') !== $this->css) { - throw new InsufficientFilesystemPermissions('Could not save CSS'); - } - } - $this->notify(__('lychee.CHANGE_SUCCESS')); - } - - /** - * Takes the js input text and put it into `dist/custom.js`. - * This allows admins to actually execute custom js code on their - * Lychee-Laravel installation. - * - * @return void - * - * @throws InsufficientFilesystemPermissions - */ - public function setJS(): void - { - Gate::authorize(SettingsPolicy::CAN_EDIT, Configs::class); - - if (Storage::disk('dist')->put('custom.js', $this->js) === false) { - if (Storage::disk('dist')->get('custom.js') !== $this->js) { - throw new InsufficientFilesystemPermissions('Could not save JS'); - } - } - $this->notify(__('lychee.CHANGE_SUCCESS')); - } -} diff --git a/app/Livewire/Components/Pages/Sharing.php b/app/Livewire/Components/Pages/Sharing.php deleted file mode 100644 index a5249aad4fa..00000000000 --- a/app/Livewire/Components/Pages/Sharing.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ - public function getPermsProperty(): array - { - // This could be optimized, but whatever. - return - AccessPermission::with(['album', 'user']) - ->when(!Auth::user()->may_administrate, fn ($q) => $q->whereIn('base_album_id', BaseAlbumImpl::select('id')->where('owner_id', '=', Auth::id()))) - ->whereNotNull('user_id') - ->orderBy('base_album_id', 'asc') - ->get()->all(); - } - - /** - * Set up the profile page. - * - * @return void - * - * @throws ConfigurationKeyMissingException - */ - public function mount(): void - { - Gate::authorize(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, null]); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.sharing'); - } - - public function back(): mixed - { - $this->dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } - - public function delete(int $id): void - { - $perm = AccessPermission::with('album')->findOrFail($id); - Gate::authorize(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $perm->album]); - - AccessPermission::query()->where('id', '=', $id)->delete(); - } -} diff --git a/app/Livewire/Components/Pages/Users.php b/app/Livewire/Components/Pages/Users.php deleted file mode 100644 index d825832b7ee..00000000000 --- a/app/Livewire/Components/Pages/Users.php +++ /dev/null @@ -1,122 +0,0 @@ - */ - public Collection $users; - private Create $create; - - public string $username = ''; - public string $password = ''; - public bool $may_upload = false; - public bool $may_edit_own_settings = false; - - /** - * Init the private properties. - * - * @return void - */ - public function boot(): void - { - $this->create = resolve(Create::class); - } - - /** - * Load users. - * - * @return void - */ - public function mount(): void - { - Gate::authorize(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, User::class); - - $this->loadUsers(); - } - - /** - * Rendering of the front-end. - * - * @return View - */ - public function render(): View - { - return view('livewire.pages.users'); - } - - /** - * Refresh the user List. - * - * @return void - */ - public function loadUsers(): void - { - $this->users = User::orderBy('id', 'asc')->get(); - } - - /** - * Create a new user. - * - * @return void - */ - public function create(): void - { - Gate::authorize(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, User::class); - - // Create user - $this->create->do( - username: $this->username, - password: $this->password, - mayUpload: $this->may_upload, - mayEditOwnSettings: $this->may_edit_own_settings); - - // reset attributes and reload user list (triggers refresh) - $this->username = ''; - $this->password = ''; - $this->may_upload = false; - $this->may_edit_own_settings = false; - $this->loadUsers(); - } - - public function back(): mixed - { - $this->dispatch('closeLeftMenu')->to(LeftMenu::class); - - return $this->redirect(route('livewire-gallery'), true); - } - - /** - * Delete an existing credential. - * - * @param int $id - * - * @return void - */ - public function delete(int $id): void - { - if ($id === Auth::id()) { - throw new UnauthorizedException('You are not allowed to delete yourself'); - } - - Gate::authorize(UserPolicy::CAN_CREATE_OR_EDIT_OR_DELETE, [User::class]); - - User::where('id', '=', $id)->delete(); - $this->loadUsers(); - } -} diff --git a/app/Livewire/DTO/AlbumFlags.php b/app/Livewire/DTO/AlbumFlags.php deleted file mode 100644 index 78636c47e57..00000000000 --- a/app/Livewire/DTO/AlbumFlags.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -class AlbumFlags implements Wireable -{ - /** @phpstan-use UseWireable */ - use UseWireable; - - public function __construct( - public bool $is_accessible = false, - public bool $is_password_protected = false, - public bool $is_map_accessible = false, - public bool $is_base_album = false, - public bool $is_mod_frame_enabled = false, - public bool $is_search_accessible = false, - public string $album_thumb_css_aspect_ratio = '', - public string|null $cover_id = null, - ) { - $this->is_map_accessible = Configs::getValueAsBool('map_display'); - $this->is_map_accessible = $this->is_map_accessible && (Auth::check() || Configs::getValueAsBool('map_display_public')); - $this->is_mod_frame_enabled = Configs::getValueAsBool('mod_frame_enabled'); - $this->album_thumb_css_aspect_ratio = Configs::getValueAsEnum('default_album_thumb_aspect_ratio', AspectRatioType::class)->css(); - $this->is_search_accessible = Auth::check() || Configs::getValueAsBool('search_public'); - } -} \ No newline at end of file diff --git a/app/Livewire/DTO/AlbumRights.php b/app/Livewire/DTO/AlbumRights.php deleted file mode 100644 index 54ee9cb782f..00000000000 --- a/app/Livewire/DTO/AlbumRights.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -class AlbumRights implements Wireable -{ - /** @phpstan-use UseWireable */ - use UseWireable; - - public function __construct( - public bool $can_edit = false, - public bool $can_share = false, - public bool $can_share_with_users = false, - public bool $can_download = false, - public bool $can_upload = false, - public bool $can_move = false, - public bool $can_delete = false, - public bool $can_access_original = false, - ) { - } - - /** - * Builder for easy instanciation. - * - * @param AbstractAlbum $abstractAlbum - * - * @return self - */ - public static function make(?AbstractAlbum $abstractAlbum): AlbumRights - { - return new self( - can_edit: Gate::check(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, $abstractAlbum]), - can_share: Gate::check(AlbumPolicy::CAN_SHARE, [AbstractAlbum::class, $abstractAlbum]), - can_share_with_users: Gate::check(AlbumPolicy::CAN_SHARE_WITH_USERS, [AbstractAlbum::class, $abstractAlbum]), - can_download: Gate::check(AlbumPolicy::CAN_DOWNLOAD, [AbstractAlbum::class, $abstractAlbum]), - can_upload: Gate::check(AlbumPolicy::CAN_UPLOAD, [AbstractAlbum::class, $abstractAlbum]), - can_move: Gate::check(AlbumPolicy::CAN_DELETE, [AbstractAlbum::class, $abstractAlbum]) && $abstractAlbum instanceof Album, - can_delete: Gate::check(AlbumPolicy::CAN_DELETE, [AbstractAlbum::class, $abstractAlbum]), - can_access_original: Gate::check(AlbumPolicy::CAN_ACCESS_FULL_PHOTO, [AbstractAlbum::class, $abstractAlbum]), - ); - } -} diff --git a/app/Livewire/DTO/AlbumsFlags.php b/app/Livewire/DTO/AlbumsFlags.php deleted file mode 100644 index 0a8d1ffaa15..00000000000 --- a/app/Livewire/DTO/AlbumsFlags.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -class AlbumsFlags implements Wireable -{ - /** @phpstan-use UseWireable */ - use UseWireable; - - public function __construct( - public bool $can_edit = false, - public bool $can_use_2fa = false, - public bool $is_map_accessible = false, - public bool $is_mod_frame_enabled = false, - public bool $is_search_accessible = false, - public string $album_thumb_css_aspect_ratio = '', - ) { - $count_locations = Photo::whereNotNull('latitude')->whereNotNull('longitude')->count() > 0; - $this->is_map_accessible = $count_locations && Configs::getValueAsBool('map_display'); - $this->is_map_accessible = $this->is_map_accessible && (Auth::check() || Configs::getValueAsBool('map_display_public')); - $this->is_mod_frame_enabled = Configs::getValueAsBool('mod_frame_enabled'); - $this->can_use_2fa = !Auth::check() && (WebAuthnCredential::query()->whereNull('disabled_at')->count() > 0); - $this->can_edit = Gate::check(AlbumPolicy::CAN_EDIT, [AbstractAlbum::class, null]); - $this->is_search_accessible = Auth::check() || Configs::getValueAsBool('search_public'); - $this->album_thumb_css_aspect_ratio = Configs::getValueAsEnum('default_album_thumb_aspect_ratio', AspectRatioType::class)->css(); - } -} \ No newline at end of file diff --git a/app/Livewire/DTO/Layouts.php b/app/Livewire/DTO/Layouts.php deleted file mode 100644 index 95ed6e9d7b4..00000000000 --- a/app/Livewire/DTO/Layouts.php +++ /dev/null @@ -1,30 +0,0 @@ -photo_layout_justified_row_height ??= Configs::getValueAsInt('photo_layout_justified_row_height'); - $this->photo_layout_masonry_column_width ??= Configs::getValueAsInt('photo_layout_masonry_column_width'); - $this->photo_layout_grid_column_width ??= Configs::getValueAsInt('photo_layout_grid_column_width'); - $this->photo_layout_square_column_width ??= Configs::getValueAsInt('photo_layout_square_column_width'); - $this->photo_layout_gap ??= Configs::getValueAsInt('photo_layout_gap'); - $this->photos_layout ??= Configs::getValueAsEnum('layout', PhotoLayoutType::class)->value; - } - - public function photos_layout(): PhotoLayoutType - { - return PhotoLayoutType::from($this->photos_layout); - } -} diff --git a/app/Livewire/DTO/OauthData.php b/app/Livewire/DTO/OauthData.php deleted file mode 100644 index dd1d747b64b..00000000000 --- a/app/Livewire/DTO/OauthData.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -class OauthData implements Wireable -{ - /** @phpstan-use UseWireable */ - use UseWireable; - - public function __construct( - public string $providerType, - public bool $isEnabled, - public string $registrationRoute, - ) { - } -} \ No newline at end of file diff --git a/app/Livewire/DTO/PhotoFlags.php b/app/Livewire/DTO/PhotoFlags.php deleted file mode 100644 index 126b9df7d23..00000000000 --- a/app/Livewire/DTO/PhotoFlags.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -class PhotoFlags implements Wireable -{ - /** @phpstan-use UseWireable */ - use UseWireable; - - public function __construct( - public bool $can_autoplay, - public bool $can_rotate, - public bool $can_edit, - ) { - } -} \ No newline at end of file diff --git a/app/Livewire/DTO/ProtectedCollection.php b/app/Livewire/DTO/ProtectedCollection.php deleted file mode 100644 index 0939188005e..00000000000 --- a/app/Livewire/DTO/ProtectedCollection.php +++ /dev/null @@ -1,52 +0,0 @@ -|null $collection - * - * @return void - */ - public function __construct( - private string $type, - private bool $is_loaded = false, - private ?Collection $collection = null, - ) { - } - - /** - * @return Collection|null collection encapsulated - * - * @throws LycheeLogicException we queried it too early - */ - public function get(): Collection|null - { - if ($this->is_loaded) { - return $this->collection; - } - - throw new LycheeLogicException(sprintf('Collection %s data is not available.', $this->type)); - } - - /** - * Set the collection. - * - * @param Collection|null $collection - * - * @return void - */ - public function set(Collection|null $collection) - { - $this->is_loaded = true; - $this->collection = $collection; - } -} \ No newline at end of file diff --git a/app/Livewire/DTO/SessionFlags.php b/app/Livewire/DTO/SessionFlags.php deleted file mode 100644 index 5f5190a1c29..00000000000 --- a/app/Livewire/DTO/SessionFlags.php +++ /dev/null @@ -1,34 +0,0 @@ - */ - #[Locked] - public array $configs; - - /** @var string[] */ - public array $values; - - /** - * This allows Livewire to know which values of the $configs we - * want to display in the wire:model. Sort of a white listing. - * - * @var array - */ - protected $rules = [ - 'values.*' => 'nullable', - ]; - - /** - * Initialize form data. - * - * @param Collection $configs - * - * @return void - */ - public function setConfigs(Collection $configs): void - { - // ! IMPORTANT, WE MUST use all() to get an array and not use the collections, - // ! otherwise this messes up the ordering. - $this->configs = $configs->all(); - $this->values = $configs->map(fn (Configs $c, int $k) => $c->value)->all(); - } - - /** - * Save form data. - * - * @return void - * - * @throws ValidationException - * @throws LycheeAssertionError - */ - public function save(): void - { - $this->validate(); - $n = count($this->values); - if ($n !== count($this->configs)) { - throw new LycheeAssertionError('Number of values do not match number of configs'); - } - - for ($idx = 0; $idx < $n; $idx++) { - $c = $this->configs[$idx]; - $candidateValue = $this->values[$idx]; - $template = 'Error: Expected %s, got ' . ($candidateValue ?? 'NULL') . '.'; - - $error_msg = $c->sanity($candidateValue, $template); - if ($error_msg === '') { - $c->value = $candidateValue; - $c->save(); - } else { - $this->addError('values.' . $idx, $error_msg); - } - } - } -} diff --git a/app/Livewire/Forms/ImportFromUrlForm.php b/app/Livewire/Forms/ImportFromUrlForm.php deleted file mode 100644 index caa2790a8c7..00000000000 --- a/app/Livewire/Forms/ImportFromUrlForm.php +++ /dev/null @@ -1,77 +0,0 @@ - - */ - protected function rules(): array - { - return [ - RequestAttribute::ALBUM_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], - RequestAttribute::URLS_ATTRIBUTE => 'required|array|min:1', - RequestAttribute::URLS_ATTRIBUTE . '.*' => 'required|string', - ]; - } - - /** - * split path into paths array. - * - * @return void - */ - public function prepare() - { - $this->urls = array_values(array_filter(explode("\n", $this->urlArea), fn ($elem) => $elem !== '')); - - // The replacement below looks suspicious. - // If it was really necessary, then there would be much more special - // characters (e.i. for example umlauts in international domain names) - // which would require replacement by their corresponding %-encoding. - // However, I assume that the PHP method `fopen` is happily fine with - // any character and internally handles special characters itself. - // Hence, either use a proper encoding method here instead of our - // home-brewed, poor-man replacement or drop it entirely. - // TODO: Find out what is needed and proceed accordingly. - // ? We can't use URL encode because we need to preserve :// and ? - $this->urls = str_replace(' ', '%20', $this->urls); - } - - /** - * Initialize form data. - * - * @param ?string $albumID - * - * @return void - */ - public function init(?string $albumID): void - { - $this->albumID = $albumID; - } - - public function getAlbum(): Album|null - { - /** @var Album $album */ - $album = $this->albumID === null ? null : Album::query()->findOrFail($this->albumID); - - return $album; - } -} diff --git a/app/Livewire/Forms/PhotoUpdateForm.php b/app/Livewire/Forms/PhotoUpdateForm.php deleted file mode 100644 index e8620526dfb..00000000000 --- a/app/Livewire/Forms/PhotoUpdateForm.php +++ /dev/null @@ -1,106 +0,0 @@ -tags = collect(explode(',', $this->tagsWithComma))->map(fn ($v) => trim($v))->filter(fn ($v) => $v !== '')->all(); - $this->date = $this->uploadDate . ':' . $this->uploadTz; - } - - /** - * This allows Livewire to know which values of the $configs we - * want to display in the wire:model. Sort of a white listing. - * - * @return array - */ - protected function rules(): array - { - return [ - RequestAttribute::TITLE_ATTRIBUTE => ['required', new TitleRule()], - ...SetPhotoDescriptionRuleSet::rules(), - RequestAttribute::TAGS_ATTRIBUTE => 'present|array', - RequestAttribute::TAGS_ATTRIBUTE . '.*' => 'required|string|min:1', - RequestAttribute::LICENSE_ATTRIBUTE => ['required', new Enum(LicenseType::class)], - RequestAttribute::DATE_ATTRIBUTE => 'required|date', - ]; - } - - /** - * Validate form. - * - * @return array> - */ - public function validate(): array - { - /** @var Validator $validator */ - $validator = ValidatorFacade::make($this->all(), $this->rules()); - - if ($validator->fails()) { - return $validator->getMessageBag()->messages(); - } - - return []; - } - - /** - * Fetch photo associated with request. - * - * @return Photo - */ - public function getPhoto(): Photo - { - $this->photo = Photo::query()->findOrFail($this->photoID); - - return $this->photo; - } - - /** - * Save data in photo. - * - * @return void - */ - public function save(): void - { - $photo = Photo::query()->where('id', '=', $this->photoID)->first(); - - $photo->title = $this->title; - $photo->description = $this->description; - $photo->created_at = $this->date; - $photo->tags = $this->tags; - $photo->license = LicenseType::from($this->license); - $photo->save(); - } - - /** - * @return array - */ - public function all(): array - { - return Utils::getPublicProperties($this); - } -} diff --git a/app/Livewire/Synth/AlbumFlagsSynth.php b/app/Livewire/Synth/AlbumFlagsSynth.php deleted file mode 100644 index f98a47633d9..00000000000 --- a/app/Livewire/Synth/AlbumFlagsSynth.php +++ /dev/null @@ -1,80 +0,0 @@ -> - */ - public function dehydrate($target): array - { - $result = []; - $cls = new \ReflectionClass(AlbumFlags::class); - $props = $cls->getProperties(\ReflectionProperty::IS_PUBLIC); - foreach ($props as $prop) { - $propertyValue = $prop->getValue($target); - if (is_object($propertyValue)) { - throw new LycheeLogicException(sprintf('wrong value type for %s', get_class($propertyValue))); - } - $result[$prop->getName()] = $propertyValue; - } - - return [$result, []]; - } - - /** - * @param array $value - * - * @return AlbumFlags - */ - public function hydrate($value): AlbumFlags - { - $cls = new \ReflectionClass(AlbumFlags::class); - - /** @var AlbumFlags $flags */ - $flags = $cls->newInstanceWithoutConstructor(); - $props = $cls->getProperties(\ReflectionProperty::IS_PUBLIC); - foreach ($props as $prop) { - $flags->{$prop->getName()} = $value[$prop->getName()]; - } - - return $flags; - } - - /** - * @param AlbumFlags $target - * @param string $key - * - * @return string - */ - public function get(&$target, $key) - { - return $target->{$key}; - } - - /** - * @param AlbumFlags $target - * @param string $key - * @param bool $value - * - * @return void - */ - public function set(&$target, $key, $value) - { - $target->{$key} = $value; - } -} \ No newline at end of file diff --git a/app/Livewire/Synth/AlbumSynth.php b/app/Livewire/Synth/AlbumSynth.php deleted file mode 100644 index d6a62f19094..00000000000 --- a/app/Livewire/Synth/AlbumSynth.php +++ /dev/null @@ -1,42 +0,0 @@ -> - */ - public function dehydrate($target): array - { - return [[ - 'id' => $target->id, - ], []]; - } - - /** - * @param array $value - * - * @return AbstractAlbum - */ - public function hydrate($value): AbstractAlbum - { - /** @var AlbumFactory $albumFactory */ - $albumFactory = resolve(AlbumFactory::class); - - return $albumFactory->findAbstractAlbumOrFail($value['id']); - } -} \ No newline at end of file diff --git a/app/Livewire/Synth/PhotoSynth.php b/app/Livewire/Synth/PhotoSynth.php deleted file mode 100644 index d8e762cf9f3..00000000000 --- a/app/Livewire/Synth/PhotoSynth.php +++ /dev/null @@ -1,38 +0,0 @@ -> - */ - public function dehydrate($target): array - { - return [[ - 'id' => $target->id, - ], []]; - } - - /** - * @param array $value - * - * @return Photo - */ - public function hydrate($value): Photo - { - return Photo::findOrFail($value['id']); - } -} \ No newline at end of file diff --git a/app/Livewire/Synth/SessionFlagsSynth.php b/app/Livewire/Synth/SessionFlagsSynth.php deleted file mode 100644 index a872a7cbf79..00000000000 --- a/app/Livewire/Synth/SessionFlagsSynth.php +++ /dev/null @@ -1,81 +0,0 @@ -> - */ - public function dehydrate($target): array - { - $result = []; - $cls = new \ReflectionClass(SessionFlags::class); - $props = $cls->getProperties(\ReflectionProperty::IS_PUBLIC); - foreach ($props as $prop) { - $propertyValue = $prop->getValue($target); - if (is_object($propertyValue)) { - throw new LycheeLogicException(sprintf('wrong value type for %s', get_class($propertyValue))); - } - $result[$prop->getName()] = $propertyValue; - } - - return [$result, []]; - } - - /** - * @param array $value - * - * @return SessionFlags - */ - public function hydrate($value): SessionFlags - { - $cls = new \ReflectionClass(SessionFlags::class); - - /** @var SessionFlags $flags */ - $flags = $cls->newInstanceWithoutConstructor(); - $props = $cls->getProperties(\ReflectionProperty::IS_PUBLIC); - foreach ($props as $prop) { - $flags->{$prop->getName()} = $value[$prop->getName()]; - } - - return $flags; - } - - /** - * @param SessionFlags $target - * @param string $key - * - * @return string - */ - public function get(&$target, $key) - { - return $target->{$key}; - } - - /** - * @param SessionFlags $target - * @param string $key - * @param bool $value - * - * @return void - */ - public function set(&$target, $key, $value) - { - $target->{$key} = $value; - $target->save(); - } -} \ No newline at end of file diff --git a/app/Livewire/Traits/AlbumsPhotosContextMenus.php b/app/Livewire/Traits/AlbumsPhotosContextMenus.php deleted file mode 100644 index bd7514a9571..00000000000 --- a/app/Livewire/Traits/AlbumsPhotosContextMenus.php +++ /dev/null @@ -1,89 +0,0 @@ -dispatch( - 'openContextMenu', - 'menus.AlbumAdd', - [Params::PARENT_ID => $this->albumId], - 'right: 30px; top: 30px; transform-origin: top right;' - )->to(ContextMenu::class); - } - - #[Renderless] - public function openPhotoDropdown(int $x, int $y, string $photoId): void - { - $this->dispatch( - 'openContextMenu', - 'menus.PhotoDropdown', - [Params::ALBUM_ID => $this->albumId, Params::PHOTO_ID => $photoId], - $this->getCss($x, $y) - )->to(ContextMenu::class); - } - - /** - * @param int $x - * @param int $y - * @param string[] $photoIds - * - * @return void - */ - #[Renderless] - public function openPhotosDropdown(int $x, int $y, array $photoIds): void - { - $this->dispatch( - 'openContextMenu', - 'menus.PhotosDropdown', - [Params::ALBUM_ID => $this->albumId, Params::PHOTO_IDS => $photoIds], - $this->getCss($x, $y) - )->to(ContextMenu::class); - } - - #[Renderless] - public function openAlbumDropdown(int $x, int $y, string $albumID): void - { - $this->dispatch( - 'openContextMenu', - 'menus.AlbumDropdown', - [Params::PARENT_ID => $this->albumId, Params::ALBUM_ID => $albumID], - $this->getCss($x, $y) - )->to(ContextMenu::class); - } - - /** - * @param int $x - * @param int $y - * @param string[] $albumIds - * - * @return void - */ - #[Renderless] - public function openAlbumsDropdown(int $x, int $y, array $albumIds): void - { - $this->dispatch( - 'openContextMenu', - 'menus.AlbumsDropdown', - [Params::PARENT_ID => $this->albumId, Params::ALBUM_IDS => $albumIds], - $this->getCss($x, $y) - )->to(ContextMenu::class); - } - - private function getCss(int $x, int $y): string - { - return sprintf('transform-origin: top left; left: %dpx; top: %dpx;', $x, $y); - } -} diff --git a/app/Livewire/Traits/InteractWithContextMenu.php b/app/Livewire/Traits/InteractWithContextMenu.php deleted file mode 100644 index 168942507ca..00000000000 --- a/app/Livewire/Traits/InteractWithContextMenu.php +++ /dev/null @@ -1,18 +0,0 @@ -dispatch('closeContextMenu')->to(ContextMenu::class); - } -} diff --git a/app/Livewire/Traits/InteractWithModal.php b/app/Livewire/Traits/InteractWithModal.php deleted file mode 100644 index d607ff6113f..00000000000 --- a/app/Livewire/Traits/InteractWithModal.php +++ /dev/null @@ -1,45 +0,0 @@ - $params Parameters for said component - * - * @return void - */ - protected function openModal(string $form, array $params = []): void - { - $this->dispatch('openModal', $form, '', $params)->to(Modal::class); - } - - /** - * Open Modal with form and paramters. - * - * @param string $form Livewire component to include in the modal - * @param string $close_text text to put if we use a close button - * @param array $params Parameters for said component - * - * @return void - */ - protected function openClosableModal(string $form, string $close_text, array $params = []): void - { - $this->dispatch('openModal', $form, $close_text, $params)->to(Modal::class); - } - - /** - * Close the modal. - * - * @return void - */ - protected function closeModal(): void - { - $this->dispatch('closeModal')->to(Modal::class); - } -} diff --git a/app/Livewire/Traits/Notify.php b/app/Livewire/Traits/Notify.php deleted file mode 100644 index 4b2a91ebe3f..00000000000 --- a/app/Livewire/Traits/Notify.php +++ /dev/null @@ -1,24 +0,0 @@ -dispatch('notify', ['msg' => $message, 'type' => $type->value]); - } -} \ No newline at end of file diff --git a/app/Livewire/Traits/SilentUpdate.php b/app/Livewire/Traits/SilentUpdate.php deleted file mode 100644 index 03ad78cb1c7..00000000000 --- a/app/Livewire/Traits/SilentUpdate.php +++ /dev/null @@ -1,23 +0,0 @@ -isOpen = true; - } - - /** - * Close the component. - * - * @return void - */ - #[On('close')] - public function close(): void - { - $this->isOpen = false; - } - - /** - * Toggle the component. - * - * @return void - */ - #[On('toggle')] - public function toggle(): void - { - $this->isOpen = !$this->isOpen; - } -} \ No newline at end of file diff --git a/app/Livewire/Traits/UsePhotoViewActions.php b/app/Livewire/Traits/UsePhotoViewActions.php deleted file mode 100644 index 2804dfb9d1c..00000000000 --- a/app/Livewire/Traits/UsePhotoViewActions.php +++ /dev/null @@ -1,145 +0,0 @@ -validate(); - if ($valdiation !== []) { - $msg = ''; - foreach ($valdiation as $value) { - $msg .= ($msg !== '' ? '
' : '') . implode('
', $value); - } - $this->notify($msg, NotificationType::ERROR); - - return null; - } - - Gate::authorize(PhotoPolicy::CAN_EDIT, [Photo::class, $form->getPhoto()]); - - $form->save(); - - $this->notify(__('lychee.CHANGE_SUCCESS')); - - return PhotoResource::make($form->getPhoto()); - } - - /** - * Flip the star of a given photo. - * - * @param array<0,string> $photoIDarg - * - * @return bool - */ - #[Renderless] - public function toggleStar(array $photoIDarg): bool - { - if (count($photoIDarg) !== 1 || !is_string($photoIDarg[0])) { - $this->notify('wrong ID', NotificationType::ERROR); - - return false; - } - $photo = Photo::query()->findOrFail($photoIDarg[0]); - - Gate::authorize(PhotoPolicy::CAN_EDIT, [Photo::class, $photo]); - $photo->is_starred = !$photo->is_starred; - $photo->save(); - - return true; - } - - /** - * Rotate selected photo Counter ClockWise. - * - * @param string $photoID - * - * @return void - */ - public function rotate_ccw(string $photoID): void - { - if (!Configs::getValueAsBool('editor_enabled')) { - return; - } - - $photo = Photo::query()->findOrFail($photoID); - Gate::authorize(PhotoPolicy::CAN_EDIT, [Photo::class, $photo]); - $rotate = new Rotate($photo, -1); - $photo = $rotate->do(); - // Force hard refresh of the page (to load the rotated image) - $this->redirect(route('livewire-gallery-photo', ['albumId' => $this->albumId, 'photoId' => $photo->id])); - } - - /** - * Rotate selected photo ClockWise. - * - * @param string $photoID - * - * @return void - */ - public function rotate_cw(string $photoID): void - { - if (!Configs::getValueAsBool('editor_enabled')) { - return; - } - - $photo = Photo::query()->findOrFail($photoID); - Gate::authorize(PhotoPolicy::CAN_EDIT, [Photo::class, $photo]); - $rotate = new Rotate($photo, 1); - $photo = $rotate->do(); - // Force hard refresh of the page (to load the rotated image) - $this->redirect(route('livewire-gallery-photo', ['albumId' => $this->albumId, 'photoId' => $photo->id])); - } - - /** - * Set all photos for given id as starred. - * - * @param string[] $photoIDs - * - * @return void - */ - #[Renderless] - public function setStar(array $photoIDs): void - { - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $photoIDs]); - Photo::whereIn('id', $photoIDs)->update(['is_starred' => true]); - } - - /** - * Set all photos for given id as NOT starred. - * - * @param string[] $photoIDs - * - * @return void - */ - #[Renderless] - public function unsetStar(array $photoIDs): void - { - Gate::authorize(PhotoPolicy::CAN_EDIT_ID, [Photo::class, $photoIDs]); - Photo::whereIn('id', $photoIDs)->update(['is_starred' => false]); - } -} \ No newline at end of file diff --git a/app/Livewire/Traits/UseValidator.php b/app/Livewire/Traits/UseValidator.php deleted file mode 100644 index da1cc037c03..00000000000 --- a/app/Livewire/Traits/UseValidator.php +++ /dev/null @@ -1,37 +0,0 @@ -> $rules - * - * @return bool - */ - public function areValid(array $rules): bool - { - /** @var Validator $validator */ - $validator = ValidatorFacade::make($this->all(), $rules); - - if ($validator->fails()) { - $msg = ''; - foreach ($validator->getMessageBag()->messages() as $value) { - $msg .= ($msg !== '' ? '
' : '') . implode('
', $value); - } - $this->dispatch('notify', ['msg' => $msg, 'type' => 'error']); - - return false; - } - - return true; - } -} \ No newline at end of file diff --git a/app/Livewire/Traits/UseWireable.php b/app/Livewire/Traits/UseWireable.php deleted file mode 100644 index f248297dc33..00000000000 --- a/app/Livewire/Traits/UseWireable.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * @throws LycheeLogicException - */ - public function toLivewire(): array - { - $result = []; - $cls = new \ReflectionClass($this); - $props = $cls->getProperties(\ReflectionProperty::IS_PUBLIC); - - foreach ($props as $prop) { - $propertyValue = $prop->getValue($this); - if (is_object($propertyValue)) { - throw new LycheeLogicException(sprintf('Convertion of %s is not supported', get_class($propertyValue))); - } - $result[$prop->getName()] = $propertyValue; - } - - return $result; - } - - /** - * @param mixed $data - * - * @return TModelClass - * - * @throws LycheeLogicException - * @throws \ReflectionException - */ - public static function fromLivewire(mixed $data) - { - if (!is_array($data)) { - throw new LycheeLogicException('data is not an array'); - } - - $cls = new \ReflectionClass(self::class); - - return $cls->newInstanceArgs($data); - } -} \ No newline at end of file diff --git a/app/Metadata/Extractor.php b/app/Metadata/Extractor.php index 94f2bbec1ff..14359f9fdc9 100644 --- a/app/Metadata/Extractor.php +++ b/app/Metadata/Extractor.php @@ -96,6 +96,7 @@ public static function createFromFile(NativeLocalFile $file, int $fileLastModifi // as `application/octet-stream`, but this work-around only // succeeds if the file has a recognized extension. $exif = $reader->read($file->getRealPath()); + // @codeCoverageIgnoreStart } catch (PhpExifReaderException $e) { // thrown by $reader->read if EXIF could not be extracted, // don't give up yet, only log the event @@ -111,6 +112,7 @@ public static function createFromFile(NativeLocalFile $file, int $fileLastModifi throw new MediaFileOperationException('Could not even extract basic EXIF data with the native adapter', $e); } } + // @codeCoverageIgnoreEnd // Attempt to get sidecar metadata if it exists, make sure to check 'real' path in case of symlinks $sidecarData = []; @@ -118,6 +120,7 @@ public static function createFromFile(NativeLocalFile $file, int $fileLastModifi $sidecarFile = new NativeLocalFile($file->getPath() . '.xmp'); if (Configs::hasExiftool() && $sidecarFile->exists()) { + // @codeCoverageIgnoreStart try { // Don't use the same reader as the file in case it's a video $sidecarReader = Reader::factory(ReaderType::EXIFTOOL); @@ -135,6 +138,7 @@ public static function createFromFile(NativeLocalFile $file, int $fileLastModifi } catch (\Exception $e) { Handler::reportSafely($e); } + // @codeCoverageIgnoreEnd } $metadata->type = ($exif->getMimeType() !== false) ? $exif->getMimeType() : $file->getMimeType(); @@ -442,10 +446,12 @@ public static function createFromFile(NativeLocalFile $file, int $fileLastModifi if ($metadata->location !== null) { $metadata->location = substr($metadata->location, 0, self::MAX_LOCATION_STRING_LENGTH); } + // @codeCoverageIgnoreStart } catch (ExternalComponentFailedException|StringsException $e) { Handler::reportSafely($e); $metadata->location = null; } + // @codeCoverageIgnoreEnd return $metadata; } diff --git a/app/Metadata/Json/JsonRequestFunctions.php b/app/Metadata/Json/JsonRequestFunctions.php index 87e1928b8c3..163d2fe9abf 100644 --- a/app/Metadata/Json/JsonRequestFunctions.php +++ b/app/Metadata/Json/JsonRequestFunctions.php @@ -27,6 +27,8 @@ public function init(string $url, int $ttl): void /** * {@inheritDoc} + * + * @codeCoverageIgnore */ public function clear_cache(): void { @@ -42,7 +44,9 @@ public function get_age_text(): string { $age = Cache::get($this->url . '_age'); if (!$age instanceof \DateTimeInterface) { + // @codeCoverageIgnoreStart return 'unknown'; + // @codeCoverageIgnoreEnd } try { $text = match (0) { @@ -52,13 +56,15 @@ public function get_age_text(): string now()->diffInWeeks($age) => now()->diffInDays($age) . ' days', now()->diffInMonths($age) => now()->diffInWeeks($age) . ' weeks', now()->diffInYears($age) => now()->diffInMonths($age) . ' months', - default => now()->diffInYears($age) . ' years' + default => now()->diffInYears($age) . ' years', }; return $text . ' ago'; + // @codeCoverageIgnoreStart } catch (\Throwable) { return 'unknown'; } + // @codeCoverageIgnoreEnd } /** @@ -79,6 +85,7 @@ public function get_json(bool $useCache = false): mixed } return $this->decodedJson; + // @codeCoverageIgnoreStart } catch (JsonRequestFailedException $e) { Log::error(__METHOD__ . ':' . __LINE__ . ' ' . $e->getMessage()); } catch (\JsonException $e) { @@ -87,6 +94,7 @@ public function get_json(bool $useCache = false): mixed $this->clear_cache(); return null; + // @codeCoverageIgnoreEnd } /** @@ -112,12 +120,16 @@ private function fetchFromServer(): string $raw = file_get_contents($this->url, false, $context); if ($raw === '') { + // @codeCoverageIgnoreStart throw new JsonRequestFailedException('file_get_contents() failed'); + // @codeCoverageIgnoreEnd } return $raw; + // @codeCoverageIgnoreStart } catch (\Throwable $e) { throw new JsonRequestFailedException('Could not fetch ' . $this->url, $e); } + // @codeCoverageIgnoreEnd } } diff --git a/app/Metadata/RateLimiterStore.php b/app/Metadata/RateLimiterStore.php deleted file mode 100644 index 9a817d01db7..00000000000 --- a/app/Metadata/RateLimiterStore.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ - public function get(): array - { - return Cache::get('rate-limiter', []); - } - - public function push(int $timestamp, int $limit): void - { - Cache::put('rate-limiter', array_merge($this->get(), [$timestamp])); - } -} diff --git a/app/Metadata/Versions/GitHubVersion.php b/app/Metadata/Versions/GitHubVersion.php index 5a7d3a16af0..c6f0dcc9fd4 100644 --- a/app/Metadata/Versions/GitHubVersion.php +++ b/app/Metadata/Versions/GitHubVersion.php @@ -89,16 +89,18 @@ public function isUpToDate(): bool public function getBehindTest(): string { return match ($this->countBehind) { + // @codeCoverageIgnoreStart false => 'Could not compare.', 0 => sprintf('Up to date (%s).', $this->remote->getAgeText() ?? '??'), 30 => sprintf('More than 30 %s behind (%s).', $this->remote->getType(), $this->remote->getAgeText() ?? '??'), + // @codeCoverageIgnoreEnd default => sprintf('%d %s behind %s (%s)', $this->countBehind, $this->remote->getType(), $this->remote->getHead() ?? '??', - $this->remote->getAgeText() ?? '??') + $this->remote->getAgeText() ?? '??'), }; } @@ -135,7 +137,9 @@ private function isGit(): bool if (Str::startsWith($branch, 'ref:')) { $this->remote = resolve(GitCommits::class); } else { + // @codeCoverageIgnoreStart $this->remote = resolve(GitTags::class); + // @codeCoverageIgnoreEnd } return true; @@ -167,9 +171,11 @@ private function hydrateLocalBranch(): void $branch = explode('/', $branchOrCommit, 3); $this->localBranch = trim($branch[2]); } else { + // @codeCoverageIgnoreStart // This is tagged/CICD behaviour // we leave localBranch as null so that we know that we are not on master $this->localHead = $this->trim($branchOrCommit); + // @codeCoverageIgnoreEnd } } @@ -214,6 +220,8 @@ private function hydrateLocalHead(): void * @param bool $useCache * * @return void + * + * @codeCoverageIgnore the code path here depends whether you are on a PR or on master... */ private function hydrateRemote(bool $useCache): void { diff --git a/app/Metadata/Versions/InstalledVersion.php b/app/Metadata/Versions/InstalledVersion.php index b97e6356cb1..8f9c90d7549 100644 --- a/app/Metadata/Versions/InstalledVersion.php +++ b/app/Metadata/Versions/InstalledVersion.php @@ -63,7 +63,9 @@ public function isDev(): bool public function getVersion(): Version { if (!Schema::hasTable('configs')) { + // @codeCoverageIgnoreStart return Version::createFromInt(10000); + // @codeCoverageIgnoreEnd } return Version::createFromInt(Configs::getValueAsInt('version')); diff --git a/app/Metadata/Versions/Remote/AbstractGitRemote.php b/app/Metadata/Versions/Remote/AbstractGitRemote.php index 0a6ce4e6977..a6b2f905620 100644 --- a/app/Metadata/Versions/Remote/AbstractGitRemote.php +++ b/app/Metadata/Versions/Remote/AbstractGitRemote.php @@ -47,7 +47,9 @@ public function fetchRemote(bool $useCache): array $data = $request->get_json($useCache); if (!is_array($data) || count($data) === 0) { // if $gitData is null we already logged the problem + // @codeCoverageIgnoreStart return []; + // @codeCoverageIgnoreEnd } $this->head = $this->dataToName($data[0]); diff --git a/app/ModelFunctions/MOVFormat.php b/app/ModelFunctions/MOVFormat.php index da5b139ae67..e8c62fdf1ea 100644 --- a/app/ModelFunctions/MOVFormat.php +++ b/app/ModelFunctions/MOVFormat.php @@ -26,6 +26,9 @@ public function __construct() } } + /** + * @codeCoverageIgnore + */ public function supportBFrames(): bool { return false; diff --git a/app/Models/AccessPermission.php b/app/Models/AccessPermission.php index 7bd68cd8c72..c29578a82e8 100644 --- a/app/Models/AccessPermission.php +++ b/app/Models/AccessPermission.php @@ -8,6 +8,7 @@ use App\Models\Extensions\HasAttributesPatch; use App\Models\Extensions\ThrowsConsistentExceptions; use App\Models\Extensions\UTCBasedTimes; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -60,6 +61,8 @@ class AccessPermission extends Model use UTCBasedTimes; use HasAttributesPatch; use ThrowsConsistentExceptions; + /** @phpstan-use HasFactory<\Database\Factories\AccessPermissionFactory> */ + use HasFactory; protected $casts = [ 'created_at' => 'datetime', @@ -101,7 +104,7 @@ public function newEloquentBuilder($query): AccessPermissionBuilder /** * Returns the relationship between an AccessPermission and its associated album. * - * @return BelongsTo + * @return BelongsTo */ public function album(): BelongsTo { @@ -111,7 +114,7 @@ public function album(): BelongsTo /** * Returns the relationship between an AccessPermission and its applied User. * - * @return BelongsTo + * @return BelongsTo */ public function user(): BelongsTo { diff --git a/app/Models/Album.php b/app/Models/Album.php index 6d29c8670fa..a48e894d7a0 100644 --- a/app/Models/Album.php +++ b/app/Models/Album.php @@ -124,13 +124,14 @@ * * // * @mixin \Eloquent * - * @implements Node + * @implements Node */ class Album extends BaseAlbum implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; use ToArrayThrowsNotImplemented; + /** @phpstan-use HasFactory<\Database\Factories\AlbumFactory> */ use HasFactory; /** @@ -181,7 +182,7 @@ class Album extends BaseAlbum implements Node * * @return HasManyChildPhotos */ - public function photos(): HasManyChildPhotos + public function photos(): HasManyChildPhotos // @phpstan-ignore-line { return new HasManyChildPhotos($this); } @@ -215,24 +216,26 @@ public function children(): HasManyChildAlbums /** * Get query for descendants of the node. * - * @return DescendantsRelation + * @return DescendantsRelation * * @throws QueryBuilderException */ public function descendants(): DescendantsRelation { try { - /** @var DescendantsRelation */ + /** @var DescendantsRelation */ return new DescendantsRelation($this->newQuery(), $this); + // @codeCoverageIgnoreStart } catch (\Throwable $e) { throw new QueryBuilderException($e); } + // @codeCoverageIgnoreEnd } /** * Return the relationship between an album and its cover. * - * @return HasOne + * @return HasOne */ public function cover(): HasOne { @@ -242,7 +245,7 @@ public function cover(): HasOne /** * Return the relationship between an album and its header. * - * @return HasOne + * @return HasOne */ public function header(): HasOne { @@ -252,19 +255,23 @@ public function header(): HasOne /** * Return the License used by the album. * - * @param string $value + * @param string|LicenseType|null $value * * @return LicenseType * * @throws ConfigurationKeyMissingException */ - protected function getLicenseAttribute(string $value): LicenseType + protected function getLicenseAttribute(string|LicenseType|null $value): LicenseType { - if ($value === 'none') { + if ($value === null || $value === 'none' || $value === LicenseType::NONE) { return Configs::getValueAsEnum('default_license', LicenseType::class); } - return LicenseType::from($value); + if (is_string($value)) { + return LicenseType::from($value); + } + + return $value; } /** @@ -292,6 +299,8 @@ public function performDeleteOnModel(): void * Hence, we must avoid any attempt to delete the descendants twice. * * @return void + * + * @codeCoverageIgnore */ protected function deleteDescendants(): void { diff --git a/app/Models/BaseAlbumImpl.php b/app/Models/BaseAlbumImpl.php index 5b9bbd5a0e4..e81954b43e7 100644 --- a/app/Models/BaseAlbumImpl.php +++ b/app/Models/BaseAlbumImpl.php @@ -8,6 +8,7 @@ use App\DTO\PhotoSortingCriterion; use App\Enum\ColumnSortingType; use App\Enum\OrderSortingType; +use App\Enum\PhotoLayoutType; use App\Models\Builders\BaseAlbumImplBuilder; use App\Models\Extensions\HasAttributesPatch; use App\Models\Extensions\HasBidirectionalRelationships; @@ -94,6 +95,7 @@ * @property Carbon $updated_at * @property string $title * @property string|null $description + * @property PhotoLayoutType|null $photo_layout * @property int $owner_id * @property User $owner * @property bool $is_nsfw @@ -178,6 +180,7 @@ class BaseAlbumImpl extends Model implements HasRandomID 'copyright' => null, // Special visibility attributes 'is_nsfw' => false, + 'photo_layout' => null, ]; /** @@ -190,6 +193,7 @@ class BaseAlbumImpl extends Model implements HasRandomID 'updated_at' => 'datetime', 'is_nsfw' => 'boolean', 'owner_id' => 'integer', + 'photo_layout' => PhotoLayoutType::class, ]; /** @@ -210,7 +214,7 @@ public function newEloquentBuilder($query): BaseAlbumImplBuilder /** * Returns the relationship between an album and its owner. * - * @return BelongsTo + * @return BelongsTo */ public function owner(): BelongsTo { @@ -221,7 +225,7 @@ public function owner(): BelongsTo * Returns the relationship between an album and all users with whom * this album is shared. * - * @return BelongsToMany + * @return BelongsToMany */ public function shared_with(): BelongsToMany { @@ -236,7 +240,7 @@ public function shared_with(): BelongsToMany /** * Returns the relationship between an album and its associated permissions. * - * @return hasMany + * @return hasMany */ public function access_permissions(): hasMany { diff --git a/app/Models/Builders/AlbumBuilder.php b/app/Models/Builders/AlbumBuilder.php index 9a9c09ff8ba..1e8fe6c469a 100644 --- a/app/Models/Builders/AlbumBuilder.php +++ b/app/Models/Builders/AlbumBuilder.php @@ -48,7 +48,7 @@ * @method $this whereNull(string|array $columns, string $boolean = 'and', bool $not = false) * @method $this orderByDesc($column) * - * @extends NSQueryBuilder + * @extends NSQueryBuilder */ class AlbumBuilder extends NSQueryBuilder { @@ -64,7 +64,7 @@ class AlbumBuilder extends NSQueryBuilder * * @param string[]|string $columns * - * @return Album[] + * @return array * * @throws InternalLycheeException */ diff --git a/app/Models/Builders/TagAlbumBuilder.php b/app/Models/Builders/TagAlbumBuilder.php index ec87520c434..6eb306727f0 100644 --- a/app/Models/Builders/TagAlbumBuilder.php +++ b/app/Models/Builders/TagAlbumBuilder.php @@ -28,7 +28,7 @@ class TagAlbumBuilder extends FixedQueryBuilder * * @param array|string $columns * - * @return TagAlbum[] + * @return array * * @throws QueryBuilderException */ diff --git a/app/Models/Configs.php b/app/Models/Configs.php index b7832dbff01..82a3cf40c0b 100644 --- a/app/Models/Configs.php +++ b/app/Models/Configs.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enum\ConfigType; use App\Enum\LicenseType; use App\Enum\MapProviders; use App\Exceptions\ConfigurationKeyMissingException; @@ -28,6 +29,8 @@ * @property string $type_range * @property bool $is_secret * @property string $description + * @property string $details + * @property int $level * * @method static ConfigsBuilder|Configs addSelect($column) * @method static ConfigsBuilder|Configs join(string $table, string $first, string $operator = null, string $second = null, string $type = 'inner', string $where = false) @@ -55,23 +58,12 @@ class Configs extends Model use ConfigsHas; use ThrowsConsistentExceptions; - protected const INT = 'int'; - protected const POSTIIVE = 'positive'; - protected const STRING = 'string'; - protected const STRING_REQ = 'string_required'; - protected const BOOL = '0|1'; - protected const BOOL_STRING = 'bool'; - protected const TERNARY = '0|1|2'; - protected const DISABLED = ''; - protected const LICENSE = 'license'; - protected const MAP_PROVIDER = 'map_provider'; - /** * The attributes that are mass assignable. * * @var array */ - protected $fillable = ['key', 'value', 'cat', 'type_range', 'is_secret', 'description']; + protected $fillable = ['key', 'value', 'cat', 'type_range', 'is_secret', 'description', 'level']; /** * this is a parameter for Laravel to indicate that there is no created_at, updated_at columns. @@ -107,45 +99,43 @@ public function sanity(?string $candidateValue, ?string $message_template = null { $message = ''; $val_range = [ - self::BOOL_STRING => ['0', '1'], - self::BOOL => explode('|', self::BOOL), - self::TERNARY => explode('|', self::TERNARY), + ConfigType::BOOL->value => explode('|', ConfigType::BOOL->value), + ConfigType::TERNARY->value => explode('|', ConfigType::TERNARY->value), ]; $message_template ??= 'Error: Wrong property for ' . $this->key . ', expected %s, got ' . ($candidateValue ?? 'NULL') . '.'; switch ($this->type_range) { - case self::STRING: - case self::DISABLED: + case ConfigType::STRING->value: + case ConfigType::DISABLED->value: break; - case self::STRING_REQ: + case ConfigType::STRING_REQ->value: if ($candidateValue === '' || $candidateValue === null) { $message = 'Error: ' . $this->key . ' empty or not set'; } break; - case self::INT: + case ConfigType::INT->value: // we make sure that we only have digits in the chosen value. if (!ctype_digit(strval($candidateValue))) { $message = sprintf($message_template, 'positive integer or 0'); } break; - case self::POSTIIVE: + case ConfigType::POSTIIVE->value: if (!ctype_digit(strval($candidateValue)) || intval($candidateValue, 10) === 0) { $message = sprintf($message_template, 'strictly positive integer'); } break; - case self::BOOL_STRING: - case self::BOOL: - case self::TERNARY: + case ConfigType::BOOL->value: + case ConfigType::TERNARY->value: if (!in_array($candidateValue, $val_range[$this->type_range], true)) { // BOOL or TERNARY $message = sprintf($message_template, implode(' or ', $val_range[$this->type_range])); } break; - case self::LICENSE: + case ConfigType::LICENSE->value: if (LicenseType::tryFrom($candidateValue) === null) { $message = sprintf($message_template, 'a valid license'); } break; - case self::MAP_PROVIDER: + case ConfigType::MAP_PROVIDER->value: if (MapProviders::tryFrom($candidateValue) === null) { $message = sprintf($message_template, 'a valid map provider'); } @@ -177,9 +167,11 @@ public static function get(): array ->select(['key', 'value']) ->pluck('value', 'key') ->all(); + // @codeCoverageIgnoreStart } catch (\Throwable) { self::$cache = []; } + // @codeCoverageIgnoreEnd return self::$cache; } @@ -203,9 +195,11 @@ public static function getValue(string $key): int|bool|string|null /* * For some reason the $default is not returned above... */ + // @codeCoverageIgnoreStart Log::critical(__METHOD__ . ':' . __LINE__ . ' ' . $key . ' does not exist in config (local) !'); throw new ConfigurationKeyMissingException($key . ' does not exist in config!'); + // @codeCoverageIgnoreEnd } return self::$cache[$key]; @@ -264,7 +258,9 @@ public static function getValueAsBool(string $key): bool public static function getValueAsEnum(string $key, string $type): \BackedEnum|null { if (!function_exists('enum_exists') || !enum_exists($type) || !method_exists($type, 'tryFrom')) { + // @codeCoverageIgnoreStart throw new UnexpectedException(); + // @codeCoverageIgnoreEnd } return $type::tryFrom(self::getValue($key)); @@ -298,7 +294,9 @@ public static function set(string $key, string|int|bool|\BackedEnum $value): voi $strValue = match (gettype($value)) { 'boolean' => $value === true ? '1' : '0', 'integer', 'string' => strval($value), - default => throw new LycheeAssertionError('Unexpected type') + // @codeCoverageIgnoreStart + default => throw new LycheeAssertionError('Unexpected type'), + // @codeCoverageIgnoreEnd }; /** @@ -310,10 +308,12 @@ public static function set(string $key, string|int|bool|\BackedEnum $value): voi } $config->value = $strValue; $config->save(); + // @codeCoverageIgnoreStart } catch (ModelNotFoundException $e) { throw new InvalidConfigOption('key ' . $key . ' not found!', $e); } catch (ModelDBException $e) { throw new InvalidConfigOption('Could not save configuration', $e); + // @codeCoverageIgnoreEnd } finally { // invalidate cache. self::$cache = []; diff --git a/app/Models/Extensions/BaseAlbum.php b/app/Models/Extensions/BaseAlbum.php index 4fbcdc36e46..fda81129de8 100644 --- a/app/Models/Extensions/BaseAlbum.php +++ b/app/Models/Extensions/BaseAlbum.php @@ -6,6 +6,7 @@ use App\Contracts\Models\AbstractAlbum; use App\Contracts\Models\HasRandomID; use App\DTO\PhotoSortingCriterion; +use App\Enum\PhotoLayoutType; use App\Models\AccessPermission; use App\Models\BaseAlbumImpl; use App\Models\User; @@ -30,6 +31,7 @@ * @property string|null $description * @property bool $is_nsfw * @property string|null $copyright + * @property PhotoLayoutType|null $photo_layout * @property int $owner_id * @property User $owner * @property Collection $access_permissions @@ -58,7 +60,7 @@ abstract class BaseAlbum extends Model implements AbstractAlbum, HasRandomID public $incrementing = false; /** - * @return BelongsTo + * @return BelongsTo */ public function base_class(): BelongsTo { @@ -79,7 +81,7 @@ public function owner(): BelongsTo * Returns the relationship between an album and all users with whom * this album is shared. * - * @return BelongsToMany + * @return BelongsToMany */ public function shared_with(): BelongsToMany { @@ -89,7 +91,7 @@ public function shared_with(): BelongsToMany /** * Returns the relationship between an album and its associated permissions. * - * @return HasMany + * @return HasMany */ public function access_permissions(): HasMany { @@ -117,7 +119,7 @@ public function public_permissions(): AccessPermission|null } /** - * @return Relation<\App\Models\Photo> + * @return Relation<\App\Models\Photo,AbstractAlbum&Model,Collection> */ abstract public function photos(): Relation; diff --git a/app/Models/Extensions/BaseConfigMigration.php b/app/Models/Extensions/BaseConfigMigration.php index ab8945c52b0..37195fc859b 100644 --- a/app/Models/Extensions/BaseConfigMigration.php +++ b/app/Models/Extensions/BaseConfigMigration.php @@ -10,6 +10,7 @@ abstract class BaseConfigMigration extends Migration public const BOOL = '0|1'; public const POSITIVE = 'positive'; public const INT = 'int'; + public const STRING = 'string'; /** * @return array diff --git a/app/Models/Extensions/ForwardsToParentImplementation.php b/app/Models/Extensions/ForwardsToParentImplementation.php index 8a1edba13ba..830d1600e45 100644 --- a/app/Models/Extensions/ForwardsToParentImplementation.php +++ b/app/Models/Extensions/ForwardsToParentImplementation.php @@ -75,9 +75,7 @@ public function initializeForwardsToParentImplementation(): void /** * Perform a model insert operation. * - * @template TModel of \Illuminate\Database\Eloquent\Model - * - * @param Builder $query + * @param Builder $query * * @return bool * @@ -106,9 +104,7 @@ protected function performInsert(Builder $query): bool /** * Perform a model update operation. * - * @template TModel of \Illuminate\Database\Eloquent\Model - * - * @param Builder $query + * @param Builder $query * * @return bool */ @@ -331,6 +327,7 @@ public function getAttribute($key): mixed // If the "attribute" exists as a method on the model, we will just assume // it is a relationship and will load and return results from the query // and hydrate the relationship's value on the "relationships" array. + /** @disregard */ if ( method_exists($this, $key) || (static::$relationResolvers[get_class($this)][$key] ?? null) @@ -406,6 +403,7 @@ public function getRelationValue($key): mixed // If the "attribute" exists as a method on the model, we will just assume // it is a relationship and will load and return results from the query // and hydrate the relationship's value on the "relationships" array. + /** @disregard */ if ( method_exists($this, $key) || (static::$relationResolvers[get_class($this)][$key] ?? null) diff --git a/app/Models/Extensions/HasBidirectionalRelationships.php b/app/Models/Extensions/HasBidirectionalRelationships.php index b29cc02fa80..eefed37ce79 100644 --- a/app/Models/Extensions/HasBidirectionalRelationships.php +++ b/app/Models/Extensions/HasBidirectionalRelationships.php @@ -69,7 +69,7 @@ protected function getRelationshipFromMethod($method): mixed * @param string|null $localKey * @param string|null $foreignMethodName * - * @return HasManyBidirectionally + * @return HasManyBidirectionally */ public function hasManyBidirectionally(string $related, ?string $foreignKey = null, ?string $localKey = null, ?string $foreignMethodName = null): HasManyBidirectionally { diff --git a/app/Models/Extensions/HasRandomIDAndLegacyTimeBasedID.php b/app/Models/Extensions/HasRandomIDAndLegacyTimeBasedID.php index b442465a323..a38b7c0af17 100644 --- a/app/Models/Extensions/HasRandomIDAndLegacyTimeBasedID.php +++ b/app/Models/Extensions/HasRandomIDAndLegacyTimeBasedID.php @@ -74,7 +74,7 @@ public function setAttribute($key, $value): mixed * The method is mostly copied & pasted from {@link \Illuminate\Database\Eloquent\Model::performInsert()} * with adoptions regarding key generation. * - * @param Builder $query + * @param Builder $query * * @return bool true on success * diff --git a/app/Models/Extensions/SizeVariants.php b/app/Models/Extensions/SizeVariants.php index 789b4914b43..91536a6a5b8 100644 --- a/app/Models/Extensions/SizeVariants.php +++ b/app/Models/Extensions/SizeVariants.php @@ -144,7 +144,7 @@ public function getSizeVariant(SizeVariantType $sizeVariantType): ?SizeVariant SizeVariantType::SMALL2X => $this->small2x, SizeVariantType::SMALL => $this->small, SizeVariantType::THUMB2X => $this->thumb2x, - SizeVariantType::THUMB => $this->thumb + SizeVariantType::THUMB => $this->thumb, }; } diff --git a/app/Models/Extensions/Thumb.php b/app/Models/Extensions/Thumb.php index d51dfb03e21..109b557fdd2 100644 --- a/app/Models/Extensions/Thumb.php +++ b/app/Models/Extensions/Thumb.php @@ -36,14 +36,14 @@ protected function __construct(string $id, string $type, string $thumbUrl, ?stri * Restricts the given relation for size variants such that only the * necessary variants for a thumbnail are selected. * - * @param HasMany $relation + * @param HasMany $relation * - * @return HasMany + * @return HasMany */ - public static function sizeVariantsFilter(HasMany $relation): HasMany + public static function sizeVariantsFilter(HasMany $relation): HasMany // @phpstan-ignore-line { $svAlbumThumbs = [SizeVariantType::THUMB, SizeVariantType::THUMB2X]; - if (Features::active('livewire')) { + if (Features::active('vuejs')) { $svAlbumThumbs = [SizeVariantType::SMALL, SizeVariantType::SMALL2X, SizeVariantType::THUMB, SizeVariantType::THUMB2X]; } @@ -56,8 +56,11 @@ public static function sizeVariantsFilter(HasMany $relation): HasMany * Note, this method assumes that the relation is already restricted * such that it only returns photos which the current user may see. * - * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb - * @param SortingCriterion $sorting the sorting criterion + * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model + * @template TResult + * + * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb + * @param SortingCriterion $sorting the sorting criterion * * @return Thumb|null the created thumbnail; null if the relation is empty * @@ -69,7 +72,7 @@ public static function createFromQueryable(Relation|Builder $photoQueryable, Sor try { /** @var Photo|null $cover */ $cover = $photoQueryable - ->withOnly(['size_variants' => (fn (HasMany $r) => self::sizeVariantsFilter($r))]) + ->withOnly(['size_variants' => (fn ($r) => self::sizeVariantsFilter($r))]) ->orderBy('photos.' . ColumnSortingPhotoType::IS_STARRED->value, OrderSortingType::DESC->value) ->orderBy('photos.' . $sorting->column->value, $sorting->order->value) ->select(['photos.id', 'photos.type']) @@ -88,7 +91,10 @@ public static function createFromQueryable(Relation|Builder $photoQueryable, Sor * Note, this method assumes that the relation is already restricted * such that it only returns photos which the current user may see. * - * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb + * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model + * @template TResult + * + * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb * * @return Thumb|null the created thumbnail; null if the relation is empty * @@ -100,7 +106,7 @@ public static function createFromRandomQueryable(Relation|Builder $photoQueryabl try { /** @var Photo|null $cover */ $cover = $photoQueryable - ->withOnly(['size_variants' => (fn (HasMany $r) => self::sizeVariantsFilter($r))]) + ->withOnly(['size_variants' => (fn ($r) => self::sizeVariantsFilter($r))]) ->inRandomOrder() ->select(['photos.id', 'photos.type']) ->first(); @@ -122,28 +128,18 @@ public static function createFromRandomQueryable(Relation|Builder $photoQueryabl */ public static function createFromPhoto(?Photo $photo): ?Thumb { - $thumb = (Features::active('livewire') && $photo?->size_variants->getSmall() !== null) - ? $photo->size_variants->getSmall() - : $photo?->size_variants->getThumb(); + if ($photo === null) { + return null; + } + + $thumb = $photo->size_variants->getSmall() ?? $photo->size_variants->getThumb(); if ($thumb === null) { return null; } - $thumb2x = (Features::active('livewire') && $photo?->size_variants->getSmall() !== null) + $thumb2x = $photo->size_variants->getSmall() !== null ? $photo->size_variants->getSmall2x() - : $photo?->size_variants->getThumb2x(); - - /** - * TODO: Code for later when Livewire is the only front-end. - */ - // $thumb = $photo?->size_variants->getSmall() ?? $photo?->size_variants->getThumb(); - // if ($thumb === null) { - // return null; - // } - - // $thumb2x = $photo?->size_variants->getSmall() !== null - // ? $photo?->size_variants->getSmall2x() - // : $photo?->size_variants->getThumb2x(); + : $photo->size_variants->getThumb2x(); return new self( $photo->id, diff --git a/app/Models/JobHistory.php b/app/Models/JobHistory.php index 43139591051..5abc1f85c66 100644 --- a/app/Models/JobHistory.php +++ b/app/Models/JobHistory.php @@ -5,6 +5,7 @@ use App\Enum\JobStatus; use App\Models\Builders\JobHistoryBuilder; use App\Models\Extensions\ThrowsConsistentExceptions; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -73,7 +74,7 @@ public function newEloquentBuilder($query): JobHistoryBuilder /** * Returns the relationship between an Job and its owner. * - * @return BelongsTo + * @return BelongsTo */ public function owner(): BelongsTo { diff --git a/app/Models/OauthCredential.php b/app/Models/OauthCredential.php index a6e01245c0e..3022cfd123a 100644 --- a/app/Models/OauthCredential.php +++ b/app/Models/OauthCredential.php @@ -47,7 +47,7 @@ class OauthCredential extends Model /** * Return the relationship between a Photo and its Album. * - * @return BelongsTo + * @return BelongsTo */ public function user(): BelongsTo { diff --git a/app/Models/Photo.php b/app/Models/Photo.php index 51975d2fc38..5197c1991db 100644 --- a/app/Models/Photo.php +++ b/app/Models/Photo.php @@ -121,6 +121,7 @@ */ class Photo extends Model { + /** @phpstan-use HasFactory<\Database\Factories\PhotoFactory> */ use HasFactory; use UTCBasedTimes; use HasAttributesPatch; @@ -183,7 +184,7 @@ public function newEloquentBuilder($query): PhotoBuilder /** * Return the relationship between a Photo and its Album. * - * @return BelongsTo + * @return BelongsTo */ public function album(): BelongsTo { @@ -193,7 +194,7 @@ public function album(): BelongsTo /** * Return the relationship between a Photo and its Owner. * - * @return BelongsTo + * @return BelongsTo */ public function owner(): BelongsTo { @@ -289,16 +290,6 @@ protected function getLicenseAttribute(?string $license): LicenseType return Configs::getValueAsEnum('default_license', LicenseType::class); } - /** - * This is to avoid loading the license from configs & albums. - * - * @return ?string - */ - public function getOriginalLicense(): ?string - { - return $this->attributes['license']; - } - /** * Accessor for attribute `focal`. * @@ -380,7 +371,9 @@ protected function getAspectRatioAttribute(): float public function isPhoto(): bool { if ($this->type === null || $this->type === '') { + // @codeCoverageIgnoreStart throw new IllegalOrderOfOperationException('Photo::isPhoto() must not be called before Photo::$type has been set'); + // @codeCoverageIgnoreEnd } return BaseMediaFile::isSupportedImageMimeType($this->type); @@ -396,7 +389,9 @@ public function isPhoto(): bool public function isVideo(): bool { if ($this->type === null || $this->type === '') { + // @codeCoverageIgnoreStart throw new IllegalOrderOfOperationException('Photo::isVideo() must not be called before Photo::$type has been set'); + // @codeCoverageIgnoreEnd } return BaseMediaFile::isSupportedVideoMimeType($this->type); diff --git a/app/Models/SizeVariant.php b/app/Models/SizeVariant.php index 34bc4092da2..70cd37034a3 100644 --- a/app/Models/SizeVariant.php +++ b/app/Models/SizeVariant.php @@ -9,6 +9,7 @@ use App\Exceptions\ConfigurationException; use App\Exceptions\MediaFileOperationException; use App\Exceptions\ModelDBException; +use App\Http\Resources\Models\SizeVariantResource; use App\Image\Files\FlysystemFile; use App\Models\Builders\SizeVariantBuilder; use App\Models\Extensions\HasAttributesPatch; @@ -37,7 +38,6 @@ * @property SizeVariantType $type * @property string $short_path * @property string $url - * @property string $full_path * @property int $width * @property int $height * @property float $ratio @@ -73,6 +73,7 @@ class SizeVariant extends Model use HasBidirectionalRelationships; use ThrowsConsistentExceptions; use ToArrayThrowsNotImplemented; + /** @phpstan-use HasFactory<\Database\Factories\SizeVariantFactory> */ use HasFactory; /** @@ -89,7 +90,6 @@ class SizeVariant extends Model protected $casts = [ 'id' => 'integer', 'type' => SizeVariantType::class, - 'full_path' => MustNotSetCast::class . ':short_path', 'url' => MustNotSetCast::class . ':short_path', 'width' => 'integer', 'height' => 'integer', @@ -140,7 +140,7 @@ public function newEloquentBuilder($query): SizeVariantBuilder * Returns the association to the photo which this size variant belongs * to. * - * @return BelongsTo + * @return BelongsTo */ public function photo(): BelongsTo { @@ -151,7 +151,7 @@ public function photo(): BelongsTo * Returns the association to the symbolics links which point to this * size variant. * - * @return HasManyBidirectionally + * @return HasManyBidirectionally */ public function sym_links(): HasManyBidirectionally { @@ -188,7 +188,9 @@ public function getUrlAttribute(): string /** @disregard P1013 */ $storageAdapter = $imageDisk->getAdapter(); if ($storageAdapter instanceof AwsS3V3Adapter) { + // @codeCoverageIgnoreStart return $this->getAwsUrl(); + // @codeCoverageIgnoreEnd } if ($storageAdapter instanceof LocalFilesystemAdapter) { @@ -202,6 +204,8 @@ public function getUrlAttribute(): string * Retrieve the tempary url from AWS if possible. * * @return string + * + * @codeCoverageIgnore */ private function getAwsUrl(): string { @@ -242,24 +246,6 @@ private function getSymLinkUrl(): string return $symLink->url; } - /** - * Accessor for the "virtual" attribute {@link SizeVariant::$full_path}. - * - * Returns the full path of the size variant as it needs to be input into - * some low-level PHP functions like `unlink`. - * This is a convenient method and wraps {@link SizeVariant::$short_path} - * into {@link \Illuminate\Support\Facades\Storage::path()}. - * - * TODO: Remove this method eventually, we must not use paths. - * - * @return string the full path of the file - */ - public function getFullPathAttribute(): string - { - /** @disregard P1013 */ - return Storage::disk($this->storage_disk->value)->path($this->short_path); - } - public function getFile(): FlysystemFile { return new FlysystemFile( @@ -280,4 +266,9 @@ protected function performDeleteOnModel(): void $this->exists = false; $fileDeleter->do(); } + + public function toResource(bool $noUrl = false): SizeVariantResource + { + return new SizeVariantResource($this, noUrl: $noUrl); + } } diff --git a/app/Models/SymLink.php b/app/Models/SymLink.php index b40a615530d..0378148c436 100644 --- a/app/Models/SymLink.php +++ b/app/Models/SymLink.php @@ -90,7 +90,7 @@ public function newEloquentBuilder($query): SymLinkBuilder } /** - * @return BelongsTo + * @return BelongsTo */ public function size_variant(): BelongsTo { @@ -142,7 +142,7 @@ protected function getUrlAttribute(): string * If this method cannot create the symbolic link, then this method * cancels the insert operation. * - * @param Builder $query + * @param Builder $query * * @return bool * diff --git a/app/Models/TagAlbum.php b/app/Models/TagAlbum.php index dc7568a4bca..7a9cea33721 100644 --- a/app/Models/TagAlbum.php +++ b/app/Models/TagAlbum.php @@ -10,6 +10,7 @@ use App\Models\Extensions\ToArrayThrowsNotImplemented; use App\Relations\HasManyPhotosByTag; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Query\Builder as BaseBuilder; /** @@ -49,6 +50,8 @@ class TagAlbum extends BaseAlbum { use ToArrayThrowsNotImplemented; + /** @phpstan-use HasFactory<\Database\Factories\TagAlbumFactory> */ + use HasFactory; /** * The model's attributes. @@ -92,7 +95,7 @@ class TagAlbum extends BaseAlbum 'thumb', ]; - public function photos(): HasManyPhotosByTag + public function photos(): HasManyPhotosByTag // @phpstan-ignore-line { return new HasManyPhotosByTag($this); } diff --git a/app/Models/User.php b/app/Models/User.php index d291b264980..5fa6b74a20d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -38,6 +38,9 @@ * @property bool $may_administrate * @property bool $may_upload * @property bool $may_edit_own_settings + * @property int $quota_kb + * @property string|null $description + * @property string|null $note * @property string|null $token * @property string|null $remember_token * @property Collection $albums @@ -76,6 +79,7 @@ */ class User extends Authenticatable implements WebAuthnAuthenticatable { + /** @phpstan-use HasFactory<\Database\Factories\UserFactory> */ use HasFactory; use Notifiable; use WebAuthnAuthentication; @@ -104,6 +108,7 @@ class User extends Authenticatable implements WebAuthnAuthenticatable 'may_administrate' => 'boolean', 'may_upload' => 'boolean', 'may_edit_own_settings' => 'boolean', + 'quota_kb' => 'integer', ]; protected $hidden = []; @@ -123,7 +128,7 @@ public function newEloquentBuilder($query): UserBuilder /** * Return the albums owned by the user. * - * @return HasMany + * @return HasMany */ public function albums(): HasMany { @@ -134,7 +139,7 @@ public function albums(): HasMany /** * Return the photos owned by the user. * - * @return HasMany + * @return HasMany */ public function photos(): HasMany { @@ -144,7 +149,7 @@ public function photos(): HasMany /** * Return the albums shared to the user. * - * @return BelongsToMany + * @return BelongsToMany */ public function shared(): BelongsToMany { @@ -159,7 +164,7 @@ public function shared(): BelongsToMany /** * Return the Oauth credentials owned by the user. * - * @return HasMany + * @return HasMany */ public function oauthCredentials(): HasMany { @@ -203,7 +208,7 @@ public function getNameAttribute(): string */ public function delete(): bool { - /** @var HasMany[] $ownershipRelations */ + /** @var HasMany[] $ownershipRelations */ $ownershipRelations = [$this->photos(), $this->albums()]; $hasAny = false; diff --git a/app/Policies/AlbumPolicy.php b/app/Policies/AlbumPolicy.php index 4d0c3d7ba87..f82e49ff974 100644 --- a/app/Policies/AlbumPolicy.php +++ b/app/Policies/AlbumPolicy.php @@ -27,6 +27,7 @@ class AlbumPolicy extends BasePolicy public const CAN_ACCESS_MAP = 'canAccessMap'; public const CAN_DOWNLOAD = 'canDownload'; public const CAN_DELETE = 'canDelete'; + public const CAN_TRANSFER = 'canTransfer'; public const CAN_UPLOAD = 'canUpload'; public const CAN_EDIT = 'canEdit'; public const CAN_EDIT_ID = 'canEditById'; @@ -275,6 +276,25 @@ public function canDelete(User $user, ?AbstractAlbum $abstractAlbum = null): boo return false; } + /** + * Check if user is allowed to USE transfer in current album. + * + * @param User $user + * @param AbstractAlbum|null $baseAlbum + * + * @return bool + * + * @throws ConfigurationKeyMissingException + */ + public function canTransfer(User $user, ?AbstractAlbum $baseAlbum = null): bool + { + if (!$baseAlbum instanceof BaseAlbum) { + return false; + } + + return $this->isOwner($user, $baseAlbum); + } + /** * Checks whether the album-user has the full photo access. * diff --git a/app/Policies/AlbumQueryPolicy.php b/app/Policies/AlbumQueryPolicy.php index ebceee7ca49..fd31019a60c 100644 --- a/app/Policies/AlbumQueryPolicy.php +++ b/app/Policies/AlbumQueryPolicy.php @@ -376,6 +376,82 @@ public function appendUnreachableAlbumsCondition(BaseBuilder $builder, int|strin } } + /** + * Adds the conditions of a sensitive album by recursion to the query. + * + * An album is called _recursive sensitive_, if it is marked as sensitive or contains a sensitive parent. + * + * **Attention:** This method is only meant for internal use by + * this class or {@link PhotoQueryPolicy}. + * + * This method adds the WHERE conditions without any further pre-cautions. + * The method silently assumes that the passed query builder is used + * within an outer query whose SELECT clause contains the table + * + * - **`albums`**. + * + * Moreover, the raw clauses are added. + * They are not wrapped into a nesting braces `()`. + * + * @param BaseBuilder $builder the album query which shall be + * restricted + * @param int|string|null $originLeft optionally constrains the search + * base; an integer value is + * interpreted a raw left bound of the + * search base; a string value is + * interpreted as a reference to a + * column which shall be used as a + * left bound + * @param int|string|null $originRight like `$originLeft` but for the + * right bound + * + * @return BaseBuilder + * + * @throws InternalLycheeException + */ + public function appendRecursiveSensitiveAlbumsCondition(BaseBuilder $builder, int|string|null $originLeft, int|string|null $originRight): BaseBuilder + { + if (gettype($originLeft) !== gettype($originRight)) { + throw new LycheeInvalidArgumentException('$originLeft and $originRight must simultaneously either be integers, strings or null'); + } + + try { + // There are outers albums ... + // WE MUST JOIN LEFT HERE + $builder->from('albums', 'outers'); + $this->joinBaseAlbumSensitive($builder, 'outers.id', 'outers_'); + + // ... on the path from the origin ... + if (is_int($originLeft)) { + // (We must exclude the origin as an outer node + // because the origin might have set as is_nsfw, but + // we do not care, because the user has already got + // somehow into the origin) + $builder + ->where('outers._lft', '>', $originLeft) + ->where('outers._rgt', '<', $originRight); + } elseif (is_string($originLeft) && is_string($originRight)) { + $builder + ->whereColumn('outers._lft', '>', $originLeft) + ->whereColumn('outers._rgt', '<', $originRight); + } + + // ... to the target ... + $builder + // (We must include the target into the list of outer nodes, + // because we must also check whether the target is unreachable.) + ->whereColumn('outers._lft', '<=', 'albums._lft') + ->whereColumn('outers._rgt', '>=', 'albums._rgt'); + // ... which are unreachable. + + $builder->where('outers_base_albums.is_nsfw', '=', true); + + return $builder; + } catch (\InvalidArgumentException $e) { + throw new QueryBuilderException($e); + } + } + /** * Throws an exception if the given query does not query for an album. * @@ -501,7 +577,7 @@ public function joinSubComputedAccessPermissions( } /** - * Join BaseAlbum. + * Join BaseAlbum for ownership and more. * This aim to give lighter sub selection to make the queries run faster. * * @param AlbumBuilder|FixedQueryBuilder|FixedQueryBuilder|BaseBuilder $query @@ -517,7 +593,7 @@ public function joinBaseAlbumOwnerId( AlbumBuilder|FixedQueryBuilder|BaseBuilder $query, string $second = 'inner.id', string $prefix = '', - bool $full = true + bool $full = true, ): void { $columns = [ $prefix . 'base_albums.id', @@ -540,4 +616,37 @@ public function joinBaseAlbumOwnerId( type: 'left' ); } + + /** + * Join BaseAlbum for sensitivity only. + * This aim to give lighter sub selection to make the queries run faster. + * + * @param AlbumBuilder|FixedQueryBuilder|FixedQueryBuilder|BaseBuilder $query + * @param string $second + * @param string $prefix + * + * @return void + * + * @throws \InvalidArgumentException + */ + public function joinBaseAlbumSensitive( + AlbumBuilder|FixedQueryBuilder|BaseBuilder $query, + string $second = 'inner.id', + string $prefix = '', + ): void { + $columns = [ + $prefix . 'base_albums.id', + $prefix . 'base_albums.is_nsfw', + ]; + + $query->joinSub( + query: DB::table('base_albums', $prefix . 'base_albums') + ->select($columns), + as: $prefix . 'base_albums', + first: $prefix . 'base_albums.id', + operator: '=', + second: $second, + type: 'left' + ); + } } diff --git a/app/Policies/PhotoQueryPolicy.php b/app/Policies/PhotoQueryPolicy.php index 4518637ce59..6d53696915f 100644 --- a/app/Policies/PhotoQueryPolicy.php +++ b/app/Policies/PhotoQueryPolicy.php @@ -7,6 +7,7 @@ use App\Exceptions\Internal\InvalidQueryModelException; use App\Exceptions\Internal\QueryBuilderException; use App\Models\Album; +use App\Models\Configs; use App\Models\Photo; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as BaseBuilder; @@ -106,6 +107,10 @@ public function applySearchabilityFilter(FixedQueryBuilder $query, ?Album $origi ->where('albums._rgt', '<=', $origin->_rgt); } + if (Configs::getValueAsBool('hide_nsfw_in_smart_albums_and_search')) { + $query->where(fn (Builder $query) => $this->appendSensitivityConditions($query->getQuery(), $origin?->_lft, $origin?->_rgt)); + } + if (Auth::user()?->may_administrate === true) { return $query; } @@ -185,6 +190,60 @@ public function appendSearchabilityConditions(BaseBuilder $query, int|string|nul return $query; } + /** + * Adds the conditions of _sensitive_ photos to the query. + * + * **Attention:** This method is only meant for internal use. + * Use {@link PhotoQueryPolicy::applySearchabilityFilter()} + * if called from other places instead. + * + * This method adds the WHERE conditions without any further pre-cautions. + * The method silently assumes that the SELECT clause contains the tables + * + * - **`albums`**. + * + * Moreover, the raw clauses are added. + * They are not wrapped into a nesting braces `()`. + * + * @param BaseBuilder $query the photo query which shall be + * restricted + * + * @return BaseBuilder the restricted photo query + * + * @throws QueryBuilderException + */ + public function appendSensitivityConditions(BaseBuilder $query, int|string|null $originLeft, int|string|null $originRight): BaseBuilder + { + $userId = Auth::id(); + + try { + // there must be no unreachable album between the origin and the photo + $query->whereNotExists(function (BaseBuilder $q) use ($originLeft, $originRight) { + $this->albumQueryPolicy->appendRecursiveSensitiveAlbumsCondition($q, $originLeft, $originRight); + }); + + // Special care needs to be taken for unsorted photo, i.e. photos on + // the root level: + // The condition for "no unreachable albums along the path" fails for + // root album due to two reasons: + // a) the path of albums between to the root album is empty; hence, + // there are never any unreachable albums in between + // b) while all users (even unauthenticated users) may access the + // root album, they must only see their own photos or public + // photos (this is different to any other album: if users are + // allowed to access an album, they may also see its content) + $query->orWhereNull('photos.album_id'); + + if ($userId !== null) { + $query->orWhere('photos.owner_id', '=', $userId); + } + } catch (\Throwable $e) { + throw new QueryBuilderException($e); + } + + return $query; + } + /** * Throws an exception if the given query does not query for a photo. * diff --git a/app/Policies/SettingsPolicy.php b/app/Policies/SettingsPolicy.php index 38efd770109..3872aca6fd5 100644 --- a/app/Policies/SettingsPolicy.php +++ b/app/Policies/SettingsPolicy.php @@ -14,6 +14,7 @@ class SettingsPolicy extends BasePolicy public const CAN_SEE_LOGS = 'canSeeLogs'; public const CAN_CLEAR_LOGS = 'canClearLogs'; public const CAN_SEE_DIAGNOSTICS = 'canSeeDiagnostics'; + public const CAN_SEE_STATISTICS = 'canSeeStatistics'; public const CAN_UPDATE = 'canUpdate'; public const CAN_ACCESS_DEV_TOOLS = 'canAccessDevTools'; @@ -68,6 +69,19 @@ public function canSeeDiagnostics(User $user): bool return false; } + /** + * This function returns false as it is bypassed by the before() + * which directly checks for admin rights. + * + * @param User $user + * + * @return bool + */ + public function canSeeStatistics(User $user): bool + { + return true; + } + /** * This function returns false as it is bypassed by the before() * which directly checks for admin rights. @@ -78,7 +92,7 @@ public function canSeeDiagnostics(User $user): bool */ public function canUpdate(User $user): bool { - return $user->id === 0; // Edge case of migration not applied yet. + return false; } /** diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 2ac5bfb5a8d..16e396d2d8b 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,10 +11,6 @@ use App\Factories\AlbumFactory; use App\Image\SizeVariantDefaultFactory; use App\Image\StreamStatFilter; -use App\Livewire\Synth\AlbumFlagsSynth; -use App\Livewire\Synth\AlbumSynth; -use App\Livewire\Synth\PhotoSynth; -use App\Livewire\Synth\SessionFlagsSynth; use App\Metadata\Json\CommitsRequest; use App\Metadata\Json\UpdateRequest; use App\Metadata\Versions\FileVersion; @@ -34,11 +30,9 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Log; -use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\URL; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; -use Livewire\Livewire; use Opcodes\LogViewer\Facades\LogViewer; use Safe\Exceptions\StreamException; use function Safe\stream_filter_register; @@ -86,15 +80,6 @@ class AppServiceProvider extends ServiceProvider GitTags::class => GitTags::class, ]; - /** @var array */ - private array $livewireSynth = - [ - AlbumSynth::class, - PhotoSynth::class, - SessionFlagsSynth::class, - AlbumFlagsSynth::class, - ]; - /** * Bootstrap any application services. * @@ -167,22 +152,6 @@ public function boot() // return true to allow viewing the Log Viewer. return Auth::authenticate() !== null && Gate::check(SettingsPolicy::CAN_SEE_LOGS, Configs::class); }); - - foreach ($this->livewireSynth as $synth) { - Livewire::propertySynthesizer($synth); - } - - $dir_url = config('app.dir_url') === '' ? '' : (config('app.dir_url') . '/'); - - Livewire::setScriptRoute(function ($handle) use ($dir_url) { - return config('app.debug') === true - ? Route::get($dir_url . 'livewire/livewire.js', $handle) - : Route::get($dir_url . 'livewire/livewire.min.js', $handle); - }); - - Livewire::setUpdateRoute(function ($handle) use ($dir_url) { - return Route::post($dir_url . 'livewire/update', $handle)->middleware('web-livewire'); - }); } /** @@ -236,7 +205,7 @@ private function logSQL(QueryExecuted $query): void 'NULL' => "''", 'string' => "'{$q}'", 'boolean' => $q ? '1' : '0', - default => $q + default => $q, }; })->all(); diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index e65f4f32dda..3f48d9df278 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use App\Assets\Features; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Http\Request; @@ -41,22 +42,29 @@ public function boot() // "catch all" route and the routes are considered in a "first match" // fashion. $this->routes(function () { - Route::middleware('api') - ->prefix('api') - ->group(base_path('routes/api.php')); + Features::when('vuejs', fn () => $this->getLycheeV6Routes(), fn () => $this->getLegacyRoutes()); + }); + } - Route::middleware('web-install') - ->group(base_path('routes/web-install.php')); + private function getLycheeV6Routes(): void + { + Route::middleware('web-admin')->group(base_path('routes/web-admin-v2.php')); + Route::middleware('api')->prefix('api/v2')->group(base_path('routes/api_v2.php')); + Route::middleware('web-install')->group(base_path('routes/web-install.php')); - Route::middleware('web-admin') - ->group(base_path('routes/web-admin.php')); + if (Features::active('legacy_api')) { + Route::middleware('api')->prefix('api')->group(base_path('routes/api_v1.php')); + } - Route::middleware('web') - ->group(base_path('routes/web-livewire.php')); + Route::middleware('web')->group(base_path('routes/web_v2.php')); + } - Route::middleware('web') - ->group(base_path('routes/web.php')); - }); + private function getLegacyRoutes(): void + { + Route::middleware('web-install')->group(base_path('routes/web-install.php')); + Route::middleware('api')->prefix('api')->group(base_path('routes/api_v1.php')); + Route::middleware('web-admin')->group(base_path('routes/web-admin-v1.php')); + Route::middleware('web')->group(base_path('routes/web_v1.php')); } /** diff --git a/app/Relations/BaseHasManyPhotos.php b/app/Relations/BaseHasManyPhotos.php index 94efedfb756..939f8f38d36 100644 --- a/app/Relations/BaseHasManyPhotos.php +++ b/app/Relations/BaseHasManyPhotos.php @@ -5,9 +5,11 @@ use App\DTO\SortingCriterion; use App\Eloquent\FixedQueryBuilder; use App\Exceptions\Internal\InvalidOrderDirectionException; +use App\Models\Album; use App\Models\Extensions\BaseAlbum; use App\Models\Extensions\SortingDecorator; use App\Models\Photo; +use App\Models\TagAlbum; use App\Policies\PhotoQueryPolicy; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\Relation; @@ -17,13 +19,18 @@ * direct parent of the queried photos, but include the photo due to some * indirect condition. * - * @extends Relation + * @template TDeclaringModel of TagAlbum|Album + * + * @extends Relation> */ abstract class BaseHasManyPhotos extends Relation { protected PhotoQueryPolicy $photoQueryPolicy; - public function __construct(BaseAlbum $owningAlbum) + /** + * @param TagAlbum|Album $owningAlbum + */ + public function __construct(TagAlbum|Album $owningAlbum) { // Sic! We must initialize attributes of this class before we call // the parent constructor. @@ -48,6 +55,7 @@ public function __construct(BaseAlbum $owningAlbum) // Moreover, it is impossible to pass `null`. // As a work-around we store the owning album in our own attribute // `$owningAlbum` and always use that instead of `$parent`. + /** @var Album|TagAlbum $owningAlbum */ parent::__construct( // Sic! We also must load the album eagerly. // This relation is not used by albums which own the queried @@ -56,6 +64,7 @@ public function __construct(BaseAlbum $owningAlbum) // Hence, the actually owning albums of the photos are not // necessarily loaded. Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links']), + // @phpstan-ignore-next-line $owningAlbum ); } @@ -83,8 +92,6 @@ public function getParent(): BaseAlbum * because it was set in the constructor as `$owningAlbum`. * * @noinspection PhpIncompatibleReturnTypeInspection - * - * @phpstan-ignore-next-line */ return $this->parent; } @@ -96,14 +103,14 @@ public function getParent(): BaseAlbum * In this case, the default value is an empty collection of * {@link \App\Models\Photo}. * - * @param array $models a list of owning models, i.e. a list of albums - * @param string $relation the name of the relation on the owning models + * @param array $models a list of owning models, i.e. a list of albums + * @param string $relation the name of the relation on the owning models * - * @return array always returns $models + * @return array always returns $models */ public function initRelation(array $models, $relation): array { - /** @var BaseAlbum $model */ + /** @var TagAlbum|Album $model */ foreach ($models as $model) { $model->setRelation($relation, $this->related->newCollection()); } diff --git a/app/Relations/HasAlbumThumb.php b/app/Relations/HasAlbumThumb.php index e93ac12f2c8..a3e2f0731cf 100644 --- a/app/Relations/HasAlbumThumb.php +++ b/app/Relations/HasAlbumThumb.php @@ -14,7 +14,6 @@ use App\Policies\PhotoQueryPolicy; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Query\Builder as BaseBuilder; use Illuminate\Support\Facades\Auth; @@ -23,7 +22,9 @@ /** * @mixin Builder * - * @extends Relation + * @extends Relation + * + * @disregard P1037 */ class HasAlbumThumb extends Relation { @@ -41,7 +42,7 @@ public function __construct(Album $parent) $this->photoQueryPolicy = resolve(PhotoQueryPolicy::class); $this->sorting = PhotoSortingCriterion::createDefault(); parent::__construct( - Photo::query()->with(['size_variants' => (fn (HasMany $r) => Thumb::sizeVariantsFilter($r))]), + Photo::query()->with(['size_variants' => (fn ($r) => Thumb::sizeVariantsFilter($r))]), $parent ); } diff --git a/app/Relations/HasManyBidirectionally.php b/app/Relations/HasManyBidirectionally.php index 563552a6221..8be72f32267 100644 --- a/app/Relations/HasManyBidirectionally.php +++ b/app/Relations/HasManyBidirectionally.php @@ -10,9 +10,9 @@ /** * @template TRelatedModel of \Illuminate\Database\Eloquent\Model - * @template TParentModel of \Illuminate\Database\Eloquent\Model + * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model * - * @extends HasMany + * @extends HasMany */ class HasManyBidirectionally extends HasMany implements BidirectionalRelation { @@ -20,7 +20,7 @@ class HasManyBidirectionally extends HasMany implements BidirectionalRelation /** * @param Builder $query - * @param TParentModel $parent + * @param TDeclaringModel $parent * @param string $foreignKey * @param string $localKey * @param string $foreignMethodName @@ -29,7 +29,6 @@ class HasManyBidirectionally extends HasMany implements BidirectionalRelation */ public function __construct(Builder $query, Model $parent, string $foreignKey, string $localKey, string $foreignMethodName) { - /** @phpstan-ignore-next-line */ parent::__construct($query, $parent, $foreignKey, $localKey); $this->foreignMethodName = $foreignMethodName; } @@ -42,11 +41,11 @@ public function __construct(Builder $query, Model $parent, string $foreignKey, s * but additionally sets the reverse association of the child object * back to its parent object. * - * @param TParentModel[] $models an array of parent models + * @param TDeclaringModel[] $models an array of parent models * @param Collection $results the unified collection of all child models of all parent models * @param string $relation the name of the relation from the parent to the child models * - * @return TParentModel[] + * @return array */ public function match(array $models, Collection $results, $relation): array { diff --git a/app/Relations/HasManyChildAlbums.php b/app/Relations/HasManyChildAlbums.php index 6293f96207e..129accd36d3 100644 --- a/app/Relations/HasManyChildAlbums.php +++ b/app/Relations/HasManyChildAlbums.php @@ -81,6 +81,7 @@ public function addEagerConstraints(array $models) public function getResults(): Collection { if (is_null($this->getParentKey())) { + /** @var Collection */ return $this->related->newCollection(); } @@ -99,7 +100,7 @@ public function getResults(): Collection * @param Collection $results the unified collection of all child models of all parent models * @param string $relation the name of the relation from the parent to the child models * - * @return Album[] + * @return array */ public function match(array $models, Collection $results, $relation): array { diff --git a/app/Relations/HasManyChildPhotos.php b/app/Relations/HasManyChildPhotos.php index 4c07d0cc9fd..2e5fa3e530c 100644 --- a/app/Relations/HasManyChildPhotos.php +++ b/app/Relations/HasManyChildPhotos.php @@ -60,8 +60,6 @@ public function getParent(): Album * because it was set in the constructor as `$owningAlbum`. * * @noinspection PhpIncompatibleReturnTypeInspection - * - * @phpstan-ignore-next-line */ return $this->parent; } @@ -119,7 +117,7 @@ public function getResults(): Collection * @param Collection $results the unified collection of all child models of all parent models * @param string $relation the name of the relation from the parent to the child models * - * @return Album[] + * @return array * * @throws \LogicException * @throws InvalidCastException diff --git a/app/Relations/HasManyPhotosByTag.php b/app/Relations/HasManyPhotosByTag.php index 0403fce27f7..6fd7294971a 100644 --- a/app/Relations/HasManyPhotosByTag.php +++ b/app/Relations/HasManyPhotosByTag.php @@ -10,6 +10,11 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +/** + * @disregard + * + * @extends BaseHasManyPhotos + */ class HasManyPhotosByTag extends BaseHasManyPhotos { public function __construct(TagAlbum $owningAlbum) @@ -30,7 +35,6 @@ public function __construct(TagAlbum $owningAlbum) public function addConstraints(): void { if (static::$constraints) { - /** @phpstan-ignore-next-line */ $this->addEagerConstraints([$this->parent]); } } @@ -78,7 +82,7 @@ public function addEagerConstraints(array $albums): void * @param Collection $photos collection of {@link Photo} models which needs to be mapped to the albums * @param string $relation the name of the relation * - * @return TagAlbum[] + * @return array * * @throws NotImplementedException */ diff --git a/app/Relations/HasManyPhotosRecursively.php b/app/Relations/HasManyPhotosRecursively.php index 33073d70296..f6ba804b2a3 100644 --- a/app/Relations/HasManyPhotosRecursively.php +++ b/app/Relations/HasManyPhotosRecursively.php @@ -12,6 +12,11 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Facades\Gate; +/** + * @disregard + * + * @extends BaseHasManyPhotos + */ class HasManyPhotosRecursively extends BaseHasManyPhotos { protected AlbumQueryPolicy $albumQueryPolicy; @@ -33,8 +38,6 @@ public function getParent(): Album * because it was set in the constructor as `$owningAlbum`. * * @noinspection PhpIncompatibleReturnTypeInspection - * - * @phpstan-ignore-next-line */ return $this->parent; } @@ -102,7 +105,7 @@ public function getResults(): Collection * @param Collection $photos collection of {@link Photo} models which needs to be mapped to the albums * @param string $relation the name of the relation * - * @return Album[] + * @return array * * @throws NotImplementedException */ diff --git a/app/Relations/HasManySizeVariants.php b/app/Relations/HasManySizeVariants.php index d341c24bfb5..7018e2e56a5 100644 --- a/app/Relations/HasManySizeVariants.php +++ b/app/Relations/HasManySizeVariants.php @@ -16,7 +16,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; /** - * @extends HasMany + * @extends HasMany */ class HasManySizeVariants extends HasMany { @@ -24,7 +24,7 @@ public function __construct(Photo $owningPhoto) { parent::__construct( SizeVariant::query(), - $owningPhoto, /** @phpstan-ignore-line */ + $owningPhoto, 'photo_id', 'id' ); @@ -62,7 +62,7 @@ public function getResults(): SizeVariants * @param Photo[] $models * @param string $relation * - * @return Photo[] + * @return array */ public function initRelation(array $models, $relation): array { @@ -89,7 +89,7 @@ public function initRelation(array $models, $relation): array * @param Collection $results the unified collection of all child models of all parent models * @param string $relation the name of the relation from the parent to the child models * - * @return Photo[] + * @return array */ public function match(array $models, Collection $results, $relation): array { diff --git a/app/Rules/AlbumIDRule.php b/app/Rules/AlbumIDRule.php index ea585f56c49..976f061bb1f 100644 --- a/app/Rules/AlbumIDRule.php +++ b/app/Rules/AlbumIDRule.php @@ -33,8 +33,9 @@ public function passes(string $attribute, mixed $value): bool */ public function message(): string { - return ':attribute ' . - ' must either be null, a string with ' . RandomID::ID_LENGTH . ' characters or one of the built-in IDs ' . + return ':attribute must be' . + ($this->isNullable ? ' either null, or' : '') . + ' a string with ' . RandomID::ID_LENGTH . ' characters or one of the built-in IDs ' . implode(', ', SmartAlbumType::values()); } } diff --git a/app/Rules/BooleanRequireSupportRule.php b/app/Rules/BooleanRequireSupportRule.php new file mode 100644 index 00000000000..df6fed39191 --- /dev/null +++ b/app/Rules/BooleanRequireSupportRule.php @@ -0,0 +1,38 @@ +verify = $verify; + $this->expected = $expected; + } + + /** + * {@inheritDoc} + */ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + $value = filter_var($value, FILTER_VALIDATE_BOOLEAN); + if ($value === $this->expected) { + return; + } + + if ($this->verify->is_supporter()) { + return; + } + + $fail('Error: This functionality is only available in the Supporter Edition of Lychee. See here: https://lycheeorg.github.io/get-supporter-edition/'); + } +} diff --git a/app/Rules/ConfigKeyRequireSupportRule.php b/app/Rules/ConfigKeyRequireSupportRule.php new file mode 100644 index 00000000000..07d1c4c8a8c --- /dev/null +++ b/app/Rules/ConfigKeyRequireSupportRule.php @@ -0,0 +1,44 @@ +verify = $verify; + } + + /** + * {@inheritDoc} + */ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + if (is_string($value) === false) { + // This is taken care of in ConfigKeyRule + return; + } + + /** @var string $value */ + if (!array_key_exists($value, Configs::get())) { + // This is taken care of in ConfigKeyRule + return; + } + + /** @var string $value */ + $config = Configs::where('key', '=', $value)->firstOrFail(); + if ($config->level === 1 && !$this->verify->is_supporter()) { + $fail('Error: This functionality is only available in the Supporter Edition of Lychee. See here: https://lycheeorg.github.io/get-supporter-edition/'); + + return; + } + } +} diff --git a/app/Rules/ConfigKeyRule.php b/app/Rules/ConfigKeyRule.php new file mode 100644 index 00000000000..1cc40f8f820 --- /dev/null +++ b/app/Rules/ConfigKeyRule.php @@ -0,0 +1,28 @@ + */ + private Collection $configs; + + /** + * All of the data under validation. + * + * @var array + */ + protected $data = []; + + public function __construct() + { + $this->configs = Configs::all(); + } + + /** + * Set the data under validation. + * + * @param array $data + * + * @phpstan-ignore-next-line + */ + public function setData(array $data): static + { + $this->data = $data; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function passes(string $attribute, mixed $value): bool + { + $path = explode('.', $attribute); + if (count($path) !== 3) { + throw new LycheeLogicException('ConfigValueRule: attribute must be in the form of "xxx.*.value"'); + } + + $template = 'Error: Expected %s, got ' . ($value ?? 'NULL') . '.'; + $array_key = $this->data[$path[0]][intval($path[1])]['key']; + + return '' === $this->configs->first(fn (Configs $c) => $c->key === $array_key)->sanity($value, $template); + } + + /** + * {@inheritDoc} + */ + public function message(): string + { + return ':attribute is not a valid configuration value.'; + } +} diff --git a/app/Rules/ExtensionRule.php b/app/Rules/ExtensionRule.php new file mode 100644 index 00000000000..0dbf18aa6e9 --- /dev/null +++ b/app/Rules/ExtensionRule.php @@ -0,0 +1,96 @@ + + */ + protected $data = []; + + /** + * Set the data under validation. + * + * @param array $data + * + * @phpstan-ignore-next-line + */ + public function setData(array $data): static + { + $this->data = $data; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + $value = $value === '' ? null : $value; + + if ($attribute !== 'extension') { + throw new LycheeLogicException('ExtensionRule: attribute must be "extension"'); + } + + $chunk_number = intval($this->data['chunk_number'] ?? null); + if ($chunk_number === 0) { + return; // we are going to fail elsewhere. + } + + if ($chunk_number === 1 && $value === null) { + return; // it is normal that it is not set yet. + } + + if ($chunk_number === 1 && $value !== null) { + $fail('Error: Expected NULL in :attribute , got ' . $value . '.'); + + return; // it is not normal that it is set. + } + + if (is_string($value) === false) { + $fail(':attribute is not a string.'); + + return; + } + + if (Str::of($value)->isMatch('/^\.[a-zA-Z0-9]*$/') === false) { + $fail(':attribute is not a valid extension.'); + + return; + } + + $file_name = $this->data['file_name'] ?? null; + if ($file_name === null) { + return; // we are going to fail elsewhere + } + + $extension = '.' . pathinfo($file_name, PATHINFO_EXTENSION); + if ($value !== $extension) { + $fail('Error: Expected ' . $extension . ' in :attribute, got ' . $value . '.'); + + return; + } + + $file_name = $this->data['uuid_name'] ?? null; + if ($file_name === null) { + return; // we are going to fail elsewhere if chunk is not 1. + } + + $extension = '.' . pathinfo($this->data['uuid_name'] ?? '', PATHINFO_EXTENSION); + if ($value !== $extension) { + $fail('Error: Expected ' . $extension . ' in :attribute, got ' . $value . '.'); + } + } +} diff --git a/app/Rules/FileUuidRule.php b/app/Rules/FileUuidRule.php new file mode 100644 index 00000000000..76ea4057788 --- /dev/null +++ b/app/Rules/FileUuidRule.php @@ -0,0 +1,88 @@ + + */ + protected $data = []; + + /** + * Set the data under validation. + * + * @param array $data + * + * @phpstan-ignore-next-line + */ + public function setData(array $data): static + { + $this->data = $data; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + $value = $value === '' ? null : $value; + + if ($attribute !== 'uuid_name') { + throw new LycheeLogicException('FileUuidRule: attribute must be "uuid_name"'); + } + + $chunk_number = intval($this->data['chunk_number'] ?? null); + if ($chunk_number === 0) { + return; // we are going to fail elsewhere. + } + + if ($chunk_number === 1 && $value === null) { + return; // it is normal that it is not set yet. + } + + if ($chunk_number === 1 && $value !== null) { + $fail('Error: Expected NULL in :attribute , got ' . $value . '.'); + + return; // it is not normal that it is set. + } + + if (is_string($value) === false) { + $fail(':attribute is not a string.'); + + return; + } + + $file_name = $this->data['file_name'] ?? null; + if ($file_name === null) { + return; // we are going to fail elsewhere + } + + $extension = pathinfo($file_name, PATHINFO_EXTENSION); + + $pattern = '/[a-zA-Z0-9-_]{16}\.' . $extension . '/'; + if (Str::of($value)->isMatch($pattern) === false) { + $fail(':attribute is not a valid random string.'); + + return; + } + + if (!Storage::disk(PhotoController::DISK_NAME)->exists($value)) { + $fail(':attribute is not a valid target file.'); + } + } +} diff --git a/app/Rules/IntegerRequireSupportRule.php b/app/Rules/IntegerRequireSupportRule.php new file mode 100644 index 00000000000..c975ba444a0 --- /dev/null +++ b/app/Rules/IntegerRequireSupportRule.php @@ -0,0 +1,37 @@ +verify = $verify; + $this->expected = $expected; + } + + /** + * {@inheritDoc} + */ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + if (is_int($value) && intval($value) === $this->expected) { + return; + } + + if ($this->verify->is_supporter()) { + return; + } + + $fail('Error: This functionality is only available in the Supporter Edition of Lychee. See here: https://lycheeorg.github.io/get-supporter-edition/'); + } +} diff --git a/app/Rules/StringRequireSupportRule.php b/app/Rules/StringRequireSupportRule.php new file mode 100644 index 00000000000..979477e66c6 --- /dev/null +++ b/app/Rules/StringRequireSupportRule.php @@ -0,0 +1,38 @@ +verify = $verify; + $this->expected = $expected === '' ? null : $expected; + } + + /** + * {@inheritDoc} + */ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + $value = $value === '' ? null : $value; + if ($value === $this->expected) { + return; + } + + if ($this->verify->is_supporter()) { + return; + } + + $fail('Error: This functionality is only available in the Supporter Edition of Lychee. See here: https://lycheeorg.github.io/get-supporter-edition/'); + } +} diff --git a/app/Services/Auth/SessionOrTokenGuard.php b/app/Services/Auth/SessionOrTokenGuard.php index 32482ad9a06..bf3cd66adfe 100644 --- a/app/Services/Auth/SessionOrTokenGuard.php +++ b/app/Services/Auth/SessionOrTokenGuard.php @@ -119,6 +119,7 @@ public static function createGuard(Application $app, string $name, array $config $guard = new self($name, $userProvider, $app->make('session.store')); $guard->setCookieJar($app->make('cookie')); $guard->setDispatcher($app->make('events')); + /** @disregard P1013 */ $guard->setRequest($app->refresh('request', $guard, 'setRequest')); if (isset($config['remember'])) { $guard->setRememberDuration($config['remember']); @@ -344,7 +345,7 @@ protected function getUserByToken(): ?Authenticatable $authenticable !== null => $authenticable, $hasBearer && $configThrow => throw new BadRequestHeaderException('Invalid token'), $hasBearer => null, - default => throw new BadRequestHeaderException('Invalid token') + default => throw new BadRequestHeaderException('Invalid token'), }; } } diff --git a/app/SmartAlbums/BaseSmartAlbum.php b/app/SmartAlbums/BaseSmartAlbum.php index 7712ec0a007..2c44639b3eb 100644 --- a/app/SmartAlbums/BaseSmartAlbum.php +++ b/app/SmartAlbums/BaseSmartAlbum.php @@ -74,10 +74,12 @@ protected function __construct(SmartAlbumType $id, \Closure $smartCondition) */ public function photos(): Builder { - return $this->photoQueryPolicy + $query = $this->photoQueryPolicy ->applySearchabilityFilter( Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links']) )->where($this->smartPhotoCondition); + + return $query; } /** diff --git a/app/SmartAlbums/UnsortedAlbum.php b/app/SmartAlbums/UnsortedAlbum.php index 1aade470113..9df28a02a6c 100644 --- a/app/SmartAlbums/UnsortedAlbum.php +++ b/app/SmartAlbums/UnsortedAlbum.php @@ -5,6 +5,7 @@ use App\Enum\SmartAlbumType; use App\Exceptions\ConfigurationKeyMissingException; use App\Exceptions\Internal\FrameworkException; +use App\Models\Photo; use Illuminate\Database\Eloquent\Builder; class UnsortedAlbum extends BaseSmartAlbum @@ -28,4 +29,20 @@ public static function getInstance(): self { return self::$instance ??= new self(); } + + /** + * In the case of unsorted, we cannot determine whether the photo is visible or not from its parent. + * If the Unsorted album is made public, then all the pictures in it are visible (including pictures which are not owned by the current user). + * + * @return \App\Eloquent\FixedQueryBuilder + */ + public function photos(): Builder + { + if ($this->publicPermissions !== null) { + return Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links']) + ->where($this->smartPhotoCondition); + } + + return parent::photos(); + } } diff --git a/app/SmartAlbums/Utils/MimicModel.php b/app/SmartAlbums/Utils/MimicModel.php index fc58a8ed308..81e9bf2ed5a 100644 --- a/app/SmartAlbums/Utils/MimicModel.php +++ b/app/SmartAlbums/Utils/MimicModel.php @@ -4,49 +4,12 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\Exceptions\Internal\LycheeInvalidArgumentException; -use Illuminate\Database\Eloquent\JsonEncodingException; use Illuminate\Support\Str; trait MimicModel { abstract public function toArray(): array; - /** - * Serializes this object into an array. - * - * @return array The serialized properties of this object - * - * @throws \JsonException - */ - public function jsonSerialize(): array - { - try { - return $this->toArray(); - } catch (\Exception $e) { - throw new \JsonException(get_class($this) . '::toArray() failed', 0, $e); - } - } - - /** - * Convert the model instance to JSON. - * - * The error message is inspired by {@link JsonEncodingException::forModel()}. - * - * @param int $options - * - * @return string - * - * @throws JsonEncodingException - */ - public function toJson($options = 0): string - { - try { - return json_encode($this->jsonSerialize(), $options | JSON_THROW_ON_ERROR); - } catch (\JsonException $e) { - throw new JsonEncodingException('Error encoding [' . get_class($this) . '] to JSON', 0, $e); - } - } - /** * Gets a property dynamically. * @@ -84,18 +47,6 @@ public function __get(string $key) } } - /** - * Convert the model to its string representation. - * - * @return string - * - * @throws JsonEncodingException - */ - public function __toString(): string - { - return $this->toJson(); - } - /** * Determine if the given relation is loaded. * diff --git a/app/View/Components/BackButtonHeader.php b/app/View/Components/BackButtonHeader.php deleted file mode 100644 index 5a7f11384f6..00000000000 --- a/app/View/Components/BackButtonHeader.php +++ /dev/null @@ -1,43 +0,0 @@ -class = $class; - $this->enabled = Configs::getValueAsBool('back_button_enabled'); - $this->label = Configs::getValueAsString('back_button_text'); - $this->url = Configs::getValueAsString('back_button_url'); - } - - /** - * Render component. - * - * @return View - */ - public function render(): View - { - return view('components.header.back-button'); - } -} diff --git a/app/View/Components/Footer.php b/app/View/Components/Footer.php deleted file mode 100644 index f2104cafd7a..00000000000 --- a/app/View/Components/Footer.php +++ /dev/null @@ -1,74 +0,0 @@ -layout = $layout; - $this->show_socials = Configs::getValueAsBool('footer_show_social_media'); - $this->facebook = Configs::getValueAsString('sm_facebook_url'); - $this->flickr = Configs::getValueAsString('sm_flickr_url'); - $this->twitter = Configs::getValueAsString('sm_twitter_url'); - $this->instagram = Configs::getValueAsString('sm_instagram_url'); - $this->youtube = Configs::getValueAsString('sm_youtube_url'); - - $this->hosted_by = __('lychee.HOSTED_WITH_LYCHEE'); - - if (Configs::getValueAsBool('footer_show_copyright')) { - $copyright_year = Configs::getValueAsString('site_copyright_begin'); - $copyright_year_end = Configs::getValueAsString('site_copyright_end'); - if ($copyright_year !== $copyright_year_end) { - $copyright_year = $copyright_year . '-' . $copyright_year_end; - } - - $this->copyright = sprintf( - __('lychee.FOOTER_COPYRIGHT'), - Configs::getValueAsString('site_owner'), - $copyright_year - ); - } - - $this->additional_footer_text = Configs::getValueAsString('footer_additional_text'); - } - - /** - * Render component. - * - * @return View - * - * @throws BindingResolutionException - */ - public function render(): View - { - return view('components.' . $this->layout); - } -} diff --git a/app/View/Components/Gallery/Album/SharingLinks.php b/app/View/Components/Gallery/Album/SharingLinks.php deleted file mode 100644 index b04bbaa83db..00000000000 --- a/app/View/Components/Gallery/Album/SharingLinks.php +++ /dev/null @@ -1,30 +0,0 @@ -url = route('livewire-gallery-album', ['albumId' => $albumId]); - $this->rawUrl = rawurlencode($this->url); - $raw_title = rawurlencode($albumTitle); - $this->twitter_link = 'https://twitter.com/share?url=' . $this->rawUrl; - $this->facebook_link = 'https://www.facebook.com/sharer.php?u=' . $this->rawUrl . '?t=' . $raw_title; - $this->mailTo_link = 'mailto:?subject=' . $raw_title . '&body=' . $this->rawUrl; - } - - public function render(): View - { - return view('components.gallery.album.sharing-links'); - } -} \ No newline at end of file diff --git a/app/View/Components/Gallery/Album/Thumbs/Album.php b/app/View/Components/Gallery/Album/Thumbs/Album.php deleted file mode 100644 index 0618acd6592..00000000000 --- a/app/View/Components/Gallery/Album/Thumbs/Album.php +++ /dev/null @@ -1,87 +0,0 @@ -aspect_ratio_class = $strAspectRatioClass; - - $date_format = Configs::getValueAsString('date_format_album_thumb'); - - $displayOverlay = Configs::getValueAsEnum('display_thumb_album_overlay', ThumbOverlayVisibilityType::class); - $this->subType = Configs::getValueAsEnum('album_subtitle_type', ThumbAlbumSubtitleType::class)->value; - - $this->id = $data->id; - $this->thumb = $data->thumb; - $this->title = $data->title; - - if ($data instanceof BaseSmartAlbum) { - $policy = AlbumProtectionPolicy::ofSmartAlbum($data); - } else { - /** @var BaseAlbum $data */ - $this->max_taken_at = $data->max_taken_at?->format($date_format); - $this->min_taken_at = $data->min_taken_at?->format($date_format); - $this->created_at = $data->created_at->format($date_format); - $policy = AlbumProtectionPolicy::ofBaseAlbum($data); - } - - $this->css_overlay = match ($displayOverlay) { - ThumbOverlayVisibilityType::NEVER => 'hidden', - ThumbOverlayVisibilityType::HOVER => 'opacity-0 group-hover:opacity-100 transition-all ease-out', - default => '', - }; - - $this->is_nsfw = $policy->is_nsfw; - $this->is_nsfw_blurred = $this->is_nsfw && Configs::getValueAsBool('nsfw_blur'); - $this->is_public = $policy->is_public; - $this->is_link_required = $policy->is_link_required; - $this->is_password_required = $policy->is_password_required; - - $this->is_tag_album = $data instanceof TagAlbum; - // This aims to indicate whether the current thumb is used to determine the parent. - $this->is_cover_id = $data instanceof AlbumModel && $data->thumb !== null && $coverId === $data->thumb->id; - $this->has_subalbum = $data instanceof AlbumModel && !$data->isLeaf(); - } - - public function render() - { - return view('components.gallery.album.thumbs.album'); - } -} \ No newline at end of file diff --git a/app/View/Components/Gallery/Album/Thumbs/AlbumThumb.php b/app/View/Components/Gallery/Album/Thumbs/AlbumThumb.php deleted file mode 100644 index b83ebba9958..00000000000 --- a/app/View/Components/Gallery/Album/Thumbs/AlbumThumb.php +++ /dev/null @@ -1,48 +0,0 @@ -class = $class; - if ($thumb === 'uploads/thumb/') { - $this->src = Str::contains($type, 'video') ? URL::asset('img/play-icon.png') : URL::asset('img/placeholder.png'); - $this->dataSrc = Str::contains($type, 'raw') ? URL::asset('img/no_images.svg') : ''; - } else { - $this->src = URL::asset('img/no_images.svg'); - - if ($thumb !== '') { - $this->dataSrc = $thumb; - } - } - - $this->src = sprintf("src='%s'", $this->src); - if ($this->dataSrc !== '') { - $this->dataSrc = sprintf("data-src='%s'", $this->dataSrc); - } - - if ($thumb2x !== '') { - $this->dataSrcSet = sprintf("data-srcset='%s 2x'", $thumb2x); - } - } - - public function render() - { - return view('components.gallery.album.thumbs.album-thumb'); - } -} diff --git a/app/View/Components/Gallery/Album/Thumbs/Photo.php b/app/View/Components/Gallery/Album/Thumbs/Photo.php deleted file mode 100644 index 327efe2f255..00000000000 --- a/app/View/Components/Gallery/Album/Thumbs/Photo.php +++ /dev/null @@ -1,180 +0,0 @@ -idx = $idx; - $date_format = Configs::getValueAsString('date_format_photo_thumb'); - $displayOverlay = Configs::getValueAsEnum('display_thumb_photo_overlay', ThumbOverlayVisibilityType::class); - - $this->album_id = $albumId; - $this->photo_id = $data->id; - $this->title = $data->title; - $this->taken_at = $data->taken_at?->format($date_format) ?? ''; - $this->created_at = $data->created_at->format($date_format); - - $this->is_video = $data->isVideo(); - $this->is_livephoto = $data->live_photo_url !== null; - $this->is_cover_id = $coverId === $data->id; - - $this->css_overlay = match ($displayOverlay) { - ThumbOverlayVisibilityType::NEVER => 'hidden', - ThumbOverlayVisibilityType::HOVER => 'opacity-0 group-hover:opacity-100 transition-all ease-out', - default => '', - }; - - $thumb = $data->size_variants->getSizeVariant(SizeVariantType::THUMB); - $thumb2x = $data->size_variants->getSizeVariant(SizeVariantType::THUMB2X); - - $this->set_src($thumb); - - $dim = 200; - $dim2x = 400; - $thumbUrl = $thumb?->url; - $thumb2xUrl = $thumb2x?->url; - - // Probably this code needs some fix/refactoring, too. However, where is this method invoked and - // what is the structure of the passed `data` array? (Could find any invocation.) - - if ($data->size_variants->hasMediumOrSmall()) { - $thumbsUrls = $this->setThumbUrls($data->size_variants); - - $this->_w = $thumbsUrls['w']; - $this->_h = $thumbsUrls['h']; - $dim2x = $thumbsUrls['w2x']; - $thumbUrl = $thumbsUrls['thumbUrl']; - $thumb2xUrl = $thumbsUrls['thumb2xUrl']; - - $dim = $this->_w; - } elseif (!$data->isVideo()) { - $original = $data->size_variants->getSizeVariant(SizeVariantType::ORIGINAL); - - $this->_w ??= $original->width; - $this->_h ??= $original->height; - // Fallback for images with no small or medium. - $thumbUrl ??= $original->url; - } elseif ($thumbUrl === null) { - // Fallback for videos with no small (the case of no thumb is handled else where). - $dim = 200; - $dim2x = 200; - } - - $this->srcset = sprintf("data-src='%s'", $thumbUrl); - $this->srcset2x = $thumb2xUrl !== null ? sprintf("data-srcset='%s %dw, %s %dw'", $thumbUrl, $dim, $thumb2xUrl, $dim2x) : ''; - } - - /** - * Define src. - * - * this is what will be first deplayed before loading. - * - * @param SizeVariant|null $thumb - * - * @return void - */ - private function set_src(?SizeVariant $thumb): void - { - // default is place holder - $this->src = URL::asset('img/placeholder.png'); - - // if thumb is not null then directly return: - // it will be replaced later by src-set - if ($thumb !== null) { - $this->src = sprintf("src='%s'", $this->src); - - return; - } - - // change the png in the other cases. - // no need to lazyload too. - $this->is_lazyload = false; - $this->src = $this->is_video ? URL::asset('img/play-icon.png') : $this->src; - $this->src = $this->is_livephoto ? URL::asset('img/live-photo-icon.png') : $this->src; - $this->src = sprintf("src='%s'", $this->src); - } - - /** - * Fetch the thumbs data. - * - * @param SizeVariants $sizeVariants - * - * @return array{w:int,w2x:int|null,h:int,thumbUrl:string,thumb2xUrl:string|null} - * - * @throws InvalidSizeVariantException - */ - private function setThumbUrls(SizeVariants $sizeVariants): array - { - $small = $sizeVariants->getSizeVariant(SizeVariantType::SMALL); - $small2x = $sizeVariants->getSizeVariant(SizeVariantType::SMALL2X); - $medium = $sizeVariants->getSizeVariant(SizeVariantType::MEDIUM); - $medium2x = $sizeVariants->getSizeVariant(SizeVariantType::MEDIUM2X); - - /** @var int $w */ - $w = $small?->width ?? $medium?->width; - $w2x = $small2x?->width ?? $medium2x?->width; - /** @var int $h */ - $h = $small?->height ?? $medium?->height; - - /** @var string $thumbUrl */ - $thumbUrl = $small?->url ?? $medium?->url; - $thumb2xUrl = $small2x?->url ?? $medium2x?->url; - - return ['w' => $w, 'w2x' => $w2x, 'h' => $h, 'thumbUrl' => $thumbUrl, 'thumb2xUrl' => $thumb2xUrl]; - } - - /** - * Get the view / contents that represent the component. - * - * @return \Illuminate\Contracts\View\View|\Closure|string - * - * @throws BindingResolutionException - */ - public function render() - { - return view('components.gallery.album.thumbs.photo'); - } -} diff --git a/app/View/Components/Gallery/Photo/Download.php b/app/View/Components/Gallery/Photo/Download.php deleted file mode 100644 index 5357be75304..00000000000 --- a/app/View/Components/Gallery/Photo/Download.php +++ /dev/null @@ -1,62 +0,0 @@ - */ - public array $size_variants; - - /** - * Mount the photo model and initialize the Component. - * - * @param Photo $photo - * - * @return void - */ - public function __construct(Photo $photo) - { - $this->photoId = $photo->id; - - $downgrade = !Gate::check(PhotoPolicy::CAN_ACCESS_FULL_PHOTO, [Photo::class, $photo]) && - !$photo->isVideo() && - $photo->size_variants->hasMedium() === true; - - $rq = request(); - - // TODO: Add Live photo - $this->size_variants = collect(SizeVariantType::cases()) - ->map(fn ($v) => $photo->size_variants->getSizeVariant($v)) - ->filter(fn ($e) => $e !== null) - ->map(fn ($v) => SizeVariantResource::make($v)) - ->map(fn ($v, $k) => $k === 0 ? $v->setNoUrl($downgrade) : $v) // 0 = original - ->map(fn ($v) => $v->toArray($rq)) - ->map(function ($v) { - /** @var array{filesize:int} $v */ - $v['filesize'] = Helpers::getSymbolByQuantity(intval($v['filesize'])); - - return $v; - })->all(); - } - - /** - * Render the component. - * - * @return View - */ - public function render(): View - { - return view('components.gallery.photo.downloads'); - } -} diff --git a/app/View/Components/Meta.php b/app/View/Components/Meta.php index d5c0826bd0b..c2b7b25992e 100644 --- a/app/View/Components/Meta.php +++ b/app/View/Components/Meta.php @@ -2,10 +2,14 @@ namespace App\View\Components; +use App\Contracts\Models\AbstractAlbum; use App\Exceptions\ConfigurationKeyMissingException; -use App\Legacy\V1\Controllers\IndexController; +use App\Http\Resources\Traits\HasHeaderUrl; use App\Models\Configs; +use App\Models\Extensions\BaseAlbum; +use App\Models\Photo; use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Support\Facades\Storage; use Illuminate\View\Component; use Illuminate\View\View; @@ -15,15 +19,17 @@ */ class Meta extends Component { + use HasHeaderUrl; + public string $pageTitle; public string $pageDescription; public string $siteOwner; public string $imageUrl; public string $pageUrl; + public string $baseUrl; public bool $rssEnable; public string $userCssUrl; public string $userJsUrl; - public string $frame; /** * Initialize the footer once for all. @@ -32,33 +38,34 @@ class Meta extends Component */ public function __construct() { - $siteTitle = Configs::getValueAsString('site_title'); - $title = ''; - $description = ''; - $imageUrl = ''; + $this->pageTitle = Configs::getValueAsString('site_title'); + $this->pageDescription = ''; + $this->imageUrl = ''; + + if (session()->has('album')) { + /** @var AbstractAlbum $album */ + $album = session()->get('album'); + $this->pageTitle = $album->title; + if ($album instanceof BaseAlbum) { + $this->pageDescription = $album->description ?? Configs::getValueAsString('site_title'); + } + $this->imageUrl = $this->getHeaderUrl($album) ?? ''; + } - // if ($this->photoId !== null) { - // $photo = Photo::findOrFail($this->photoId); - // $title = $photo->title; - // $description = $photo->description; - // $imageUrl = url()->to($photo->size_variants->getMedium()?->url ?? $photo->size_variants->getOriginal()->url); - // } elseif ($this->albumId !== null) { - // $albumFactory = resolve(AlbumFactory::class); - // $album = $albumFactory->findAbstractAlbumOrFail($this->albumId, false); - // $title = $album->title; - // $description = $album instanceof BaseAlbum ? $album->description : ''; - // $imageUrl = url()->to($album->thumb->thumbUrl ?? ''); - // } + if (session()->has('photo')) { + /** @var Photo $photo */ + $photo = session()->get('photo'); + $this->pageTitle = $photo->title; + $this->pageDescription = $photo->description ?? Configs::getValueAsString('site_title'); + $this->imageUrl = $photo->size_variants->getSmall()->url; + } - $this->pageTitle = $siteTitle . (!blank($siteTitle) && !blank($title) ? ' – ' : '') . $title; - $this->pageDescription = !blank($description) ? $description . ' – via Lychee' : ''; $this->siteOwner = Configs::getValueAsString('site_owner'); - $this->imageUrl = $imageUrl; $this->pageUrl = url()->current(); $this->rssEnable = Configs::getValueAsBool('rss_enable'); - $this->userCssUrl = IndexController::getUserCustomFiles('user.css'); - $this->userJsUrl = IndexController::getUserCustomFiles('custom.js'); - $this->frame = ''; + $this->userCssUrl = self::getUserCustomFiles('user.css'); + $this->userJsUrl = self::getUserCustomFiles('custom.js'); + $this->baseUrl = url('/'); } /** @@ -72,4 +79,23 @@ public function render(): View { return view('components.meta'); } + + /** + * Returns user.css url with cache busting if file has been updated. + * + * @param string $fileName + * + * @return string + */ + public static function getUserCustomFiles(string $fileName): string + { + $cssCacheBusting = ''; + /** @disregard P1013 */ + if (Storage::disk('dist')->fileExists($fileName)) { + $cssCacheBusting = '?' . Storage::disk('dist')->lastModified($fileName); + } + + /** @disregard P1013 */ + return Storage::disk('dist')->url($fileName) . $cssCacheBusting; + } } \ No newline at end of file diff --git a/codecov.yml b/codecov.yml index 4e4037f335d..b6a4ef4f351 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,7 +2,7 @@ codecov: require_ci_to_pass: true notify: - after_n_builds: 9 + after_n_builds: 6 wait_for_ci: true comment: behavior: default @@ -24,7 +24,16 @@ ignore: - "^app/Console/.*" - "^app/Exceptions/.*" - "^app/Http/Middleware/VerifyCsrfToken.*" +- "^app/Http/Middleware/VerifyCsrfToken.*" - "^app/Providers/BroadcastServiceProvider.*" +- "^app/Jobs/UploadSizeVariantToS3Job.php" +# We do not test those +- "^app/Mail/.*" +- "^app/Notifications/.*" +# Legacy shit +- "^app/Legacy/Actions/Photo/.*" +- "^app/Livewire/.*" +- "^app/View/.*" parsers: gcov: branch_detection: diff --git a/composer.json b/composer.json index 2b0c3b9279b..be37248e8c4 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,10 @@ { "type": "vcs", "url": "https://github.com/LycheeOrg/log-viewer" + }, + { + "type": "vcs", + "url": "https://github.com/LycheeOrg/verify" } ], "license": "MIT", @@ -53,9 +57,9 @@ "laminas/laminas-text": "^2.9", "laragear/webauthn": "^2.0", "laravel/framework": "^11.0", - "league/flysystem-aws-s3-v3": "^3.22", "laravel/socialite": "^5.11", - "livewire/livewire": "^3.0", + "league/flysystem-aws-s3-v3": "^3.22", + "lychee-org/lycheeverify": "^1.0.2", "lychee-org/nestedset": "^9.0", "lychee-org/php-exif": "^1.0.4", "maennchen/zipstream-php": "^3.1", @@ -72,9 +76,12 @@ "socialiteproviders/keycloak": "^5.3", "socialiteproviders/microsoft": "^4.2", "socialiteproviders/nextcloud": "^4.0", + "spatie/enum": "^3.13", "spatie/guzzle-rate-limiter-middleware": "^2.0", + "spatie/laravel-data": "^4.7", "spatie/laravel-feed": "^4.0", "spatie/laravel-image-optimizer": "^1.8", + "spatie/laravel-typescript-transformer": "^2.4", "symfony/cache": "^v6.0.0", "thecodingmachine/safe": "^2.4" }, @@ -84,16 +91,17 @@ "ext-zip": "*", "barryvdh/laravel-debugbar": "^3.13", "barryvdh/laravel-ide-helper": "^3.0", - "dedoc/scramble": "^0.10", + "brianium/paratest": "^7.4", + "fakerphp/faker": "^1.23.0", "filp/whoops": "^2.5", "friendsofphp/php-cs-fixer": "^3.3", "itsgoingd/clockwork": "^5.1", + "larastan/larastan": "^2.0", "lychee-org/phpstan-lychee": "^v1.0.1", "mockery/mockery": "^1.5", - "larastan/larastan": "^2.0", + "nunomaduro/collision": "^8.3", "php-parallel-lint/php-parallel-lint": "^1.3", - "phpunit/phpunit": "^10.0", - "fakerphp/faker": "^1.23.0" + "phpunit/phpunit": "^10.0" }, "autoload": { "classmap": [ diff --git a/composer.lock b/composer.lock index 06857762dd7..a66a56234ec 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,879 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8674432987412fffb5c4dbacd2a42b27", + "content-hash": "98c3bd77cb220e44b8187f60936e80fd", "packages": [ + { + "name": "amphp/amp", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "138801fb68cfc9c329da8a7b39d01ce7291ee4b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/138801fb68cfc9c329da8a7b39d01ce7291ee4b0", + "reference": "138801fb68cfc9c329da8a7b39d01ce7291ee4b0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Future/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-05-10T21:37:46+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "daa00f2efdbd71565bf64ffefa89e37542addf93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/daa00f2efdbd71565bf64ffefa89e37542addf93", + "reference": "daa00f2efdbd71565bf64ffefa89e37542addf93", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2.3" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.22.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v2.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-02-17T04:49:38+00:00" + }, + { + "name": "amphp/cache", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/cache.git", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Cache\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A fiber-aware cache API based on Amp and Revolt.", + "homepage": "https://amphp.org/cache", + "support": { + "issues": "https://github.com/amphp/cache/issues", + "source": "https://github.com/amphp/cache/tree/v2.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:38:06+00:00" + }, + { + "name": "amphp/dns", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/dns.git", + "reference": "758266b0ea7470e2e42cd098493bc6d6c7100cf7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/dns/zipball/758266b0ea7470e2e42cd098493bc6d6c7100cf7", + "reference": "758266b0ea7470e2e42cd098493bc6d6c7100cf7", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/windows-registry": "^1.0.1", + "daverandom/libdns": "^2.0.2", + "ext-filter": "*", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Dns\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Wright", + "email": "addr@daverandom.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Async DNS resolution for Amp.", + "homepage": "https://github.com/amphp/dns", + "keywords": [ + "amp", + "amphp", + "async", + "client", + "dns", + "resolve" + ], + "support": { + "issues": "https://github.com/amphp/dns/issues", + "source": "https://github.com/amphp/dns/tree/v2.2.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-06-02T19:54:12+00:00" + }, + { + "name": "amphp/parallel", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/parallel.git", + "reference": "9777db1460d1535bc2a843840684fb1205225b87" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parallel/zipball/9777db1460d1535bc2a843840684fb1205225b87", + "reference": "9777db1460d1535bc2a843840684fb1205225b87", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/pipeline": "^1", + "amphp/process": "^2", + "amphp/serialization": "^1", + "amphp/socket": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "files": [ + "src/Context/functions.php", + "src/Context/Internal/functions.php", + "src/Ipc/functions.php", + "src/Worker/functions.php" + ], + "psr-4": { + "Amp\\Parallel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Parallel processing component for Amp.", + "homepage": "https://github.com/amphp/parallel", + "keywords": [ + "async", + "asynchronous", + "concurrent", + "multi-processing", + "multi-threading" + ], + "support": { + "issues": "https://github.com/amphp/parallel/issues", + "source": "https://github.com/amphp/parallel/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-09-14T19:16:14+00:00" + }, + { + "name": "amphp/parser", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/parser.git", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/parser/issues", + "source": "https://github.com/amphp/parser/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:16:53+00:00" + }, + { + "name": "amphp/pipeline", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/pipeline.git", + "reference": "66c095673aa5b6e689e63b52d19e577459129ab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/66c095673aa5b6e689e63b52d19e577459129ab3", + "reference": "66c095673aa5b6e689e63b52d19e577459129ab3", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Asynchronous iterators and operators.", + "homepage": "https://amphp.org/pipeline", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "iterator", + "non-blocking" + ], + "support": { + "issues": "https://github.com/amphp/pipeline/issues", + "source": "https://github.com/amphp/pipeline/tree/v1.2.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-07-04T00:56:47+00:00" + }, + { + "name": "amphp/process", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Process\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A fiber-aware process manager based on Amp and Revolt.", + "homepage": "https://amphp.org/process", + "support": { + "issues": "https://github.com/amphp/process/issues", + "source": "https://github.com/amphp/process/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:13:44+00:00" + }, + { + "name": "amphp/serialization", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/serialization.git", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "phpunit/phpunit": "^9 || ^8 || ^7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Serialization\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Serialization tools for IPC and data storage in PHP.", + "homepage": "https://github.com/amphp/serialization", + "keywords": [ + "async", + "asynchronous", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/amphp/serialization/issues", + "source": "https://github.com/amphp/serialization/tree/master" + }, + "time": "2020-03-25T21:39:07+00:00" + }, + { + "name": "amphp/socket", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/socket.git", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/dns": "^2", + "ext-openssl": "*", + "kelunik/certificate": "^1.1", + "league/uri": "^6.5 | ^7", + "league/uri-interfaces": "^2.3 | ^7", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php", + "src/SocketAddress/functions.php" + ], + "psr-4": { + "Amp\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@gmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", + "homepage": "https://github.com/amphp/socket", + "keywords": [ + "amp", + "async", + "encryption", + "non-blocking", + "sockets", + "tcp", + "tls" + ], + "support": { + "issues": "https://github.com/amphp/socket/issues", + "source": "https://github.com/amphp/socket/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T14:33:03+00:00" + }, + { + "name": "amphp/sync", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/217097b785130d77cfcc58ff583cf26cd1770bf1", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Sync\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "support": { + "issues": "https://github.com/amphp/sync/issues", + "source": "https://github.com/amphp/sync/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-08-03T19:31:26+00:00" + }, + { + "name": "amphp/windows-registry", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/windows-registry.git", + "reference": "0d569e8f256cca974e3842b6e78b4e434bf98306" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/windows-registry/zipball/0d569e8f256cca974e3842b6e78b4e434bf98306", + "reference": "0d569e8f256cca974e3842b6e78b4e434bf98306", + "shasum": "" + }, + "require": { + "amphp/byte-stream": "^2", + "amphp/process": "^2", + "php": ">=8.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\WindowsRegistry\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Windows Registry Reader.", + "support": { + "issues": "https://github.com/amphp/windows-registry/issues", + "source": "https://github.com/amphp/windows-registry/tree/v1.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-01-30T23:01:51+00:00" + }, { "name": "aws/aws-crt-php", - "version": "v1.2.6", + "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "a63485b65b6b3367039306496d49737cf1995408" + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/a63485b65b6b3367039306496d49737cf1995408", - "reference": "a63485b65b6b3367039306496d49737cf1995408", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", "shasum": "" }, "require": { @@ -56,22 +915,22 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.6" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" }, - "time": "2024-06-13T17:21:28+00:00" + "time": "2024-10-18T22:15:13+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.315.5", + "version": "3.324.9", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "3e6d619d45d8e1a8681dd58de61ddfe90e8341e6" + "reference": "e6cb2597e6365c420f42d218a3a4e82a20df700d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3e6d619d45d8e1a8681dd58de61ddfe90e8341e6", - "reference": "3e6d619d45d8e1a8681dd58de61ddfe90e8341e6", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e6cb2597e6365c420f42d218a3a4e82a20df700d", + "reference": "e6cb2597e6365c420f42d218a3a4e82a20df700d", "shasum": "" }, "require": { @@ -124,7 +983,10 @@ ], "psr-4": { "Aws\\": "src/" - } + }, + "exclude-from-classmap": [ + "src/data/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -151,9 +1013,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.315.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.324.9" }, - "time": "2024-07-03T18:12:51+00:00" + "time": "2024-10-23T18:06:30+00:00" }, { "name": "bepsvpt/secure-headers", @@ -428,18 +1290,62 @@ ], "time": "2023-12-20T15:40:13+00:00" }, + { + "name": "daverandom/libdns", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/DaveRandom/LibDNS.git", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "Required for IDN support" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "LibDNS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "DNS protocol implementation written in pure PHP", + "keywords": [ + "dns" + ], + "support": { + "issues": "https://github.com/DaveRandom/LibDNS/issues", + "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" + }, + "time": "2024-04-12T12:12:48+00:00" + }, { "name": "dflydev/dot-access-data", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/dflydev/dflydev-dot-access-data.git", - "reference": "f41715465d65213d644d3141a6a93081be5d3549" + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", - "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", "shasum": "" }, "require": { @@ -499,9 +1405,9 @@ ], "support": { "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", - "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" }, - "time": "2022-10-27T11:44:00+00:00" + "time": "2024-07-08T12:26:09+00:00" }, { "name": "doctrine/cache", @@ -598,16 +1504,16 @@ }, { "name": "doctrine/dbal", - "version": "3.8.6", + "version": "3.9.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "b7411825cf7efb7e51f9791dea19d86e43b399a1" + "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/b7411825cf7efb7e51f9791dea19d86e43b399a1", - "reference": "b7411825cf7efb7e51f9791dea19d86e43b399a1", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", + "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", "shasum": "" }, "require": { @@ -623,12 +1529,12 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.11.5", + "phpstan/phpstan": "1.12.6", "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "9.6.19", + "phpunit/phpunit": "9.6.20", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.10.1", + "squizlabs/php_codesniffer": "3.10.2", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" @@ -691,7 +1597,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.6" + "source": "https://github.com/doctrine/dbal/tree/3.9.3" }, "funding": [ { @@ -707,7 +1613,7 @@ "type": "tidelift" } ], - "time": "2024-06-19T10:38:17+00:00" + "time": "2024-10-10T17:56:43+00:00" }, { "name": "doctrine/deprecations", @@ -1017,16 +1923,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.3", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { @@ -1039,10 +1945,14 @@ "require-dev": { "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", - "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -1066,7 +1976,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, "funding": [ { @@ -1074,7 +1984,7 @@ "type": "github" } ], - "time": "2023-08-10T19:36:49+00:00" + "time": "2024-10-09T13:47:03+00:00" }, { "name": "egulias/email-validator", @@ -1638,24 +2548,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.2", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2" + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -1684,7 +2594,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -1696,26 +2606,26 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:16:48+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.8.1", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "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" @@ -1726,9 +2636,9 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1806,7 +2716,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -1822,20 +2732,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:35:24+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.2", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { @@ -1843,7 +2753,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -1889,7 +2799,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.2" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -1905,20 +2815,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:19:20+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -1933,8 +2843,8 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2005,7 +2915,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.2" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -2021,7 +2931,7 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:05:35+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "guzzlehttp/uri-template", @@ -2109,6 +3019,64 @@ ], "time": "2023-12-03T19:50:20+00:00" }, + { + "name": "kelunik/certificate", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/kelunik/certificate.git", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=7.0" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^6 | 7 | ^8 | ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Kelunik\\Certificate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Access certificate details and transform between different formats.", + "keywords": [ + "DER", + "certificate", + "certificates", + "openssl", + "pem", + "x509" + ], + "support": { + "issues": "https://github.com/kelunik/certificate/issues", + "source": "https://github.com/kelunik/certificate/tree/v1.1.3" + }, + "time": "2023-02-03T21:26:53+00:00" + }, { "name": "laminas/laminas-servicemanager", "version": "3.22.1", @@ -2473,16 +3441,16 @@ }, { "name": "laravel/framework", - "version": "v11.14.0", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "657e8464e13147d56bc3a399115c8c26f38d4821" + "reference": "425054512c362835ba9c0307561973c8eeac7385" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/657e8464e13147d56bc3a399115c8c26f38d4821", - "reference": "657e8464e13147d56bc3a399115c8c26f38d4821", + "url": "https://api.github.com/repos/laravel/framework/zipball/425054512c362835ba9c0307561973c8eeac7385", + "reference": "425054512c362835ba9c0307561973c8eeac7385", "shasum": "" }, "require": { @@ -2501,7 +3469,7 @@ "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1.18", + "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", "laravel/serializable-closure": "^1.3", "league/commonmark": "^2.2.1", "league/flysystem": "^3.8.0", @@ -2544,6 +3512,7 @@ "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", "illuminate/conditionable": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", @@ -2586,9 +3555,9 @@ "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.6", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^9.1.5", + "orchestra/testbench-core": "^9.5", "pda/pheanstalk": "^5.0", - "phpstan/phpstan": "^1.4.7", + "phpstan/phpstan": "^1.11.5", "phpunit/phpunit": "^10.5|^11.0", "predis/predis": "^2.0.2", "resend/resend-php": "^0.10.0", @@ -2644,6 +3613,8 @@ "src/Illuminate/Events/functions.php", "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], "psr-4": { @@ -2675,25 +3646,25 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-07-02T17:23:58+00:00" + "time": "2024-10-22T14:13:31+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.24", + "version": "v0.3.1", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "409b0b4305273472f3754826e68f4edbd0150149" + "reference": "0f3848a445562dac376b27968f753c65e7e1036e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/409b0b4305273472f3754826e68f4edbd0150149", - "reference": "409b0b4305273472f3754826e68f4edbd0150149", + "url": "https://api.github.com/repos/laravel/prompts/zipball/0f3848a445562dac376b27968f753c65e7e1036e", + "reference": "0f3848a445562dac376b27968f753c65e7e1036e", "shasum": "" }, "require": { + "composer-runtime-api": "^2.2", "ext-mbstring": "*", - "illuminate/collections": "^10.0|^11.0", "php": "^8.1", "symfony/console": "^6.2|^7.0" }, @@ -2702,6 +3673,7 @@ "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { + "illuminate/collections": "^10.0|^11.0", "mockery/mockery": "^1.5", "pestphp/pest": "^2.3", "phpstan/phpstan": "^1.11", @@ -2713,7 +3685,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "0.1.x-dev" + "dev-main": "0.3.x-dev" } }, "autoload": { @@ -2731,32 +3703,33 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.24" + "source": "https://github.com/laravel/prompts/tree/v0.3.1" }, - "time": "2024-06-17T13:58:22+00:00" + "time": "2024-10-09T19:42:26+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.3.3", + "version": "v1.3.5", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "3dbf8a8e914634c48d389c1234552666b3d43754" + "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754", - "reference": "3dbf8a8e914634c48d389c1234552666b3d43754", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", + "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", "shasum": "" }, "require": { "php": "^7.3|^8.0" }, "require-dev": { - "nesbot/carbon": "^2.61", + "illuminate/support": "^8.0|^9.0|^10.0|^11.0", + "nesbot/carbon": "^2.61|^3.0", "pestphp/pest": "^1.21.3", "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11" + "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" }, "type": "library", "extra": { @@ -2793,20 +3766,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2023-11-08T14:08:06+00:00" + "time": "2024-09-23T13:33:08+00:00" }, { "name": "laravel/socialite", - "version": "v5.15.1", + "version": "v5.16.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "cc02625f0bd1f95dc3688eb041cce0f1e709d029" + "reference": "40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/cc02625f0bd1f95dc3688eb041cce0f1e709d029", - "reference": "cc02625f0bd1f95dc3688eb041cce0f1e709d029", + "url": "https://api.github.com/repos/laravel/socialite/zipball/40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf", + "reference": "40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf", "shasum": "" }, "require": { @@ -2865,38 +3838,38 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2024-06-28T20:09:34+00:00" + "time": "2024-09-03T09:46:57+00:00" }, { "name": "lcobucci/clock", - "version": "3.2.0", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "6f28b826ea01306b07980cb8320ab30b966cd715" + "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/6f28b826ea01306b07980cb8320ab30b966cd715", - "reference": "6f28b826ea01306b07980cb8320ab30b966cd715", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b", + "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "infection/infection": "^0.27", - "lcobucci/coding-standard": "^11.0.0", + "infection/infection": "^0.29", + "lcobucci/coding-standard": "^11.1.0", "phpstan/extension-installer": "^1.3.1", "phpstan/phpstan": "^1.10.25", "phpstan/phpstan-deprecation-rules": "^1.1.3", "phpstan/phpstan-phpunit": "^1.3.13", "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^10.2.3" + "phpunit/phpunit": "^11.3.6" }, "type": "library", "autoload": { @@ -2917,7 +3890,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.2.0" + "source": "https://github.com/lcobucci/clock/tree/3.3.1" }, "funding": [ { @@ -2929,42 +3902,42 @@ "type": "patreon" } ], - "time": "2023-11-17T17:00:27+00:00" + "time": "2024-09-24T20:45:14+00:00" }, { "name": "lcobucci/jwt", - "version": "5.3.0", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83" + "reference": "aac4fd512681fd5cb4b77d2105ab7ec700c72051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/08071d8d2c7f4b00222cc4b1fb6aa46990a80f83", - "reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/aac4fd512681fd5cb4b77d2105ab7ec700c72051", + "reference": "aac4fd512681fd5cb4b77d2105ab7ec700c72051", "shasum": "" }, "require": { "ext-openssl": "*", "ext-sodium": "*", - "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", "psr/clock": "^1.0" }, "require-dev": { - "infection/infection": "^0.27.0", - "lcobucci/clock": "^3.0", + "infection/infection": "^0.29", + "lcobucci/clock": "^3.2", "lcobucci/coding-standard": "^11.0", - "phpbench/phpbench": "^1.2.9", + "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.2", "phpstan/phpstan": "^1.10.7", "phpstan/phpstan-deprecation-rules": "^1.1.3", "phpstan/phpstan-phpunit": "^1.3.10", "phpstan/phpstan-strict-rules": "^1.5.0", - "phpunit/phpunit": "^10.2.6" + "phpunit/phpunit": "^11.1" }, "suggest": { - "lcobucci/clock": ">= 3.0" + "lcobucci/clock": ">= 3.2" }, "type": "library", "autoload": { @@ -2990,7 +3963,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/5.3.0" + "source": "https://github.com/lcobucci/jwt/tree/5.4.0" }, "funding": [ { @@ -3002,20 +3975,20 @@ "type": "patreon" } ], - "time": "2024-04-11T23:07:54+00:00" + "time": "2024-10-08T22:06:45+00:00" }, { "name": "league/commonmark", - "version": "2.4.2", + "version": "2.5.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "91c24291965bd6d7c46c46a12ba7492f83b1cadf" + "reference": "b650144166dfa7703e62a22e493b853b58d874b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/91c24291965bd6d7c46c46a12ba7492f83b1cadf", - "reference": "91c24291965bd6d7c46c46a12ba7492f83b1cadf", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0", + "reference": "b650144166dfa7703e62a22e493b853b58d874b0", "shasum": "" }, "require": { @@ -3028,8 +4001,8 @@ }, "require-dev": { "cebe/markdown": "^1.0", - "commonmark/cmark": "0.30.3", - "commonmark/commonmark.js": "0.30.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", "composer/package-versions-deprecated": "^1.8", "embed/embed": "^4.4", "erusev/parsedown": "^1.0", @@ -3051,7 +4024,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "2.6-dev" } }, "autoload": { @@ -3108,7 +4081,7 @@ "type": "tidelift" } ], - "time": "2024-02-02T11:59:32+00:00" + "time": "2024-08-16T11:46:16+00:00" }, { "name": "league/config", @@ -3194,16 +4167,16 @@ }, { "name": "league/flysystem", - "version": "3.28.0", + "version": "3.29.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c" + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c", - "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", "shasum": "" }, "require": { @@ -3271,22 +4244,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.28.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" }, - "time": "2024-05-22T10:09:12+00:00" + "time": "2024-10-08T08:58:34+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.28.0", + "version": "3.29.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "22071ef1604bc776f5ff2468ac27a752514665c8" + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/22071ef1604bc776f5ff2468ac27a752514665c8", - "reference": "22071ef1604bc776f5ff2468ac27a752514665c8", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9", "shasum": "" }, "require": { @@ -3326,22 +4299,22 @@ "storage" ], "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.28.0" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0" }, - "time": "2024-05-06T20:05:52+00:00" + "time": "2024-08-17T13:10:48+00:00" }, { "name": "league/flysystem-local", - "version": "3.28.0", + "version": "3.29.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40" + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/13f22ea8be526ea58c2ddff9e158ef7c296e4f40", - "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", "shasum": "" }, "require": { @@ -3375,22 +4348,22 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.28.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" }, - "time": "2024-05-06T20:05:52+00:00" + "time": "2024-08-09T21:24:39+00:00" }, { "name": "league/mime-type-detection", - "version": "1.15.0", + "version": "1.16.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301" + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301", - "reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", "shasum": "" }, "require": { @@ -3421,7 +4394,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.15.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" }, "funding": [ { @@ -3433,7 +4406,7 @@ "type": "tidelift" } ], - "time": "2024-01-28T23:22:08+00:00" + "time": "2024-09-21T08:32:55+00:00" }, { "name": "league/oauth1-client", @@ -3512,56 +4485,131 @@ "time": "2022-04-15T14:02:14+00:00" }, { - "name": "livewire/livewire", - "version": "v3.5.2", + "name": "league/uri", + "version": "7.4.1", "source": { "type": "git", - "url": "https://github.com/livewire/livewire.git", - "reference": "636725c1f87bc7844dd80277488268db27eec1aa" + "url": "https://github.com/thephpleague/uri.git", + "reference": "bedb6e55eff0c933668addaa7efa1e1f2c417cc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/636725c1f87bc7844dd80277488268db27eec1aa", - "reference": "636725c1f87bc7844dd80277488268db27eec1aa", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/bedb6e55eff0c933668addaa7efa1e1f2c417cc4", + "reference": "bedb6e55eff0c933668addaa7efa1e1f2c417cc4", "shasum": "" }, "require": { - "illuminate/database": "^10.0|^11.0", - "illuminate/routing": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "illuminate/validation": "^10.0|^11.0", - "league/mime-type-detection": "^1.9", + "league/uri-interfaces": "^7.3", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.4.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-03-23T07:42:40+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.4.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "8d43ef5c841032c87e2de015972c06f3865ef718" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/8d43ef5c841032c87e2de015972c06f3865ef718", + "reference": "8d43ef5c841032c87e2de015972c06f3865ef718", + "shasum": "" + }, + "require": { + "ext-filter": "*", "php": "^8.1", - "symfony/console": "^6.0|^7.0", - "symfony/http-kernel": "^6.2|^7.0" + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" }, - "require-dev": { - "calebporzio/sushi": "^2.1", - "laravel/framework": "^10.15.0|^11.0", - "laravel/prompts": "^0.1.6", - "mockery/mockery": "^1.3.1", - "orchestra/testbench": "^8.21.0|^9.0", - "orchestra/testbench-dusk": "^8.24|^9.1", - "phpunit/phpunit": "^10.4", - "psy/psysh": "^0.11.22|^0.12" + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", "extra": { - "laravel": { - "providers": [ - "Livewire\\LivewireServiceProvider" - ], - "aliases": { - "Livewire": "Livewire\\Livewire" - } + "branch-alias": { + "dev-master": "7.x-dev" } }, "autoload": { - "files": [ - "src/helpers.php" - ], "psr-4": { - "Livewire\\": "src/" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -3570,35 +4618,149 @@ ], "authors": [ { - "name": "Caleb Porzio", - "email": "calebporzio@gmail.com" + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.4.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-03-23T07:42:40+00:00" + }, + { + "name": "lychee-org/lycheeverify", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/LycheeOrg/verify.git", + "reference": "d09d003452f70b05ddbe2affbef856b5f31ea705" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/LycheeOrg/verify/zipball/d09d003452f70b05ddbe2affbef856b5f31ea705", + "reference": "d09d003452f70b05ddbe2affbef856b5f31ea705", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^11.0", + "php": "^8.2", + "thecodingmachine/safe": "^2.5" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.3", + "larastan/larastan": "^2.9", + "lychee-org/phpstan-lychee": "^v1.0.1", + "nunomaduro/collision": "^8.3", + "orchestra/testbench": "^9.0.0||^8.22.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LycheeVerify\\VerifyServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LycheeVerify\\": "src/", + "LycheeVerify\\Database\\Factories\\": "database/factories/" + } + }, + "autoload-dev": { + "psr-4": { + "LycheeVerify\\Tests\\": "tests/", + "Workbench\\App\\": "workbench/app/" } + }, + "scripts": { + "post-autoload-dump": [ + "@composer run prepare" + ], + "clear": [ + "@php vendor/bin/testbench package:purge-lycheeverify --ansi" + ], + "prepare": [ + "@php vendor/bin/testbench package:discover --ansi" + ], + "build": [ + "@composer run prepare", + "@php vendor/bin/testbench workbench:build --ansi" + ], + "start": [ + "Composer\\Config::disableProcessTimeout", + "@composer run build", + "@php vendor/bin/testbench serve" + ], + "analyse": [ + "vendor/bin/phpstan analyse" + ], + "test": [ + "vendor/bin/phpunit" + ] + }, + "license": [ + "MIT" ], - "description": "A front-end framework for Laravel.", + "description": "Verification package for Lychee", + "homepage": "https://github.com/LycheeOrg/verify", "support": { - "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.5.2" + "source": "https://github.com/LycheeOrg/verify/tree/1.0.2", + "issues": "https://github.com/LycheeOrg/verify/issues" }, "funding": [ { - "url": "https://github.com/livewire", - "type": "github" + "type": "github", + "url": "https://github.com/LycheeOrg" } ], - "time": "2024-07-03T17:22:45+00:00" + "time": "2024-10-15T11:41:02+00:00" }, { "name": "lychee-org/nestedset", - "version": "v9.0.0", + "version": "v9.0.1", "source": { "type": "git", "url": "https://github.com/LycheeOrg/laravel-nestedset.git", - "reference": "1a1f200ac78cc495b1f3cd5c568e1e5dc7bbd179" + "reference": "dcd86fa1dfcc7343a4b0ceddbda32ba55b2b440a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LycheeOrg/laravel-nestedset/zipball/1a1f200ac78cc495b1f3cd5c568e1e5dc7bbd179", - "reference": "1a1f200ac78cc495b1f3cd5c568e1e5dc7bbd179", + "url": "https://api.github.com/repos/LycheeOrg/laravel-nestedset/zipball/dcd86fa1dfcc7343a4b0ceddbda32ba55b2b440a", + "reference": "dcd86fa1dfcc7343a4b0ceddbda32ba55b2b440a", "shasum": "" }, "require": { @@ -3609,8 +4771,8 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.3", + "larastan/larastan": "^2.0", "lychee-org/phpstan-lychee": "^1.0.4", - "nunomaduro/larastan": "^2.0", "orchestra/testbench": "^9.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpunit/phpunit": "^10.5" @@ -3650,9 +4812,9 @@ "nsm" ], "support": { - "source": "https://github.com/LycheeOrg/laravel-nestedset/tree/v9.0.0" + "source": "https://github.com/LycheeOrg/laravel-nestedset/tree/v9.0.1" }, - "time": "2024-06-10T16:33:01+00:00" + "time": "2024-10-23T21:46:18+00:00" }, { "name": "lychee-org/php-exif", @@ -3746,16 +4908,16 @@ }, { "name": "maennchen/zipstream-php", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1" + "reference": "6187e9cc4493da94b9b63eb2315821552015fca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6187e9cc4493da94b9b63eb2315821552015fca9", + "reference": "6187e9cc4493da94b9b63eb2315821552015fca9", "shasum": "" }, "require": { @@ -3811,19 +4973,15 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.1" }, "funding": [ { "url": "https://github.com/maennchen", "type": "github" - }, - { - "url": "https://opencollective.com/zipstream", - "type": "open_collective" } ], - "time": "2023-06-21T14:59:35+00:00" + "time": "2024-10-10T12:33:01+00:00" }, { "name": "monolog/monolog", @@ -3928,16 +5086,16 @@ }, { "name": "mtdowling/jmespath.php", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b" + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/bbb69a935c2cbb0c03d7f481a238027430f6440b", - "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", "shasum": "" }, "require": { @@ -3954,7 +5112,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -3988,22 +5146,22 @@ ], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.7.0" + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" }, - "time": "2023-08-25T10:54:48+00:00" + "time": "2024-09-04T18:46:31+00:00" }, { "name": "nesbot/carbon", - "version": "3.6.0", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "39c8ef752db6865717cc3fba63970c16f057982c" + "reference": "bbd3eef89af8ba66a3aa7952b5439168fbcc529f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/39c8ef752db6865717cc3fba63970c16f057982c", - "reference": "39c8ef752db6865717cc3fba63970c16f057982c", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bbd3eef89af8ba66a3aa7952b5439168fbcc529f", + "reference": "bbd3eef89af8ba66a3aa7952b5439168fbcc529f", "shasum": "" }, "require": { @@ -4096,28 +5254,28 @@ "type": "tidelift" } ], - "time": "2024-06-20T15:52:59+00:00" + "time": "2024-08-19T06:22:39+00:00" }, { "name": "nette/schema", - "version": "v1.3.0", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188" + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", - "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.3" + "php": "8.1 - 8.4" }, "require-dev": { - "nette/tester": "^2.4", + "nette/tester": "^2.5.2", "phpstan/phpstan-nette": "^1.0", "tracy/tracy": "^2.8" }, @@ -4156,26 +5314,26 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.0" + "source": "https://github.com/nette/schema/tree/v1.3.2" }, - "time": "2023-12-11T11:54:22+00:00" + "time": "2024-10-06T23:10:23+00:00" }, { "name": "nette/utils", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "d3ad0aa3b9f934602cb3e3902ebccf10be34d218" + "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/d3ad0aa3b9f934602cb3e3902ebccf10be34d218", - "reference": "d3ad0aa3b9f934602cb3e3902ebccf10be34d218", + "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", + "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", "shasum": "" }, "require": { - "php": ">=8.0 <8.4" + "php": "8.0 - 8.4" }, "conflict": { "nette/finder": "<3", @@ -4242,38 +5400,95 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.4" + "source": "https://github.com/nette/utils/tree/v4.0.5" + }, + "time": "2024-08-07T15:39:19+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "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.3.1" }, - "time": "2024-01-17T16:50:36+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.0.1", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "58c4c58cf23df7f498daeb97092e34f5259feb6a" + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/58c4c58cf23df7f498daeb97092e34f5259feb6a", - "reference": "58c4c58cf23df7f498daeb97092e34f5259feb6a", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/42c84e4e8090766bbd6445d06cd6e57650626ea3", + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.0.4" + "symfony/console": "^7.1.5" }, "require-dev": { - "ergebnis/phpstan-rules": "^2.2.0", - "illuminate/console": "^11.0.0", - "laravel/pint": "^1.14.0", - "mockery/mockery": "^1.6.7", - "pestphp/pest": "^2.34.1", - "phpstan/phpstan": "^1.10.59", - "phpstan/phpstan-strict-rules": "^1.5.2", - "symfony/var-dumper": "^7.0.4", + "illuminate/console": "^11.28.0", + "laravel/pint": "^1.18.1", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -4316,7 +5531,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.0.1" + "source": "https://github.com/nunomaduro/termwind/tree/v2.2.0" }, "funding": [ { @@ -4332,7 +5547,7 @@ "type": "github" } ], - "time": "2024-03-06T16:17:14+00:00" + "time": "2024-10-15T16:15:16+00:00" }, { "name": "opcodesio/log-viewer", @@ -4701,16 +5916,16 @@ }, { "name": "php-http/discovery", - "version": "1.19.4", + "version": "1.20.0", "source": { "type": "git", "url": "https://github.com/php-http/discovery.git", - "reference": "0700efda8d7526335132360167315fdab3aeb599" + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/0700efda8d7526335132360167315fdab3aeb599", - "reference": "0700efda8d7526335132360167315fdab3aeb599", + "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", "shasum": "" }, "require": { @@ -4774,9 +5989,9 @@ ], "support": { "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.19.4" + "source": "https://github.com/php-http/discovery/tree/1.20.0" }, - "time": "2024-03-29T13:00:05+00:00" + "time": "2024-10-02T11:20:13+00:00" }, { "name": "php-http/guzzle7-adapter", @@ -4842,16 +6057,16 @@ }, { "name": "php-http/httplug", - "version": "2.4.0", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/php-http/httplug.git", - "reference": "625ad742c360c8ac580fcc647a1541d29e257f67" + "reference": "5cad731844891a4c282f3f3e1b582c46839d22f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/httplug/zipball/625ad742c360c8ac580fcc647a1541d29e257f67", - "reference": "625ad742c360c8ac580fcc647a1541d29e257f67", + "url": "https://api.github.com/repos/php-http/httplug/zipball/5cad731844891a4c282f3f3e1b582c46839d22f4", + "reference": "5cad731844891a4c282f3f3e1b582c46839d22f4", "shasum": "" }, "require": { @@ -4893,22 +6108,22 @@ ], "support": { "issues": "https://github.com/php-http/httplug/issues", - "source": "https://github.com/php-http/httplug/tree/2.4.0" + "source": "https://github.com/php-http/httplug/tree/2.4.1" }, - "time": "2023-04-14T15:10:03+00:00" + "time": "2024-09-23T11:39:58+00:00" }, { "name": "php-http/message", - "version": "1.16.1", + "version": "1.16.2", "source": { "type": "git", "url": "https://github.com/php-http/message.git", - "reference": "5997f3289332c699fa2545c427826272498a2088" + "reference": "06dd5e8562f84e641bf929bfe699ee0f5ce8080a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/5997f3289332c699fa2545c427826272498a2088", - "reference": "5997f3289332c699fa2545c427826272498a2088", + "url": "https://api.github.com/repos/php-http/message/zipball/06dd5e8562f84e641bf929bfe699ee0f5ce8080a", + "reference": "06dd5e8562f84e641bf929bfe699ee0f5ce8080a", "shasum": "" }, "require": { @@ -4961,36 +6176,286 @@ "psr-7" ], "support": { - "issues": "https://github.com/php-http/message/issues", - "source": "https://github.com/php-http/message/tree/1.16.1" + "issues": "https://github.com/php-http/message/issues", + "source": "https://github.com/php-http/message/tree/1.16.2" + }, + "time": "2024-10-02T11:34:13+00:00" + }, + { + "name": "php-http/promise", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3", + "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/php-http/promise/issues", + "source": "https://github.com/php-http/promise/tree/1.3.1" + }, + "time": "2024-03-15T13:55:21+00:00" + }, + { + "name": "phpdocumentor/reflection", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/Reflection.git", + "reference": "61e2f1fe7683e9647b9ed8d9e53d08699385267d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/61e2f1fe7683e9647b9ed8d9e53d08699385267d", + "reference": "61e2f1fe7683e9647b9ed8d9e53d08699385267d", + "shasum": "" + }, + "require": { + "nikic/php-parser": "~4.18 || ^5.0", + "php": "8.1.*|8.2.*|8.3.*", + "phpdocumentor/reflection-common": "^2.1", + "phpdocumentor/reflection-docblock": "^5", + "phpdocumentor/type-resolver": "^1.2", + "symfony/polyfill-php80": "^1.28", + "webmozart/assert": "^1.7" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "doctrine/coding-standard": "^12.0", + "mikey179/vfsstream": "~1.2", + "mockery/mockery": "~1.6.0", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^10.0", + "psalm/phar": "^5.24", + "rector/rector": "^1.0.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-5.x": "5.3.x-dev", + "dev-6.x": "6.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\": "src/phpDocumentor" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Reflection library to do Static Analysis for PHP Projects", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/Reflection/issues", + "source": "https://github.com/phpDocumentor/Reflection/tree/6.0.0" + }, + "time": "2024-05-23T19:28:12+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" }, - "time": "2024-03-07T13:22:09+00:00" + "time": "2024-05-21T05:55:05+00:00" }, { - "name": "php-http/promise", - "version": "1.3.1", + "name": "phpdocumentor/type-resolver", + "version": "1.8.2", "source": { "type": "git", - "url": "https://github.com/php-http/promise.git", - "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83" + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/promise/zipball/fc85b1fba37c169a69a07ef0d5a8075770cc1f83", - "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" }, "require-dev": { - "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3", - "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4" + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, "autoload": { "psr-4": { - "Http\\Promise\\": "src/" + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4999,37 +6464,29 @@ ], "authors": [ { - "name": "Joel Wurtz", - "email": "joel.wurtz@gmail.com" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Promise used for asynchronous HTTP requests", - "homepage": "http://httplug.io", - "keywords": [ - "promise" - ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { - "issues": "https://github.com/php-http/promise/issues", - "source": "https://github.com/php-http/promise/tree/1.3.1" + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2024-03-15T13:55:21+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.2", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { @@ -5037,13 +6494,13 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -5079,7 +6536,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -5091,20 +6548,20 @@ "type": "tidelift" } ], - "time": "2023-11-12T21:59:55+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { "name": "phpseclib/phpseclib", - "version": "3.0.39", + "version": "3.0.42", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "211ebc399c6e73c225a018435fe5ae209d1d1485" + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/211ebc399c6e73c225a018435fe5ae209d1d1485", - "reference": "211ebc399c6e73c225a018435fe5ae209d1d1485", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98", "shasum": "" }, "require": { @@ -5185,7 +6642,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.39" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.42" }, "funding": [ { @@ -5201,7 +6658,54 @@ "type": "tidelift" } ], - "time": "2024-06-24T06:27:33+00:00" + "time": "2024-09-16T03:06:04+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": "psr/cache", @@ -5560,16 +7064,16 @@ }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -5604,9 +7108,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "psr/simple-cache", @@ -5884,18 +7388,90 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "revolt/event-loop", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/revoltphp/event-loop.git", + "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/25de49af7223ba039f64da4ae9a28ec2d10d0254", + "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Revolt\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.6" + }, + "time": "2023-11-30T05:34:44+00:00" + }, { "name": "revolution/socialite-mastodon", - "version": "1.4.4", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/kawax/socialite-mastodon.git", - "reference": "09490b011ae085b9a7dc9a43652c7145dc5ae10c" + "reference": "2013943f9258b247215dc342504c016c33535e8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kawax/socialite-mastodon/zipball/09490b011ae085b9a7dc9a43652c7145dc5ae10c", - "reference": "09490b011ae085b9a7dc9a43652c7145dc5ae10c", + "url": "https://api.github.com/repos/kawax/socialite-mastodon/zipball/2013943f9258b247215dc342504c016c33535e8e", + "reference": "2013943f9258b247215dc342504c016c33535e8e", "shasum": "" }, "require": { @@ -5904,7 +7480,8 @@ "php": "^8.0" }, "require-dev": { - "orchestra/testbench": "^9.0" + "orchestra/testbench": "^9.0", + "revolution/laravel-mastodon-api": "^3.1" }, "type": "library", "extra": { @@ -5936,10 +7513,9 @@ "socialite" ], "support": { - "issues": "https://github.com/kawax/socialite-mastodon/issues", - "source": "https://github.com/kawax/socialite-mastodon/tree/1.4.4" + "source": "https://github.com/kawax/socialite-mastodon/tree/1.5.2" }, - "time": "2024-04-04T07:57:07+00:00" + "time": "2024-10-02T08:20:07+00:00" }, { "name": "socialiteproviders/amazon", @@ -6304,16 +7880,16 @@ }, { "name": "socialiteproviders/microsoft", - "version": "4.4.0", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Microsoft.git", - "reference": "f907a1744f33e6ede6315bb50c0302e178422784" + "reference": "9f55e544f183c36096a14b2e61b5d6c9dc23961e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Microsoft/zipball/f907a1744f33e6ede6315bb50c0302e178422784", - "reference": "f907a1744f33e6ede6315bb50c0302e178422784", + "url": "https://api.github.com/repos/SocialiteProviders/Microsoft/zipball/9f55e544f183c36096a14b2e61b5d6c9dc23961e", + "reference": "9f55e544f183c36096a14b2e61b5d6c9dc23961e", "shasum": "" }, "require": { @@ -6350,7 +7926,7 @@ "issues": "https://github.com/socialiteproviders/providers/issues", "source": "https://github.com/socialiteproviders/providers" }, - "time": "2024-07-02T06:43:41+00:00" + "time": "2024-07-12T02:43:55+00:00" }, { "name": "socialiteproviders/nextcloud", @@ -6393,6 +7969,82 @@ }, "time": "2021-02-27T23:17:54+00:00" }, + { + "name": "spatie/enum", + "version": "3.13.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/enum.git", + "reference": "f1a0f464ba909491a53e60a955ce84ad7cd93a2c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/enum/zipball/f1a0f464ba909491a53e60a955ce84ad7cd93a2c", + "reference": "f1a0f464ba909491a53e60a955ce84ad7cd93a2c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.0" + }, + "require-dev": { + "fakerphp/faker": "^1.9.1", + "larapack/dd": "^1.1", + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "^4.3" + }, + "suggest": { + "fakerphp/faker": "To use the enum faker provider", + "phpunit/phpunit": "To use the enum assertions" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Enum\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brent Roose", + "email": "brent@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Tom Witkowski", + "email": "dev@gummibeer.de", + "homepage": "https://gummibeer.de", + "role": "Developer" + } + ], + "description": "PHP Enums", + "homepage": "https://github.com/spatie/enum", + "keywords": [ + "enum", + "enumerable", + "spatie" + ], + "support": { + "docs": "https://docs.spatie.be/enum", + "issues": "https://github.com/spatie/enum/issues", + "source": "https://github.com/spatie/enum" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2022-04-22T08:51:55+00:00" + }, { "name": "spatie/guzzle-rate-limiter-middleware", "version": "2.0.1", @@ -6488,17 +8140,101 @@ "role": "Developer" } ], - "description": "Easily optimize images using PHP", - "homepage": "https://github.com/spatie/image-optimizer", + "description": "Easily optimize images using PHP", + "homepage": "https://github.com/spatie/image-optimizer", + "keywords": [ + "image-optimizer", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/image-optimizer/issues", + "source": "https://github.com/spatie/image-optimizer/tree/1.7.5" + }, + "time": "2024-05-16T08:48:33+00:00" + }, + { + "name": "spatie/laravel-data", + "version": "4.11.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-data.git", + "reference": "df5b58baebae34475ca35338b4e9a131c9e2a8e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/df5b58baebae34475ca35338b4e9a131c9e2a8e0", + "reference": "df5b58baebae34475ca35338b4e9a131c9e2a8e0", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^10.0|^11.0", + "php": "^8.1", + "phpdocumentor/reflection": "^6.0", + "spatie/laravel-package-tools": "^1.9.0", + "spatie/php-structure-discoverer": "^2.0" + }, + "require-dev": { + "fakerphp/faker": "^1.14", + "friendsofphp/php-cs-fixer": "^3.0", + "inertiajs/inertia-laravel": "^1.2", + "livewire/livewire": "^3.0", + "mockery/mockery": "^1.6", + "nesbot/carbon": "^2.63", + "nunomaduro/larastan": "^2.0", + "orchestra/testbench": "^8.0|^9.0", + "pestphp/pest": "^2.31", + "pestphp/pest-plugin-laravel": "^2.0", + "pestphp/pest-plugin-livewire": "^2.1", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpunit/phpunit": "^10.0", + "spatie/invade": "^1.0", + "spatie/laravel-typescript-transformer": "^2.5", + "spatie/pest-plugin-snapshots": "^2.1", + "spatie/test-time": "^1.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelData\\LaravelDataServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "role": "Developer" + } + ], + "description": "Create unified resources and data transfer objects", + "homepage": "https://github.com/spatie/laravel-data", "keywords": [ - "image-optimizer", + "laravel", + "laravel-data", "spatie" ], "support": { - "issues": "https://github.com/spatie/image-optimizer/issues", - "source": "https://github.com/spatie/image-optimizer/tree/1.7.5" + "issues": "https://github.com/spatie/laravel-data/issues", + "source": "https://github.com/spatie/laravel-data/tree/4.11.1" }, - "time": "2024-05-16T08:48:33+00:00" + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-10-23T07:14:53+00:00" }, { "name": "spatie/laravel-feed", @@ -6662,16 +8398,16 @@ }, { "name": "spatie/laravel-package-tools", - "version": "1.16.4", + "version": "1.16.5", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53" + "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", - "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/c7413972cf22ffdff97b68499c22baa04eddb6a2", + "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2", "shasum": "" }, "require": { @@ -6710,15 +8446,176 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.4" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.5" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-08-27T18:56:10+00:00" + }, + { + "name": "spatie/laravel-typescript-transformer", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-typescript-transformer.git", + "reference": "cdf82498b7e02f89f5a3c0eeed78ac0d633a212b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-typescript-transformer/zipball/cdf82498b7e02f89f5a3c0eeed78ac0d633a212b", + "reference": "cdf82498b7e02f89f5a3c0eeed78ac0d633a212b", + "shasum": "" + }, + "require": { + "illuminate/console": "^8.83|^9.30|^10.0|^11.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.12", + "spatie/typescript-transformer": "^2.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.0", + "mockery/mockery": "^1.4", + "nesbot/carbon": "^2.63", + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0", + "pestphp/pest": "^1.22|^2.0", + "phpunit/phpunit": "^9.0|^10.0|^11.0", + "spatie/data-transfer-object": "^2.0", + "spatie/enum": "^3.0", + "spatie/laravel-model-states": "^1.6|^2.0", + "spatie/pest-plugin-snapshots": "^1.1|^2.0", + "spatie/phpunit-snapshot-assertions": "^4.2|^5.0", + "spatie/temporary-directory": "^1.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelTypeScriptTransformer\\TypeScriptTransformerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelTypeScriptTransformer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Transform your PHP structures to TypeScript types", + "homepage": "https://github.com/spatie/typescript-transformer", + "keywords": [ + "spatie", + "typescript-transformer" + ], + "support": { + "issues": "https://github.com/spatie/laravel-typescript-transformer/issues", + "source": "https://github.com/spatie/laravel-typescript-transformer/tree/2.5.0" }, "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, { "url": "https://github.com/spatie", "type": "github" } ], - "time": "2024-03-20T07:29:11+00:00" + "time": "2024-10-04T13:26:07+00:00" + }, + { + "name": "spatie/php-structure-discoverer", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/php-structure-discoverer.git", + "reference": "271542206169d95dd2ffe346ddf11f37672553a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/php-structure-discoverer/zipball/271542206169d95dd2ffe346ddf11f37672553a2", + "reference": "271542206169d95dd2ffe346ddf11f37672553a2", + "shasum": "" + }, + "require": { + "amphp/amp": "^v3.0", + "amphp/parallel": "^2.2", + "illuminate/collections": "^10.0|^11.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.4.3", + "symfony/finder": "^6.0|^7.0" + }, + "require-dev": { + "illuminate/console": "^10.0|^11.0", + "laravel/pint": "^1.0", + "nunomaduro/collision": "^7.0|^8.0", + "nunomaduro/larastan": "^2.0.1", + "orchestra/testbench": "^7.0|^8.0|^9.0", + "pestphp/pest": "^2.0", + "pestphp/pest-plugin-laravel": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5|^10.0", + "spatie/laravel-ray": "^1.26" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\StructureDiscoverer\\StructureDiscovererServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\StructureDiscoverer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "role": "Developer" + } + ], + "description": "Automatically discover structures within your PHP application", + "homepage": "https://github.com/spatie/php-structure-discoverer", + "keywords": [ + "discover", + "laravel", + "php", + "php-structure-discoverer" + ], + "support": { + "issues": "https://github.com/spatie/php-structure-discoverer/issues", + "source": "https://github.com/spatie/php-structure-discoverer/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/LaravelAutoDiscoverer", + "type": "github" + } + ], + "time": "2024-08-29T10:43:45+00:00" }, { "name": "spatie/temporary-directory", @@ -6781,18 +8678,90 @@ ], "time": "2023-12-25T11:46:58+00:00" }, + { + "name": "spatie/typescript-transformer", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/typescript-transformer.git", + "reference": "130c2447e0aa83f8d8d0ff590bc5bc402b17d641" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/typescript-transformer/zipball/130c2447e0aa83f8d8d0ff590bc5bc402b17d641", + "reference": "130c2447e0aa83f8d8d0ff590bc5bc402b17d641", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18|^5.0", + "php": "^8.0", + "phpdocumentor/type-resolver": "^1.6.2", + "symfony/process": "^5.2|^6.0|^7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.40", + "larapack/dd": "^1.1", + "myclabs/php-enum": "^1.7", + "pestphp/pest": "^1.22", + "phpstan/extension-installer": "^1.1", + "phpunit/phpunit": "^9.0", + "spatie/data-transfer-object": "^2.0", + "spatie/enum": "^3.0", + "spatie/pest-plugin-snapshots": "^1.1", + "spatie/temporary-directory": "^1.2|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\TypeScriptTransformer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Transform your PHP structures to TypeScript types", + "homepage": "https://github.com/spatie/typescript-transformer", + "keywords": [ + "spatie", + "typescript-transformer" + ], + "support": { + "issues": "https://github.com/spatie/typescript-transformer/issues", + "source": "https://github.com/spatie/typescript-transformer/tree/2.4.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-10-04T13:13:08+00:00" + }, { "name": "symfony/cache", - "version": "v6.4.8", + "version": "v6.4.12", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "287142df5579ce223c485b3872df3efae8390984" + "reference": "a463451b7f6ac4a47b98dbfc78ec2d3560c759d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/287142df5579ce223c485b3872df3efae8390984", - "reference": "287142df5579ce223c485b3872df3efae8390984", + "url": "https://api.github.com/repos/symfony/cache/zipball/a463451b7f6ac4a47b98dbfc78ec2d3560c759d8", + "reference": "a463451b7f6ac4a47b98dbfc78ec2d3560c759d8", "shasum": "" }, "require": { @@ -6859,7 +8828,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.8" + "source": "https://github.com/symfony/cache/tree/v6.4.12" }, "funding": [ { @@ -6875,7 +8844,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-09-16T16:01:33+00:00" }, { "name": "symfony/cache-contracts", @@ -7029,16 +8998,16 @@ }, { "name": "symfony/console", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0aa29ca177f432ab68533432db0de059f39c92ae" + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0aa29ca177f432ab68533432db0de059f39c92ae", - "reference": "0aa29ca177f432ab68533432db0de059f39c92ae", + "url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee", "shasum": "" }, "require": { @@ -7102,7 +9071,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.2" + "source": "https://github.com/symfony/console/tree/v7.1.5" }, "funding": [ { @@ -7118,7 +9087,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/css-selector", @@ -7254,16 +9223,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.1.2", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "2412d3dddb5c9ea51a39cfbff1c565fc9844ca32" + "reference": "432bb369952795c61ca1def65e078c4a80dad13c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/2412d3dddb5c9ea51a39cfbff1c565fc9844ca32", - "reference": "2412d3dddb5c9ea51a39cfbff1c565fc9844ca32", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/432bb369952795c61ca1def65e078c4a80dad13c", + "reference": "432bb369952795c61ca1def65e078c4a80dad13c", "shasum": "" }, "require": { @@ -7309,7 +9278,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.1.2" + "source": "https://github.com/symfony/error-handler/tree/v7.1.3" }, "funding": [ { @@ -7325,7 +9294,7 @@ "type": "tidelift" } ], - "time": "2024-06-25T19:55:06+00:00" + "time": "2024-07-26T13:02:51+00:00" }, { "name": "symfony/event-dispatcher", @@ -7485,16 +9454,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.1", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6" + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fbb0ba67688b780efbc886c1a0a0948dcf7205d6", - "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", "shasum": "" }, "require": { @@ -7529,7 +9498,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.1" + "source": "https://github.com/symfony/finder/tree/v7.1.4" }, "funding": [ { @@ -7545,20 +9514,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.1.1", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "74d171d5b6a1d9e4bfee09a41937c17a7536acfa" + "reference": "e30ef73b1e44eea7eb37ba69600a354e553f694b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/74d171d5b6a1d9e4bfee09a41937c17a7536acfa", - "reference": "74d171d5b6a1d9e4bfee09a41937c17a7536acfa", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e30ef73b1e44eea7eb37ba69600a354e553f694b", + "reference": "e30ef73b1e44eea7eb37ba69600a354e553f694b", "shasum": "" }, "require": { @@ -7606,7 +9575,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.1.1" + "source": "https://github.com/symfony/http-foundation/tree/v7.1.5" }, "funding": [ { @@ -7622,20 +9591,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ae3fa717db4d41a55d14c2bd92399e37cf5bc0f6" + "reference": "44204d96150a9df1fc57601ec933d23fefc2d65b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ae3fa717db4d41a55d14c2bd92399e37cf5bc0f6", - "reference": "ae3fa717db4d41a55d14c2bd92399e37cf5bc0f6", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/44204d96150a9df1fc57601ec933d23fefc2d65b", + "reference": "44204d96150a9df1fc57601ec933d23fefc2d65b", "shasum": "" }, "require": { @@ -7720,7 +9689,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.2" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.5" }, "funding": [ { @@ -7736,20 +9705,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T13:13:31+00:00" + "time": "2024-09-21T06:09:21+00:00" }, { "name": "symfony/mailer", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "8fcff0af9043c8f8a8e229437cea363e282f9aee" + "reference": "bbf21460c56f29810da3df3e206e38dfbb01e80b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/8fcff0af9043c8f8a8e229437cea363e282f9aee", - "reference": "8fcff0af9043c8f8a8e229437cea363e282f9aee", + "url": "https://api.github.com/repos/symfony/mailer/zipball/bbf21460c56f29810da3df3e206e38dfbb01e80b", + "reference": "bbf21460c56f29810da3df3e206e38dfbb01e80b", "shasum": "" }, "require": { @@ -7800,7 +9769,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.1.2" + "source": "https://github.com/symfony/mailer/tree/v7.1.5" }, "funding": [ { @@ -7816,20 +9785,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T08:00:31+00:00" + "time": "2024-09-08T12:32:26+00:00" }, { "name": "symfony/mime", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "26a00b85477e69a4bab63b66c5dce64f18b0cbfc" + "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/26a00b85477e69a4bab63b66c5dce64f18b0cbfc", - "reference": "26a00b85477e69a4bab63b66c5dce64f18b0cbfc", + "url": "https://api.github.com/repos/symfony/mime/zipball/711d2e167e8ce65b05aea6b258c449671cdd38ff", + "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff", "shasum": "" }, "require": { @@ -7884,7 +9853,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.2" + "source": "https://github.com/symfony/mime/tree/v7.1.5" }, "funding": [ { @@ -7900,24 +9869,24 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -7963,7 +9932,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -7979,24 +9948,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -8023,109 +9992,25 @@ "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.30.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-05-31T15:07:36+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a6e83bdeb3c84391d1dfe16f42e40727ce524a5c", - "reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "idn", + "grapheme", "intl", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -8141,24 +10026,25 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "name": "symfony/polyfill-intl-idn", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" @@ -8175,11 +10061,8 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8187,26 +10070,30 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "idn", "intl", - "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -8222,30 +10109,27 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" + "php": ">=7.2" }, "suggest": { - "ext-mbstring": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { @@ -8259,8 +10143,11 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8276,17 +10163,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", + "intl", + "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -8302,24 +10190,30 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php72", - "version": "v1.30.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "10112722600777e02d2745716b70c5db4ca70442" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/10112722600777e02d2745716b70c5db4ca70442", - "reference": "10112722600777e02d2745716b70c5db4ca70442", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", "extra": { @@ -8333,7 +10227,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" + "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -8350,16 +10244,17 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -8375,24 +10270,24 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -8439,7 +10334,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -8455,24 +10350,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -8515,7 +10410,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -8531,24 +10426,24 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:35:24+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "2ba1f33797470debcda07fe9dce20a0003df18e9" + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/2ba1f33797470debcda07fe9dce20a0003df18e9", - "reference": "2ba1f33797470debcda07fe9dce20a0003df18e9", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -8594,7 +10489,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" }, "funding": [ { @@ -8610,20 +10505,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v7.1.1", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "febf90124323a093c7ee06fdb30e765ca3c20028" + "reference": "5c03ee6369281177f07f7c68252a280beccba847" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/febf90124323a093c7ee06fdb30e765ca3c20028", - "reference": "febf90124323a093c7ee06fdb30e765ca3c20028", + "url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847", + "reference": "5c03ee6369281177f07f7c68252a280beccba847", "shasum": "" }, "require": { @@ -8655,7 +10550,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.1" + "source": "https://github.com/symfony/process/tree/v7.1.5" }, "funding": [ { @@ -8671,20 +10566,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-19T21:48:23+00:00" }, { "name": "symfony/routing", - "version": "v7.1.1", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "60c31bab5c45af7f13091b87deb708830f3c96c0" + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/60c31bab5c45af7f13091b87deb708830f3c96c0", - "reference": "60c31bab5c45af7f13091b87deb708830f3c96c0", + "url": "https://api.github.com/repos/symfony/routing/zipball/1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", "shasum": "" }, "require": { @@ -8736,7 +10631,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.1" + "source": "https://github.com/symfony/routing/tree/v7.1.4" }, "funding": [ { @@ -8752,7 +10647,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-08-29T08:16:25+00:00" }, { "name": "symfony/service-contracts", @@ -8839,16 +10734,16 @@ }, { "name": "symfony/string", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8" + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/14221089ac66cf82e3cf3d1c1da65de305587ff8", - "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8", + "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", "shasum": "" }, "require": { @@ -8906,7 +10801,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.2" + "source": "https://github.com/symfony/string/tree/v7.1.5" }, "funding": [ { @@ -8922,20 +10817,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:27:18+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/translation", - "version": "v7.1.1", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "cf5ae136e124fc7681b34ce9fac9d5b9ae8ceee3" + "reference": "235535e3f84f3dfbdbde0208ede6ca75c3a489ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/cf5ae136e124fc7681b34ce9fac9d5b9ae8ceee3", - "reference": "cf5ae136e124fc7681b34ce9fac9d5b9ae8ceee3", + "url": "https://api.github.com/repos/symfony/translation/zipball/235535e3f84f3dfbdbde0208ede6ca75c3a489ea", + "reference": "235535e3f84f3dfbdbde0208ede6ca75c3a489ea", "shasum": "" }, "require": { @@ -9000,7 +10895,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.1.1" + "source": "https://github.com/symfony/translation/tree/v7.1.5" }, "funding": [ { @@ -9016,7 +10911,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-16T06:30:38+00:00" }, { "name": "symfony/translation-contracts", @@ -9098,16 +10993,16 @@ }, { "name": "symfony/uid", - "version": "v7.1.1", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "bb59febeecc81528ff672fad5dab7f06db8c8277" + "reference": "8c7bb8acb933964055215d89f9a9871df0239317" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/bb59febeecc81528ff672fad5dab7f06db8c8277", - "reference": "bb59febeecc81528ff672fad5dab7f06db8c8277", + "url": "https://api.github.com/repos/symfony/uid/zipball/8c7bb8acb933964055215d89f9a9871df0239317", + "reference": "8c7bb8acb933964055215d89f9a9871df0239317", "shasum": "" }, "require": { @@ -9152,7 +11047,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.1" + "source": "https://github.com/symfony/uid/tree/v7.1.5" }, "funding": [ { @@ -9168,20 +11063,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-17T09:16:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "5857c57c6b4b86524c08cf4f4bc95327270a816d" + "reference": "e20e03889539fd4e4211e14d2179226c513c010d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/5857c57c6b4b86524c08cf4f4bc95327270a816d", - "reference": "5857c57c6b4b86524c08cf4f4bc95327270a816d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e20e03889539fd4e4211e14d2179226c513c010d", + "reference": "e20e03889539fd4e4211e14d2179226c513c010d", "shasum": "" }, "require": { @@ -9235,7 +11130,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.2" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.5" }, "funding": [ { @@ -9251,7 +11146,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T08:00:31+00:00" + "time": "2024-09-16T10:07:02+00:00" }, { "name": "symfony/var-exporter", @@ -9523,23 +11418,23 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.2", + "graham-campbell/result-type": "^1.1.3", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2", + "phpoption/phpoption": "^1.9.3", "symfony/polyfill-ctype": "^1.24", "symfony/polyfill-mbstring": "^1.24", "symfony/polyfill-php80": "^1.24" @@ -9556,7 +11451,7 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "5.6-dev" @@ -9591,7 +11486,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" }, "funding": [ { @@ -9603,7 +11498,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:43:29+00:00" + "time": "2024-07-20T21:52:34+00:00" }, { "name": "voku/portable-ascii", @@ -9803,23 +11698,23 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.13.5", + "version": "v3.14.6", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "92d86be45ee54edff735e46856f64f14b6a8bb07" + "reference": "14e4517bd49130d6119228107eb21ae47ae120ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/92d86be45ee54edff735e46856f64f14b6a8bb07", - "reference": "92d86be45ee54edff735e46856f64f14b6a8bb07", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/14e4517bd49130d6119228107eb21ae47ae120ab", + "reference": "14e4517bd49130d6119228107eb21ae47ae120ab", "shasum": "" }, "require": { "illuminate/routing": "^9|^10|^11", "illuminate/session": "^9|^10|^11", "illuminate/support": "^9|^10|^11", - "maximebf/debugbar": "~1.22.0", + "maximebf/debugbar": "~1.23.0", "php": "^8.0", "symfony/finder": "^6|^7" }, @@ -9832,7 +11727,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.13-dev" + "dev-master": "3.14-dev" }, "laravel": { "providers": [ @@ -9871,7 +11766,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.13.5" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.6" }, "funding": [ { @@ -9883,41 +11778,41 @@ "type": "github" } ], - "time": "2024-04-12T11:20:37+00:00" + "time": "2024-10-18T13:15:12+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v3.0.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "bc1d67f01ce8c77e3f97d48ba51fa1d81874f622" + "reference": "7956ccb4943f8532d008c17a1094b34bb6394d56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/bc1d67f01ce8c77e3f97d48ba51fa1d81874f622", - "reference": "bc1d67f01ce8c77e3f97d48ba51fa1d81874f622", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/7956ccb4943f8532d008c17a1094b34bb6394d56", + "reference": "7956ccb4943f8532d008c17a1094b34bb6394d56", "shasum": "" }, "require": { - "barryvdh/reflection-docblock": "^2.1.1", + "barryvdh/reflection-docblock": "^2.1.2", "composer/class-map-generator": "^1.0", "ext-json": "*", - "illuminate/console": "^10 || ^11", - "illuminate/database": "^10.38 || ^11", - "illuminate/filesystem": "^10 || ^11", - "illuminate/support": "^10 || ^11", + "illuminate/console": "^11.15", + "illuminate/database": "^11.15", + "illuminate/filesystem": "^11.15", + "illuminate/support": "^11.15", "nikic/php-parser": "^4.18 || ^5", - "php": "^8.1", + "php": "^8.2", "phpdocumentor/type-resolver": "^1.1.0" }, "require-dev": { "ext-pdo_sqlite": "*", "friendsofphp/php-cs-fixer": "^3", - "illuminate/config": "^9 || ^10 || ^11", - "illuminate/view": "^9 || ^10 || ^11", + "illuminate/config": "^11.15", + "illuminate/view": "^11.15", "mockery/mockery": "^1.4", - "orchestra/testbench": "^8 || ^9", + "orchestra/testbench": "^9.2", "phpunit/phpunit": "^10.5", "spatie/phpunit-snapshot-assertions": "^4 || ^5", "vimeo/psalm": "^5.4" @@ -9928,7 +11823,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" }, "laravel": { "providers": [ @@ -9965,7 +11860,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.0.0" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.2.0" }, "funding": [ { @@ -9977,20 +11872,20 @@ "type": "github" } ], - "time": "2024-03-01T12:53:18+00:00" + "time": "2024-10-17T16:43:13+00:00" }, { "name": "barryvdh/reflection-docblock", - "version": "v2.1.1", + "version": "v2.1.3", "source": { "type": "git", "url": "https://github.com/barryvdh/ReflectionDocBlock.git", - "reference": "e6811e927f0ecc37cc4deaa6627033150343e597" + "reference": "c6fad15f7c878be21650c51e1f841bca7e49752e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/e6811e927f0ecc37cc4deaa6627033150343e597", - "reference": "e6811e927f0ecc37cc4deaa6627033150343e597", + "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/c6fad15f7c878be21650c51e1f841bca7e49752e", + "reference": "c6fad15f7c878be21650c51e1f841bca7e49752e", "shasum": "" }, "require": { @@ -10027,9 +11922,102 @@ } ], "support": { - "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.1.1" + "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.1.3" + }, + "time": "2024-10-23T11:41:03+00:00" + }, + { + "name": "brianium/paratest", + "version": "v7.4.8", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "cf16fcbb9b8107a7df6b97e497fc91e819774d8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/cf16fcbb9b8107a7df6b97e497fc91e819774d8b", + "reference": "cf16fcbb9b8107a7df6b97e497fc91e819774d8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^1.2.0", + "jean85/pretty-package-versions": "^2.0.6", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-timer": "^6.0.0", + "phpunit/phpunit": "^10.5.36", + "sebastian/environment": "^6.1.0", + "symfony/console": "^6.4.7 || ^7.1.5", + "symfony/process": "^6.4.7 || ^7.1.5" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0.0", + "ext-pcov": "*", + "ext-posix": "*", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "squizlabs/php_codesniffer": "^3.10.3", + "symfony/filesystem": "^6.4.3 || ^7.1.5" + }, + "bin": [ + "bin/paratest", + "bin/paratest_for_phpstorm" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v7.4.8" }, - "time": "2023-06-14T05:06:27+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2024-10-15T12:45:19+00:00" }, { "name": "clue/ndjson-react", @@ -10097,16 +12085,16 @@ }, { "name": "composer/class-map-generator", - "version": "1.3.4", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "b1b3fd0b4eaf3ddf3ee230bc340bf3fff454a1a3" + "reference": "98bbf6780e56e0fd2404fe4b82eb665a0f93b783" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/b1b3fd0b4eaf3ddf3ee230bc340bf3fff454a1a3", - "reference": "b1b3fd0b4eaf3ddf3ee230bc340bf3fff454a1a3", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/98bbf6780e56e0fd2404fe4b82eb665a0f93b783", + "reference": "98bbf6780e56e0fd2404fe4b82eb665a0f93b783", "shasum": "" }, "require": { @@ -10119,8 +12107,8 @@ "phpstan/phpstan-deprecation-rules": "^1", "phpstan/phpstan-phpunit": "^1", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/filesystem": "^5.4 || ^6", - "symfony/phpunit-bridge": "^5" + "phpunit/phpunit": "^8", + "symfony/filesystem": "^5.4 || ^6" }, "type": "library", "extra": { @@ -10150,7 +12138,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.3.4" + "source": "https://github.com/composer/class-map-generator/tree/1.4.0" }, "funding": [ { @@ -10166,34 +12154,42 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:13:04+00:00" + "time": "2024-10-03T18:14:00+00:00" }, { "name": "composer/pcre", - "version": "3.1.4", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "04229f163664973f68f38f6f73d917799168ef24" + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", - "reference": "04229f163664973f68f38f6f73d917799168ef24", + "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, "require-dev": { - "phpstan/phpstan": "^1.3", + "phpstan/phpstan": "^1.11.10", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -10221,7 +12217,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.4" + "source": "https://github.com/composer/pcre/tree/3.3.1" }, "funding": [ { @@ -10237,28 +12233,28 @@ "type": "tidelift" } ], - "time": "2024-05-27T13:40:54+00:00" + "time": "2024-08-27T18:44:43+00:00" }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "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.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", "extra": { @@ -10302,7 +12298,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "source": "https://github.com/composer/semver/tree/3.4.3" }, "funding": [ { @@ -10318,7 +12314,7 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-09-19T14:15:21+00:00" }, { "name": "composer/xdebug-handler", @@ -10386,80 +12382,6 @@ ], "time": "2024-05-06T16:37:16+00:00" }, - { - "name": "dedoc/scramble", - "version": "v0.10.13", - "source": { - "type": "git", - "url": "https://github.com/dedoc/scramble.git", - "reference": "d8c3ed9c69fe6c0900f22ec0c7520b9b579d9ec3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dedoc/scramble/zipball/d8c3ed9c69fe6c0900f22ec0c7520b9b579d9ec3", - "reference": "d8c3ed9c69fe6c0900f22ec0c7520b9b579d9ec3", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^10.0|^11.0", - "nikic/php-parser": "^5.0", - "php": "^8.1", - "phpstan/phpdoc-parser": "^1.0", - "spatie/laravel-package-tools": "^1.9.2" - }, - "require-dev": { - "laravel/pint": "^v1.1.0", - "nunomaduro/collision": "^7.0|^8.0", - "orchestra/testbench": "^8.0|^9.0", - "pestphp/pest": "^2.34", - "pestphp/pest-plugin-laravel": "^2.3", - "phpunit/phpunit": "^10.5", - "spatie/pest-plugin-snapshots": "^2.1" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Dedoc\\Scramble\\ScrambleServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Dedoc\\Scramble\\": "src", - "Dedoc\\Scramble\\Database\\Factories\\": "database/factories" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Lytvynenko", - "email": "litvinenko95@gmail.com", - "role": "Developer" - } - ], - "description": "Automatic generation of API documentation for Laravel applications.", - "homepage": "https://github.com/dedoc/scramble", - "keywords": [ - "documentation", - "laravel", - "openapi" - ], - "support": { - "issues": "https://github.com/dedoc/scramble/issues", - "source": "https://github.com/dedoc/scramble/tree/v0.10.13" - }, - "funding": [ - { - "url": "https://github.com/romalytvynenko", - "type": "github" - } - ], - "time": "2024-06-05T17:01:46+00:00" - }, { "name": "fakerphp/faker", "version": "v1.23.1", @@ -10525,16 +12447,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" + "reference": "8520451a140d3f46ac33042715115e290cf5785f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", - "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", "shasum": "" }, "require": { @@ -10574,7 +12496,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" }, "funding": [ { @@ -10582,30 +12504,30 @@ "type": "github" } ], - "time": "2024-02-07T09:43:46+00:00" + "time": "2024-08-06T10:04:20+00:00" }, { "name": "filp/whoops", - "version": "2.15.4", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", - "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", + "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", + "php": "^7.1 || ^8.0", "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { - "mockery/mockery": "^0.9 || ^1.0", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", - "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", @@ -10645,7 +12567,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.15.4" + "source": "https://github.com/filp/whoops/tree/2.16.0" }, "funding": [ { @@ -10653,20 +12575,20 @@ "type": "github" } ], - "time": "2023-11-03T12:00:00+00:00" + "time": "2024-09-25T12:00:00+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.59.3", + "version": "v3.64.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29" + "reference": "58dd9c931c785a79739310aef5178928305ffa67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/30ba9ecc2b0e5205e578fe29973c15653d9bfd29", - "reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/58dd9c931c785a79739310aef5178928305ffa67", + "reference": "58dd9c931c785a79739310aef5178928305ffa67", "shasum": "" }, "require": { @@ -10748,7 +12670,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.59.3" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.64.0" }, "funding": [ { @@ -10756,7 +12678,7 @@ "type": "github" } ], - "time": "2024-06-16T14:17:03+00:00" + "time": "2024-08-30T23:09:38+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -10836,18 +12758,88 @@ }, "type": "library", "extra": { - "laravel": { - "providers": [ - "Clockwork\\Support\\Laravel\\ClockworkServiceProvider" - ], - "aliases": { - "Clockwork": "Clockwork\\Support\\Laravel\\Facade" - } + "laravel": { + "providers": [ + "Clockwork\\Support\\Laravel\\ClockworkServiceProvider" + ], + "aliases": { + "Clockwork": "Clockwork\\Support\\Laravel\\Facade" + } + } + }, + "autoload": { + "psr-4": { + "Clockwork\\": "Clockwork/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "itsgoingd", + "email": "itsgoingd@luzer.sk", + "homepage": "https://twitter.com/itsgoingd" + } + ], + "description": "php dev tools in your browser", + "homepage": "https://underground.works/clockwork", + "keywords": [ + "Devtools", + "debugging", + "laravel", + "logging", + "lumen", + "profiling", + "slim" + ], + "support": { + "issues": "https://github.com/itsgoingd/clockwork/issues", + "source": "https://github.com/itsgoingd/clockwork/tree/v5.2.2" + }, + "funding": [ + { + "url": "https://github.com/itsgoingd", + "type": "github" + } + ], + "time": "2024-04-14T10:49:22+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^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.4", + "vimeo/psalm": "^4.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "Clockwork\\": "Clockwork/" + "Jean85\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -10856,66 +12848,56 @@ ], "authors": [ { - "name": "itsgoingd", - "email": "itsgoingd@luzer.sk", - "homepage": "https://twitter.com/itsgoingd" + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" } ], - "description": "php dev tools in your browser", - "homepage": "https://underground.works/clockwork", + "description": "A library to get pretty versions strings of installed dependencies", "keywords": [ - "Devtools", - "debugging", - "laravel", - "logging", - "lumen", - "profiling", - "slim" + "composer", + "package", + "release", + "versions" ], "support": { - "issues": "https://github.com/itsgoingd/clockwork/issues", - "source": "https://github.com/itsgoingd/clockwork/tree/v5.2.2" + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" }, - "funding": [ - { - "url": "https://github.com/itsgoingd", - "type": "github" - } - ], - "time": "2024-04-14T10:49:22+00:00" + "time": "2024-03-08T09:58:59+00:00" }, { "name": "larastan/larastan", - "version": "v2.9.7", + "version": "v2.9.9", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "5c805f636095cc2e0b659e3954775cf8f1dad1bb" + "reference": "148faa138f0d8acb7d85f4a55693d3e13b6048d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/5c805f636095cc2e0b659e3954775cf8f1dad1bb", - "reference": "5c805f636095cc2e0b659e3954775cf8f1dad1bb", + "url": "https://api.github.com/repos/larastan/larastan/zipball/148faa138f0d8acb7d85f4a55693d3e13b6048d2", + "reference": "148faa138f0d8acb7d85f4a55693d3e13b6048d2", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.16", "php": "^8.0.2", "phpmyadmin/sql-parser": "^5.9.0", - "phpstan/phpstan": "^1.11.1" + "phpstan/phpstan": "^1.12.5" }, "require-dev": { "doctrine/coding-standard": "^12.0", "nikic/php-parser": "^4.19.1", "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.2", "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.3", + "phpstan/phpstan-deprecation-rules": "^1.2", "phpunit/phpunit": "^9.6.13 || ^10.5.16" }, "suggest": { @@ -10964,7 +12946,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.9.7" + "source": "https://github.com/larastan/larastan/tree/v2.9.9" }, "funding": [ { @@ -10984,20 +12966,20 @@ "type": "patreon" } ], - "time": "2024-05-27T18:33:26+00:00" + "time": "2024-10-15T19:41:22+00:00" }, { "name": "lychee-org/phpstan-lychee", - "version": "v1.0.4", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/LycheeOrg/phpstan-lychee.git", - "reference": "4f04a10680fbe50884159b0ef8c06a670117f16d" + "reference": "fcdd430577c26178da59809db4e1dd0f0f12fc5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LycheeOrg/phpstan-lychee/zipball/4f04a10680fbe50884159b0ef8c06a670117f16d", - "reference": "4f04a10680fbe50884159b0ef8c06a670117f16d", + "url": "https://api.github.com/repos/LycheeOrg/phpstan-lychee/zipball/fcdd430577c26178da59809db4e1dd0f0f12fc5e", + "reference": "fcdd430577c26178da59809db4e1dd0f0f12fc5e", "shasum": "" }, "require": { @@ -11030,23 +13012,23 @@ ], "description": "Set of rules for all Lychee related php repo", "support": { - "source": "https://github.com/LycheeOrg/phpstan-lychee/tree/v1.0.4", + "source": "https://github.com/LycheeOrg/phpstan-lychee/tree/v1.0.5", "issues": "https://github.com/LycheeOrg/phpstan-lychee/issues" }, - "time": "2024-05-25T20:57:05+00:00" + "time": "2024-10-23T21:13:51+00:00" }, { "name": "maximebf/debugbar", - "version": "v1.22.3", + "version": "v1.23.2", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96" + "reference": "689720d724c771ac4add859056744b7b3f2406da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96", - "reference": "7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/689720d724c771ac4add859056744b7b3f2406da", + "reference": "689720d724c771ac4add859056744b7b3f2406da", "shasum": "" }, "require": { @@ -11068,7 +13050,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.22-dev" + "dev-master": "1.23-dev" } }, "autoload": { @@ -11099,9 +13081,9 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.22.3" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.23.2" }, - "time": "2024-04-03T19:39:26+00:00" + "time": "2024-09-16T11:23:09+00:00" }, { "name": "mockery/mockery", @@ -11247,62 +13229,101 @@ "time": "2024-06-12T14:39:25+00:00" }, { - "name": "nikic/php-parser", - "version": "v5.1.0", + "name": "nunomaduro/collision", + "version": "v8.5.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "url": "https://github.com/nunomaduro/collision.git", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", + "php": "^8.2.0", + "symfony/console": "^7.1.5" + }, + "conflict": { + "laravel/framework": "<11.0.0 || >=12.0.0", + "phpunit/phpunit": "<10.5.1 || >=12.0.0" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" + "larastan/larastan": "^2.9.8", + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, "branch-alias": { - "dev-master": "5.0-dev" + "dev-8.x": "8.x-dev" } }, "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], "psr-4": { - "PhpParser\\": "lib/PhpParser" + "NunoMaduro\\Collision\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "A PHP parser written in PHP", + "description": "Cli error handling for console/command-line PHP applications.", "keywords": [ - "parser", - "php" + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" ], "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" }, - "time": "2024-07-01T20:03:41+00:00" + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2024-10-15T16:06:32+00:00" }, { "name": "phar-io/manifest", @@ -11483,129 +13504,18 @@ }, "time": "2024-03-27T12:14:49+00:00" }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.8.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" - }, - "time": "2024-02-23T11:10:43+00:00" - }, { "name": "phpmyadmin/sql-parser", - "version": "5.9.0", + "version": "5.10.0", "source": { "type": "git", "url": "https://github.com/phpmyadmin/sql-parser.git", - "reference": "011fa18a4e55591fac6545a821921dd1d61c6984" + "reference": "91d980ab76c3f152481e367f62b921adc38af451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/011fa18a4e55591fac6545a821921dd1d61c6984", - "reference": "011fa18a4e55591fac6545a821921dd1d61c6984", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/91d980ab76c3f152481e367f62b921adc38af451", + "reference": "91d980ab76c3f152481e367f62b921adc38af451", "shasum": "" }, "require": { @@ -11623,8 +13533,7 @@ "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.9.12", "phpstan/phpstan-phpunit": "^1.3.3", - "phpunit/php-code-coverage": "*", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "phpunit/phpunit": "^8.5 || ^9.6", "psalm/plugin-phpunit": "^0.16.1", "vimeo/psalm": "^4.11", "zumba/json-serializer": "~3.0.2" @@ -11680,67 +13589,20 @@ "type": "other" } ], - "time": "2024-01-20T20:34:02+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.29.1", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", - "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", - "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.29.1" - }, - "time": "2024-05-31T08:52:43+00:00" + "time": "2024-08-29T20:56:34+00:00" }, { "name": "phpstan/phpstan", - "version": "1.11.6", + "version": "1.12.7", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee" + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6ac78f1165346c83b4a753f7e4186d969c6ad0ee", - "reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", "shasum": "" }, "require": { @@ -11785,25 +13647,25 @@ "type": "github" } ], - "time": "2024-07-01T15:33:06+00:00" + "time": "2024-10-18T11:12:07+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "fa8cce7720fa782899a0aa97b6a41225d1bb7b26" + "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/fa8cce7720fa782899a0aa97b6a41225d1bb7b26", - "reference": "fa8cce7720fa782899a0aa97b6a41225d1bb7b26", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/f94d246cc143ec5a23da868f8f7e1393b50eaa82", + "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "phpstan/phpstan": "^1.12" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", @@ -11830,27 +13692,27 @@ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.0" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.1" }, - "time": "2024-04-20T06:39:48+00:00" + "time": "2024-09-11T15:52:35+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "363f921dd8441777d4fc137deb99beb486c77df1" + "reference": "daeec748b53de80a97498462513066834ec28f8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/363f921dd8441777d4fc137deb99beb486c77df1", - "reference": "363f921dd8441777d4fc137deb99beb486c77df1", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/daeec748b53de80a97498462513066834ec28f8b", + "reference": "daeec748b53de80a97498462513066834ec28f8b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "phpstan/phpstan": "^1.12.4" }, "require-dev": { "nikic/php-parser": "^4.13.0", @@ -11879,38 +13741,38 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.0" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.1" }, - "time": "2024-04-20T06:37:51+00:00" + "time": "2024-09-20T14:04:44+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.15", + "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae" + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", - "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", + "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.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=8.1", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-text-template": "^3.0", - "sebastian/code-unit-reverse-lookup": "^3.0", - "sebastian/complexity": "^3.0", - "sebastian/environment": "^6.0", - "sebastian/lines-of-code": "^2.0", - "sebastian/version": "^4.0", - "theseer/tokenizer": "^1.2.0" + "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" @@ -11922,7 +13784,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -11951,7 +13813,7 @@ "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.15" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -11959,7 +13821,7 @@ "type": "github" } ], - "time": "2024-06-29T08:25:15+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -12206,16 +14068,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.25", + "version": "10.5.37", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "831bf82312be6037e811833ddbea0b8de60ea314" + "reference": "c7cffa0efa2b70c22366523e6d804c9419eb2400" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/831bf82312be6037e811833ddbea0b8de60ea314", - "reference": "831bf82312be6037e811833ddbea0b8de60ea314", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c7cffa0efa2b70c22366523e6d804c9419eb2400", + "reference": "c7cffa0efa2b70c22366523e6d804c9419eb2400", "shasum": "" }, "require": { @@ -12225,26 +14087,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.5", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-invoker": "^4.0", - "phpunit/php-text-template": "^3.0", - "phpunit/php-timer": "^6.0", - "sebastian/cli-parser": "^2.0", - "sebastian/code-unit": "^2.0", - "sebastian/comparator": "^5.0", - "sebastian/diff": "^5.0", - "sebastian/environment": "^6.0", - "sebastian/exporter": "^5.1", - "sebastian/global-state": "^6.0.1", - "sebastian/object-enumerator": "^5.0", - "sebastian/recursion-context": "^5.0", - "sebastian/type": "^4.0", - "sebastian/version": "^4.0" + "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" @@ -12287,7 +14149,7 @@ "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.25" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.37" }, "funding": [ { @@ -12303,7 +14165,7 @@ "type": "tidelift" } ], - "time": "2024-07-03T05:49:17+00:00" + "time": "2024-10-19T13:03:41+00:00" }, { "name": "react/cache", @@ -12679,31 +14541,31 @@ }, { "name": "react/socket", - "version": "v1.15.0", + "version": "v1.16.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038" + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/216d3aec0b87f04a40ca04f481e6af01bdd1d038", - "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", - "react/dns": "^1.11", + "react/dns": "^1.13", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.6 || ^1.2.1", - "react/stream": "^1.2" + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" }, "require-dev": { "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", + "react/async": "^4.3 || ^3.3 || ^2", "react/promise-stream": "^1.4", - "react/promise-timer": "^1.10" + "react/promise-timer": "^1.11" }, "type": "library", "autoload": { @@ -12747,7 +14609,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.15.0" + "source": "https://github.com/reactphp/socket/tree/v1.16.0" }, "funding": [ { @@ -12755,7 +14617,7 @@ "type": "open_collective" } ], - "time": "2023-12-15T11:02:10+00:00" + "time": "2024-07-26T10:38:09+00:00" }, { "name": "react/stream", @@ -13005,16 +14867,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.1", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", "shasum": "" }, "require": { @@ -13025,7 +14887,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -13070,7 +14932,7 @@ "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.1" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" }, "funding": [ { @@ -13078,7 +14940,7 @@ "type": "github" } ], - "time": "2023-08-14T13:18:12+00:00" + "time": "2024-10-18T14:56:07+00:00" }, { "name": "sebastian/complexity", @@ -13753,29 +15615,29 @@ }, { "name": "slam/phpstan-extensions", - "version": "v6.4.0", + "version": "v6.4.1", "source": { "type": "git", "url": "https://github.com/Slamdunk/phpstan-extensions.git", - "reference": "e485ec42d76f3dcdbbb6bd10ef3333ae1b1ec6f0" + "reference": "389ac3a952b64386dda56becf376c16c493edccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Slamdunk/phpstan-extensions/zipball/e485ec42d76f3dcdbbb6bd10ef3333ae1b1ec6f0", - "reference": "e485ec42d76f3dcdbbb6bd10ef3333ae1b1ec6f0", + "url": "https://api.github.com/repos/Slamdunk/phpstan-extensions/zipball/389ac3a952b64386dda56becf376c16c493edccb", + "reference": "389ac3a952b64386dda56becf376c16c493edccb", "shasum": "" }, "require": { - "nikic/php-parser": "^4.19.1 || ^5.0.2", "php": "~8.2.0 || ~8.3.0", - "phpstan/phpstan": "^1.11.4" + "phpstan/phpstan": "^1.11.8" }, "require-dev": { "nette/di": "^3.2.2", - "nette/neon": "^3.4.1", + "nette/neon": "^3.4.3", + "nikic/php-parser": "^4.19.1 || ^5.0.2", "phpstan/phpstan-phpunit": "^1.4.0", - "phpunit/phpunit": "^11.2.1", - "slam/php-cs-fixer-extensions": "^3.10.0" + "phpunit/phpunit": "^11.2.9", + "slam/php-cs-fixer-extensions": "^3.11.1" }, "type": "phpstan-extension", "extra": { @@ -13804,7 +15666,7 @@ "description": "Slam extension of phpstan", "support": { "issues": "https://github.com/Slamdunk/phpstan-extensions/issues", - "source": "https://github.com/Slamdunk/phpstan-extensions/tree/v6.4.0" + "source": "https://github.com/Slamdunk/phpstan-extensions/tree/v6.4.1" }, "funding": [ { @@ -13816,20 +15678,20 @@ "type": "github" } ], - "time": "2024-06-11T10:06:12+00:00" + "time": "2024-08-01T13:49:19+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.1", + "version": "3.10.3", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877" + "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877", - "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", + "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", "shasum": "" }, "require": { @@ -13896,20 +15758,20 @@ "type": "open_collective" } ], - "time": "2024-05-22T21:24:41+00:00" + "time": "2024-09-18T10:38:58+00:00" }, { "name": "symfony/filesystem", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/61fe0566189bf32e8cfee78335d8776f64a66f5a", + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a", "shasum": "" }, "require": { @@ -13946,7 +15808,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.2" + "source": "https://github.com/symfony/filesystem/tree/v7.1.5" }, "funding": [ { @@ -13962,7 +15824,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-09-17T09:16:35+00:00" }, { "name": "symfony/options-resolver", @@ -14033,20 +15895,20 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af" + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/3fb075789fb91f9ad9af537c4012d523085bd5af", - "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -14089,7 +15951,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" }, "funding": [ { @@ -14105,7 +15967,7 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/stopwatch", @@ -14360,5 +16222,5 @@ "platform-overrides": { "php": "8.2" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/app.php b/config/app.php index 1d041f93501..62ff18af14f 100644 --- a/config/app.php +++ b/config/app.php @@ -15,7 +15,7 @@ if (!function_exists('renv')) { function renv(string $cst, ?string $default = null): string { - return rtrim(env($cst, $default) ?? '', '/'); + return rtrim((string) (env($cst, $default) ?? ''), '/'); } } @@ -76,7 +76,7 @@ function renv(string $cst, ?string $default = null): string 'url' => renv('APP_URL', 'http://localhost'), - 'dir_url' => env('APP_DIR', '') === '' ? '' : ('/' . trim(env('APP_DIR'), '/')), + 'dir_url' => env('APP_DIR', '') === '' ? '' : ('/' . trim((string) (env('APP_DIR') ?? ''), '/')), 'asset_url' => null, @@ -151,7 +151,7 @@ function renv(string $cst, ?string $default = null): string | Allows to define class names of diagnostics checks that will be skipped. | */ - 'skip_diagnostics_checks' => explode(',', env('SKIP_DIAGNOSTICS_CHECKS', '')), + 'skip_diagnostics_checks' => explode(',', (string) env('SKIP_DIAGNOSTICS_CHECKS', '')), /* |-------------------------------------------------------------------------- @@ -218,7 +218,6 @@ function renv(string $cst, ?string $default = null): string Illuminate\Pipeline\PipelineServiceProvider::class, Illuminate\Queue\QueueServiceProvider::class, Illuminate\Redis\RedisServiceProvider::class, - // Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, @@ -238,6 +237,7 @@ function renv(string $cst, ?string $default = null): string App\Providers\AuthServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, + LycheeVerify\VerifyServiceProvider::class, ], /* @@ -263,8 +263,7 @@ function renv(string $cst, ?string $default = null): string 'UserPolicy' => App\Policies\UserPolicy::class, 'User' => App\Models\User::class, 'SizeVariantType' => App\Enum\SizeVariantType::class, - 'FileStatus' => App\Enum\Livewire\FileStatus::class, - 'Params' => App\Contracts\Livewire\Params::class, + 'FileStatus' => App\Enum\FileStatus::class, 'PhotoLayoutType' => \App\Enum\PhotoLayoutType::class, ])->toArray(), ]; diff --git a/config/cache.php b/config/cache.php index da158160bca..2e68fee947a 100644 --- a/config/cache.php +++ b/config/cache.php @@ -102,5 +102,5 @@ | */ - 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'Lychee'), '_') . '_cache_'), + 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'Lychee'), '_') . '_cache_'), ]; diff --git a/config/data.php b/config/data.php new file mode 100644 index 00000000000..eee755ef956 --- /dev/null +++ b/config/data.php @@ -0,0 +1,201 @@ + DATE_ATOM, + + /** + * When transforming or casting dates, the following timezone will be used to + * convert the date to the correct timezone. If set to null no timezone will + * be passed. + */ + 'date_timezone' => null, + + /** + * It is possible to enable certain features of the package, these would otherwise + * be breaking changes, and thus they are disabled by default. In the next major + * version of the package, these features will be enabled by default. + */ + 'features' => [ + 'cast_and_transform_iterables' => false, + + /** + * When trying to set a computed property value, the package will throw an exception. + * You can disable this behaviour by setting this option to true, which will then just + * ignore the value being passed into the computed property and recalculate it. + */ + 'ignore_exception_when_trying_to_set_computed_property_value' => false, + ], + + /** + * Global transformers will take complex types and transform them into simple + * types. + */ + 'transformers' => [ + DateTimeInterface::class => DateTimeInterfaceTransformer::class, + \Illuminate\Contracts\Support\Arrayable::class => ArrayableTransformer::class, + BackedEnum::class => EnumTransformer::class, + ], + + /** + * Global casts will cast values into complex types when creating a data + * object from simple types. + */ + 'casts' => [ + DateTimeInterface::class => DateTimeInterfaceCast::class, + BackedEnum::class => EnumCast::class, + // Enumerable::class => Spatie\LaravelData\Casts\EnumerableCast::class, + ], + + /** + * Rule inferrers can be configured here. They will automatically add + * validation rules to properties of a data object based upon + * the type of the property. + */ + 'rule_inferrers' => [ + SometimesRuleInferrer::class, + NullableRuleInferrer::class, + RequiredRuleInferrer::class, + BuiltInTypesRuleInferrer::class, + AttributesRuleInferrer::class, + ], + + /** + * Normalizers return an array representation of the payload, or null if + * it cannot normalize the payload. The normalizers below are used for + * every data object, unless overridden in a specific data object class. + */ + 'normalizers' => [ + ModelNormalizer::class, + // FormRequestNormalizer::class, + ArrayableNormalizer::class, + ObjectNormalizer::class, + ArrayNormalizer::class, + JsonNormalizer::class, + ], + + /** + * Data objects can be wrapped into a key like 'data' when used as a resource, + * this key can be set globally here for all data objects. You can pass in + * `null` if you want to disable wrapping. + */ + 'wrap' => null, + + /** + * Adds a specific caster to the Symphony VarDumper component which hides + * some properties from data objects and collections when being dumped + * by `dump` or `dd`. Can be 'enabled', 'disabled' or 'development' + * which will only enable the caster locally. + */ + 'var_dumper_caster_mode' => 'development', + + /** + * It is possible to skip the PHP reflection analysis of data objects + * when running in production. This will speed up the package. You + * can configure where data objects are stored and which cache + * store should be used. + * + * Structures are cached forever as they'll become stale when your + * application is deployed with changes. You can set a duration + * in seconds if you want the cache to clear after a certain + * timeframe. + */ + 'structure_caching' => [ + 'enabled' => true, + 'directories' => [app_path('Data')], + 'cache' => [ + 'store' => env('CACHE_STORE', env('CACHE_DRIVER', 'file')), + 'prefix' => 'laravel-data', + 'duration' => null, + ], + 'reflection_discovery' => [ + 'enabled' => true, + 'base_path' => base_path(), + 'root_namespace' => null, + ], + ], + + /** + * A data object can be validated when created using a factory or when calling the from + * method. By default, only when a request is passed the data is being validated. This + * behaviour can be changed to always validate or to completely disable validation. + */ + 'validation_strategy' => \Spatie\LaravelData\Support\Creation\ValidationStrategy::OnlyRequests->value, + + /** + * When using an invalid include, exclude, only or except partial, the package will + * throw an exception. You can disable this behaviour by setting this option to true. + */ + 'ignore_invalid_partials' => false, + + /** + * When transforming a nested chain of data objects, the package can end up in an infinite + * loop when including a recursive relationship. The max transformation depth can be + * set as a safety measure to prevent this from happening. When set to null, the + * package will not enforce a maximum depth. + */ + 'max_transformation_depth' => null, + + /** + * When the maximum transformation depth is reached, the package will throw an exception. + * You can disable this behaviour by setting this option to true which will return an + * empty array. + */ + 'throw_when_max_transformation_depth_reached' => true, + + /** + * When using the `make:data` command, the package will use these settings to generate + * the data classes. You can override these settings by passing options to the command. + */ + 'commands' => [ + /** + * Provides default configuration for the `make:data` command. These settings can be overridden with options + * passed directly to the `make:data` command for generating single Data classes, or if not set they will + * automatically fall back to these defaults. See `php artisan make:data --help` for more information. + */ + 'make' => [ + /** + * The default namespace for generated Data classes. This exists under the application's root namespace, + * so the default 'Data` will end up as '\App\Data', and generated Data classes will be placed in the + * app/Data/ folder. Data classes can live anywhere, but this is where `make:data` will put them. + */ + 'namespace' => 'Data', + + /** + * This suffix will be appended to all data classes generated by make:data, so that they are less likely + * to conflict with other related classes, controllers or models with a similar name without resorting + * to adding an alias for the Data object. Set to a blank string (not null) to disable. + */ + 'suffix' => 'Resource', + ], + ], + + /** + * When using Livewire, the package allows you to enable or disable the synths + * these synths will automatically handle the data objects and their + * properties when used in a Livewire component. + */ + 'livewire' => [ + 'enable_synths' => false, + ], +]; diff --git a/config/database.php b/config/database.php index ada6f697b1f..da0afd5aa7b 100644 --- a/config/database.php +++ b/config/database.php @@ -183,7 +183,7 @@ 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'Lychee'), '_') . '_database_'), + 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'Lychee'), '_') . '_database_'), ], 'default' => [ diff --git a/config/features.php b/config/features.php index cd61e99d2ed..b6a27b551bb 100644 --- a/config/features.php +++ b/config/features.php @@ -3,14 +3,24 @@ return [ /* |-------------------------------------------------------------------------- - | Use Livewire Front-end + | Use VueJS Front-end |-------------------------------------------------------------------------- | - | This value determines whether livewire front-end is enabled as it is + | This value determines whether vuejs front-end is enabled as it is | currently under development. | */ - 'livewire' => (bool) env('LIVEWIRE_ENABLED', true), + 'vuejs' => (bool) env('VUEJS_ENABLED', true), + + /* + |-------------------------------------------------------------------------- + | Use Legacy API + |-------------------------------------------------------------------------- + | + | This value determines whether the Legacy API is still available. + | + */ + 'legacy_api' => (bool) env('LEGACY_API_ENABLED', !(bool) env('VUEJS_ENABLED', true)), /* |-------------------------------------------------------------------------- @@ -49,7 +59,7 @@ | | Use pipeline design pattern instead of hardcoded Strategies. */ - 'create-photo-via-pipes' => (bool) env('PHOTO_PIPES', false), + 'create-photo-via-pipes' => (bool) env('PHOTO_PIPES', true), /* |-------------------------------------------------------------------------- diff --git a/config/feed.php b/config/feed.php index ec692629242..b66cc4748d3 100644 --- a/config/feed.php +++ b/config/feed.php @@ -11,7 +11,7 @@ * You can also pass an argument to that method. Note that their key must be the name of the parameter: * * [App\Model::class, 'getAllFeedItems', 'parameterName' => 'argument'] */ - 'items' => [App\Legacy\V1\Controllers\RSSController::class, 'getRSS'], + 'items' => [App\Http\Controllers\RSSController::class, 'getRSS'], /* * The feed will be available on this url. diff --git a/config/filesystems.php b/config/filesystems.php index d28493e0c3c..b79f3149d55 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -11,7 +11,7 @@ if (!function_exists('renv')) { function renv(string $cst, ?string $default = null): string { - return rtrim(env($cst, $default) ?? '', '/'); + return rtrim((string) (env($cst, $default) ?? ''), '/'); } } @@ -25,7 +25,7 @@ function renv(string $cst, ?string $default = null): string if (!function_exists('renv_cond')) { function renv_cond(string $cst): string { - return env($cst, '') === '' ? '' : ('/' . trim(env($cst), '/')); + return env($cst, '') === '' ? '' : ('/' . trim((string) env($cst), '/')); } } @@ -73,7 +73,7 @@ function renv_cond(string $cst): string // Lychee uses the disk "images" to store the media files 'images' => [ 'driver' => 'local', - 'root' => env('LYCHEE_UPLOADS', public_path(env('LYCHEE_UPLOADS_DIR', 'uploads/'))), + 'root' => env('LYCHEE_UPLOADS', public_path((string) env('LYCHEE_UPLOADS_DIR', 'uploads/'))), 'url' => env('LYCHEE_UPLOADS_URL', '') !== '' ? renv('LYCHEE_UPLOADS_URL') : (renv('APP_URL', '') . renv_cond('APP_DIR') . '/' . renv('LYCHEE_UPLOADS_DIR', 'uploads')), @@ -112,7 +112,7 @@ function renv_cond(string $cst): string 'dist' => [ 'driver' => 'local', 'root' => env('LYCHEE_DIST', public_path('dist/')), - 'url' => env('LYCHEE_DIST_URL', 'dist/'), + 'url' => env('LYCHEE_DIST_URL', renv_cond('APP_DIR') . '/dist/'), 'visibility' => 'public', ], @@ -131,30 +131,30 @@ function renv_cond(string $cst): string // We use this space to temporarily store images when uploading. // Mostly chunks and incomplete images are placed here - 'livewire-upload' => [ + 'image-upload' => [ 'driver' => 'local', - 'root' => env('LYCHEE_TMP_UPLOAD', storage_path('livewire-tmp')), + 'root' => env('LYCHEE_TMP_UPLOAD', storage_path('tmp/uploads')), 'visibility' => 'private', ], // We use this space to process the images, 'image-jobs' => [ 'driver' => 'local', - 'root' => env('LYCHEE_IMAGE_JOBS', storage_path('image-jobs')), + 'root' => env('LYCHEE_IMAGE_JOBS', storage_path('tmp/jobs')), 'visibility' => 'private', ], // This is where we extract zip files before importing them. 'extract-jobs' => [ 'driver' => 'local', - 'root' => env('LYCHEE_EXTRACT_JOBS', storage_path('extract-jobs')), + 'root' => env('LYCHEE_EXTRACT_JOBS', storage_path('tmp/extract')), 'visibility' => 'private', ], // For tests purposes 'tmp-for-tests' => [ 'driver' => 'local', - 'root' => storage_path('image-tmp/'), + 'root' => storage_path('tmp/uploads'), 'visibility' => 'private', ], ], diff --git a/config/livewire.php b/config/livewire.php deleted file mode 100644 index be049beb49b..00000000000 --- a/config/livewire.php +++ /dev/null @@ -1,158 +0,0 @@ - 'App\\Livewire\\Components', - - /* - |--------------------------------------------------------------------------- - | View Path - |--------------------------------------------------------------------------- - | - | This value is used to specify where Livewire component Blade templates are - | stored when running file creation commands like `artisan make:livewire`. - | It is also used if you choose to omit a component's render() method. - | - */ - - 'view_path' => resource_path('views/livewire'), - - /* - |--------------------------------------------------------------------------- - | Layout - |--------------------------------------------------------------------------- - | The view that will be used as the layout when rendering a single component - | as an entire page via `Route::get('/post/create', CreatePost::class);`. - | In this case, the view returned by CreatePost will render into $slot. - | - */ - - 'layout' => 'components.layouts.app', - - /* - |--------------------------------------------------------------------------- - | Lazy Loading Placeholder - |--------------------------------------------------------------------------- - | Livewire allows you to lazy load components that would otherwise slow down - | the initial page load. Every component can have a custom placeholder or - | you can define the default placeholder view for all components below. - | - */ - - 'lazy_placeholder' => null, - - /* - |--------------------------------------------------------------------------- - | Temporary File Uploads - |--------------------------------------------------------------------------- - | - | Livewire handles file uploads by storing uploads in a temporary directory - | before the file is stored permanently. All file uploads are directed to - | a global endpoint for temporary storage. You may configure this below: - | - */ - - 'temporary_file_upload' => [ - 'disk' => null, // Example: 'local', 's3' | Default: 'default' - 'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB) - 'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp' - 'middleware' => 'throttle:10000,1', // Example: 'throttle:5,1' | Default: 'throttle:60,1' - 'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs... - 'png', 'gif', 'bmp', 'svg', 'wav', 'mp4', - 'mov', 'avi', 'wmv', 'mp3', 'm4a', - 'jpg', 'jpeg', 'mpga', 'webp', 'wma', - ], - 'max_upload_time' => 60, // Max duration (in minutes) before an upload is invalidated... - ], - - /* - |--------------------------------------------------------------------------- - | Render On Redirect - |--------------------------------------------------------------------------- - | - | This value determines if Livewire will run a component's `render()` method - | after a redirect has been triggered using something like `redirect(...)` - | Setting this to true will render the view once more before redirecting - | - */ - - 'render_on_redirect' => false, - - /* - |--------------------------------------------------------------------------- - | Eloquent Model Binding - |--------------------------------------------------------------------------- - | - | Previous versions of Livewire supported binding directly to eloquent model - | properties using wire:model by default. However, this behavior has been - | deemed too "magical" and has therefore been put under a feature flag. - | - */ - - 'legacy_model_binding' => false, - - /* - |--------------------------------------------------------------------------- - | Auto-inject Frontend Assets - |--------------------------------------------------------------------------- - | - | By default, Livewire automatically injects its JavaScript and CSS into the - | and of pages containing Livewire components. By disabling - | this behavior, you need to use @livewireStyles and @livewireScripts. - | - */ - - 'inject_assets' => true, - - /* - |--------------------------------------------------------------------------- - | Navigate (SPA mode) - |--------------------------------------------------------------------------- - | - | By adding `wire:navigate` to links in your Livewire application, Livewire - | will prevent the default link handling and instead request those pages - | via AJAX, creating an SPA-like effect. Configure this behavior here. - | - */ - - 'navigate' => [ - 'show_progress_bar' => true, - 'progress_bar_color' => '#2299dd', - ], - - /* - |--------------------------------------------------------------------------- - | HTML Morph Markers - |--------------------------------------------------------------------------- - | - | Livewire intelligently "morphs" existing HTML into the newly rendered HTML - | after each update. To make this process more reliable, Livewire injects - | "markers" into the rendered Blade surrounding @if, @class & @foreach. - | - */ - - 'inject_morph_markers' => true, - - /* - |--------------------------------------------------------------------------- - | Pagination Theme - |--------------------------------------------------------------------------- - | - | When enabling Livewire's pagination feature by using the `WithPagination` - | trait, Livewire will use Tailwind templates to render pagination views - | on the page. If you want Bootstrap CSS, you can specify: "bootstrap" - | - */ - - 'pagination_theme' => 'tailwind', -]; diff --git a/config/log-viewer.php b/config/log-viewer.php index 8ad54748e90..00118ba58f3 100644 --- a/config/log-viewer.php +++ b/config/log-viewer.php @@ -5,7 +5,7 @@ if (!function_exists('renv')) { function renv(string $cst, ?string $default = null): string { - return rtrim(env($cst, $default) ?? '', '/'); + return rtrim((string) (env($cst, $default) ?? ''), '/'); } } @@ -19,7 +19,7 @@ function renv(string $cst, ?string $default = null): string if (!function_exists('renv_cond')) { function renv_cond(string $cst): string { - return env($cst, '') === '' ? '' : ('/' . trim(env($cst), '/')); + return env($cst, '') === '' ? '' : ('/' . trim((string) env($cst), '/')); } } @@ -66,7 +66,7 @@ function renv_cond(string $cst): string | */ - 'back_to_system_url' => renv('APP_URL', 'http://localhost') . renv_cond('APP_DIR'), + 'back_to_system_url' => renv('APP_URL', 'http://localhost') . renv_cond('APP_DIR') . '/gallery', 'back_to_system_label' => null, // Displayed by default: "Back to {{ app.name }}" @@ -128,7 +128,7 @@ function renv_cond(string $cst): string 'hosts' => [ 'local' => [ - 'name' => ucfirst(env('APP_ENV', 'local')), + 'name' => ucfirst((string) env('APP_ENV', 'local')), ], // 'staging' => [ diff --git a/config/scramble.php b/config/scramble.php deleted file mode 100644 index 436afbe7160..00000000000 --- a/config/scramble.php +++ /dev/null @@ -1,50 +0,0 @@ - 'api', - - /* - * Your API domain. By default, app domain is used. This is also a part of the default API routes - * matcher, so when implementing your own, make sure you use this config if needed. - */ - 'api_domain' => null, - - 'info' => [ - /* - * API version. - */ - 'version' => env('API_VERSION', '0.0.1'), - - /* - * Description rendered on the home page of the API documentation (`/docs/api`). - */ - 'description' => '', - ], - - /* - * The list of servers of the API. By default (when `null`), server URL will be created from - * `scramble.api_path` and `scramble.api_domain` config variables. When providing an array, you - * will need to specify the local server URL manually (if needed). - * - * Example of non-default config (final URLs are generated using Laravel `url` helper): - * - * ```php - * 'servers' => [ - * 'Live' => 'api', - * 'Prod' => 'https://scramble.dedoc.co/api', - * ], - * ``` - */ - 'servers' => null, - - 'middleware' => [ - // Only available for admin - 'web-admin', - ], - - 'extensions' => [], -]; diff --git a/config/secure-headers.php b/config/secure-headers.php index 74ce5c58706..e537c5ca534 100644 --- a/config/secure-headers.php +++ b/config/secure-headers.php @@ -349,7 +349,7 @@ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src 'connect-src' => array_merge( ['https://lycheeorg.github.io/update.json'], - explode(',', env('SECURITY_HEADER_CSP_CONNECT_SRC', '')) + explode(',', (string) env('SECURITY_HEADER_CSP_CONNECT_SRC', '')) ), // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src @@ -488,7 +488,7 @@ 'allow' => array_merge( ['https://www.dropbox.com/static/api/1/dropins.js'], - explode(',', env('SECURITY_HEADER_SCRIPT_SRC_ALLOW', '')) + explode(',', (string) env('SECURITY_HEADER_SCRIPT_SRC_ALLOW', '')) ), 'schemes' => [ diff --git a/config/session.php b/config/session.php index 4a577c124f0..7aa69178ad4 100644 --- a/config/session.php +++ b/config/session.php @@ -128,7 +128,7 @@ 'cookie' => env( 'SESSION_COOKIE', - Str::slug(env('APP_NAME', 'Lychee'), '_') . '_session' + Str::slug((string) env('APP_NAME', 'Lychee'), '_') . '_session' ), /* diff --git a/config/typescript-transformer.php b/config/typescript-transformer.php new file mode 100644 index 00000000000..fbe6cb1119a --- /dev/null +++ b/config/typescript-transformer.php @@ -0,0 +1,86 @@ + [ + app_path(), + ], + + /* + * Collectors will search for classes in the `auto_discover_types` paths and choose the correct + * transformer to transform them. By default, we include a DefaultCollector which will search + * for @typescript annotated and #[TypeScript] attributed classes to transform. + */ + + 'collectors' => [ + DefaultCollector::class, + EnumCollector::class, + ], + + /* + * Transformers take PHP classes(e.g., enums) as an input and will output + * a TypeScript representation of the PHP class. + */ + + 'transformers' => [ + SpatieStateTransformer::class, + EnumTransformer::class, + SpatieEnumTransformer::class, + DtoTransformer::class, + ], + + /* + * In your classes, you sometimes have types that should always be replaced + * by the same TypeScript representations. For example, you can replace a + * Datetime always with a string. You define these replacements here. + */ + + 'default_type_replacements' => [ + DateTime::class => 'string', + DateTimeImmutable::class => 'string', + Carbon\CarbonInterface::class => 'string', + Carbon\CarbonImmutable::class => 'string', + Carbon\Carbon::class => 'string', + ], + + /* + * The package will write the generated TypeScript to this file. + */ + + 'output_file' => resource_path('js/lychee.d.ts'), + + /* + * When the package is writing types to the output file, a writer is used to + * determine the format. By default, this is the `TypeDefinitionWriter`. + * But you can also use the `ModuleWriter` or implement your own. + */ + + 'writer' => TypeDefinitionWriter::class, + + /* + * The generated TypeScript file can be formatted. We ship a Prettier formatter + * out of the box: `PrettierFormatter` but you can also implement your own one. + * The generated TypeScript will not be formatted when no formatter was set. + */ + + 'formatter' => null, + + /* + * Enums can be transformed into types or native TypeScript enums, by default + * the package will transform them to types. + */ + + 'transform_to_native_enums' => false, +]; diff --git a/database/factories/AccessPermissionFactory.php b/database/factories/AccessPermissionFactory.php new file mode 100644 index 00000000000..5256ed21a47 --- /dev/null +++ b/database/factories/AccessPermissionFactory.php @@ -0,0 +1,134 @@ + + */ +class AccessPermissionFactory extends Factory +{ + /** + * The name of the factory's corresponding model. + * + * @var string + */ + protected $model = AccessPermission::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return + [ + 'is_link_required' => true, + 'grants_full_photo_access' => false, + 'grants_download' => false, + 'grants_upload' => false, + 'grants_edit' => false, + 'grants_delete' => false, + ]; + } + + public function public() + { + return $this->state(function (array $attributes) { + return [ + 'user_id' => null, + ]; + }); + } + + public function locked() + { + return $this->state(function (array $attributes) { + return [ + 'password' => Hash::make('password'), + ]; + }); + } + + public function for_user(User $user) + { + return $this->state(function (array $attributes) use ($user) { + return [ + 'user_id' => $user->id, + ]; + })->afterCreating(function (AccessPermission $perm) { + $perm->load('album', 'user'); + }); + } + + public function grants_edit() + { + return $this->state(function (array $attributes) { + return [ + 'grants_edit' => true, + ]; + }); + } + + public function grants_delete() + { + return $this->state(function (array $attributes) { + return [ + 'grants_delete' => true, + ]; + }); + } + + public function grants_upload() + { + return $this->state(function (array $attributes) { + return [ + 'grants_upload' => true, + ]; + }); + } + + public function grants_download() + { + return $this->state(function (array $attributes) { + return [ + 'grants_download' => true, + ]; + }); + } + + public function grants_full_photo() + { + return $this->state(function (array $attributes) { + return [ + 'grants_full_photo_access' => true, + ]; + }); + } + + public function visible() + { + return $this->state(function (array $attributes) { + return [ + 'is_link_required' => false, + ]; + }); + } + + public function for_album(Album $album) + { + return $this->state(function (array $attributes) use ($album) { + return [ + 'base_album_id' => $album->id, + ]; + })->afterCreating(function (AccessPermission $perm) { + $perm->load('album', 'user'); + }); + } +} \ No newline at end of file diff --git a/database/factories/PhotoFactory.php b/database/factories/PhotoFactory.php index ae2f8384cfe..bbe27aaa48f 100644 --- a/database/factories/PhotoFactory.php +++ b/database/factories/PhotoFactory.php @@ -98,6 +98,16 @@ public function with_subGPS_coordinates(): self }); } + /** define tags for that picture */ + public function with_tags(string $tags): self + { + return $this->state(function (array $attributes) use ($tags) { + return [ + 'tags' => $tags, + ]; + }); + } + /** * Set a bunch of GPS coordinates (in Netherlands). * diff --git a/database/factories/TagAlbumFactory.php b/database/factories/TagAlbumFactory.php new file mode 100644 index 00000000000..4e4bd82a032 --- /dev/null +++ b/database/factories/TagAlbumFactory.php @@ -0,0 +1,44 @@ + + */ +class TagAlbumFactory extends Factory +{ + use OwnedBy; + + /** + * The name of the factory's corresponding model. + * + * @var string + */ + protected $model = TagAlbum::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'title' => 'Tag Album ' . fake()->year(), + 'owner_id' => 1, + ]; + } + + public function of_tags(string $tags): self + { + return $this->state(function (array $attributes) use ($tags) { + return [ + 'show_tags' => $tags, + ]; + }); + } +} diff --git a/database/migrations/2022_04_18_174417_fix_live_photo_short_path.php b/database/migrations/2022_04_18_174417_fix_live_photo_short_path.php index 673fd025935..9c053c40177 100644 --- a/database/migrations/2022_04_18_174417_fix_live_photo_short_path.php +++ b/database/migrations/2022_04_18_174417_fix_live_photo_short_path.php @@ -30,7 +30,7 @@ public function up(): void $sqlConcatLivePhotoPath = match ($this->driverName) { 'mysql' => DB::raw('CONCAT(\'big/\', live_photo_short_path)'), 'pgsql', 'sqlite' => DB::raw('\'big/\' || live_photo_short_path'), - default => throw new \RuntimeException('Unknown DBMS') + default => throw new \RuntimeException('Unknown DBMS'), }; DB::table('photos') @@ -52,7 +52,7 @@ public function down(): void $sqlSubstringLivePhotoPath = match ($this->driverName) { 'mysql', 'pgsql' => DB::raw('SUBSTRING(live_photo_short_path FROM 5)'), 'sqlite' => DB::raw('SUBSTR(live_photo_short_path, 5)'), - default => throw new \RuntimeException('Unknown DBMS') + default => throw new \RuntimeException('Unknown DBMS'), }; DB::table('photos') diff --git a/database/migrations/2024_07_06_214241_thumb_min_max_take_date_order.php b/database/migrations/2024_07_06_214241_thumb_min_max_take_date_order.php new file mode 100644 index 00000000000..5e39ec032b5 --- /dev/null +++ b/database/migrations/2024_07_06_214241_thumb_min_max_take_date_order.php @@ -0,0 +1,29 @@ + 'thumb_min_max_order', + 'value' => 'younger_older', + 'is_secret' => true, + 'cat' => self::GALLERY, + 'type_range' => 'older_younger|younger_older', + 'description' => 'Set which date to display first in thumb. Allowed values: older_younger, younger_older', + ], + [ + 'key' => 'header_min_max_order', + 'value' => 'older_younger', + 'is_secret' => true, + 'cat' => self::GALLERY, + 'type_range' => 'older_younger|younger_older', + 'description' => 'Set which date to display first in header. Allowed values: older_younger, younger_older', + ], + ]; + } +}; diff --git a/database/migrations/2024_07_12_183751_add_auto_play_config.php b/database/migrations/2024_07_12_183751_add_auto_play_config.php new file mode 100644 index 00000000000..9b8cf3a191e --- /dev/null +++ b/database/migrations/2024_07_12_183751_add_auto_play_config.php @@ -0,0 +1,21 @@ + 'autoplay_enabled', + 'value' => '1', + 'is_secret' => true, + 'cat' => self::GALLERY, + 'type_range' => self::BOOL, + 'description' => 'Set autoplay attribute on videos.', + ], + ]; + } +}; diff --git a/database/migrations/2024_07_26_120007_simplify_config.php b/database/migrations/2024_07_26_120007_simplify_config.php new file mode 100644 index 00000000000..b05c0b3b7af --- /dev/null +++ b/database/migrations/2024_07_26_120007_simplify_config.php @@ -0,0 +1,26 @@ +where('cat', '=', self::BOOL_STRING)->update(['cat' => self::BOOL]); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Nothing to do + } +}; diff --git a/database/migrations/2024_07_29_172018_fix_settings.php b/database/migrations/2024_07_29_172018_fix_settings.php new file mode 100644 index 00000000000..4a4b3a2d002 --- /dev/null +++ b/database/migrations/2024_07_29_172018_fix_settings.php @@ -0,0 +1,33 @@ +where('key', '=', 'site_owner')->update(['description' => 'Website Owner']); + DB::table('configs')->where('key', '=', 'mod_frame_enabled')->update(['description' => 'Enable Mod Frame']); + DB::table('configs')->where('key', '=', 'sm_facebook_url')->update(['description' => 'Url of facebook profile']); + DB::table('configs')->where('key', '=', 'sm_flickr_url')->update(['description' => 'Url of flickr profile']); + DB::table('configs')->where('key', '=', 'sm_twitter_url')->update(['description' => 'Url of twitter profile']); + DB::table('configs')->where('key', '=', 'sm_instagram_url')->update(['description' => 'Url of instagram profile']); + DB::table('configs')->where('key', '=', 'sm_youtube_url')->update(['description' => 'Url of youtube profile']); + DB::table('configs')->where('key', '=', 'footer_show_copyright')->update(['description' => 'Display copyright in footer.']); + DB::table('configs')->where('key', '=', 'footer_additional_text')->update(['description' => 'Additional text of the footer.']); + DB::table('configs')->where('key', '=', 'footer_show_social_media')->update(['description' => 'Show social media links in footer.']); + DB::table('configs')->where('key', '=', 'grants_download')->update(['description' => 'Grants download by default.']); + DB::table('configs')->where('key', '=', 'nsfw_banner_override')->update(['description' => 'Custom warning text instead of default.']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // nothing to do. + } +}; diff --git a/database/migrations/2024_08_09_205532_white_theme.php b/database/migrations/2024_08_09_205532_white_theme.php new file mode 100644 index 00000000000..1503ece0b6e --- /dev/null +++ b/database/migrations/2024_08_09_205532_white_theme.php @@ -0,0 +1,21 @@ + 'dark_mode_enabled', + 'value' => '1', + 'is_secret' => false, + 'cat' => self::CONFIG, + 'type_range' => self::BOOL, + 'description' => 'Use dark mode for Lychee.', + ], + ]; + } +}; diff --git a/database/migrations/2024_08_31_090626_config_help_popup.php b/database/migrations/2024_08_31_090626_config_help_popup.php new file mode 100644 index 00000000000..0fec0005f6f --- /dev/null +++ b/database/migrations/2024_08_31_090626_config_help_popup.php @@ -0,0 +1,28 @@ + 'show_keybinding_help_popup', + 'value' => '1', + 'is_secret' => false, + 'cat' => 'config', + 'type_range' => self::BOOL, + 'description' => 'Display keybinding help pop-up on login.', + ], + [ + 'key' => 'show_keybinding_help_button', + 'value' => '1', + 'is_secret' => false, + 'cat' => 'config', + 'type_range' => self::BOOL, + 'description' => 'Show keybinding help button in header.', + ], + ]; + } +}; + diff --git a/database/migrations/2024_08_31_090740_fix_description_always_hover_hidden_photo.php b/database/migrations/2024_08_31_090740_fix_description_always_hover_hidden_photo.php new file mode 100644 index 00000000000..4b4ba4b08d8 --- /dev/null +++ b/database/migrations/2024_08_31_090740_fix_description_always_hover_hidden_photo.php @@ -0,0 +1,23 @@ +where('key', '=', 'display_thumb_photo_overlay')->update(['description' => 'Display the title and metadata on photo thumbs (always|hover|never)']); + DB::table('configs')->where('key', '=', 'small_max_width')->update(['description' => 'Maximum width for small thumbs (album view)']); + DB::table('configs')->where('key', '=', 'small_max_height')->update(['description' => 'Maximum height for small thumbs (album view)']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Nothing. + } +}; diff --git a/database/migrations/2024_09_14_143949_add_settings_level.php b/database/migrations/2024_09_14_143949_add_settings_level.php new file mode 100644 index 00000000000..b0b1228e858 --- /dev/null +++ b/database/migrations/2024_09_14_143949_add_settings_level.php @@ -0,0 +1,31 @@ +string('details', 200)->default(''); + $table->integer('level')->default(0); // 0 for all modifiable, 1 for supported, 2 for plus (if we ever decide to use that) + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('configs', function (Blueprint $table) { + $table->dropColumn('details'); + }); + Schema::table('configs', function (Blueprint $table) { + $table->dropColumn('level'); + }); + } +}; diff --git a/database/migrations/2024_09_14_153948_fix_more_descriptions.php b/database/migrations/2024_09_14_153948_fix_more_descriptions.php new file mode 100644 index 00000000000..a2538e19aa0 --- /dev/null +++ b/database/migrations/2024_09_14_153948_fix_more_descriptions.php @@ -0,0 +1,98 @@ +where('key', '=', 'zip_deflate_level')->update([ + 'details' => '-1 = disable compression (use STORE method), 0 = no compression (use DEFLATE method), 1 = minimal compression (fast), ... 9 = maximum compression (slow)', + 'description' => 'Zip compression level.', + ]); + DB::table('configs')->where('key', '=', 'default_album_protection')->update(['description' => 'Default protection for newly created albums']); + DB::table('configs')->where('key', '=', 'login_button_position')->update(['description' => 'Position of the login button']); + + DB::table('configs')->where('key', '=', 'date_format_photo_thumb')->update(['description' => 'Format the date for the photo thumbs.']); + DB::table('configs')->where('key', '=', 'date_format_photo_overlay')->update(['description' => 'Format the date for the photo overlay.']); + DB::table('configs')->where('key', '=', 'date_format_sidebar_uploaded')->update(['description' => 'Format the upload date for the photo sidebar.']); + DB::table('configs')->where('key', '=', 'date_format_sidebar_taken_at')->update(['description' => 'Format the capture date for the photo sidebar.']); + DB::table('configs')->where('key', '=', 'date_format_hero_min_max')->update(['description' => 'Format the date for the album hero.']); + DB::table('configs')->where('key', '=', 'date_format_hero_created_at')->update(['description' => 'Format the created date for the album details.']); + DB::table('configs')->where('key', '=', 'date_format_album_thumb')->update(['description' => 'Format the date for the album thumbs.']); + DB::table('configs')->whereIn('key', [ + 'date_format_photo_thumb', + 'date_format_photo_overlay', + 'date_format_sidebar_uploaded', + 'date_format_sidebar_taken_at', + 'date_format_hero_min_max', + 'date_format_hero_created_at', + 'date_format_album_thumb', + ])->update(['details' => 'See https://www.php.net/manual/en/datetime.format.php']); + DB::table('configs')->where('key', '=', 'display_thumb_album_overlay')->update(['description' => 'Display the title and metadata on album thumbs']); + DB::table('configs')->where('key', '=', 'display_thumb_photo_overlay')->update(['description' => 'Display the title and metadata on photo thumbs']); + DB::table('configs')->where('key', '=', 'default_album_thumb_aspect_ratio')->update(['description' => 'Default aspect ratio for album thumbs']); + DB::table('configs')->where('key', '=', 'use_album_compact_header')->update(['description' => 'Disable the header image in albums']); + DB::table('configs')->where('key', '=', 'thumb_min_max_order')->update(['description' => 'Set which date to display first in thumb.']); + DB::table('configs')->where('key', '=', 'header_min_max_order')->update(['description' => 'Set which date to display first in header.']); + DB::table('configs')->where('key', '=', 'current_job_processing_visible')->update(['description' => 'Make the processing job queue visible by default']); + DB::table('configs')->where('key', '=', 'local_takestamp_video_formats')->update(['description' => 'Use local takestamp for the following video formats']); + DB::table('configs')->where('key', '=', 'back_button_enabled')->update(['description' => 'Enable/disable back button on gallery']); + + DB::table('configs')->where('key', '=', 'enable_unsorted')->update(['description' => 'Enable Unsorted smart album.', + 'details' => 'Warning! Disabling this will make pictures without an album invisible.']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('key', '=', 'zip_deflate_level')->update([ + 'details' => '', + 'description' => 'DEFLATE compression level: -1 = disable compression (use STORE method), 0 = no compression (use DEFLATE method), 1 = minimal compression (fast), ... 9 = maximum compression (slow)', + ]); + DB::table('configs')->where('key', '=', 'default_album_protection')->update(['description' => 'Default protection for newly created albums. 1 = private, 2 = public, 3 = inherit from parent']); + DB::table('configs')->where('key', '=', 'login_button_position')->update(['description' => 'Position of the login button (left | right)']); + + DB::table('configs')->where('key', '=', 'date_format_photo_thumb')->update([ + 'details' => '', + 'description' => 'Format the date for the photo thumbs. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'date_format_photo_overlay')->update([ + 'details' => '', + 'description' => 'Format the date for the photo overlay. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'date_format_sidebar_uploaded')->update([ + 'details' => '', + 'description' => 'Format the upload date for the photo sidebar. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'date_format_sidebar_taken_at')->update([ + 'details' => '', + 'description' => 'Format the capture date for the photo sidebar. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'date_format_hero_min_max')->update([ + 'details' => '', + 'description' => 'Format the date for the album hero. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'date_format_hero_created_at')->update([ + 'details' => '', + 'description' => 'Format the created date for the album details. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'date_format_album_thumb')->update([ + 'details' => '', + 'description' => 'Format the date for the album thumbs. See https://www.php.net/manual/en/datetime.format.php', + ]); + DB::table('configs')->where('key', '=', 'display_thumb_album_overlay')->update(['description' => 'Display the title and metadata on album thumbs (always|hover|never)']); + DB::table('configs')->where('key', '=', 'display_thumb_photo_overlay')->update(['description' => 'Display the title and metadata on photo thumbs (always|hover|never)']); + DB::table('configs')->where('key', '=', 'default_album_thumb_aspect_ratio')->update(['description' => 'Default aspect ratio for album thumbs, one of: 1/1, 2/3, 3/2, 4/5, 5/4, 16/9']); + DB::table('configs')->where('key', '=', 'use_album_compact_header')->update(['description' => 'Disable the header image in albums (0|1)']); + DB::table('configs')->where('key', '=', 'thumb_min_max_order')->update(['description' => 'Set which date to display first in thumb. Allowed values: older_younger, younger_older']); + DB::table('configs')->where('key', '=', 'header_min_max_order')->update(['description' => 'Set which date to display first in header. Allowed values: older_younger, younger_older']); + DB::table('configs')->where('key', '=', 'current_job_processing_visible')->update(['description' => 'Make the processing job queue visible by default (0|1).']); + DB::table('configs')->where('key', '=', 'back_button_enabled')->update(['description' => 'Enable/disable back button on gallery (0 | 1)']); + DB::table('configs')->where('key', '=', 'enable_unsorted')->update(['description' => 'Enable Unsorted smart album. Warning! Disabling this will make pictures without an album invisible.']); + } +}; diff --git a/database/migrations/2024_09_27_144741_add_supporter_fields.php b/database/migrations/2024_09_27_144741_add_supporter_fields.php new file mode 100644 index 00000000000..7cb57f63e3a --- /dev/null +++ b/database/migrations/2024_09_27_144741_add_supporter_fields.php @@ -0,0 +1,49 @@ + 'email', + 'value' => '', + 'is_secret' => true, + 'cat' => self::SE, + 'type_range' => self::STRING, + 'description' => 'Email used when requesting the license.', + 'details' => '', + ], + [ + 'key' => 'license_key', + 'value' => '', + 'is_secret' => true, + 'cat' => self::SE, + 'type_range' => self::STRING, + 'description' => 'Lychee License key', + 'details' => 'Get Supporter Edition here: https://lycheeorg.github.io/get-supporter-edition', + ], + [ + 'key' => 'disable_se_call_for_actions', + 'value' => '0', + 'is_secret' => false, + 'cat' => self::SE, + 'type_range' => self::BOOL, + 'description' => 'Disable Lychee SE hint', + 'details' => 'Hides Lychee SE call for actions.', + ], + [ + 'key' => 'enable_se_preview', + 'value' => '0', + 'is_secret' => false, + 'cat' => self::SE, + 'type_range' => self::BOOL, + 'description' => 'Enable preview of Lychee SE features', + 'details' => '', + ], + ]; + } +}; diff --git a/database/migrations/2024_10_05_125328_add_slideshow_timeout.php b/database/migrations/2024_10_05_125328_add_slideshow_timeout.php new file mode 100644 index 00000000000..d3d2e53baea --- /dev/null +++ b/database/migrations/2024_10_05_125328_add_slideshow_timeout.php @@ -0,0 +1,22 @@ + 'slideshow_timeout', + 'value' => '5', + 'is_secret' => false, + 'cat' => self::GALLERY, + 'type_range' => self::POSITIVE, + 'description' => 'Refresh rate of the slideshow in seconds.', + 'details' => 'Show next picture after x seconds.', + ], + ]; + } +}; diff --git a/database/migrations/2024_10_05_125833_lang_is_admin_setting.php b/database/migrations/2024_10_05_125833_lang_is_admin_setting.php new file mode 100644 index 00000000000..8992c306ef4 --- /dev/null +++ b/database/migrations/2024_10_05_125833_lang_is_admin_setting.php @@ -0,0 +1,21 @@ +where('key', '=', 'lang')->update(['cat' => 'Admin']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('key', '=', 'lang')->update(['cat' => 'Gallery']); + } +}; diff --git a/database/migrations/2024_10_05_184315_bump_version060000.php b/database/migrations/2024_10_05_184315_bump_version060000.php new file mode 100644 index 00000000000..35fe30d41d8 --- /dev/null +++ b/database/migrations/2024_10_05_184315_bump_version060000.php @@ -0,0 +1,26 @@ +where('key', 'version')->update(['value' => '060000']); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + DB::table('configs')->where('key', 'version')->update(['value' => '050501']); + } +}; diff --git a/database/migrations/2024_10_09_191528_image_processing_backup.php b/database/migrations/2024_10_09_191528_image_processing_backup.php new file mode 100644 index 00000000000..35286dbaa9d --- /dev/null +++ b/database/migrations/2024_10_09_191528_image_processing_backup.php @@ -0,0 +1,22 @@ + 'keep_original_untouched', + 'value' => '1', + 'cat' => self::PROCESSING, + 'type_range' => self::BOOL, + 'description' => 'Keep Original image untouched.', + 'details' => 'In case of auto rotation, the original image will be kept untouched.', + 'is_secret' => false, + ], + ]; + } +}; \ No newline at end of file diff --git a/database/migrations/2024_10_09_194010_image_processing_details_and_others.php b/database/migrations/2024_10_09_194010_image_processing_details_and_others.php new file mode 100644 index 00000000000..f3f51e8c9f2 --- /dev/null +++ b/database/migrations/2024_10_09_194010_image_processing_details_and_others.php @@ -0,0 +1,41 @@ +where('key', 'auto_fix_orientation')->update(['details' => ' Original images will be overwritten and compressed.']); + DB::table('configs')->whereIn('key', [ + 'date_format_photo_thumb', + 'date_format_photo_overlay', + 'date_format_sidebar_uploaded', + 'date_format_sidebar_taken_at', + 'date_format_hero_min_max', + 'date_format_hero_created_at', + 'date_format_album_thumb', + ])->update(['details' => 'See datetime.format.php']); + DB::table('configs')->where('key', 'license_key')->update(['details' => 'Get Supporter Edition here: https://lycheeorg.github.io/get-supporter-edition']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('key', 'auto_fix_orientation')->update(['details' => '']); + DB::table('configs')->whereIn('key', [ + 'date_format_photo_thumb', + 'date_format_photo_overlay', + 'date_format_sidebar_uploaded', + 'date_format_sidebar_taken_at', + 'date_format_hero_min_max', + 'date_format_hero_created_at', + 'date_format_album_thumb', + ])->update(['details' => 'See https://www.php.net/manual/en/datetime.format.php']); + } +}; diff --git a/database/migrations/2024_10_10_101333_set_dropbox_disabled.php b/database/migrations/2024_10_10_101333_set_dropbox_disabled.php new file mode 100644 index 00000000000..14c6461b0a7 --- /dev/null +++ b/database/migrations/2024_10_10_101333_set_dropbox_disabled.php @@ -0,0 +1,32 @@ +where('key', '=', 'dropbox_key') + ->where('value', '=', '') + ->update([ + 'value' => 'disabled', + 'details' => 'Use value "disabled" to mark this setting as such.']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs') + ->where('key', '=', 'dropbox_key') + ->where('value', '=', 'disabled') + ->update([ + 'value' => '', + 'details' => '']); + } +}; diff --git a/database/migrations/2024_10_11_173054_add_space_quota_per_user.php b/database/migrations/2024_10_11_173054_add_space_quota_per_user.php new file mode 100644 index 00000000000..2250944345d --- /dev/null +++ b/database/migrations/2024_10_11_173054_add_space_quota_per_user.php @@ -0,0 +1,36 @@ +bigInteger('quota_kb')->nullable(true)->default(null); + $table->text('description')->nullable(true)->default(null); + $table->text('note')->nullable(true)->default(null); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('quota_kb'); + }); + + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('description'); + }); + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('note'); + }); + } +}; diff --git a/database/migrations/2024_10_11_173106_add_space_quota_configuration.php b/database/migrations/2024_10_11_173106_add_space_quota_configuration.php new file mode 100644 index 00000000000..267ee98df8b --- /dev/null +++ b/database/migrations/2024_10_11_173106_add_space_quota_configuration.php @@ -0,0 +1,23 @@ + 'default_user_quota', + 'value' => '0', + 'cat' => self::OAUTH, + 'type_range' => self::INT, + 'description' => 'Default space quota for new users.', + 'details' => 'Value in KB, keep at 0 to disable quota.', + 'is_secret' => true, + 'level' => 1, + ], + ]; + } +}; diff --git a/database/migrations/2024_10_13_134419_oath_group_to_users.php b/database/migrations/2024_10_13_134419_oath_group_to_users.php new file mode 100644 index 00000000000..57682690cfa --- /dev/null +++ b/database/migrations/2024_10_13_134419_oath_group_to_users.php @@ -0,0 +1,25 @@ +where('cat', self::OAUTH)->update(['cat' => self::USERS]); + DB::table('configs')->where('key', '=', 'allow_username_change')->update(['cat' => self::USERS]); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('cat', self::USERS)->update(['cat' => self::OAUTH]); + } +}; diff --git a/database/migrations/2024_10_14_104644_show_nsfw_in_smart_albums.php b/database/migrations/2024_10_14_104644_show_nsfw_in_smart_albums.php new file mode 100644 index 00000000000..996415ae1ec --- /dev/null +++ b/database/migrations/2024_10_14_104644_show_nsfw_in_smart_albums.php @@ -0,0 +1,23 @@ + 'hide_nsfw_in_smart_albums_and_search', + 'value' => '1', // safe default + 'cat' => 'Mod NSFW', + 'type_range' => self::BOOL, + 'description' => 'Do not show sensitive photos in Smart Albums and Search.', + 'details' => 'Pictures placed in sensive albums will not be shown in Smart Albums and Search.', + 'is_secret' => false, + 'level' => 0, + ], + ]; + } +}; diff --git a/database/migrations/2024_10_14_104823_refine_text_enable_unsorted_smart_album.php b/database/migrations/2024_10_14_104823_refine_text_enable_unsorted_smart_album.php new file mode 100644 index 00000000000..3c4657323ef --- /dev/null +++ b/database/migrations/2024_10_14_104823_refine_text_enable_unsorted_smart_album.php @@ -0,0 +1,21 @@ +where('key', '=', 'enable_unsorted')->update(['details' => ' Disabling this smart album will make pictures without an album invisible.']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('key', '=', 'enable_unsorted')->update(['details' => 'Warning! Disabling this will make pictures without an album invisible.']); + } +}; \ No newline at end of file diff --git a/database/migrations/2024_10_20_125449_move-socials-to-footer.php b/database/migrations/2024_10_20_125449_move-socials-to-footer.php new file mode 100644 index 00000000000..57c5e93382f --- /dev/null +++ b/database/migrations/2024_10_20_125449_move-socials-to-footer.php @@ -0,0 +1,22 @@ +where('cat', 'Social Media')->update(['cat' => 'Footer']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->whereLike('key', 'sm_%_url')->update(['cat' => 'Social Media']); + } +}; diff --git a/database/migrations/2024_10_20_173904_add_photo_layout_per_album.php b/database/migrations/2024_10_20_173904_add_photo_layout_per_album.php new file mode 100644 index 00000000000..8de3f8b9d5a --- /dev/null +++ b/database/migrations/2024_10_20_173904_add_photo_layout_per_album.php @@ -0,0 +1,30 @@ +string(self::PHOTO_LAYOUT_COLUMN_NAME, 20)->nullable()->default(null)->after('copyright'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table(self::BASE_ALBUM, function (Blueprint $table) { + $table->dropColumn(self::PHOTO_LAYOUT_COLUMN_NAME); + }); + } +}; diff --git a/database/migrations/2024_10_23_222857_change_header.php b/database/migrations/2024_10_23_222857_change_header.php new file mode 100644 index 00000000000..932abcc15d0 --- /dev/null +++ b/database/migrations/2024_10_23_222857_change_header.php @@ -0,0 +1,22 @@ +where('value', '=', 'Lychee v5')->update(['value' => 'Lychee v6']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('value', '=', 'Lychee v6')->update(['value' => 'Lychee v5']); + } +}; diff --git a/database/migrations/2024_10_23_225332_warning_html_content.php b/database/migrations/2024_10_23_225332_warning_html_content.php new file mode 100644 index 00000000000..b658bd0fb90 --- /dev/null +++ b/database/migrations/2024_10_23_225332_warning_html_content.php @@ -0,0 +1,21 @@ +whereIn('key', ['nsfw_banner_override', 'footer_additional_text'])->update(['details' => ' Unsanitized html field.']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->whereIn('key', ['nsfw_banner_override', 'footer_additional_text'])->update(['details' => '']); + } +}; diff --git a/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php b/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php index b22a90cc798..2d1d6e87a53 100644 --- a/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php +++ b/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php @@ -18,11 +18,11 @@ * Unfortunately, we need the `fixTree()` algorithm and there is no * implementation which uses low-level DB queries. * - * @implements Node + * @implements Node */ class NestedSetForAlbums_AlbumModel extends Model implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; protected $table = 'albums'; diff --git a/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php b/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php index df1ff72b782..340333b7805 100644 --- a/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php +++ b/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php @@ -18,11 +18,11 @@ * Unfortunately, we need the `fixTree()` algorithm and there is no * implementation which uses low-level DB queries. * - * @implements Node + * @implements Node */ class RefactorAlbumModel_AlbumModel extends Model implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; protected $table = 'albums'; diff --git a/developer-notes.md b/developer-notes.md index 715c4d91eb8..fc39d7a4691 100644 --- a/developer-notes.md +++ b/developer-notes.md @@ -133,3 +133,19 @@ With respect to functional behaviour, we have two "broken" mappings that should This means only the methods `timestamp_tz` and `datetime` are usable in a DB-independent manner. Also, the convenient method `timestamps` must not be used. Taking into account the conclusion from above, the Lychee Application only uses `Blueprint::datetime`, because it shows identical behaviour for each DBMS and has no year-2038-problem on MySQL. + + +### Responses types + +To generate proper responses types, we use Spatie Data + Spatie Typescript. + +Create a new resource and add the attribute `#[TypeScript()]` from `use Spatie\TypeScriptTransformer\Attributes\TypeScript;` + +Generate the types with: +```sh +php artisan typescript:transform +``` + +### Language translations + +We use https://github.com/xiCO2k/laravel-vue-i18n diff --git a/lang/en/lychee.php b/lang/en/lychee.php index 5b4c6c31162..18bb5d77ed2 100644 --- a/lang/en/lychee.php +++ b/lang/en/lychee.php @@ -8,7 +8,7 @@ 'ENTER' => 'Enter', 'CANCEL' => 'Cancel', 'CONFIRM' => 'Confirm', - 'SIGN_IN' => 'Sign In', + 'SIGN_IN' => 'Sign-In', 'CLOSE' => 'Close', 'SETTINGS' => 'Settings', 'SEARCH' => 'Search …', diff --git a/package-lock.json b/package-lock.json index b8f39b10652..f90e7b282cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,36 +6,56 @@ "": { "dependencies": { "@fortawesome/fontawesome-free": "^6.5.1", + "@primevue/themes": "^4.0.0-rc.2", + "@sidsbrmnn/scrollspy": "^1.1.0", + "@types/dropbox-chooser": "^1.0.8", "@types/justified-layout": "^4.1.4", - "autoprefixer": "^10.4.17", - "is-mobile": "^4.0.0", + "@vueuse/core": "^11.0.0", + "autoprefixer": "^10.4.19", + "axios": "^1.7.6", + "axios-cache-interceptor": "^1.5.3", "justified-layout": "^4.1.0", "laravel-vite-plugin": "^1.0.1", - "lazysizes": "^5.3.2", + "laravel-vue-i18n": "^2.7.7", "leaflet": "^1.9.4", "leaflet-gpx": "^1.7.0", "leaflet-rotatedmarker": "^0.2.0", "leaflet.markercluster": "^1.5.3", + "pinia": "^2.1.7", "postcss": "^8.4.33", "prettier": "^3.2.4", + "primeicons": "^7.0.0", + "primevue": "^4.0.0-rc.2", "qrcode": "^1.5.3", + "sprintf-js": "^1.1.3", "tailwindcss": "^3.4.1", + "tailwindcss-primeui": "^0.3.4", "tinygesture": "^3.0.0", "ts-loader": "^9.5.1", "typescript": "^5.3.3", "vite": "^5.4.6", - "vite-plugin-commonjs": "^0.10.1" + "vite-plugin-commonjs": "^0.10.1", + "vue": "^3.2.37", + "vue-collapsed": "^1.3.3", + "vue-i18n": "^9.2.0", + "vue-router": "^4.4.0" }, "devDependencies": { "@lychee-org/leaflet.photo": "^1.0.0", + "@popperjs/core": "^2.11.6", "@tailwindcss/typography": "^0.5.12", "@types/alpinejs": "^3.13.6", "@types/leaflet": "^1.9.8", "@types/leaflet-rotatedmarker": "^0.2.5", "@types/leaflet.markercluster": "^1.5.4", "@types/mousetrap": "^1.6.15", + "@types/node": "^20.14.9", "@types/photoswipe": "^4.1.6", - "@types/qrcode": "^1.5.5" + "@types/qrcode": "^1.5.5", + "@types/sprintf-js": "^1.1.4", + "@vitejs/plugin-vue": "^4.5.0", + "sass": "^1.77.6", + "vue-tsc": "^2.0.24" } }, "node_modules/@alloc/quick-lru": { @@ -49,6 +69,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", + "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", + "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -395,14 +457,54 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz", - "integrity": "sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==", - "hasInstallScript": true, + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", + "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", "engines": { "node": ">=6" } }, + "node_modules/@intlify/core-base": { + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.14.1.tgz", + "integrity": "sha512-rG5/hlNW6Qfve41go37szEf0mVLcfhYuOu83JcY0jZKasnwsrcZYYWDzebCcuO5I/6Sy1JFWo9p+nvkQS1Dy+w==", + "dependencies": { + "@intlify/message-compiler": "9.14.1", + "@intlify/shared": "9.14.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.14.1.tgz", + "integrity": "sha512-MY8hwukJBnXvGAncVKlHsqKDQ5ZcQx4peqEmI8wBUTXn4pezrtTGYXNoz81cLyEEHB+L/zlKWVBSh5TiX4gYoQ==", + "dependencies": { + "@intlify/shared": "9.14.1", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.14.1.tgz", + "integrity": "sha512-XjHu6PEQup9MnP1x0W9y0nXXfq9jFftAYSfV11hryjtH4XqXP8HrzMvXI+ZVifF+jZLszaTzIhvukllplxTQTg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -459,9 +561,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -510,6 +612,279 @@ "node": ">= 8" } }, + "node_modules/@parcel/watcher": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", + "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "devOptional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", + "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", + "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", + "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", + "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", + "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", + "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", + "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", + "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", + "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", + "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", + "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", + "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -519,10 +894,77 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@primeuix/styled": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.2.0.tgz", + "integrity": "sha512-3Q6bDrmwTW88tzJsFIFenC0VyXLj0+/wYw+TZnJ/4CCDfehR4WfTs4EZdpuFtYqvmbpJ6zWXAiwSCNdSYTZkyA==", + "dependencies": { + "@primeuix/utils": "^0.2.0" + }, + "engines": { + "node": ">=12.11.0" + } + }, + "node_modules/@primeuix/utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.2.0.tgz", + "integrity": "sha512-AaDIeRFlsbkVTk2s0mlEjnGSLi31X669NVwo+n+AVAnBdDiQznjipNTpHbOobVBtjOKZize74PChK6uoaSBRUw==", + "engines": { + "node": ">=12.11.0" + } + }, + "node_modules/@primevue/core": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.1.1.tgz", + "integrity": "sha512-jUDrTh3g0FskTdD6rCCsoWfxKky0R7959p7vnaNYI6wMLreaTL3yC3nzYlEniIpb+F51Sm3KJ1eSJBN6DnSB8Q==", + "dependencies": { + "@primeuix/styled": "^0.2.0", + "@primeuix/utils": "^0.2.0" + }, + "engines": { + "node": ">=12.11.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@primevue/icons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.1.1.tgz", + "integrity": "sha512-Ybeb+AHUsVybITuYNwS7goqWcXLLgCDSiCPoymyYwYkzn5qLakvJbQH1EX8lGOsrvqK0hG+s+n7Wm2MHJ8A72w==", + "dependencies": { + "@primeuix/utils": "^0.2.0", + "@primevue/core": "4.1.1" + }, + "engines": { + "node": ">=12.11.0" + } + }, + "node_modules/@primevue/themes": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@primevue/themes/-/themes-4.1.1.tgz", + "integrity": "sha512-ec2gBN2vP0ydGtGAzC0nYCFqYN7CzvXxnlJqcvcPIo3rP/pcdj+FkzAe3y2DMG3OorYtqdzoyGtBefQrx3v5ag==", + "dependencies": { + "@primeuix/styled": "^0.2.0" + }, + "engines": { + "node": ">=12.11.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], @@ -532,9 +974,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], @@ -544,9 +986,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], @@ -556,9 +998,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], @@ -568,9 +1010,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], @@ -580,9 +1022,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], @@ -592,9 +1034,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], @@ -604,9 +1046,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], @@ -616,9 +1058,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], @@ -628,9 +1070,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], @@ -640,9 +1082,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], @@ -652,9 +1094,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], @@ -664,9 +1106,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], @@ -676,9 +1118,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], @@ -688,9 +1130,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], @@ -700,9 +1142,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], @@ -711,10 +1153,15 @@ "win32" ] }, + "node_modules/@sidsbrmnn/scrollspy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sidsbrmnn/scrollspy/-/scrollspy-1.1.0.tgz", + "integrity": "sha512-xLZdHlnPX3vlc/+SBxLLIIG/IXSaMpNTU0+AgUCwSQLpeWppn0IVtToLSV6o3GWoYakuofy1sE01xsEl6atzCA==" + }, "node_modules/@tailwindcss/typography": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.13.tgz", - "integrity": "sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz", + "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==", "dev": true, "dependencies": { "lodash.castarray": "^4.4.0", @@ -723,7 +1170,7 @@ "postcss-selector-parser": "6.0.10" }, "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" } }, "node_modules/@types/alpinejs": { @@ -732,10 +1179,15 @@ "integrity": "sha512-ah53tF6mWuuwerpDE7EHwbZErNDJQlsLISPqJhYj2RZ9nuTYbRknSkqebUd3igkhLIZKkPa7IiXjSn9qsU9O2w==", "dev": true }, + "node_modules/@types/dropbox-chooser": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/dropbox-chooser/-/dropbox-chooser-1.0.8.tgz", + "integrity": "sha512-iXAJPSOgucUTAVOYipdzbA4VHFJ9AiAWBdAq0/fR+W3DUcPCH7lGZ2TAonK2WX4vYkSY7omLwfggX591HhsEVQ==" + }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/geojson": { "version": "7946.0.14", @@ -755,9 +1207,9 @@ "integrity": "sha512-q2ybP0u0NVj87oMnGZOGxY2iUN8ddr48zPOBHBdbOLpsMTA/keGj+93ou+OMCnJk0xewzlNIaVEkxM6VBD3E2w==" }, "node_modules/@types/leaflet": { - "version": "1.9.12", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", - "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", + "version": "1.9.14", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.14.tgz", + "integrity": "sha512-sx2q6MDJaajwhKeVgPSvqXd8rhNJSTA3tMidQGduZn9S6WBYxDkCpSpV5xXEmSg7Cgdk/5vJGhVF1kMYLzauBg==", "dev": true, "dependencies": { "@types/geojson": "*" @@ -788,11 +1240,11 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "20.16.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.15.tgz", + "integrity": "sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/photoswipe": { @@ -810,6 +1262,269 @@ "@types/node": "*" } }, + "node_modules/@types/sprintf-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.4.tgz", + "integrity": "sha512-aWK1reDYWxcjgcIIPmQi3u+OQDuYa9b+lr6eIsGWrekJ9vr1NSjr4Eab8oQ1iKuH1ltFHpXGyerAv1a3FMKxzQ==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.6.tgz", + "integrity": "sha512-FxUfxaB8sCqvY46YjyAAV6c3mMIq/NWQMVvJ+uS4yxr1KzOvyg61gAuOnNvgCvO4TZ7HcLExBEsWcDu4+K4E8A==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.6" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.6.tgz", + "integrity": "sha512-Nsh7UW2ruK+uURIPzjJgF0YRGP5CX9nQHypA2OMqdM2FKy7rh+uv3XgPnWPw30JADbKvZ5HuBzG4gSbVDYVtiw==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.6.tgz", + "integrity": "sha512-NMIrA7y5OOqddL9VtngPWYmdQU03htNKFtAYidbYfWA0TOhyGVd9tfcP4TsLWQ+RBWDZCbBqsr8xzU0ZOxYTCQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.6", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz", + "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.12", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz", + "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", + "dependencies": { + "@vue/compiler-core": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz", + "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.12", + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz", + "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==", + "dependencies": { + "@vue/compiler-dom": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" + }, + "node_modules/@vue/language-core": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.6.tgz", + "integrity": "sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==", + "dev": true, + "dependencies": { + "@volar/language-core": "~2.4.1", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz", + "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==", + "dependencies": { + "@vue/shared": "3.5.12" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz", + "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==", + "dependencies": { + "@vue/reactivity": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz", + "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==", + "dependencies": { + "@vue/reactivity": "3.5.12", + "@vue/runtime-core": "3.5.12", + "@vue/shared": "3.5.12", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz", + "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==", + "dependencies": { + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12" + }, + "peerDependencies": { + "vue": "3.5.12" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz", + "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==" + }, + "node_modules/@vueuse/core": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.1.0.tgz", + "integrity": "sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "11.1.0", + "@vueuse/shared": "11.1.0", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.1.0.tgz", + "integrity": "sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.1.0.tgz", + "integrity": "sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==", + "dependencies": { + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -969,9 +1684,9 @@ "peer": true }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "bin": { "acorn": "bin/acorn" }, @@ -1014,9 +1729,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "engines": { "node": ">=12" }, @@ -1060,10 +1775,15 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "funding": [ { "type": "opencollective", @@ -1079,11 +1799,11 @@ } ], "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -1096,6 +1816,35 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios-cache-interceptor": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.6.2.tgz", + "integrity": "sha512-YLbAODIHZZIcD4b3WYFVQOa5W2TY/WnJ6sBHqAg6Z+hx+RVj8/OcjQyRopO6awn7/kOkGL5X9TP16AucnlJ/lw==", + "dependencies": { + "cache-parser": "1.2.5", + "fast-defer": "1.1.8", + "object-code": "1.3.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/arthurfiorette/axios-cache-interceptor?sponsor=1" + }, + "peerDependencies": { + "axios": "^1" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1132,9 +1881,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -1150,10 +1899,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1168,6 +1917,11 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "peer": true }, + "node_modules/cache-parser": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.5.tgz", + "integrity": "sha512-Md/4VhAHByQ9frQ15WD6LrMNiVw9AEl/J7vWIXw+sxT6fSOpbtt6LHTp76vy8+bOESPBO94117Hm2bIjlI7XjA==" + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1185,9 +1939,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001628", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001628.tgz", - "integrity": "sha512-S3BnR4Kh26TBxbi5t5kpbcUlLJb9lhtDXISDPwOfI+JoC+ik0QksvkZtUVyikw3hjnkgkMPSJ8oIM9yMm9vflA==", + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", "funding": [ { "type": "opencollective", @@ -1219,37 +1973,18 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "devOptional": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" } }, "node_modules/chrome-trace-event": { @@ -1337,6 +2072,17 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1345,6 +2091,12 @@ "node": ">= 6" } }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1369,6 +2121,17 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1377,6 +2140,26 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "devOptional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1398,20 +2181,15 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.790", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.790.tgz", - "integrity": "sha512-eVGeQxpaBYbomDBa/Mehrs28MdvCXfJmEFzaMFsv8jH/MJDLIylJN81eTJ5kvx7B7p18OiPK0BkC06lydEy63A==" + "version": "1.5.43", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.43.tgz", + "integrity": "sha512-NxnmFBHDl5Sachd2P46O7UJiMaMHMLSofoIWVJq3mj8NJgG0umiSeljAVP9lGzjI0UDLJJ5jjoGjcrB8RSbjLQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, - "node_modules/encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" - }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -1424,10 +2202,21 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-module-lexer": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz", - "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==" + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "node_modules/esbuild": { "version": "0.21.5", @@ -1467,9 +2256,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -1517,6 +2306,11 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -1532,6 +2326,11 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "peer": true }, + "node_modules/fast-defer": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.8.tgz", + "integrity": "sha512-lEJeOH5VL5R09j6AA0D4Uvq7AgsHw0dAImQQ+F3iSyHZuAxyQfWobsagGpTcOPvJr3urmKRHrs+Gs9hV+/Qm/Q==" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -1595,10 +2394,29 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -1610,6 +2428,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -1652,22 +2483,20 @@ } }, "node_modules/glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -1713,6 +2542,21 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "devOptional": true + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1725,11 +2569,14 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1762,11 +2609,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-mobile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-4.0.0.tgz", - "integrity": "sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew==" - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1781,15 +2623,12 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -1827,9 +2666,9 @@ } }, "node_modules/jiti": { - "version": "1.21.3", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.3.tgz", - "integrity": "sha512-uy2bNX5zQ+tESe+TiC7ilGRz8AtRGmnJH55NC5S0nSUjvvvM2hJHmefHErugGXN4pNv4Qx7vLsnNw9qJ9mtIsw==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "bin": { "jiti": "bin/jiti.js" } @@ -1852,9 +2691,9 @@ "integrity": "sha512-M5FimNMXgiOYerVRGsXZ2YK9YNCaTtwtYp7Hb2308U1Q9TXXHx5G0p08mcVR5O53qf8bWY4NJcPBxE6zuayXSg==" }, "node_modules/laravel-vite-plugin": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.4.tgz", - "integrity": "sha512-dEj8Q/Fsn0kKbOQ55bl/NmyJL+dD6OxnVaM/nNByw5XV4b00ky6FzXKVuHLDr4BvSJKH1y6oaOcEG5wKpCZ5+A==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.5.tgz", + "integrity": "sha512-Zv+to82YLBknDCZ6g3iwOv9wZ7f6EWStb9pjSm7MGe9Mfoy5ynT2ssZbGsMr1udU6rDg9HOoYEVGw5Qf+p9zbw==", "dependencies": { "picocolors": "^1.0.0", "vite-plugin-full-reload": "^1.1.0" @@ -1869,10 +2708,14 @@ "vite": "^5.0.0" } }, - "node_modules/lazysizes": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/lazysizes/-/lazysizes-5.3.2.tgz", - "integrity": "sha512-22UzWP+Vedi/sMeOr8O7FWimRVtiNJV2HCa+V8+peZOw6QbswN9k58VUhd7i6iK5bw5QkYrF01LJbeJe0PV8jg==" + "node_modules/laravel-vue-i18n": { + "version": "2.7.7", + "resolved": "https://registry.npmjs.org/laravel-vue-i18n/-/laravel-vue-i18n-2.7.7.tgz", + "integrity": "sha512-rvjRTUY0eYEduEYgyxqNno/5A0ryUQfT+70qYvubMPUxWhmucitUfjDQAQUjvD7WNaUbG5iroAUt3UqBBc5qDw==", + "dependencies": { + "php-parser": "3.1.3", + "vue": "^3.2.45" + } }, "node_modules/leaflet": { "version": "1.9.4", @@ -1949,19 +2792,16 @@ "dev": true }, "node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/merge-stream": { @@ -1994,7 +2834,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true, "engines": { "node": ">= 0.6" } @@ -2003,7 +2842,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -2012,9 +2850,9 @@ } }, "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2033,6 +2871,12 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -2066,10 +2910,16 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "peer": true }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "devOptional": true + }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -2095,6 +2945,11 @@ "node": ">=0.10.0" } }, + "node_modules/object-code": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/object-code/-/object-code-1.3.3.tgz", + "integrity": "sha512-/Ds4Xd5xzrtUOJ+xJQ57iAy0BZsZltOHssnDgcZ8DOhgh41q1YJCnTPnWdWSLkNGNnxYzhYChjc5dgC9mEERCA==" + }, "node_modules/object-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", @@ -2136,6 +2991,17 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2172,10 +3038,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/php-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.1.3.tgz", + "integrity": "sha512-hPvBmnRYPqWEtMfIFOlyjQv1q75UUtxt4U+YscKIQViGmEE2Xa4BuS1B1/cZdjy7MVcwtnr0WkEsr915LgRKOw==" + }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -2196,6 +3067,56 @@ "node": ">=0.10.0" } }, + "node_modules/pinia": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.4.tgz", + "integrity": "sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -2308,9 +3229,9 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "engines": { "node": ">=14" }, @@ -2319,27 +3240,33 @@ } }, "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-nested/node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2367,9 +3294,9 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prettier": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", - "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "bin": { "prettier": "bin/prettier.cjs" }, @@ -2380,6 +3307,30 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/primeicons": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-7.0.0.tgz", + "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" + }, + "node_modules/primevue": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/primevue/-/primevue-4.1.1.tgz", + "integrity": "sha512-FeJkv7FhfePfUBoApW0qAhid6Znq18VgbGFZdmhUcxvOD49Y2Eo/k2Yn7ypPhRbRApWiaSRN0v/2G1I4AMj3xg==", + "dependencies": { + "@primeuix/styled": "^0.2.0", + "@primeuix/utils": "^0.2.0", + "@primevue/core": "4.1.1", + "@primevue/icons": "4.1.1" + }, + "engines": { + "node": ">=12.11.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2390,12 +3341,11 @@ } }, "node_modules/qrcode": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", - "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", "dependencies": { "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, @@ -2443,14 +3393,16 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "devOptional": true, "engines": { - "node": ">=8.10.0" + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/require-directory": { @@ -2492,11 +3444,11 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -2506,22 +3458,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -2567,6 +3519,24 @@ ], "peer": true }, + "node_modules/sass": { + "version": "1.80.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.3.tgz", + "integrity": "sha512-ptDWyVmDMVielpz/oWy3YP3nfs7LpJTHIJZboMVs8GEC9eUmtZTZhMHlTW98wY4aEorDfjN38+Wr/XjskFWcfA==", + "devOptional": true, + "dependencies": { + "@parcel/watcher": "^2.4.1", + "chokidar": "^4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -2586,9 +3556,9 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -2675,6 +3645,11 @@ "node": ">=0.10.0" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -2807,9 +3782,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", - "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -2842,10 +3817,52 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss-primeui": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/tailwindcss-primeui/-/tailwindcss-primeui-0.3.4.tgz", + "integrity": "sha512-5+Qfoe5Kpq2Iwrd6umBUb3rQH6b7+pL4jxJUId0Su5agUM6TwCyH5Pyl9R0y3QQB3IRuTxBNmeS11B41f+30zw==", + "peerDependencies": { + "tailwindcss": ">=3.1.0" + } + }, + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/tailwindcss/node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2854,6 +3871,17 @@ "node": ">=4" } }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -2863,9 +3891,9 @@ } }, "node_modules/terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -2980,9 +4008,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2992,14 +4020,14 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -3015,8 +4043,8 @@ } ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -3040,9 +4068,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/vite": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", - "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -3098,40 +4126,120 @@ } }, "node_modules/vite-plugin-commonjs": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/vite-plugin-commonjs/-/vite-plugin-commonjs-0.10.1.tgz", - "integrity": "sha512-taP8R9kYGlCW5OzkVR0UIWRCnG6rSxeWWuA7tnU5b9t5MniibOnDY219NhisTeDhJAeGT8cEnrhVWZ9A5yD+vg==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/vite-plugin-commonjs/-/vite-plugin-commonjs-0.10.3.tgz", + "integrity": "sha512-trtH4dfAqrbqwiUhSKcqrfjnlXnqLHdIbYuUy943y34JnDjIX8qlpExP0nFN+kE2s6/BS6r9d1cAHS0KtiF4yQ==", "dependencies": { - "acorn": "^8.8.2", - "fast-glob": "^3.2.12", - "magic-string": "^0.30.1", - "vite-plugin-dynamic-import": "^1.5.0" + "acorn": "^8.12.1", + "magic-string": "^0.30.11", + "vite-plugin-dynamic-import": "^1.6.0" } }, "node_modules/vite-plugin-dynamic-import": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/vite-plugin-dynamic-import/-/vite-plugin-dynamic-import-1.5.0.tgz", - "integrity": "sha512-Qp85c+AVJmLa8MLni74U4BDiWpUeFNx7NJqbGZyR2XJOU7mgW0cb7nwlAMucFyM4arEd92Nfxp4j44xPi6Fu7g==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-plugin-dynamic-import/-/vite-plugin-dynamic-import-1.6.0.tgz", + "integrity": "sha512-TM0sz70wfzTIo9YCxVFwS8OA9lNREsh+0vMHGSkWDTZ7bgd1Yjs5RV8EgB634l/91IsXJReg0xtmuQqP0mf+rg==", "dependencies": { - "acorn": "^8.8.2", - "es-module-lexer": "^1.2.1", - "fast-glob": "^3.2.12", - "magic-string": "^0.30.1" + "acorn": "^8.12.1", + "es-module-lexer": "^1.5.4", + "fast-glob": "^3.3.2", + "magic-string": "^0.30.11" } }, "node_modules/vite-plugin-full-reload": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.1.0.tgz", - "integrity": "sha512-3cObNDzX6DdfhD9E7kf6w2mNunFpD7drxyNgHLw+XwIYAgb+Xt16SEXo0Up4VH+TMf3n+DSVJZtW2POBGcBYAA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz", + "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==", "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" } }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/vue": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz", + "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==", + "dependencies": { + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-sfc": "3.5.12", + "@vue/runtime-dom": "3.5.12", + "@vue/server-renderer": "3.5.12", + "@vue/shared": "3.5.12" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-collapsed": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/vue-collapsed/-/vue-collapsed-1.3.4.tgz", + "integrity": "sha512-W92b+QT3n5iTrfrH6kyvx3TsriYPfy/Ymsb6DaanjeMkJYMdVl1S4wzKRYVDsxWQPDxiC+5m+UwPwT/8YAYodA==" + }, + "node_modules/vue-i18n": { + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.1.tgz", + "integrity": "sha512-xjxV0LYc1xQ8TbAVfIyZiOSS8qoU1R0YwV7V5I8I6Fd64+zvsTsdPgtylPsie3Vdt9wekeYhr+smKDeaK6RBuA==", + "dependencies": { + "@intlify/core-base": "9.14.1", + "@intlify/shared": "9.14.1", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.5.tgz", + "integrity": "sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.6.tgz", + "integrity": "sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==", + "dev": true, + "dependencies": { + "@volar/typescript": "~2.4.1", + "@vue/language-core": "2.1.6", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -3142,9 +4250,9 @@ } }, "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "peer": true, "dependencies": { "@types/estree": "^1.0.5", @@ -3302,9 +4410,9 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "node_modules/yaml": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.3.tgz", - "integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index efee3847408..d43f32deaa1 100644 --- a/package.json +++ b/package.json @@ -2,44 +2,64 @@ "private": true, "type": "module", "scripts": { - "check": "tsc --noEmit", + "check": "vue-tsc --noEmit -p tsconfig.json --composite false --skipLibCheck", "dev": "vite", "build": "vite build", - "check-formatting": "prettier --check resources/js/ resources/css/", - "format": "prettier --write resources/js/ resources/css/" + "check-formatting": "prettier --check resources/js/ resources/sass/", + "format": "prettier --write resources/js/ resources/sass/" }, "devDependencies": { "@lychee-org/leaflet.photo": "^1.0.0", + "@popperjs/core": "^2.11.6", "@tailwindcss/typography": "^0.5.12", "@types/alpinejs": "^3.13.6", "@types/leaflet": "^1.9.8", "@types/leaflet-rotatedmarker": "^0.2.5", "@types/leaflet.markercluster": "^1.5.4", "@types/mousetrap": "^1.6.15", + "@types/node": "^20.14.9", "@types/photoswipe": "^4.1.6", - "@types/qrcode": "^1.5.5" + "@types/qrcode": "^1.5.5", + "@types/sprintf-js": "^1.1.4", + "@vitejs/plugin-vue": "^4.5.0", + "sass": "^1.77.6", + "vue-tsc": "^2.0.24" }, "dependencies": { "@fortawesome/fontawesome-free": "^6.5.1", + "@primevue/themes": "^4.0.0-rc.2", + "@sidsbrmnn/scrollspy": "^1.1.0", + "@types/dropbox-chooser": "^1.0.8", "@types/justified-layout": "^4.1.4", - "autoprefixer": "^10.4.17", - "is-mobile": "^4.0.0", + "@vueuse/core": "^11.0.0", + "autoprefixer": "^10.4.19", + "axios": "^1.7.6", + "axios-cache-interceptor": "^1.5.3", "justified-layout": "^4.1.0", "laravel-vite-plugin": "^1.0.1", - "lazysizes": "^5.3.2", + "laravel-vue-i18n": "^2.7.7", "leaflet": "^1.9.4", "leaflet-gpx": "^1.7.0", "leaflet-rotatedmarker": "^0.2.0", "leaflet.markercluster": "^1.5.3", + "pinia": "^2.1.7", "postcss": "^8.4.33", "prettier": "^3.2.4", + "primeicons": "^7.0.0", + "primevue": "^4.0.0-rc.2", "qrcode": "^1.5.3", + "sprintf-js": "^1.1.3", "tailwindcss": "^3.4.1", + "tailwindcss-primeui": "^0.3.4", "tinygesture": "^3.0.0", "ts-loader": "^9.5.1", "typescript": "^5.3.3", "vite": "^5.4.6", - "vite-plugin-commonjs": "^0.10.1" + "vite-plugin-commonjs": "^0.10.1", + "vue": "^3.2.37", + "vue-collapsed": "^1.3.3", + "vue-i18n": "^9.2.0", + "vue-router": "^4.4.0" }, "browserslist": [ "defaults and fully supports es6-module" diff --git a/phpstan.neon b/phpstan.neon index 7538b50fea1..9a92ba42b59 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -39,7 +39,7 @@ parameters: - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::where(Not)?(Null|In|Between|Exists|Column|Year|Month|Day)?\(\).#' - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::delete\(\)#' - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::without\(\)#' - - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::with\(\)#' + # - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::with\(\)#' - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::count\(\).#' - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::update\(\).#' - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::inRandomOrder\(\).#' @@ -50,24 +50,21 @@ parameters: - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::exists\(\).#' - '#Dynamic call to static method App\\Models\\Builders\\.*::orderByDesc\(\).#' - '#Dynamic call to static method App\\Models\\Builders\\.*::selectRaw\(\).#' - - '#Call to an undefined method Illuminate\\Database\\Eloquent\\.*::with(Only)?\(\)#' - - '#Call to an undefined method App\\Relations\\HasManyPhotosRecursively::whereNotNull\(\)#' - - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder|Illuminate\\Database\\Eloquent\\Relations\\Relation::whereNotNull\(\).#' + # - '#Call to an undefined method Illuminate\\Database\\Eloquent\\.*::with(Only)?\(\)#' + # - '#Call to an undefined method App\\Relations\\HasManyPhotosRecursively::whereNotNull\(\)#' + # - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder|Illuminate\\Database\\Eloquent\\Relations\\Relation::whereNotNull\(\).#' - '#Call to protected method asDateTime\(\) of class Illuminate\\Database\\Eloquent\\Model.#' # Covariance - LSP princinple: https://en.wikipedia.org/wiki/Liskov_substitution_principle - - - message: '#Parameter \#1 \$column \(array\|Closure\|Illuminate\\Database\\Query\\Expression\|string\) of method .* should be contravariant with parameter \$column \(array\|\(Closure.*\)\|\(Closure.*\)\|Illuminate\\Contracts\\Database\\Query\\Expression\|string\) of method .*#' - paths: - - app/Eloquent/FixedQueryBuilderTrait.php - - '#Parameter \#1 \$models .* of method .*::initRelation\(\) should be contravariant with parameter \$models .* of method .*::initRelation\(\)#' - - '#Parameter \#(1|2) \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\) should be contravariant with parameter \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\)#' - # - '#Parameter .* of method .*::partition\(\) expects \(callable\(.*\): bool\)\|Illuminate\\Database\\Eloquent\\Model\|string, Closure\(.*\): bool given.#' - - '#Parameter .* of method .*::performInsert\(\) should be contravariant with parameter .* of method .*::performInsert\(\)#' + # - + # message: '#Parameter \#1 \$column \(array\|Closure\|Illuminate\\Database\\Query\\Expression\|string\) of method .* should be contravariant with parameter \$column \(array\|\(Closure.*\)\|\(Closure.*\)\|Illuminate\\Contracts\\Database\\Query\\Expression\|string\) of method .*#' + # paths: + # - app/Eloquent/FixedQueryBuilderTrait.php + # - '#Parameter \#1 \$models .* of method .*::initRelation\(\) should be contravariant with parameter \$models .* of method .*::initRelation\(\)#' + # - '#Parameter \#(1|2) \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\) should be contravariant with parameter \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\)#' - '#Parameter .* of method .*::replicate\(\) should be contravariant with parameter .* of method .*::replicate\(\)#' - '#Parameter .* of method .*::save\(\) should be contravariant with parameter .* of method .*::save\(\)#' - '#Parameter .* of method .*::newEloquentBuilder\(\) should be contravariant with parameter .* of method Kalnoy\\Nestedset\\Node<.*>::newEloquentBuilder\(\)#' - - '#Parameter .* of method .*::performUpdate\(\) should be contravariant with parameter .* of method .*::performUpdate\(\)#' - '#Parameter .* of method .*::isDirty\(\) should be contravariant with parameter .* of method .*::isDirty\(\)#' - '#Call to an undefined( static)? method Kalnoy\\Nestedset\\.*::(whereIn|select|join|leftJoin|orderBy|addSelect|without)\(\)#' @@ -79,21 +76,21 @@ parameters: - '#Dynamic call to static method Illuminate\\Foundation\\Application::getCachedRoutesPath\(\).#' - - '#Access to an undefined property Laragear\\WebAuthn\\Models\\WebAuthnCredential::\$authenticatable_id#' + # - '#Access to an undefined property Laragear\\WebAuthn\\Models\\WebAuthnCredential::\$authenticatable_id#' # False positive as stub code for PHP has not yet been updated to 2nd parameter, see https://github.com/php/doc-en/issues/1529 and https://www.php.net/imagick.writeimagefile - '#Method Imagick::writeImageFile\(\) invoked with 2 parameters, 1 required#' # Synth - - - message: '#Variable property access on .*#' - paths: - - app/Livewire/Synth + # - + # message: '#Variable property access on .*#' + # paths: + # - app/Livewire/Synth - - - message: '#Parameter .* of method App\\Livewire\\Synth\\.* should be contravariant with parameter .* of method Livewire\\Mechanisms\\HandleComponents\\Synthesizers\\Synth::.*#' - paths: - - app/Livewire/Synth + # - + # message: '#Parameter .* of method App\\Livewire\\Synth\\.* should be contravariant with parameter .* of method Livewire\\Mechanisms\\HandleComponents\\Synthesizers\\Synth::.*#' + # paths: + # - app/Livewire/Synth # Migrations - @@ -120,14 +117,14 @@ parameters: message: '#no value type specified in iterable type array.#' paths: - tests - - - message: '#Dynamic call to static method Illuminate\\Testing\\TestResponse::assert(Forbidden|ViewIs|Unauthorized|Ok|Status)#' - paths: - - tests - - - message: '#Call to an undefined method Illuminate\\Testing\\TestResponse::(assert)?(SeeLivewire|dispatch|call|Set|Count)#' - paths: - - tests + # - + # message: '#Dynamic call to static method Illuminate\\Testing\\TestResponse::assert(Forbidden|ViewIs|Unauthorized|Ok|Status)#' + # paths: + # - tests + # - + # message: '#Call to an undefined method Illuminate\\Testing\\TestResponse::(assert)?(SeeLivewire|dispatch|call|Set|Count)#' + # paths: + # - tests - message: '#Dynamic call to static method PHPUnit\\Framework\\Assert::assert(Is)?(Not)?(True|False|Equals|Int|Null|Empty|Count)\(\)#' paths: @@ -156,4 +153,19 @@ parameters: - message: '#Access to private property App\\Models\\Extensions\\SizeVariants::\$(original|small(2x)?|thumb(2x)?|medium(2x)?)#' paths: - - tests \ No newline at end of file + - tests + - + message: '#Call to an undefined method Mockery\\ExpectationInterface\|Mockery\\HigherOrderMessage::once\(\).#' + paths: + - tests + + - + message: '#Parameter \#3 \$fail of method App\\Rules\\.*::validate\(\) expects Closure\(string, string\|null=\): Illuminate\\Translation\\PotentiallyTranslatedString, Closure\(mixed\): void given.#' + paths: + - tests + + - + message: '#Dynamic call to static method Illuminate\\Session\\Store::(has|get|now)\(\).#' + + # Lychee verify + - '#Parameter \#1 \$paths of method .*::addFiles\(\) expects .*Collection, .*Collection given.#' \ No newline at end of file diff --git a/phpunit.ci.xml b/phpunit.ci.xml new file mode 100644 index 00000000000..64c4d6c0fba --- /dev/null +++ b/phpunit.ci.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + ./tests/Unit + + + ./tests/Feature_v1 + ./tests/Feature_v1/Base/BasePhotoTest.php + ./tests/Feature_v1/Base/BasePhotosRotateTest.php + ./tests/Feature_v1/Base/BaseSharingTest.php + ./tests/Feature_v1/LibUnitTests/AlbumsUnitTest.php + ./tests/Feature_v1/LibUnitTests/PhotosUnitTest.php + ./tests/Feature_v1/LibUnitTests/RootAlbumUnitTest.php + ./tests/Feature_v1/LibUnitTests/SessionUnitTest.php + ./tests/Feature_v1/LibUnitTests/SharingUnitTest.php + ./tests/Feature_v1/LibUnitTests/UsersUnitTest.php + + + ./tests/Feature_v2 + ./tests/Feature_v2/Base/BaseApiV2Test.php + ./tests/Feature_v2/Base/BaseV2Test.php + + + + + + + + + + + + + + + + + + + + ./app + + + + diff --git a/phpunit.xml b/phpunit.xml index 075a4bed1ee..3665cc969dd 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,6 +7,9 @@ + + ./tests/Unit + ./tests/Feature_v1 ./tests/Feature_v1/Base/BasePhotoTest.php @@ -19,9 +22,10 @@ ./tests/Feature_v1/LibUnitTests/SharingUnitTest.php ./tests/Feature_v1/LibUnitTests/UsersUnitTest.php - - ./tests/Livewire - ./tests/Livewire/Base/BaseLivewireTest.php + + ./tests/Feature_v2 + ./tests/Feature_v2/Base/BaseApiV2Test.php + ./tests/Feature_v2/Base/BaseV2Test.php @@ -30,6 +34,9 @@ + + + diff --git a/postcss.config.js b/postcss.config.js index d74a73aa69b..906537f6252 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -2,6 +2,6 @@ export default { plugins: { tailwindcss: {}, - autoprefixer: {}, + // autoprefixer: {}, }, } diff --git a/public/.htaccess b/public/.htaccess index d8848926b87..cd25ea6d20c 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -25,7 +25,7 @@ # Ensure that streamed responses are not cached, # because Apache tries to ZIP them - RewriteRule (Album::getArchive|Photo::getArchive|Import::server) - [E=no-gzip:1] + RewriteRule (Album::getArchive|Photo::getArchive|Import::server|Zip) - [E=no-gzip:1] # Send Requests To Front Controller... RewriteCond %{REQUEST_FILENAME} !-d diff --git a/public/dist/custom.js b/public/dist/custom.js deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/public/installer/assets/css/style.css b/public/installer/assets/css/style.css index 5a8b4914ab7..c6019ed57e8 100644 --- a/public/installer/assets/css/style.css +++ b/public/installer/assets/css/style.css @@ -3955,6 +3955,10 @@ input[type=text] { font-size: 16px; } +.ml-4 { + margin-left: 1.5rem; +} + .buttons { text-align: center; } @@ -3978,6 +3982,7 @@ input[type=text] { text-decoration: none; outline: none; border: none; + border-top: 1px solid #eee; -webkit-transition: background-color .2s ease, -webkit-box-shadow .2s ease; transition: box-shadow .2s ease, background-color .2s ease, -webkit-box-shadow .2s ease; cursor: pointer; @@ -3992,7 +3997,6 @@ input[type=text] { } .button--light { - padding: 3px 16px; font-size: 16px; border-top: 1px solid #eee; color: #222; diff --git a/resources/css/app.css b/resources/css/app.css deleted file mode 100644 index 3652a391904..00000000000 --- a/resources/css/app.css +++ /dev/null @@ -1,145 +0,0 @@ -@import "./fonts.css"; -@import "@fortawesome/fontawesome-free/css/all.css"; - -@tailwind base; -/* also contains normalize */ -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --primary-200: #bae6fd; - --primary-300: #7dd3fc; - --primary-400: #38bdf8; - --primary-500: #0ea5e9; - --primary-600: #0284c7; - --primary-700: #0369a1; - - --text-main-0: #ffffff; - --text-main-100: #e5e5e5; - --text-main-200: #d4d4d4; - --text-main-300: #c0c0c0; - --text-main-400: #a3a3a3; - --text-main-800: #262626; - --text-hover: #ffffff; - - --bg-50: #e0e0e0; - --bg-100: #c0c0c0; - --bg-200: #a0a0a0; - --bg-300: #404040; - --bg-400: #383838; - --bg-500: #313131; - --bg-600: #292929; - --bg-700: #212121; - --bg-800: #1a1a1a; - --bg-900: #121212; - --bg-950: #0e0e0e; - - --danger: #dc2626; - --danger-dark: #b91c1c; - --danger-darker: #991b1b; - - --success: #22c55e; - - --create: #16a34a; - --create-dark: #15803d; - - --ready: #fbbf24; - - --warning: #fb923c; - --warning-dark: #ea580c; - } - - html { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - } - - input:focus, - textarea:focus, - select:focus { - outline: none; - } - - /* Remove all ugly outlines */ - * { - outline: 2px solid transparent; - outline-offset: 2px; - } - - [x-cloak] { - display: none !important; - } - - .filter-shadow { - filter: drop-shadow(0 0 0.5rem black); - } - - .menu-shadow { - box-shadow: 3px 3px 8px -2px rgba(0, 0, 0, 0.7); - } - - .box-shadow { - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7); - } - - .text-shadow { - text-shadow: 1px 1px 2px #000; - } - - .text-shadow-sm { - text-shadow: 0 1px 3px #00000066; - } - - .max-wh-full-56 { - max-width: calc(100% - 56px); - max-height: calc(100% - 56px); - } - - input:checked + .slider:before { - transform: translateX(20px); - background-color: #fff; - } - - input:checked + .slider { - background-color: rgb(14 165 233); - } - - input:checked ~ .checkbox svg { - opacity: 1; - -ms-transform: scale(1); - -webkit-transform: scale(1); - transform: scale(1); - } - - .markdown a { - text-underline-offset: 0.2rem; - text-decoration: underline dashed; - } - - /* Trick to change the calendar picker color in chrome */ - ::-webkit-calendar-picker-indicator { - filter: invert(54%) sepia(85%) saturate(2054%) hue-rotate(166deg) brightness(93%) contrast(97%); - } - - .drop-shadow-black { - --tw-drop-shadow: drop-shadow(0 0 1px rgba(0, 0, 0, 0.3)) drop-shadow(0 0 10px rgba(0, 0, 0, 0.3)); - } - - .blurred span { - overflow: hidden; - } - - .blurred img { - /* Safari 6.0 - 9.0 */ - -webkit-filter: blur(5px); - filter: blur(5px); - } - - .aspect-2x3 { - aspect-ratio: 2/3; - } - - .aspect-3x2 { - aspect-ratio: 3/2; - } -} diff --git a/resources/js/app.ts b/resources/js/app.ts index a861ddcf394..7cfe5c52c6e 100644 --- a/resources/js/app.ts +++ b/resources/js/app.ts @@ -1,20 +1,96 @@ -import "lazysizes"; +/** + * First we will load all of this project's JavaScript dependencies which + * includes Vue and other libraries. It is a great starting point when + * building robust, powerful web applications using Vue and Laravel. + */ +import axios from "axios"; +import { createApp } from "vue"; +import { createPinia } from "pinia"; +import PrimeVue from "primevue/config"; +import Ripple from "primevue/ripple"; +import { createRouter, createWebHistory } from "vue-router"; +import { routes } from "@/router/routes"; +import Aura from "@primevue/themes/aura"; +import { i18nVue } from "laravel-vue-i18n"; +import ToastService from "primevue/toastservice"; +import AxiosConfig from "@/config/axios-config"; +import AppComponent from "@/views/App.vue"; +import { definePreset } from "@primevue/themes"; +import LycheePrimeVueConfig from "./style/preset"; +import FocusTrap from "primevue/focustrap"; +import Tooltip from "primevue/tooltip"; -import { webauthn } from "./data/webauthn"; -import { views } from "./data/views"; -import { panels } from "./data/panel"; -import { qrBuilder } from "./data/qrcode/qrBuilder"; +declare global { + var assets_url: string; +} -// suggested in the Alpine docs: -// make Alpine on window available for better DX -window.Alpine = Alpine; +// @ts-expect-error +window.axios = axios; +// @ts-expect-error +window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest"; -document.addEventListener("alpine:init", () => { - [...webauthn, ...views, ...panels].forEach(Alpine.plugin); - Alpine.plugin(qrBuilder); +const router = createRouter({ + history: createWebHistory(), + routes, +}); + +const LycheePreset = definePreset(Aura, LycheePrimeVueConfig); + +const pinia = createPinia(); - Alpine.store("photo", undefined); - Alpine.store("photos", []); - Alpine.store("photoIDs", []); - Alpine.store("albumIDs", []); +/** + * Next, we will create a fresh Vue application instance. You may then begin + * registering components with the application instance so they are ready + * to use in your application's views. An example is included for you. + */ +const app = createApp({}); +app.config.globalProperties.window = window; +app.use(pinia); +app.use(PrimeVue, { + ripple: true, + theme: { + preset: LycheePreset, + options: { + // cssLayer: false, + cssLayer: { + name: "primevue", + order: "tailwind-base, primevue, tailwind-utilities", + }, + darkModeSelector: ".dark", + }, + }, }); +app.directive("ripple", Ripple); +app.directive("focustrap", FocusTrap); +app.directive("tooltip", Tooltip); + +app.component("app", AppComponent); +app.use(router); +app.use(ToastService); + +/** + * The following block of code may be used to automatically register your + * Vue components. It will recursively scan this directory for the Vue + * components and automatically register them with their "basename". + * + * Eg. ./components/ExampleComponent.vue -> + */ + +app.use(i18nVue, { + resolve: async (lang: string) => { + if (!lang.startsWith("php")) { + lang = "php_" + lang; + } + // @ts-expect-error + const langs = import.meta.glob("../../lang/*.json"); + return await langs[`../../lang/${lang}.json`](); + }, +}); + +/** + * Finally, we will attach the application instance to a HTML element with + * an "id" attribute of "app". + */ +app.mount("#app"); + +AxiosConfig.axiosSetUp(); diff --git a/resources/js/components/diagnostics/ConfigurationsDiagnostics.vue b/resources/js/components/diagnostics/ConfigurationsDiagnostics.vue new file mode 100644 index 00000000000..ff4db3a6a18 --- /dev/null +++ b/resources/js/components/diagnostics/ConfigurationsDiagnostics.vue @@ -0,0 +1,21 @@ + + diff --git a/resources/js/components/diagnostics/ErrorsDiagnostics.vue b/resources/js/components/diagnostics/ErrorsDiagnostics.vue new file mode 100644 index 00000000000..e64581967c6 --- /dev/null +++ b/resources/js/components/diagnostics/ErrorsDiagnostics.vue @@ -0,0 +1,40 @@ + + diff --git a/resources/js/components/diagnostics/InfoDiagnostics.vue b/resources/js/components/diagnostics/InfoDiagnostics.vue new file mode 100644 index 00000000000..913f5f0aa64 --- /dev/null +++ b/resources/js/components/diagnostics/InfoDiagnostics.vue @@ -0,0 +1,21 @@ + + diff --git a/resources/js/components/diagnostics/SpaceDiagnostics.vue b/resources/js/components/diagnostics/SpaceDiagnostics.vue new file mode 100644 index 00000000000..643b68999a7 --- /dev/null +++ b/resources/js/components/diagnostics/SpaceDiagnostics.vue @@ -0,0 +1,24 @@ + + diff --git a/resources/js/components/drawers/AlbumEdit.vue b/resources/js/components/drawers/AlbumEdit.vue new file mode 100644 index 00000000000..b4503863219 --- /dev/null +++ b/resources/js/components/drawers/AlbumEdit.vue @@ -0,0 +1,99 @@ + + diff --git a/resources/js/components/drawers/AlbumStatistics.vue b/resources/js/components/drawers/AlbumStatistics.vue new file mode 100644 index 00000000000..fbf5cd3c27b --- /dev/null +++ b/resources/js/components/drawers/AlbumStatistics.vue @@ -0,0 +1,116 @@ + + diff --git a/resources/js/components/drawers/PhotoDetails.vue b/resources/js/components/drawers/PhotoDetails.vue new file mode 100644 index 00000000000..9a2e08ab303 --- /dev/null +++ b/resources/js/components/drawers/PhotoDetails.vue @@ -0,0 +1,120 @@ + + diff --git a/resources/js/components/drawers/PhotoEdit.vue b/resources/js/components/drawers/PhotoEdit.vue new file mode 100644 index 00000000000..6d9ea2e9817 --- /dev/null +++ b/resources/js/components/drawers/PhotoEdit.vue @@ -0,0 +1,141 @@ +