From 97c0368fa2b1a04fa875dea5757c6a5f6e02f86c Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Thu, 7 Dec 2023 20:12:23 -0500 Subject: [PATCH] chore: first commit --- .editorconfig | 21 + .env.dusk.ci | 59 + .env.example | 59 + .eslintignore | 1 + .eslintrc.yml | 38 + .gitattributes | 11 + .github/workflows/dusk.yml | 64 + .github/workflows/semantic.yml | 15 + .github/workflows/static.yml | 79 + .github/workflows/tests.yml | 125 + .gitignore | 21 + .php-cs-fixer.dist.php | 44 + .phpcs.xml.dist | 12 + LICENSE.md | 21 + README.md | 28 + app/Console/Commands/LocalizeApplication.php | 81 + app/Console/Commands/SetupDummyAccount.php | 132 + app/Console/Kernel.php | 27 + app/Exceptions/Handler.php | 30 + app/Helpers/helpers.php | 11 + .../Auth/AuthenticatedSessionController.php | 48 + .../Auth/ConfirmablePasswordController.php | 41 + ...mailVerificationNotificationController.php | 25 + .../EmailVerificationPromptController.php | 22 + .../Auth/NewPasswordController.php | 61 + .../Controllers/Auth/PasswordController.php | 29 + .../Auth/PasswordResetLinkController.php | 44 + .../Auth/RegisteredUserController.php | 54 + .../Auth/VerifyEmailController.php | 28 + app/Http/Controllers/Controller.php | 12 + app/Http/Controllers/LocaleController.php | 19 + app/Http/Controllers/ProfileController.php | 60 + .../Settings/SettingsController.php | 14 + .../Settings/SettingsLevelController.php | 96 + .../Settings/SettingsProfileController.php | 14 + .../Settings/SettingsRoleController.php | 96 + app/Http/Kernel.php | 70 + app/Http/Middleware/Authenticate.php | 17 + .../Middleware/CheckAdministratorRole.php | 28 + app/Http/Middleware/EncryptCookies.php | 17 + app/Http/Middleware/Locale.php | 33 + .../PreventRequestsDuringMaintenance.php | 17 + .../Middleware/RedirectIfAuthenticated.php | 30 + app/Http/Middleware/TrimStrings.php | 19 + app/Http/Middleware/TrustHosts.php | 20 + app/Http/Middleware/TrustProxies.php | 28 + app/Http/Middleware/ValidateSignature.php | 22 + app/Http/Middleware/VerifyCsrfToken.php | 17 + app/Http/Requests/Auth/LoginRequest.php | 85 + app/Http/Requests/ProfileUpdateRequest.php | 23 + .../Settings/SettingsLevelViewModel.php | 28 + .../Settings/SettingsRoleViewModel.php | 28 + app/Jobs/PopulateAccount.php | 79 + app/Models/Level.php | 31 + app/Models/Organization.php | 29 + app/Models/Role.php | 34 + app/Models/User.php | 63 + app/Providers/AppServiceProvider.php | 24 + app/Providers/AuthServiceProvider.php | 26 + app/Providers/BroadcastServiceProvider.php | 19 + app/Providers/EventServiceProvider.php | 38 + app/Providers/RouteServiceProvider.php | 40 + app/Services/BaseService.php | 36 + app/Services/CreateAccount.php | 56 + app/Services/CreateLevel.php | 41 + app/Services/CreateRole.php | 41 + app/Services/DestroyLevel.php | 44 + app/Services/DestroyRole.php | 44 + app/Services/UpdateLevel.php | 49 + app/Services/UpdateRole.php | 49 + app/Traits/Translatable.php | 28 + app/View/Components/AppLayout.php | 17 + app/View/Components/GuestLayout.php | 17 + artisan | 53 + bootstrap/app.php | 55 + bootstrap/cache/.gitignore | 2 + bun.lockb | Bin 0 -> 87201 bytes composer.json | 79 + composer.lock | 12038 ++++++++++++++++ config/app.php | 188 + config/auth.php | 115 + config/broadcasting.php | 71 + config/cache.php | 111 + config/cors.php | 34 + config/database.php | 176 + config/filesystems.php | 81 + config/hashing.php | 54 + config/localizator.php | 59 + config/localizer.php | 88 + config/logging.php | 131 + config/mail.php | 126 + config/queue.php | 109 + config/sanctum.php | 83 + config/services.php | 34 + config/session.php | 201 + config/view.php | 36 + database/.gitignore | 1 + database/factories/LevelFactory.php | 26 + database/factories/OrganizationFactory.php | 23 + database/factories/RoleFactory.php | 26 + database/factories/UserFactory.php | 47 + ...4_13_002417_create_organizations_table.php | 18 + .../2014_10_12_000000_create_users_table.php | 30 + ...000_create_password_reset_tokens_table.php | 28 + ..._08_19_000000_create_failed_jobs_table.php | 32 + ...01_create_personal_access_tokens_table.php | 33 + .../2023_11_13_200951_create_roles_table.php | 32 + database/seeders/DatabaseSeeder.php | 22 + lang/fr.json | 110 + lang/fr/auth.php | 7 + package.json | 26 + phpstan.neon | 22 + phpunit.xml | 33 + pint.json | 45 + postcss.config.js | 6 + psalm.xml | 18 + public/.htaccess | 21 + public/favicon.ico | 0 public/index.php | 55 + public/robots.txt | 2 + resources/css/app.css | 3 + resources/js/app.js | 11 + resources/js/bootstrap.js | 32 + .../views/auth/confirm-password.blade.php | 32 + .../views/auth/forgot-password.blade.php | 36 + resources/views/auth/login.blade.php | 69 + resources/views/auth/register.blade.php | 115 + resources/views/auth/reset-password.blade.php | 63 + resources/views/auth/verify-email.blade.php | 36 + .../components/application-logo.blade.php | 14 + .../views/components/danger-button.blade.php | 3 + .../views/components/dropdown-link.blade.php | 1 + resources/views/components/dropdown.blade.php | 46 + resources/views/components/help.blade.php | 6 + .../views/components/htmx-link.blade.php | 1 + .../views/components/input-error.blade.php | 9 + .../views/components/input-help.blade.php | 5 + .../views/components/input-label.blade.php | 5 + resources/views/components/link.blade.php | 3 + resources/views/components/modal.blade.php | 67 + resources/views/components/nav-link.blade.php | 9 + .../views/components/primary-button.blade.php | 3 + .../views/components/primary-link.blade.php | 1 + .../components/responsive-nav-link.blade.php | 9 + .../components/secondary-button.blade.php | 3 + .../views/components/session-status.blade.php | 7 + .../views/components/text-input.blade.php | 6 + resources/views/dashboard.blade.php | 17 + resources/views/layouts/app.blade.php | 49 + resources/views/layouts/guest.blade.php | 35 + resources/views/layouts/navigation.blade.php | 106 + resources/views/profile/edit.blade.php | 29 + .../partials/delete-user-form.blade.php | 58 + .../partials/update-password-form.blade.php | 66 + .../update-profile-information-form.blade.php | 84 + resources/views/settings/index.blade.php | 26 + resources/views/settings/level/edit.blade.php | 54 + .../views/settings/level/index.blade.php | 32 + resources/views/settings/level/new.blade.php | 52 + .../settings/level/partials/index.blade.php | 24 + .../views/settings/profile/index.blade.php | 78 + resources/views/settings/role/edit.blade.php | 54 + resources/views/settings/role/index.blade.php | 32 + resources/views/settings/role/new.blade.php | 52 + .../settings/role/partials/index.blade.php | 24 + resources/views/welcome.blade.php | 1031 ++ routes/api.php | 19 + routes/auth.php | 59 + routes/channels.php | 18 + routes/console.php | 19 + routes/web.php | 51 + storage/app/.gitignore | 3 + storage/app/public/.gitignore | 2 + storage/debugbar/.gitignore | 2 + storage/framework/.gitignore | 9 + storage/framework/cache/.gitignore | 3 + storage/framework/cache/data/.gitignore | 2 + storage/framework/sessions/.gitignore | 2 + storage/framework/testing/.gitignore | 2 + storage/framework/views/.gitignore | 2 + storage/logs/.gitignore | 2 + tailwind.config.js | 23 + tests/.env.ci.mysql | 26 + tests/.env.ci.pgsql | 26 + tests/Browser/ExampleTest.php | 22 + tests/Browser/LocaleTest.php | 21 + tests/Browser/Pages/HomePage.php | 36 + tests/Browser/Pages/Page.php | 20 + tests/Browser/SettingsRolesAndLevelsTest.php | 105 + tests/Browser/console/.gitignore | 2 + tests/Browser/screenshots/.gitignore | 2 + tests/Browser/source/.gitignore | 2 + tests/CreatesApplication.php | 21 + tests/DuskTestCase.php | 66 + tests/Feature/Auth/AuthenticationTest.php | 67 + tests/Feature/Auth/EmailVerificationTest.php | 74 + .../Feature/Auth/PasswordConfirmationTest.php | 53 + tests/Feature/Auth/PasswordResetTest.php | 83 + tests/Feature/Auth/PasswordUpdateTest.php | 57 + tests/Feature/Auth/RegistrationTest.php | 40 + tests/Feature/ProfileTest.php | 89 + tests/Feature/Settings/ManageLevelTest.php | 104 + tests/Feature/Settings/ManageRoleTest.php | 104 + tests/TestCase.php | 10 + tests/Unit/Jobs/PopulateAccountTest.php | 31 + tests/Unit/Models/LevelTest.php | 19 + tests/Unit/Models/OrganizationTest.php | 32 + tests/Unit/Models/RoleTest.php | 19 + tests/Unit/Models/UserTest.php | 24 + tests/Unit/Services/CreateAccountTest.php | 56 + tests/Unit/Services/CreateLevelTest.php | 51 + tests/Unit/Services/CreateRoleTest.php | 51 + tests/Unit/Services/DestroyLevelTest.php | 63 + tests/Unit/Services/DestroyRoleTest.php | 63 + tests/Unit/Services/UpdateLevelTest.php | 71 + tests/Unit/Services/UpdateRoleTest.php | 71 + tests/Unit/Traits/TranslatableTest.php | 36 + .../Settings/SettingsLevelViewModelTest.php | 44 + .../Settings/SettingsRoleViewModelTest.php | 44 + tlint.json | 10 + vite.config.js | 12 + 221 files changed, 21859 insertions(+) create mode 100644 .editorconfig create mode 100644 .env.dusk.ci create mode 100644 .env.example create mode 100644 .eslintignore create mode 100644 .eslintrc.yml create mode 100644 .gitattributes create mode 100644 .github/workflows/dusk.yml create mode 100644 .github/workflows/semantic.yml create mode 100644 .github/workflows/static.yml create mode 100644 .github/workflows/tests.yml create mode 100644 .gitignore create mode 100644 .php-cs-fixer.dist.php create mode 100644 .phpcs.xml.dist create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 app/Console/Commands/LocalizeApplication.php create mode 100644 app/Console/Commands/SetupDummyAccount.php create mode 100644 app/Console/Kernel.php create mode 100644 app/Exceptions/Handler.php create mode 100644 app/Helpers/helpers.php create mode 100644 app/Http/Controllers/Auth/AuthenticatedSessionController.php create mode 100644 app/Http/Controllers/Auth/ConfirmablePasswordController.php create mode 100644 app/Http/Controllers/Auth/EmailVerificationNotificationController.php create mode 100644 app/Http/Controllers/Auth/EmailVerificationPromptController.php create mode 100644 app/Http/Controllers/Auth/NewPasswordController.php create mode 100644 app/Http/Controllers/Auth/PasswordController.php create mode 100644 app/Http/Controllers/Auth/PasswordResetLinkController.php create mode 100644 app/Http/Controllers/Auth/RegisteredUserController.php create mode 100644 app/Http/Controllers/Auth/VerifyEmailController.php create mode 100644 app/Http/Controllers/Controller.php create mode 100644 app/Http/Controllers/LocaleController.php create mode 100644 app/Http/Controllers/ProfileController.php create mode 100644 app/Http/Controllers/Settings/SettingsController.php create mode 100644 app/Http/Controllers/Settings/SettingsLevelController.php create mode 100644 app/Http/Controllers/Settings/SettingsProfileController.php create mode 100644 app/Http/Controllers/Settings/SettingsRoleController.php create mode 100644 app/Http/Kernel.php create mode 100644 app/Http/Middleware/Authenticate.php create mode 100644 app/Http/Middleware/CheckAdministratorRole.php create mode 100644 app/Http/Middleware/EncryptCookies.php create mode 100644 app/Http/Middleware/Locale.php create mode 100644 app/Http/Middleware/PreventRequestsDuringMaintenance.php create mode 100644 app/Http/Middleware/RedirectIfAuthenticated.php create mode 100644 app/Http/Middleware/TrimStrings.php create mode 100644 app/Http/Middleware/TrustHosts.php create mode 100644 app/Http/Middleware/TrustProxies.php create mode 100644 app/Http/Middleware/ValidateSignature.php create mode 100644 app/Http/Middleware/VerifyCsrfToken.php create mode 100644 app/Http/Requests/Auth/LoginRequest.php create mode 100644 app/Http/Requests/ProfileUpdateRequest.php create mode 100644 app/Http/ViewModels/Settings/SettingsLevelViewModel.php create mode 100644 app/Http/ViewModels/Settings/SettingsRoleViewModel.php create mode 100644 app/Jobs/PopulateAccount.php create mode 100644 app/Models/Level.php create mode 100644 app/Models/Organization.php create mode 100644 app/Models/Role.php create mode 100644 app/Models/User.php create mode 100644 app/Providers/AppServiceProvider.php create mode 100644 app/Providers/AuthServiceProvider.php create mode 100644 app/Providers/BroadcastServiceProvider.php create mode 100644 app/Providers/EventServiceProvider.php create mode 100644 app/Providers/RouteServiceProvider.php create mode 100644 app/Services/BaseService.php create mode 100644 app/Services/CreateAccount.php create mode 100644 app/Services/CreateLevel.php create mode 100644 app/Services/CreateRole.php create mode 100644 app/Services/DestroyLevel.php create mode 100644 app/Services/DestroyRole.php create mode 100644 app/Services/UpdateLevel.php create mode 100644 app/Services/UpdateRole.php create mode 100644 app/Traits/Translatable.php create mode 100644 app/View/Components/AppLayout.php create mode 100644 app/View/Components/GuestLayout.php create mode 100755 artisan create mode 100644 bootstrap/app.php create mode 100644 bootstrap/cache/.gitignore create mode 100755 bun.lockb create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/app.php create mode 100644 config/auth.php create mode 100644 config/broadcasting.php create mode 100644 config/cache.php create mode 100644 config/cors.php create mode 100644 config/database.php create mode 100644 config/filesystems.php create mode 100644 config/hashing.php create mode 100644 config/localizator.php create mode 100644 config/localizer.php create mode 100644 config/logging.php create mode 100644 config/mail.php create mode 100644 config/queue.php create mode 100644 config/sanctum.php create mode 100644 config/services.php create mode 100644 config/session.php create mode 100644 config/view.php create mode 100644 database/.gitignore create mode 100644 database/factories/LevelFactory.php create mode 100644 database/factories/OrganizationFactory.php create mode 100644 database/factories/RoleFactory.php create mode 100644 database/factories/UserFactory.php create mode 100644 database/migrations/2014_04_13_002417_create_organizations_table.php create mode 100644 database/migrations/2014_10_12_000000_create_users_table.php create mode 100644 database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php create mode 100644 database/migrations/2019_08_19_000000_create_failed_jobs_table.php create mode 100644 database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php create mode 100644 database/migrations/2023_11_13_200951_create_roles_table.php create mode 100644 database/seeders/DatabaseSeeder.php create mode 100644 lang/fr.json create mode 100644 lang/fr/auth.php create mode 100644 package.json create mode 100644 phpstan.neon create mode 100644 phpunit.xml create mode 100644 pint.json create mode 100644 postcss.config.js create mode 100644 psalm.xml create mode 100644 public/.htaccess create mode 100644 public/favicon.ico create mode 100644 public/index.php create mode 100644 public/robots.txt create mode 100644 resources/css/app.css create mode 100644 resources/js/app.js create mode 100644 resources/js/bootstrap.js create mode 100644 resources/views/auth/confirm-password.blade.php create mode 100644 resources/views/auth/forgot-password.blade.php create mode 100644 resources/views/auth/login.blade.php create mode 100644 resources/views/auth/register.blade.php create mode 100644 resources/views/auth/reset-password.blade.php create mode 100644 resources/views/auth/verify-email.blade.php create mode 100644 resources/views/components/application-logo.blade.php create mode 100644 resources/views/components/danger-button.blade.php create mode 100644 resources/views/components/dropdown-link.blade.php create mode 100644 resources/views/components/dropdown.blade.php create mode 100644 resources/views/components/help.blade.php create mode 100644 resources/views/components/htmx-link.blade.php create mode 100644 resources/views/components/input-error.blade.php create mode 100644 resources/views/components/input-help.blade.php create mode 100644 resources/views/components/input-label.blade.php create mode 100644 resources/views/components/link.blade.php create mode 100644 resources/views/components/modal.blade.php create mode 100644 resources/views/components/nav-link.blade.php create mode 100644 resources/views/components/primary-button.blade.php create mode 100644 resources/views/components/primary-link.blade.php create mode 100644 resources/views/components/responsive-nav-link.blade.php create mode 100644 resources/views/components/secondary-button.blade.php create mode 100644 resources/views/components/session-status.blade.php create mode 100644 resources/views/components/text-input.blade.php create mode 100644 resources/views/dashboard.blade.php create mode 100644 resources/views/layouts/app.blade.php create mode 100644 resources/views/layouts/guest.blade.php create mode 100644 resources/views/layouts/navigation.blade.php create mode 100644 resources/views/profile/edit.blade.php create mode 100644 resources/views/profile/partials/delete-user-form.blade.php create mode 100644 resources/views/profile/partials/update-password-form.blade.php create mode 100644 resources/views/profile/partials/update-profile-information-form.blade.php create mode 100644 resources/views/settings/index.blade.php create mode 100644 resources/views/settings/level/edit.blade.php create mode 100644 resources/views/settings/level/index.blade.php create mode 100644 resources/views/settings/level/new.blade.php create mode 100644 resources/views/settings/level/partials/index.blade.php create mode 100644 resources/views/settings/profile/index.blade.php create mode 100644 resources/views/settings/role/edit.blade.php create mode 100644 resources/views/settings/role/index.blade.php create mode 100644 resources/views/settings/role/new.blade.php create mode 100644 resources/views/settings/role/partials/index.blade.php create mode 100644 resources/views/welcome.blade.php create mode 100644 routes/api.php create mode 100644 routes/auth.php create mode 100644 routes/channels.php create mode 100644 routes/console.php create mode 100644 routes/web.php create mode 100644 storage/app/.gitignore create mode 100644 storage/app/public/.gitignore create mode 100644 storage/debugbar/.gitignore create mode 100644 storage/framework/.gitignore create mode 100644 storage/framework/cache/.gitignore create mode 100644 storage/framework/cache/data/.gitignore create mode 100644 storage/framework/sessions/.gitignore create mode 100644 storage/framework/testing/.gitignore create mode 100644 storage/framework/views/.gitignore create mode 100644 storage/logs/.gitignore create mode 100644 tailwind.config.js create mode 100644 tests/.env.ci.mysql create mode 100644 tests/.env.ci.pgsql create mode 100644 tests/Browser/ExampleTest.php create mode 100644 tests/Browser/LocaleTest.php create mode 100644 tests/Browser/Pages/HomePage.php create mode 100644 tests/Browser/Pages/Page.php create mode 100644 tests/Browser/SettingsRolesAndLevelsTest.php create mode 100644 tests/Browser/console/.gitignore create mode 100644 tests/Browser/screenshots/.gitignore create mode 100644 tests/Browser/source/.gitignore create mode 100644 tests/CreatesApplication.php create mode 100644 tests/DuskTestCase.php create mode 100644 tests/Feature/Auth/AuthenticationTest.php create mode 100644 tests/Feature/Auth/EmailVerificationTest.php create mode 100644 tests/Feature/Auth/PasswordConfirmationTest.php create mode 100644 tests/Feature/Auth/PasswordResetTest.php create mode 100644 tests/Feature/Auth/PasswordUpdateTest.php create mode 100644 tests/Feature/Auth/RegistrationTest.php create mode 100644 tests/Feature/ProfileTest.php create mode 100644 tests/Feature/Settings/ManageLevelTest.php create mode 100644 tests/Feature/Settings/ManageRoleTest.php create mode 100644 tests/TestCase.php create mode 100644 tests/Unit/Jobs/PopulateAccountTest.php create mode 100644 tests/Unit/Models/LevelTest.php create mode 100644 tests/Unit/Models/OrganizationTest.php create mode 100644 tests/Unit/Models/RoleTest.php create mode 100644 tests/Unit/Models/UserTest.php create mode 100644 tests/Unit/Services/CreateAccountTest.php create mode 100644 tests/Unit/Services/CreateLevelTest.php create mode 100644 tests/Unit/Services/CreateRoleTest.php create mode 100644 tests/Unit/Services/DestroyLevelTest.php create mode 100644 tests/Unit/Services/DestroyRoleTest.php create mode 100644 tests/Unit/Services/UpdateLevelTest.php create mode 100644 tests/Unit/Services/UpdateRoleTest.php create mode 100644 tests/Unit/Traits/TranslatableTest.php create mode 100644 tests/Unit/ViewModels/Settings/SettingsLevelViewModelTest.php create mode 100644 tests/Unit/ViewModels/Settings/SettingsRoleViewModelTest.php create mode 100644 tlint.json create mode 100644 vite.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..897c96a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 + +[*.blade.php] +indent_size = 2 + +[*.{js,vue,scss,json,css}] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[*.yml] +indent_size = 2 diff --git a/.env.dusk.ci b/.env.dusk.ci new file mode 100644 index 0000000..c8ae74b --- /dev/null +++ b/.env.dusk.ci @@ -0,0 +1,59 @@ +APP_NAME=Shelter +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://127.0.0.1:8000 + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=shelter +DB_USERNAME=root +DB_PASSWORD= + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a757472 --- /dev/null +++ b/.env.example @@ -0,0 +1,59 @@ +APP_NAME=Shelter +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=shelter +DB_USERNAME=root +DB_PASSWORD= + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..d5feb21 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +/resources/js/app.js diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..7b2d14c --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,38 @@ +env: + browser: true + es2021: true +extends: + - eslint:recommended + - prettier +parserOptions: + ecmaVersion: latest + sourceType: module +plugins: + - simple-import-sort +rules: + array-bracket-spacing: + - error + - never + indent: + - error + - 2 + linebreak-style: + - error + - unix + no-undef: 0 + no-trailing-spaces: + - error + - ignoreComments: true + skipBlankLines: true + semi: + - error + - always + semi-spacing: + - error + - after: true + before: false + semi-style: + - error + - last + simple-import-sort/imports: + - error diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcb21d3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +CHANGELOG.md export-ignore +.styleci.yml export-ignore diff --git a/.github/workflows/dusk.yml b/.github/workflows/dusk.yml new file mode 100644 index 0000000..e4cea9d --- /dev/null +++ b/.github/workflows/dusk.yml @@ -0,0 +1,64 @@ +name: E2E tests + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize, reopened] + release: + types: [created] + +jobs: + + dusk-php: + name: Dusk + runs-on: ubuntu-latest + env: + APP_URL: "http://127.0.0.1:8000" + DB_USERNAME: root + DB_PASSWORD: root + MAIL_MAILER: log + steps: + - uses: actions/checkout@v4 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + extensions: mbstring, dom, fileinfo, mysql + coverage: none + - name: Prepare The Environment + run: cp .env.dusk.ci .env + - name: Create Database + run: | + sudo systemctl start mysql + mysql --user="root" --password="root" -e "CREATE DATABASE \`shelter\` character set UTF8mb4 collate utf8mb4_bin;" + - name: Install Composer Dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Generate Application Key + run: php artisan key:generate + - name: Run migrations + run: php artisan migrate --no-interaction -vvv + - name: Install dependencies + run: yarn install + - name: Build assets + run: yarn build + - name: Upgrade Chrome Driver + run: php artisan dusk:chrome-driver --detect + - name: Start Chrome Driver + run: ./vendor/laravel/dusk/bin/chromedriver-linux & + - name: Run Laravel Server + run: php artisan serve --no-reload & + - name: Run Dusk Tests + run: php artisan dusk + - name: Upload Screenshots + if: failure() + uses: actions/upload-artifact@v2 + with: + name: screenshots + path: tests/Browser/screenshots + - name: Upload Console Logs + if: failure() + uses: actions/upload-artifact@v2 + with: + name: console + path: tests/Browser/console diff --git a/.github/workflows/semantic.yml b/.github/workflows/semantic.yml new file mode 100644 index 0000000..0d90b44 --- /dev/null +++ b/.github/workflows/semantic.yml @@ -0,0 +1,15 @@ +name: Lint PR + +on: + pull_request: + types: [opened, edited, synchronize] + + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000..02ffded --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,79 @@ +name: Static analysis + +on: + pull_request: + types: [opened, synchronize, reopened] + +env: + php-version: '8.2' + +concurrency: + group: Static ${{ github.ref }} + cancel-in-progress: true + +jobs: + psalm: + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Setup PHP ${{ env.php-version }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.php-version }} + coverage: none + + # Composer + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer files + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ env.php-version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ env.php-version }}-${{ hashFiles('**/composer.lock') }} + ${{ runner.os }}-composer-${{ env.php-version }} + ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + + - name: Run psalm + run: vendor/bin/psalm --output-format=github + + phpstan: + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Setup PHP ${{ env.php-version }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.php-version }} + coverage: none + + # Composer + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer files + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ env.php-version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ env.php-version }}-${{ hashFiles('**/composer.lock') }} + ${{ runner.os }}-composer-${{ env.php-version }} + ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + + - name: Run phpstan + run: vendor/bin/phpstan analyse diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..01e30c7 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,125 @@ +name: Unit tests + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize, reopened] + release: + types: [created] + +env: + default-php-version: '8.2' + coverage-with: sqlite + +concurrency: + group: Build ${{ github.ref }} + cancel-in-progress: true + + +jobs: + ############# + # Run tests + ############# + tests: + runs-on: ubuntu-latest + name: PHP ${{ matrix.php-version }} + ${{ matrix.connection }} + + strategy: + fail-fast: false + matrix: + php-version: ['8.2'] + connection: [sqlite, mysql] + testsuite: [Unit] + coverage: [true] # run test with coverage, if 'coverage-with' match with the connection + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Setup PHP ${{ matrix.php-version }} without coverage + if: matrix.connection != env.coverage-with || matrix.php-version != env.default-php-version || ! matrix.coverage + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, dom, fileinfo, ${{ matrix.connection }} + coverage: none + - name: Setup PHP ${{ matrix.php-version }} + if: matrix.connection == env.coverage-with && matrix.php-version == env.default-php-version && matrix.coverage + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, dom, fileinfo, ${{ matrix.connection }} + coverage: pcov + ini-values: pcov.directory=., pcov.exclude="~vendor~" + - name: Check PHP Version + run: php -v + - name: Check Composer Version + run: composer -V + - name: Check PHP Extensions + run: php -m + + # Composer + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer files + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }} + ${{ runner.os }}-composer-${{ matrix.php-version }} + ${{ runner.os }}-composer- + + - name: Install composer dependencies + run: composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + + # Prepare + - name: Prepare environment + run: | + cp tests/.env.ci.${{ matrix.connection }} .env + mkdir -p public/build/assets + {\ + echo "{"; \ + for f in app.js app.css; do \ + [[ $first == 1 ]] && echo -n "," || first=1; \ + k=${f##*.}/$f; \ + echo "\"resources/$k\": {\"file\": \"assets/$f\", \"src\": \"resources/$k\"}"; \ + echo '' > public/build/assets/$f; \ + done; \ + echo "}"; \ + } | tee public/build/manifest.json + - name: Create sqlite database + if: matrix.connection == 'sqlite' + run: touch database/database.sqlite + - name: Create mysql database + if: matrix.connection == 'mysql' + run: | + sudo systemctl start mysql.service + mysql --protocol=tcp -u root -proot -e "CREATE DATABASE IF NOT EXISTS bivouac CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" + - name: Create pgsql database + if: matrix.connection == 'pgsql' + run: | + sudo systemctl start postgresql.service + sudo -u postgres psql --command="CREATE USER bivouac PASSWORD 'secret'" --command="\du" + sudo -u postgres createdb --owner=bivouac bivouac + PGPASSWORD=secret psql --username=bivouac --host=localhost --list bivouac + + - name: Generate key + run: php artisan key:generate + + - name: Run migrations + run: php artisan migrate --no-interaction -vvv + - name: Run seeds + run: php artisan db:seed --no-interaction -vvv + + # Test + - name: Run tests + run: vendor/bin/phpunit + env: + DB_CONNECTION: ${{ matrix.connection }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..77a5497 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +/.phpunit.cache +/node_modules +/public/build +/public/hot +/public/storage +/storage/*.key +/vendor +.env +.env.backup +.env.production +.phpunit.result.cache +Homestead.json +Homestead.yaml +auth.json +npm-debug.log +yarn-error.log +/.fleet +/.idea +/.vscode +.DS_Store +*.sqlite diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..16e556a --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,44 @@ +setFinder(PhpCsFixer::getFinder()) + ->setUsingCache(false) + ->registerCustomFixers([ + new CustomControllerOrderFixer(), + new CustomOrderedClassElementsFixer(), + new CustomPhpUnitOrderFixer(), + ]) + ->setRules([ + 'Tighten/custom_controller_order' => true, + 'Tighten/custom_ordered_class_elements' => [ + 'order' => [ + 'use_trait', + 'case', + 'property_public_static', + 'property_protected_static', + 'property_private_static', + 'constant_public', + 'constant_protected', + 'constant_private', + 'property_public', + 'property_protected', + 'property_private', + 'construct', + 'method:__invoke', + 'method_public_static', + 'method_protected_static', + 'method_private_static', + 'method_public', + 'method_protected', + 'method_private', + 'magic', + ], + ], + 'Tighten/custom_phpunit_order' => true, + ]); diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist new file mode 100644 index 0000000..5ffcf8e --- /dev/null +++ b/.phpcs.xml.dist @@ -0,0 +1,12 @@ + + + app + config + database + public + resources + routes + tests + + + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..6dbcfe0 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) Regis Freyd 2023 + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b4439b0 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +### License + +MIT license. + + +### Principles + +- Stick with Laravel's conventions as much as possible +- No dependencies if possible + +### Stack + +- We use Bun to manage front end dependencies. +- We use Composer to manage back end dependencies. +- Laravel + HTMX + TailwindCSS + +### Architecture + +- Views should be dumb and only display data from the backend +- Controllers should be thin and only handle requests +- Data that views need should be prepared by view models and called from the controllers + +### Deploy + +- `php artisan icons:clear` to clear heroicons cache +- `php artisan icons:cache` to cache all heroicons used +- `php artisan view:clear` to clear view cache +- `php artisan view:cache` to cache all views diff --git a/app/Console/Commands/LocalizeApplication.php b/app/Console/Commands/LocalizeApplication.php new file mode 100644 index 0000000..caa439e --- /dev/null +++ b/app/Console/Commands/LocalizeApplication.php @@ -0,0 +1,81 @@ +call('localize', ['lang' => implode(',', $locales)]); + + $this->loadTranslations($locales); + } + + /** + * Heavily inspired by https://stevensteel.com/blog/automatically-find-translate-and-save-missing-translation-keys. + */ + private function loadTranslations(array $locales): void + { + $path = lang_path(); + $finder = new Finder; + $finder->in($path)->name(['*.json'])->files(); + $this->googleTranslate = new GoogleTranslate; + + foreach ($finder as $file) { + $locale = $file->getFilenameWithoutExtension(); + + if (! in_array($locale, $locales)) { + continue; + } + + $this->info('loading locale: ' . $locale); + $jsonString = $file->getContents(); + $strings = json_decode($jsonString, true); + + $this->translateStrings($locale, $strings); + } + } + + private function translateStrings(string $locale, array $strings): void + { + foreach ($strings as $index => $value) { + if ($value === '') { + $this->googleTranslate->setTarget($locale); + $translated = $this->googleTranslate->translate($index); + $this->info('translating: `' . $index . '` to `' . $translated . '`'); + + // we store the translated string in the array + $strings[$index] = $translated; + } + } + + // now we need to save the array back to the file + Storage::disk('lang')->put($locale . '.json', json_encode($strings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + } +} diff --git a/app/Console/Commands/SetupDummyAccount.php b/app/Console/Commands/SetupDummyAccount.php new file mode 100644 index 0000000..dbd4e79 --- /dev/null +++ b/app/Console/Commands/SetupDummyAccount.php @@ -0,0 +1,132 @@ + 'sync']); + + $this->start(); + $this->wipeAndMigrateDB(); + $this->createFirstUser(); + $this->createOtherUsers(); + + $this->stop(); + } + + private function start(): void + { + if (! $this->confirmToProceed('Are you sure you want to proceed? This will delete ALL data in your environment.', true)) { + exit; + } + + $this->line('This process will take a few minutes to complete. Be patient and read a book in the meantime.'); + $this->faker = Faker::create(); + } + + private function wipeAndMigrateDB(): void + { + if ($this->option('migrate')) { + $this->artisan('☐ Migration of the database', 'migrate', ['--force' => true]); + } else { + $this->artisan('☐ Migration of the database', 'migrate:fresh', ['--force' => true]); + } + } + + private function stop(): void + { + $this->line(''); + $this->line('-----------------------------'); + $this->line('|'); + $this->line('| Welcome to Bivouac'); + $this->line('|'); + $this->line('-----------------------------'); + $this->info('| You can now sign in with one of these two accounts:'); + $this->line('| An account with a lot of data:'); + $this->line('| username: admin@admin.com'); + $this->line('| password: admin123'); + $this->line('|------------------------–––-'); + $this->line('|A blank account:'); + $this->line('| username: blank@blank.com'); + $this->line('| password: blank123'); + $this->line('|------------------------–––-'); + $this->line('| URL: ' . config('app.url')); + $this->line('-----------------------------'); + + $this->info('Setup is done. Have fun.'); + } + + private function createFirstUser(): void + { + $this->info('☐ Create first user of the account'); + + $this->user = (new CreateAccount( + email: 'admin@admin.com', + password: 'admin123', + firstName: 'Michael', + lastName: 'Scott', + organizationName: 'Bivouac', + ))->execute(); + $this->user->email_verified_at = Carbon::now(); + $this->user->save(); + } + + private function createOtherUsers(): void + { + $this->info('☐ Create users'); + + for ($i = 0; $i < rand(3, 15); $i++) { + User::create([ + 'first_name' => $this->faker->firstName, + 'last_name' => $this->faker->lastName, + 'email' => $this->faker->email, + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + 'name_for_avatar' => $this->faker->firstName, + 'password' => Hash::make('blank123'), + 'organization_id' => $this->user->organization_id, + ]); + } + } + + private function artisan(string $message, string $command, array $arguments = []): void + { + $this->info($message); + $this->callSilent($command, $arguments); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php new file mode 100644 index 0000000..4c1dd5a --- /dev/null +++ b/app/Console/Kernel.php @@ -0,0 +1,27 @@ +command('inspire')->hourly(); + } + + /** + * Register the commands for the application. + */ + protected function commands(): void + { + $this->load(__DIR__ . '/Commands'); + + require base_path('routes/console.php'); + } +} diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php new file mode 100644 index 0000000..f54d1c8 --- /dev/null +++ b/app/Exceptions/Handler.php @@ -0,0 +1,30 @@ + + */ + protected $dontFlash = [ + 'current_password', + 'password', + 'password_confirmation', + ]; + + /** + * Register the exception handling callbacks for the application. + */ + public function register(): void + { + $this->reportable(function (Throwable $e): void { + // + }); + } +} diff --git a/app/Helpers/helpers.php b/app/Helpers/helpers.php new file mode 100644 index 0000000..2b88628 --- /dev/null +++ b/app/Helpers/helpers.php @@ -0,0 +1,11 @@ +authenticate(); + + $request->session()->regenerate(); + + return redirect()->intended(RouteServiceProvider::HOME); + } + + /** + * Destroy an authenticated session. + */ + public function destroy(Request $request): RedirectResponse + { + Auth::guard('web')->logout(); + + $request->session()->invalidate(); + + $request->session()->regenerateToken(); + + return redirect('/'); + } +} diff --git a/app/Http/Controllers/Auth/ConfirmablePasswordController.php b/app/Http/Controllers/Auth/ConfirmablePasswordController.php new file mode 100644 index 0000000..523ddda --- /dev/null +++ b/app/Http/Controllers/Auth/ConfirmablePasswordController.php @@ -0,0 +1,41 @@ +validate([ + 'email' => $request->user()->email, + 'password' => $request->password, + ])) { + throw ValidationException::withMessages([ + 'password' => __('auth.password'), + ]); + } + + $request->session()->put('auth.password_confirmed_at', time()); + + return redirect()->intended(RouteServiceProvider::HOME); + } +} diff --git a/app/Http/Controllers/Auth/EmailVerificationNotificationController.php b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php new file mode 100644 index 0000000..96ba772 --- /dev/null +++ b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php @@ -0,0 +1,25 @@ +user()->hasVerifiedEmail()) { + return redirect()->intended(RouteServiceProvider::HOME); + } + + $request->user()->sendEmailVerificationNotification(); + + return back()->with('status', 'verification-link-sent'); + } +} diff --git a/app/Http/Controllers/Auth/EmailVerificationPromptController.php b/app/Http/Controllers/Auth/EmailVerificationPromptController.php new file mode 100644 index 0000000..186eb97 --- /dev/null +++ b/app/Http/Controllers/Auth/EmailVerificationPromptController.php @@ -0,0 +1,22 @@ +user()->hasVerifiedEmail() + ? redirect()->intended(RouteServiceProvider::HOME) + : view('auth.verify-email'); + } +} diff --git a/app/Http/Controllers/Auth/NewPasswordController.php b/app/Http/Controllers/Auth/NewPasswordController.php new file mode 100644 index 0000000..b632291 --- /dev/null +++ b/app/Http/Controllers/Auth/NewPasswordController.php @@ -0,0 +1,61 @@ + $request]); + } + + /** + * Handle an incoming new password request. + * + * @throws \Illuminate\Validation\ValidationException + */ + public function store(Request $request): RedirectResponse + { + $request->validate([ + 'token' => ['required'], + 'email' => ['required', 'email'], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + ]); + + // Here we will attempt to reset the user's password. If it is successful we + // will update the password on an actual user model and persist it to the + // database. Otherwise we will parse the error and return the response. + $status = Password::reset( + $request->only('email', 'password', 'password_confirmation', 'token'), + function ($user) use ($request): void { + $user->forceFill([ + 'password' => Hash::make($request->password), + 'remember_token' => Str::random(60), + ])->save(); + + event(new PasswordReset($user)); + } + ); + + // If the password was successfully reset, we will redirect the user back to + // the application's home authenticated view. If there is an error we can + // redirect them back to where they came from with their error message. + return $status == Password::PASSWORD_RESET + ? redirect()->route('login')->with('status', __($status)) + : back()->withInput($request->only('email')) + ->withErrors(['email' => __($status)]); + } +} diff --git a/app/Http/Controllers/Auth/PasswordController.php b/app/Http/Controllers/Auth/PasswordController.php new file mode 100644 index 0000000..6916409 --- /dev/null +++ b/app/Http/Controllers/Auth/PasswordController.php @@ -0,0 +1,29 @@ +validateWithBag('updatePassword', [ + 'current_password' => ['required', 'current_password'], + 'password' => ['required', Password::defaults(), 'confirmed'], + ]); + + $request->user()->update([ + 'password' => Hash::make($validated['password']), + ]); + + return back()->with('status', 'password-updated'); + } +} diff --git a/app/Http/Controllers/Auth/PasswordResetLinkController.php b/app/Http/Controllers/Auth/PasswordResetLinkController.php new file mode 100644 index 0000000..bf1ebfa --- /dev/null +++ b/app/Http/Controllers/Auth/PasswordResetLinkController.php @@ -0,0 +1,44 @@ +validate([ + 'email' => ['required', 'email'], + ]); + + // We will send the password reset link to this user. Once we have attempted + // to send the link, we will examine the response then see the message we + // need to show to the user. Finally, we'll send out a proper response. + $status = Password::sendResetLink( + $request->only('email') + ); + + return $status == Password::RESET_LINK_SENT + ? back()->with('status', __($status)) + : back()->withInput($request->only('email')) + ->withErrors(['email' => __($status)]); + } +} diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php new file mode 100644 index 0000000..b072915 --- /dev/null +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -0,0 +1,54 @@ +validate([ + 'first_name' => ['required', 'string', 'max:255'], + 'last_name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + ]); + + $user = (new CreateAccount( + email: $request->input('email'), + password: $request->input('password'), + firstName: $request->input('first_name'), + lastName: $request->input('last_name'), + organizationName: $request->input('organization_name'), + ))->execute(); + + event(new Registered($user)); + + Auth::login($user); + + return redirect(RouteServiceProvider::HOME); + } +} diff --git a/app/Http/Controllers/Auth/VerifyEmailController.php b/app/Http/Controllers/Auth/VerifyEmailController.php new file mode 100644 index 0000000..e7257df --- /dev/null +++ b/app/Http/Controllers/Auth/VerifyEmailController.php @@ -0,0 +1,28 @@ +user()->hasVerifiedEmail()) { + return redirect()->intended(RouteServiceProvider::HOME . '?verified=1'); + } + + if ($request->user()->markEmailAsVerified()) { + event(new Verified($request->user())); + } + + return redirect()->intended(RouteServiceProvider::HOME . '?verified=1'); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..77ec359 --- /dev/null +++ b/app/Http/Controllers/Controller.php @@ -0,0 +1,12 @@ + $locale]); + + return back(); + } +} diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php new file mode 100644 index 0000000..a48eb8d --- /dev/null +++ b/app/Http/Controllers/ProfileController.php @@ -0,0 +1,60 @@ + $request->user(), + ]); + } + + /** + * Update the user's profile information. + */ + public function update(ProfileUpdateRequest $request): RedirectResponse + { + $request->user()->fill($request->validated()); + + if ($request->user()->isDirty('email')) { + $request->user()->email_verified_at = null; + } + + $request->user()->save(); + + return Redirect::route('profile.edit')->with('status', 'profile-updated'); + } + + /** + * Delete the user's account. + */ + public function destroy(Request $request): RedirectResponse + { + $request->validateWithBag('userDeletion', [ + 'password' => ['required', 'current_password'], + ]); + + $user = $request->user(); + + Auth::logout(); + + $user->delete(); + + $request->session()->invalidate(); + $request->session()->regenerateToken(); + + return Redirect::to('/'); + } +} diff --git a/app/Http/Controllers/Settings/SettingsController.php b/app/Http/Controllers/Settings/SettingsController.php new file mode 100644 index 0000000..0e1553a --- /dev/null +++ b/app/Http/Controllers/Settings/SettingsController.php @@ -0,0 +1,14 @@ +header('hx-request') && $request->header('hx-target') == 'levels-index') { + return view('settings.level.partials.index', [ + 'data' => SettingsLevelViewModel::index(), + ]); + } + + return view('settings.level.index', [ + 'data' => SettingsLevelViewModel::index(), + ]); + } + + public function new(): View + { + return view('settings.level.new'); + } + + public function store(Request $request): RedirectResponse + { + $validated = $request->validate([ + 'label' => 'required|string|max:255', + ]); + + (new CreateLevel( + label: $validated['label'], + ))->execute(); + + $request->session()->flash('status', __('The level has been created')); + + return redirect()->route('settings.level.index'); + } + + public function edit(Request $request, Level $level): View|RedirectResponse + { + try { + Level::where('organization_id', auth()->user()->organization_id) + ->findOrFail($level->id); + } catch (ModelNotFoundException) { + return redirect()->route('settings.level.index'); + } + + return view('settings.level.edit', [ + 'data' => SettingsLevelViewModel::level($level), + ]); + } + + public function update(Request $request, Level $level): RedirectResponse + { + $validated = $request->validate([ + 'label' => 'required|string|max:255', + ]); + + (new UpdateLevel( + level: $level, + label: $validated['label'], + ))->execute(); + + $request->session()->flash('status', __('Changes saved')); + + return redirect()->route('settings.level.index'); + } + + public function destroy(Request $request, Level $level): Response + { + try { + Level::where('organization_id', auth()->user()->organization_id) + ->findOrFail($level->id); + } catch (ModelNotFoundException) { + } + + (new DestroyLevel( + level: $level, + ))->execute(); + + return response()->make('', 200, ['HX-Trigger' => 'loadLevels']); + } +} diff --git a/app/Http/Controllers/Settings/SettingsProfileController.php b/app/Http/Controllers/Settings/SettingsProfileController.php new file mode 100644 index 0000000..30bc183 --- /dev/null +++ b/app/Http/Controllers/Settings/SettingsProfileController.php @@ -0,0 +1,14 @@ +header('hx-request') && $request->header('hx-target') == 'roles-index') { + return view('settings.role.partials.index', [ + 'data' => SettingsRoleViewModel::index(), + ]); + } + + return view('settings.role.index', [ + 'data' => SettingsRoleViewModel::index(), + ]); + } + + public function new(): View + { + return view('settings.role.new'); + } + + public function store(Request $request): RedirectResponse + { + $validated = $request->validate([ + 'label' => 'required|string|max:255', + ]); + + (new CreateRole( + label: $validated['label'], + ))->execute(); + + $request->session()->flash('status', __('The role has been created')); + + return redirect()->route('settings.role.index'); + } + + public function edit(Request $request, Role $role): View|RedirectResponse + { + try { + Role::where('organization_id', auth()->user()->organization_id) + ->findOrFail($role->id); + } catch (ModelNotFoundException) { + return redirect()->route('settings.role.index'); + } + + return view('settings.role.edit', [ + 'data' => SettingsRoleViewModel::role($role), + ]); + } + + public function update(Request $request, Role $role): RedirectResponse + { + $validated = $request->validate([ + 'label' => 'required|string|max:255', + ]); + + (new UpdateRole( + role: $role, + label: $validated['label'], + ))->execute(); + + $request->session()->flash('status', __('Changes saved')); + + return redirect()->route('settings.role.index'); + } + + public function destroy(Request $request, Role $role): Response + { + try { + Role::where('organization_id', auth()->user()->organization_id) + ->findOrFail($role->id); + } catch (ModelNotFoundException) { + } + + (new DestroyRole( + role: $role, + ))->execute(); + + return response()->make('', 200, ['HX-Trigger' => 'loadRoles']); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php new file mode 100644 index 0000000..3738a53 --- /dev/null +++ b/app/Http/Kernel.php @@ -0,0 +1,70 @@ + + */ + protected $middleware = [ + // \App\Http\Middleware\TrustHosts::class, + \App\Http\Middleware\TrustProxies::class, + \Illuminate\Http\Middleware\HandleCors::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, + \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, + \App\Http\Middleware\TrimStrings::class, + \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + ]; + + /** + * The application's route middleware groups. + * + * @var array> + */ + protected $middlewareGroups = [ + 'web' => [ + \App\Http\Middleware\EncryptCookies::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\VerifyCsrfToken::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + \App\Http\Middleware\Locale::class, + ], + + 'api' => [ + // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, + \Illuminate\Routing\Middleware\ThrottleRequests::class . ':api', + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + ]; + + /** + * The application's middleware aliases. + * + * Aliases may be used instead of class names to conveniently assign middleware to routes and groups. + * + * @var array + */ + protected $middlewareAliases = [ + 'auth' => \App\Http\Middleware\Authenticate::class, + 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, + 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, + 'can' => \Illuminate\Auth\Middleware\Authorize::class, + 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, + 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, + 'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, + 'signed' => \App\Http\Middleware\ValidateSignature::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'administrator' => \App\Http\Middleware\CheckAdministratorRole::class, + ]; +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php new file mode 100644 index 0000000..d4ef644 --- /dev/null +++ b/app/Http/Middleware/Authenticate.php @@ -0,0 +1,17 @@ +expectsJson() ? null : route('login'); + } +} diff --git a/app/Http/Middleware/CheckAdministratorRole.php b/app/Http/Middleware/CheckAdministratorRole.php new file mode 100644 index 0000000..e96bc15 --- /dev/null +++ b/app/Http/Middleware/CheckAdministratorRole.php @@ -0,0 +1,28 @@ +user()->permissions === User::ROLE_ADMINISTRATOR || + $request->user()->permissions === User::ROLE_ACCOUNT_MANAGER + ) { + return $next($request); + } + + abort(401); + } +} diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 0000000..867695b --- /dev/null +++ b/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/app/Http/Middleware/Locale.php b/app/Http/Middleware/Locale.php new file mode 100644 index 0000000..efbc515 --- /dev/null +++ b/app/Http/Middleware/Locale.php @@ -0,0 +1,33 @@ +app = $app; + $this->request = $request; + } + + public function handle(Request $request, Closure $next): Response + { + if (Auth::check()) { + $this->app->setLocale(session('current_locale', auth()->user()->locale)); + } else { + $this->app->setLocale(session('current_locale', config('app.locale'))); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 0000000..74cbd9a --- /dev/null +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php new file mode 100644 index 0000000..5847241 --- /dev/null +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -0,0 +1,30 @@ +check()) { + return redirect(RouteServiceProvider::HOME); + } + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php new file mode 100644 index 0000000..88cadca --- /dev/null +++ b/app/Http/Middleware/TrimStrings.php @@ -0,0 +1,19 @@ + + */ + protected $except = [ + 'current_password', + 'password', + 'password_confirmation', + ]; +} diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php new file mode 100644 index 0000000..c9c58bd --- /dev/null +++ b/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ + + */ + public function hosts(): array + { + return [ + $this->allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php new file mode 100644 index 0000000..3391630 --- /dev/null +++ b/app/Http/Middleware/TrustProxies.php @@ -0,0 +1,28 @@ +|string|null + */ + protected $proxies; + + /** + * The headers that should be used to detect proxies. + * + * @var int + */ + protected $headers = + Request::HEADER_X_FORWARDED_FOR | + Request::HEADER_X_FORWARDED_HOST | + Request::HEADER_X_FORWARDED_PORT | + Request::HEADER_X_FORWARDED_PROTO | + Request::HEADER_X_FORWARDED_AWS_ELB; +} diff --git a/app/Http/Middleware/ValidateSignature.php b/app/Http/Middleware/ValidateSignature.php new file mode 100644 index 0000000..093bf64 --- /dev/null +++ b/app/Http/Middleware/ValidateSignature.php @@ -0,0 +1,22 @@ + + */ + protected $except = [ + // 'fbclid', + // 'utm_campaign', + // 'utm_content', + // 'utm_medium', + // 'utm_source', + // 'utm_term', + ]; +} diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php new file mode 100644 index 0000000..9e86521 --- /dev/null +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php new file mode 100644 index 0000000..cd39451 --- /dev/null +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -0,0 +1,85 @@ + + */ + public function rules(): array + { + return [ + 'email' => ['required', 'string', 'email'], + 'password' => ['required', 'string'], + ]; + } + + /** + * Attempt to authenticate the request's credentials. + * + * @throws \Illuminate\Validation\ValidationException + */ + public function authenticate(): void + { + $this->ensureIsNotRateLimited(); + + if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { + RateLimiter::hit($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => trans('auth.failed'), + ]); + } + + RateLimiter::clear($this->throttleKey()); + } + + /** + * Ensure the login request is not rate limited. + * + * @throws \Illuminate\Validation\ValidationException + */ + public function ensureIsNotRateLimited(): void + { + if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { + return; + } + + event(new Lockout($this)); + + $seconds = RateLimiter::availableIn($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => trans('auth.throttle', [ + 'seconds' => $seconds, + 'minutes' => ceil($seconds / 60), + ]), + ]); + } + + /** + * Get the rate limiting throttle key for the request. + */ + public function throttleKey(): string + { + return Str::transliterate(Str::lower($this->input('email')) . '|' . $this->ip()); + } +} diff --git a/app/Http/Requests/ProfileUpdateRequest.php b/app/Http/Requests/ProfileUpdateRequest.php new file mode 100644 index 0000000..93b0022 --- /dev/null +++ b/app/Http/Requests/ProfileUpdateRequest.php @@ -0,0 +1,23 @@ + + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', Rule::unique(User::class)->ignore($this->user()->id)], + ]; + } +} diff --git a/app/Http/ViewModels/Settings/SettingsLevelViewModel.php b/app/Http/ViewModels/Settings/SettingsLevelViewModel.php new file mode 100644 index 0000000..02481de --- /dev/null +++ b/app/Http/ViewModels/Settings/SettingsLevelViewModel.php @@ -0,0 +1,28 @@ +user()->organization_id) + ->get() + ->map(fn (Level $level) => self::level($level)) + ->sortBy('label'); + + return [ + 'levels' => $levels, + ]; + } + + public static function level(Level $level): array + { + return [ + 'id' => $level->id, + 'label' => $level->label, + ]; + } +} diff --git a/app/Http/ViewModels/Settings/SettingsRoleViewModel.php b/app/Http/ViewModels/Settings/SettingsRoleViewModel.php new file mode 100644 index 0000000..9197009 --- /dev/null +++ b/app/Http/ViewModels/Settings/SettingsRoleViewModel.php @@ -0,0 +1,28 @@ +user()->organization_id) + ->get() + ->map(fn (Role $role) => self::role($role)) + ->sortBy('label'); + + return [ + 'roles' => $roles, + ]; + } + + public static function role(Role $role): array + { + return [ + 'id' => $role->id, + 'label' => $role->label, + ]; + } +} diff --git a/app/Jobs/PopulateAccount.php b/app/Jobs/PopulateAccount.php new file mode 100644 index 0000000..eeed22e --- /dev/null +++ b/app/Jobs/PopulateAccount.php @@ -0,0 +1,79 @@ +addRoles(); + $this->addLevels(); + } + + private function addRoles(): void + { + $roles = [ + trans_key('Software Engineer'), + trans_key('Quality Assurance Engineer'), + trans_key('Project Manager'), + trans_key('Product Manager'), + trans_key('UI/UX Designer'), + trans_key('Data Analyst/Scientist'), + trans_key('DevOps Engineer'), + trans_key('Technical Support Engineer'), + trans_key('Scrum Master'), + trans_key('Sales/Account Manager'), + trans_key('Technical Writer'), + trans_key('System Administrator'), + trans_key('Chief Executive Officer'), + ]; + + foreach ($roles as $role) { + DB::table('roles')->insert([ + 'organization_id' => $this->organization->id, + 'label' => null, + 'label_translation_key' => $role, + 'created_at' => now(), + ]); + } + } + + private function addLevels(): void + { + $levels = [ + trans_key('Junior'), + trans_key('Intermediate'), + trans_key('Senior'), + trans_key('Staff'), + ]; + + foreach ($levels as $level) { + DB::table('levels')->insert([ + 'organization_id' => $this->organization->id, + 'label' => null, + 'label_translation_key' => $level, + 'created_at' => now(), + ]); + } + } +} diff --git a/app/Models/Level.php b/app/Models/Level.php new file mode 100644 index 0000000..9d2cb29 --- /dev/null +++ b/app/Models/Level.php @@ -0,0 +1,31 @@ + + */ + protected $fillable = [ + 'organization_id', + 'label', + 'label_translation_key', + ]; + + public function organization(): BelongsTo + { + return $this->belongsTo(Organization::class); + } +} diff --git a/app/Models/Organization.php b/app/Models/Organization.php new file mode 100644 index 0000000..861389f --- /dev/null +++ b/app/Models/Organization.php @@ -0,0 +1,29 @@ +hasMany(Role::class); + } + + public function levels(): HasMany + { + return $this->hasMany(Level::class); + } +} diff --git a/app/Models/Role.php b/app/Models/Role.php new file mode 100644 index 0000000..9414739 --- /dev/null +++ b/app/Models/Role.php @@ -0,0 +1,34 @@ + + */ + protected $fillable = [ + 'organization_id', + 'label', + 'label_translation_key', + ]; + + public function organization(): BelongsTo + { + return $this->belongsTo(Organization::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php new file mode 100644 index 0000000..b06e250 --- /dev/null +++ b/app/Models/User.php @@ -0,0 +1,63 @@ + + */ + protected $fillable = [ + 'first_name', + 'last_name', + 'organization_id', + 'name_for_avatar', + 'email', + 'email_verified_at', + 'password', + 'permissions', + 'locale', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + + public function organization(): BelongsTo + { + return $this->belongsTo(Organization::class); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php new file mode 100644 index 0000000..452e6b6 --- /dev/null +++ b/app/Providers/AppServiceProvider.php @@ -0,0 +1,24 @@ + + */ + protected $policies = [ + // + ]; + + /** + * Register any authentication / authorization services. + */ + public function boot(): void + { + // + } +} diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php new file mode 100644 index 0000000..2be04f5 --- /dev/null +++ b/app/Providers/BroadcastServiceProvider.php @@ -0,0 +1,19 @@ +> + */ + protected $listen = [ + Registered::class => [ + SendEmailVerificationNotification::class, + ], + ]; + + /** + * Register any events for your application. + */ + public function boot(): void + { + // + } + + /** + * Determine if events and listeners should be automatically discovered. + */ + public function shouldDiscoverEvents(): bool + { + return false; + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..b15cb4e --- /dev/null +++ b/app/Providers/RouteServiceProvider.php @@ -0,0 +1,40 @@ +by($request->user()?->id ?: $request->ip()); + }); + + $this->routes(function (): void { + Route::middleware('api') + ->prefix('api') + ->group(base_path('routes/api.php')); + + Route::middleware('web') + ->group(base_path('routes/web.php')); + }); + } +} diff --git a/app/Services/BaseService.php b/app/Services/BaseService.php new file mode 100644 index 0000000..096d045 --- /dev/null +++ b/app/Services/BaseService.php @@ -0,0 +1,36 @@ + + */ + public function rules(): array + { + return []; + } + + /** + * Get the permissions that users need to execute the service. + * + * @return array + */ + public function permissions(): array + { + return []; + } + + /** + * @param array $data + */ + public function valueOrNull(array $data, string $index): ?string + { + if (empty($data[$index])) { + return null; + } + + return $data[$index] == '' ? null : $data[$index]; + } +} diff --git a/app/Services/CreateAccount.php b/app/Services/CreateAccount.php new file mode 100644 index 0000000..7151a5f --- /dev/null +++ b/app/Services/CreateAccount.php @@ -0,0 +1,56 @@ +createOrganization(); + $this->createUser(); + + PopulateAccount::dispatch($this->organization); + + return $this->user; + } + + private function createUser(): void + { + $this->user = User::create([ + 'first_name' => $this->firstName, + 'last_name' => $this->lastName, + 'email' => $this->email, + 'name_for_avatar' => $this->firstName, + 'password' => Hash::make($this->password), + 'organization_id' => $this->organization->id, + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + } + + private function createOrganization(): void + { + $this->organization = Organization::create([ + 'name' => $this->organizationName, + ]); + } +} diff --git a/app/Services/CreateLevel.php b/app/Services/CreateLevel.php new file mode 100644 index 0000000..1be46ea --- /dev/null +++ b/app/Services/CreateLevel.php @@ -0,0 +1,41 @@ +checkPermissions(); + $this->create(); + + return $this->level; + } + + private function checkPermissions(): void + { + if (auth()->user()->permissions !== User::ROLE_ACCOUNT_MANAGER && + auth()->user()->permissions !== User::ROLE_ADMINISTRATOR) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function create(): void + { + $this->level = Level::create([ + 'organization_id' => auth()->user()->organization_id, + 'label' => $this->label, + ]); + } +} diff --git a/app/Services/CreateRole.php b/app/Services/CreateRole.php new file mode 100644 index 0000000..7aec017 --- /dev/null +++ b/app/Services/CreateRole.php @@ -0,0 +1,41 @@ +checkPermissions(); + $this->create(); + + return $this->role; + } + + private function checkPermissions(): void + { + if (auth()->user()->permissions !== User::ROLE_ACCOUNT_MANAGER && + auth()->user()->permissions !== User::ROLE_ADMINISTRATOR) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function create(): void + { + $this->role = Role::create([ + 'organization_id' => auth()->user()->organization_id, + 'label' => $this->label, + ]); + } +} diff --git a/app/Services/DestroyLevel.php b/app/Services/DestroyLevel.php new file mode 100644 index 0000000..cb77787 --- /dev/null +++ b/app/Services/DestroyLevel.php @@ -0,0 +1,44 @@ +checkPermissions(); + $this->checkLevel(); + $this->destroy(); + } + + public function destroy(): void + { + $this->level->delete(); + } + + private function checkPermissions(): void + { + if ( + auth()->user()->permissions !== User::ROLE_ACCOUNT_MANAGER && + auth()->user()->permissions !== User::ROLE_ADMINISTRATOR + ) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function checkLevel(): void + { + if ($this->level->organization_id !== auth()->user()->organization_id) { + throw new Exception(__('You do not have permission to do this action.')); + } + } +} diff --git a/app/Services/DestroyRole.php b/app/Services/DestroyRole.php new file mode 100644 index 0000000..1b4a6b8 --- /dev/null +++ b/app/Services/DestroyRole.php @@ -0,0 +1,44 @@ +checkPermissions(); + $this->checkRole(); + $this->destroy(); + } + + public function destroy(): void + { + $this->role->delete(); + } + + private function checkPermissions(): void + { + if ( + auth()->user()->permissions !== User::ROLE_ACCOUNT_MANAGER && + auth()->user()->permissions !== User::ROLE_ADMINISTRATOR + ) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function checkRole(): void + { + if ($this->role->organization_id !== auth()->user()->organization_id) { + throw new Exception(__('You do not have permission to do this action.')); + } + } +} diff --git a/app/Services/UpdateLevel.php b/app/Services/UpdateLevel.php new file mode 100644 index 0000000..e50dbd0 --- /dev/null +++ b/app/Services/UpdateLevel.php @@ -0,0 +1,49 @@ +checkPermissions(); + $this->checkLevel(); + $this->update(); + + return $this->level; + } + + private function checkPermissions(): void + { + if ( + auth()->user()->permissions !== User::ROLE_ACCOUNT_MANAGER && + auth()->user()->permissions !== User::ROLE_ADMINISTRATOR + ) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function checkLevel(): void + { + if ($this->level->organization_id !== auth()->user()->organization_id) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function update(): void + { + $this->level->update([ + 'label' => $this->label, + ]); + } +} diff --git a/app/Services/UpdateRole.php b/app/Services/UpdateRole.php new file mode 100644 index 0000000..e5ce8c7 --- /dev/null +++ b/app/Services/UpdateRole.php @@ -0,0 +1,49 @@ +checkPermissions(); + $this->checkRole(); + $this->update(); + + return $this->role; + } + + private function checkPermissions(): void + { + if ( + auth()->user()->permissions !== User::ROLE_ACCOUNT_MANAGER && + auth()->user()->permissions !== User::ROLE_ADMINISTRATOR + ) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function checkRole(): void + { + if ($this->role->organization_id !== auth()->user()->organization_id) { + throw new Exception(__('You do not have permission to do this action.')); + } + } + + private function update(): void + { + $this->role->update([ + 'label' => $this->label, + ]); + } +} diff --git a/app/Traits/Translatable.php b/app/Traits/Translatable.php new file mode 100644 index 0000000..30927bf --- /dev/null +++ b/app/Traits/Translatable.php @@ -0,0 +1,28 @@ + + */ + protected function label(): Attribute + { + return Attribute::make( + get: function ($value, $attributes) { + if (! $value) { + return __($attributes['label_translation_key']); + } + + return $value; + } + ); + } +} diff --git a/app/View/Components/AppLayout.php b/app/View/Components/AppLayout.php new file mode 100644 index 0000000..de0d46f --- /dev/null +++ b/app/View/Components/AppLayout.php @@ -0,0 +1,17 @@ +make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); + +/* +|-------------------------------------------------------------------------- +| Shutdown The Application +|-------------------------------------------------------------------------- +| +| Once Artisan has finished running, we will fire off the shutdown events +| so that any final work may be done by the application before we shut +| down the process. This is the last thing to happen to the request. +| +*/ + +$kernel->terminate($input, $status); + +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 0000000..037e17d --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + App\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + App\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + App\Exceptions\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..93c3752c3303b1d7ca4525aa5ea30008118ce0c7 GIT binary patch literal 87201 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.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-10-01T14:29:01+00:00" + }, + { + "name": "codezero/browser-locale", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/browser-locale.git", + "reference": "5dc1b89c8dcaece285b2ebb69ebdc783144e4cab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/browser-locale/zipball/5dc1b89c8dcaece285b2ebb69ebdc783144e4cab", + "reference": "5dc1b89c8dcaece285b2ebb69ebdc783144e4cab", + "shasum": "" + }, + "require": { + "php": "^7.0|^8.0" + }, + "require-dev": { + "illuminate/support": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0", + "mockery/mockery": "^1.3.3", + "phpunit/phpunit": "^6.0|^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "CodeZero\\BrowserLocale\\Laravel\\BrowserLocaleServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "CodeZero\\BrowserLocale\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "Get the most preferred locales from your visitor's browser.", + "keywords": [ + "browser", + "country", + "detect", + "language", + "locale", + "php", + "website" + ], + "support": { + "issues": "https://github.com/codezero-be/browser-locale/issues", + "source": "https://github.com/codezero-be/browser-locale/tree/3.3.0" + }, + "funding": [ + { + "url": "https://paypal.me/ivanvermeyen", + "type": "custom" + }, + { + "url": "https://ko-fi.com/ivanvermeyen", + "type": "ko_fi" + } + ], + "time": "2023-02-03T13:33:21+00:00" + }, + { + "name": "codezero/laravel-localizer", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/laravel-localizer.git", + "reference": "853ce4a78d0c446a49b6b8e4437aaad04ff0afeb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/laravel-localizer/zipball/853ce4a78d0c446a49b6b8e4437aaad04ff0afeb", + "reference": "853ce4a78d0c446a49b6b8e4437aaad04ff0afeb", + "shasum": "" + }, + "require": { + "codezero/browser-locale": "^3.0", + "illuminate/support": "^7.0|^8.0|^9.0|^10.0", + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0", + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "CodeZero\\Localizer\\LocalizerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "CodeZero\\Localizer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "Automatically detect and set an app locale that matches your visitor's preference.", + "keywords": [ + "browser", + "cookie", + "country", + "detect", + "language", + "laravel", + "locale", + "localization", + "php", + "session" + ], + "support": { + "issues": "https://github.com/codezero-be/laravel-localizer/issues", + "source": "https://github.com/codezero-be/laravel-localizer/tree/2.0.0" + }, + "funding": [ + { + "url": "https://paypal.me/ivanvermeyen", + "type": "custom" + }, + { + "url": "https://ko-fi.com/ivanvermeyen", + "type": "ko_fi" + } + ], + "time": "2023-03-24T09:36:59+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "f41715465d65213d644d3141a6a93081be5d3549" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", + "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" + }, + "time": "2022-10-27T11:44:00+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.8", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.8" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2023-06-16T13:40:37+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "84a527db05647743d50373e0ec53a152f2cde568" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", + "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-15T16:57:16+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "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", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2023-08-10T19:36:49+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2023-10-06T06:47:41+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.2", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2023-11-12T22:16:48+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2023-12-03T19:50:20+00:00" + }, + { + "name": "laravel/framework", + "version": "v10.35.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "91ec2d92d2f6007e9084fe06438b99c91845da69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/91ec2d92d2f6007e9084fe06438b99c91845da69", + "reference": "91ec2d92d2f6007e9084fe06438b99c91845da69", + "shasum": "" + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.3.2", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.1.9", + "laravel/serializable-closure": "^1.3", + "league/commonmark": "^2.2.1", + "league/flysystem": "^3.8.0", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.67", + "nunomaduro/termwind": "^1.13", + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^6.2", + "symfony/error-handler": "^6.2", + "symfony/finder": "^6.2", + "symfony/http-foundation": "^6.4", + "symfony/http-kernel": "^6.2", + "symfony/mailer": "^6.2", + "symfony/mime": "^6.2", + "symfony/process": "^6.2", + "symfony/routing": "^6.2", + "symfony/uid": "^6.2", + "symfony/var-dumper": "^6.2", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.4.1", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.235.5", + "doctrine/dbal": "^3.5.1", + "ext-gmp": "*", + "fakerphp/faker": "^1.21", + "guzzlehttp/guzzle": "^7.5", + "league/flysystem-aws-s3-v3": "^3.0", + "league/flysystem-ftp": "^3.0", + "league/flysystem-path-prefixing": "^3.3", + "league/flysystem-read-only": "^3.3", + "league/flysystem-sftp-v3": "^3.0", + "mockery/mockery": "^1.5.1", + "nyholm/psr7": "^1.2", + "orchestra/testbench-core": "^8.15.1", + "pda/pheanstalk": "^4.0", + "phpstan/phpstan": "^1.4.7", + "phpunit/phpunit": "^10.0.7", + "predis/predis": "^2.0.2", + "symfony/cache": "^6.2", + "symfony/http-client": "^6.2.4", + "symfony/psr-http-message-bridge": "^2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", + "league/flysystem-read-only": "Required to use read-only disks (^3.3)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "mockery/mockery": "Required to use mocking (^1.5.1).", + "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8|^10.0.7).", + "predis/predis": "Required to use the predis connector (^2.0.2).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^6.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-12-05T14:50:33+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.1.13", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a", + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/collections": "^10.0|^11.0", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.1.13" + }, + "time": "2023-10-27T13:53:59+00:00" + }, + { + "name": "laravel/sanctum", + "version": "v3.3.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "e1a272893bec13cf135627f7e156030b3afe1e60" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/e1a272893bec13cf135627f7e156030b3afe1e60", + "reference": "e1a272893bec13cf135627f7e156030b3afe1e60", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9.21|^10.0", + "illuminate/contracts": "^9.21|^10.0", + "illuminate/database": "^9.21|^10.0", + "illuminate/support": "^9.21|^10.0", + "php": "^8.0.2" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.28.2|^8.8.3", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2023-11-03T13:42:14+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v1.3.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2023-11-08T14:08:06+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.8.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/b936d415b252b499e8c3b1f795cd4fc20f57e1f3", + "reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.10.4|^0.11.1", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.8.2" + }, + "time": "2023-08-15T14:27:00+00:00" + }, + { + "name": "league/commonmark", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/3669d6d5f7a47a93c08ddff335e6d945481a1dd5", + "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.30.0", + "commonmark/commonmark.js": "0.30.0", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2023-08-30T16:55:00+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.23.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "d4ad81e2b67396e33dc9d7e54ec74ccf73151dcc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d4ad81e2b67396e33dc9d7e54ec74ccf73151dcc", + "reference": "d4ad81e2b67396e33dc9d7e54ec74ccf73151dcc", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.220.0", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "microsoft/azure-storage-blob": "^1.1", + "phpseclib/phpseclib": "^3.0.34", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.23.0" + }, + "funding": [ + { + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + } + ], + "time": "2023-12-04T10:16:17+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.23.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "5cf046ba5f059460e86a997c504dd781a39a109b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/5cf046ba5f059460e86a997c504dd781a39a109b", + "reference": "5cf046ba5f059460e86a997c504dd781a39a109b", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem-local/issues", + "source": "https://github.com/thephpleague/flysystem-local/tree/3.23.0" + }, + "funding": [ + { + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + } + ], + "time": "2023-12-04T10:14:46+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "b6a5854368533df0295c5761a0253656a2e52d9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/b6a5854368533df0295c5761a0253656a2e52d9e", + "reference": "b6a5854368533df0295c5761a0253656a2e52d9e", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "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.14.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2023-10-17T14:13:20+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.5.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448", + "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^10.1", + "predis/predis": "^1.1 || ^2", + "ruflin/elastica": "^7", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.5.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2023-10-27T15:32:31+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.72.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "a6885fcbad2ec4360b0e200ee0da7d9b7c90786b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/a6885fcbad2ec4360b0e200ee0da7d9b7c90786b", + "reference": "a6885fcbad2ec4360b0e200ee0da7d9b7c90786b", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "*", + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "psr/clock": "^1.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2023-11-28T10:13:25+00:00" + }, + { + "name": "nette/schema", + "version": "v1.2.5", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a", + "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a", + "shasum": "" + }, + "require": { + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": "7.1 - 8.3" + }, + "require-dev": { + "nette/tester": "^2.3 || ^2.4", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.2.5" + }, + "time": "2023-10-05T20:37:59+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.3", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/a9d127dd6a203ce6d255b2e2db49759f7506e015", + "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015", + "shasum": "" + }, + "require": { + "php": ">=8.0 <8.4" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.5", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.3" + }, + "time": "2023-10-29T21:02:13+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.17.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-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/v4.17.1" + }, + "time": "2023-08-13T19:53:39+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v1.15.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.0", + "symfony/console": "^5.3.0|^6.0.0" + }, + "require-dev": { + "ergebnis/phpstan-rules": "^1.0.", + "illuminate/console": "^8.0|^9.0", + "illuminate/support": "^8.0|^9.0", + "laravel/pint": "^1.0.0", + "pestphp/pest": "^1.21.0", + "pestphp/pest-plugin-mock": "^1.0", + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-strict-rules": "^1.1.0", + "symfony/var-dumper": "^5.2.7|^6.0.0", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v1.15.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2023-02-08T01:06:31+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.2", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-11-12T21:59:55+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.11.22", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/128fa1b608be651999ed9789c95e6e2a31b5802b", + "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^4.0 || ^3.1", + "php": "^8.0 || ^7.0.8", + "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-0.11": "0.11.x-dev" + }, + "bamarni-bin": { + "bin-links": false, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.11.22" + }, + "time": "2023-10-14T21:56:36+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.5", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.5" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2023-11-08T05:53:05+00:00" + }, + { + "name": "stichoza/google-translate-php", + "version": "v5.1.2", + "source": { + "type": "git", + "url": "https://github.com/Stichoza/google-translate-php.git", + "reference": "e43089e0c6fcc366027e8bf593060bb4e9c2c839" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Stichoza/google-translate-php/zipball/e43089e0c6fcc366027e8bf593060bb4e9c2c839", + "reference": "e43089e0c6fcc366027e8bf593060bb4e9c2c839", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "guzzlehttp/guzzle": "^7.0", + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Stichoza\\GoogleTranslate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Levan Velijanashvili", + "email": "me@stichoza.com" + } + ], + "description": "Free Google Translate API PHP Package", + "homepage": "https://github.com/Stichoza/google-translate-php", + "keywords": [ + "google", + "php", + "translate", + "translating", + "translator" + ], + "support": { + "issues": "https://github.com/Stichoza/google-translate-php/issues", + "source": "https://github.com/Stichoza/google-translate-php/tree/v5.1.2" + }, + "funding": [ + { + "url": "https://btc.com/bc1qc25j4x7yahghm8nnn6lypnw59nptylsw32nkfl", + "type": "custom" + }, + { + "url": "https://www.paypal.me/stichoza", + "type": "custom" + }, + { + "url": "https://ko-fi.com/stichoza", + "type": "ko_fi" + }, + { + "url": "https://liberapay.com/stichoza", + "type": "liberapay" + }, + { + "url": "https://opencollective.com/stichoza", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/stichoza", + "type": "patreon" + } + ], + "time": "2023-08-04T01:11:03+00:00" + }, + { + "name": "symfony/console", + "version": "v6.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-11-30T10:54:28+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/d036c6c0d0b09e24a14a35f8292146a658f986e4", + "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v6.4.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": "2023-10-31T08:40:20+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.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": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788", + "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v6.4.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": "2023-10-18T09:43:34+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e", + "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.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": "2023-07-27T16:29:09+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.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": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.4.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": "2023-10-31T17:30:12+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", + "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "symfony/cache": "<6.3" + }, + "require-dev": { + "doctrine/dbal": "^2.13.1|^3|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.3|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v6.4.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": "2023-11-20T16:41:16+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v6.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "2953274c16a229b3933ef73a6898e18388e12e1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2953274c16a229b3933ef73a6898e18388e12e1b", + "reference": "2953274c16a229b3933ef73a6898e18388e12e1b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.4", + "symfony/config": "<6.1", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<5.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.3", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.5|^6.0.5|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-exporter": "^6.2|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v6.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-12-01T17:02:02+00:00" + }, + { + "name": "symfony/mailer", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.4.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": "2023-11-12T18:02:22+00:00" + }, + { + "name": "symfony/mime", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "ca4f58b2ef4baa8f6cecbeca2573f88cd577d205" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/ca4f58b2ef4baa8f6cecbeca2573f88cd577d205", + "reference": "ca4f58b2ef4baa8f6cecbeca2573f88cd577d205", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.3.2" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3.2|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v6.4.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": "2023-10-17T11:49:05+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "875e90aeea2777b6f135677f618529449334a612" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", + "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": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "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" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.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": "2023-01-26T09:30:37+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.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": "2023-07-28T09:04:16+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.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": "2023-08-16T06:22:46+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e", + "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/process", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa", + "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.4.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": "2023-11-17T21:06:49+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/0c95c164fdba18b12523b75e64199ca3503e6d40", + "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "symfony/config": "<6.2", + "symfony/dependency-injection": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.2|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v6.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-12-01T14:54:37+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.4.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": "2023-07-30T20:28:31+00:00" + }, + { + "name": "symfony/string", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.0.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": "2023-11-29T08:40:23+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.4.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": "2023-11-29T08:14:36+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.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": "2023-07-25T15:08:44+00:00" + }, + { + "name": "symfony/uid", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "8092dd1b1a41372110d06374f99ee62f7f0b9a92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/8092dd1b1a41372110d06374f99ee62f7f0b9a92", + "reference": "8092dd1b1a41372110d06374f99ee62f7f0b9a92", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v6.4.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": "2023-10-31T08:18:17+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.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": "2023-11-09T08:28:32+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "2.2.6", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^5.5 || ^7.0 || ^8.0", + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.6" + }, + "time": "2023-01-03T09:29:04+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.2", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2023-11-12T22:43:29+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b56450eed252f6801410d810c8e1727224ae0743" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "amphp/amp", + "version": "v2.6.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "psalm/phar": "^3.11@dev", + "react/promise": "^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "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": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2022-02-20T17:52:18+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.8.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", + "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "lib" + } + }, + "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": "http://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2021-03-30T17:13:30+00:00" + }, + { + "name": "barryvdh/laravel-debugbar", + "version": "v3.9.2", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-debugbar.git", + "reference": "bfd0131c146973cab164e50f5cdd8a67cc60cab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/bfd0131c146973cab164e50f5cdd8a67cc60cab1", + "reference": "bfd0131c146973cab164e50f5cdd8a67cc60cab1", + "shasum": "" + }, + "require": { + "illuminate/routing": "^9|^10", + "illuminate/session": "^9|^10", + "illuminate/support": "^9|^10", + "maximebf/debugbar": "^1.18.2", + "php": "^8.0", + "symfony/finder": "^6" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "orchestra/testbench-dusk": "^5|^6|^7|^8", + "phpunit/phpunit": "^8.5.30|^9.0", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.8-dev" + }, + "laravel": { + "providers": [ + "Barryvdh\\Debugbar\\ServiceProvider" + ], + "aliases": { + "Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Barryvdh\\Debugbar\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "PHP Debugbar integration for Laravel", + "keywords": [ + "debug", + "debugbar", + "laravel", + "profiler", + "webprofiler" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-debugbar/issues", + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.9.2" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-08-25T18:43:57+00:00" + }, + { + "name": "barryvdh/laravel-ide-helper", + "version": "v2.13.0", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-ide-helper.git", + "reference": "81d5b223ff067a1f38e14c100997e153b837fe4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/81d5b223ff067a1f38e14c100997e153b837fe4a", + "reference": "81d5b223ff067a1f38e14c100997e153b837fe4a", + "shasum": "" + }, + "require": { + "barryvdh/reflection-docblock": "^2.0.6", + "composer/class-map-generator": "^1.0", + "doctrine/dbal": "^2.6 || ^3", + "ext-json": "*", + "illuminate/console": "^8 || ^9 || ^10", + "illuminate/filesystem": "^8 || ^9 || ^10", + "illuminate/support": "^8 || ^9 || ^10", + "nikic/php-parser": "^4.7", + "php": "^7.3 || ^8.0", + "phpdocumentor/type-resolver": "^1.1.0" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "friendsofphp/php-cs-fixer": "^2", + "illuminate/config": "^8 || ^9 || ^10", + "illuminate/view": "^8 || ^9 || ^10", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^6 || ^7 || ^8", + "phpunit/phpunit": "^8.5 || ^9", + "spatie/phpunit-snapshot-assertions": "^3 || ^4", + "vimeo/psalm": "^3.12" + }, + "suggest": { + "illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.12-dev" + }, + "laravel": { + "providers": [ + "Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\LaravelIdeHelper\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.", + "keywords": [ + "autocomplete", + "codeintel", + "helper", + "ide", + "laravel", + "netbeans", + "phpdoc", + "phpstorm", + "sublime" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.13.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-02-04T13:56:40+00:00" + }, + { + "name": "barryvdh/reflection-docblock", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/ReflectionDocBlock.git", + "reference": "e6811e927f0ecc37cc4deaa6627033150343e597" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/e6811e927f0ecc37cc4deaa6627033150343e597", + "reference": "e6811e927f0ecc37cc4deaa6627033150343e597", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.14|^9" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Barryvdh": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "support": { + "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.1.1" + }, + "time": "2023-06-14T05:06:27+00:00" + }, + { + "name": "composer/class-map-generator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/class-map-generator.git", + "reference": "953cc4ea32e0c31f2185549c7d216d7921f03da9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/953cc4ea32e0c31f2185549c7d216d7921f03da9", + "reference": "953cc4ea32e0c31f2185549c7d216d7921f03da9", + "shasum": "" + }, + "require": { + "composer/pcre": "^2.1 || ^3.1", + "php": "^7.2 || ^8.0", + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.6", + "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/filesystem": "^5.4 || ^6", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\ClassMapGenerator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Utilities to scan PHP code and generate class maps.", + "keywords": [ + "classmap" + ], + "support": { + "issues": "https://github.com/composer/class-map-generator/issues", + "source": "https://github.com/composer/class-map-generator/tree/1.1.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-06-30T13:58:57+00:00" + }, + { + "name": "composer/pcre", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-10-11T07:11:09+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T21:32:43+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/cache", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", + "shasum": "" + }, + "require": { + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2022-05-20T20:07:39+00:00" + }, + { + "name": "doctrine/dbal", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1|^2", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "12.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.1", + "phpstan/phpstan": "1.10.42", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "9.6.13", + "psalm/plugin-phpunit": "0.18.4", + "slevomat/coding-standard": "8.13.1", + "squizlabs/php_codesniffer": "3.7.2", + "symfony/cache": "^5.4|^6.0", + "symfony/console": "^4.4|^5.4|^6.0", + "vimeo/psalm": "4.30.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.7.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2023-11-19T08:06:58+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.2" + }, + "time": "2023-09-27T20:04:15+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2022-10-12T20:59:15+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "v1.21-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" + }, + "time": "2023-06-12T08:44:38+00:00" + }, + { + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "php": "^7.1 || ^8.0", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + }, + "time": "2021-06-11T22:34:44+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.2", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" + }, + "time": "2022-03-02T22:36:06+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^9.5.26 || ^8.5.31", + "theofidry/php-cs-fixer-config": "^1.0", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/0.5.1" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2022-12-24T12:35:10+00:00" + }, + { + "name": "filp/whoops", + "version": "2.15.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^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" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.15.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2023-11-03T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, + "time": "2020-07-09T08:09:16+00:00" + }, + { + "name": "laravel/breeze", + "version": "v1.26.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/breeze.git", + "reference": "60f339c38098bc5adbf8614bf5d89b77647a06c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/breeze/zipball/60f339c38098bc5adbf8614bf5d89b77647a06c5", + "reference": "60f339c38098bc5adbf8614bf5d89b77647a06c5", + "shasum": "" + }, + "require": { + "illuminate/console": "^10.17", + "illuminate/filesystem": "^10.17", + "illuminate/support": "^10.17", + "illuminate/validation": "^10.17", + "php": "^8.1.0" + }, + "require-dev": { + "orchestra/testbench": "^8.0", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Breeze\\BreezeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Breeze\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.", + "keywords": [ + "auth", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/breeze/issues", + "source": "https://github.com/laravel/breeze" + }, + "time": "2023-11-24T14:41:28+00:00" + }, + { + "name": "laravel/dusk", + "version": "v7.12.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/dusk.git", + "reference": "94534fa924600e7a103f177d41b74e9b94f0994d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/dusk/zipball/94534fa924600e7a103f177d41b74e9b94f0994d", + "reference": "94534fa924600e7a103f177d41b74e9b94f0994d", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "^7.2", + "illuminate/console": "^9.0|^10.0", + "illuminate/support": "^9.0|^10.0", + "nesbot/carbon": "^2.0", + "php": "^8.0", + "php-webdriver/webdriver": "^1.9.0", + "symfony/console": "^6.0", + "symfony/finder": "^6.0", + "symfony/process": "^6.0", + "vlucas/phpdotenv": "^5.2" + }, + "require-dev": { + "mockery/mockery": "^1.4.2", + "orchestra/testbench": "^7.33|^8.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.10|^10.0.1", + "psy/psysh": "^0.11.12" + }, + "suggest": { + "ext-pcntl": "Used to gracefully terminate Dusk when tests are running." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Dusk\\DuskServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Dusk\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Dusk provides simple end-to-end testing and browser automation.", + "keywords": [ + "laravel", + "testing", + "webdriver" + ], + "support": { + "issues": "https://github.com/laravel/dusk/issues", + "source": "https://github.com/laravel/dusk/tree/v7.12.0" + }, + "time": "2023-12-05T15:05:04+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.13.7", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "4157768980dbd977f1c4b4cc94997416d8b30ece" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/4157768980dbd977f1c4b4cc94997416d8b30ece", + "reference": "4157768980dbd977f1c4b4cc94997416d8b30ece", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.38.0", + "illuminate/view": "^10.30.1", + "laravel-zero/framework": "^10.3.0", + "mockery/mockery": "^1.6.6", + "nunomaduro/larastan": "^2.6.4", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^2.24.2" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2023-12-05T19:43:12+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.26.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "fa1ad5fbb03686dfc752bfd1861d86091cc1c32d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/fa1ad5fbb03686dfc752bfd1861d86091cc1c32d", + "reference": "fa1ad5fbb03686dfc752bfd1861d86091cc1c32d", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.0|^10.0|^11.0", + "illuminate/contracts": "^9.0|^10.0|^11.0", + "illuminate/support": "^9.0|^10.0|^11.0", + "php": "^8.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2023-12-02T18:26:39+00:00" + }, + { + "name": "maximebf/debugbar", + "version": "v1.19.1", + "source": { + "type": "git", + "url": "https://github.com/maximebf/php-debugbar.git", + "reference": "03dd40a1826f4d585ef93ef83afa2a9874a00523" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/03dd40a1826f4d585ef93ef83afa2a9874a00523", + "reference": "03dd40a1826f4d585ef93ef83afa2a9874a00523", + "shasum": "" + }, + "require": { + "php": "^7.1|^8", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4|^5|^6" + }, + "require-dev": { + "phpunit/phpunit": ">=7.5.20 <10.0", + "twig/twig": "^1.38|^2.7|^3.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.18-dev" + } + }, + "autoload": { + "psr-4": { + "DebugBar\\": "src/DebugBar/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/maximebf/php-debugbar", + "keywords": [ + "debug", + "debugbar" + ], + "support": { + "issues": "https://github.com/maximebf/php-debugbar/issues", + "source": "https://github.com/maximebf/php-debugbar/tree/v1.19.1" + }, + "time": "2023-10-12T08:10:52+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.6", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/b8e0bb7d8c604046539c1115994632c74dcb361e", + "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.10", + "psalm/plugin-phpunit": "^0.18.4", + "symplify/easy-coding-standard": "^11.5.0", + "vimeo/psalm": "^4.30" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2023-08-09T00:03:52+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "netresearch/jsonmapper", + "version": "v4.2.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", + "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + }, + "time": "2023-04-09T17:37:40+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v7.10.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.15.3", + "nunomaduro/termwind": "^1.15.1", + "php": "^8.1.0", + "symfony/console": "^6.3.4" + }, + "conflict": { + "laravel/framework": ">=11.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.3.0", + "laravel/framework": "^10.28.0", + "laravel/pint": "^1.13.3", + "laravel/sail": "^1.25.0", + "laravel/sanctum": "^3.3.1", + "laravel/tinker": "^2.8.2", + "nunomaduro/larastan": "^2.6.4", + "orchestra/testbench-core": "^8.13.0", + "pestphp/pest": "^2.23.2", + "phpunit/phpunit": "^10.4.1", + "sebastian/environment": "^6.0.1", + "spatie/laravel-ignition": "^2.3.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "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": "2023-10-11T15:45:01+00:00" + }, + { + "name": "nunomaduro/larastan", + "version": "v2.7.0", + "source": { + "type": "git", + "url": "https://github.com/larastan/larastan.git", + "reference": "a2610d46b9999cf558d9900ccb641962d1442f55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/larastan/larastan/zipball/a2610d46b9999cf558d9900ccb641962d1442f55", + "reference": "a2610d46b9999cf558d9900ccb641962d1442f55", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9.52.16 || ^10.28.0", + "illuminate/container": "^9.52.16 || ^10.28.0", + "illuminate/contracts": "^9.52.16 || ^10.28.0", + "illuminate/database": "^9.52.16 || ^10.28.0", + "illuminate/http": "^9.52.16 || ^10.28.0", + "illuminate/pipeline": "^9.52.16 || ^10.28.0", + "illuminate/support": "^9.52.16 || ^10.28.0", + "php": "^8.0.2", + "phpmyadmin/sql-parser": "^5.8.2", + "phpstan/phpstan": "^1.10.41" + }, + "require-dev": { + "nikic/php-parser": "^4.17.1", + "orchestra/canvas": "^7.11.1 || ^8.11.0", + "orchestra/testbench": "^7.33.0 || ^8.13.0", + "phpunit/phpunit": "^9.6.13" + }, + "suggest": { + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Larastan\\Larastan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Can Vural", + "email": "can9119@gmail.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan wrapper for Laravel", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "larastan", + "laravel", + "package", + "php", + "static analysis" + ], + "support": { + "issues": "https://github.com/larastan/larastan/issues", + "source": "https://github.com/larastan/larastan/tree/v2.7.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/canvural", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "abandoned": "larastan/larastan", + "time": "2023-12-04T19:21:38+00:00" + }, + { + "name": "orchestra/canvas", + "version": "v8.11.4", + "source": { + "type": "git", + "url": "https://github.com/orchestral/canvas.git", + "reference": "466ed3d7c1755e49be1c8e5557b434381b8ab6d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/canvas/zipball/466ed3d7c1755e49be1c8e5557b434381b8ab6d1", + "reference": "466ed3d7c1755e49be1c8e5557b434381b8ab6d1", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "composer/semver": "^3.0", + "illuminate/console": "^10.33", + "illuminate/database": "^10.33", + "illuminate/support": "^10.33", + "orchestra/canvas-core": "^8.10.1", + "orchestra/testbench-core": "^8.11", + "php": "^8.1", + "symfony/polyfill-php83": "^1.28", + "symfony/yaml": "^6.2" + }, + "require-dev": { + "laravel/framework": "^10.33", + "laravel/pint": "^1.6", + "mockery/mockery": "^1.5.1", + "phpstan/phpstan": "^1.10.5", + "phpunit/phpunit": "^10.1", + "spatie/laravel-ray": "^1.32.4" + }, + "bin": [ + "canvas" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.0-dev" + }, + "laravel": { + "providers": [ + "Orchestra\\Canvas\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Canvas\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Code Generators for Laravel Applications and Packages", + "support": { + "issues": "https://github.com/orchestral/canvas/issues", + "source": "https://github.com/orchestral/canvas/tree/v8.11.4" + }, + "time": "2023-11-27T04:47:24+00:00" + }, + { + "name": "orchestra/canvas-core", + "version": "v8.10.1", + "source": { + "type": "git", + "url": "https://github.com/orchestral/canvas-core.git", + "reference": "d4c3325d231deceecdc33fa0b3698efd132ce9f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/canvas-core/zipball/d4c3325d231deceecdc33fa0b3698efd132ce9f0", + "reference": "d4c3325d231deceecdc33fa0b3698efd132ce9f0", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "composer/semver": "^3.0", + "illuminate/console": "^10.26", + "illuminate/filesystem": "^10.26", + "php": "^8.1", + "symfony/polyfill-php83": "^1.28" + }, + "conflict": { + "orchestra/canvas": "<8.11.0", + "orchestra/testbench-core": "<8.2.0" + }, + "require-dev": { + "laravel/framework": "^10.26", + "laravel/pint": "^1.6", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^8.15", + "phpstan/phpstan": "^1.10.6", + "phpunit/phpunit": "^10.1", + "symfony/yaml": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.0-dev" + }, + "laravel": { + "providers": [ + "Orchestra\\Canvas\\Core\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Canvas\\Core\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Code Generators Builder for Laravel Applications and Packages", + "support": { + "issues": "https://github.com/orchestral/canvas/issues", + "source": "https://github.com/orchestral/canvas-core/tree/v8.10.1" + }, + "time": "2023-11-27T03:19:28+00:00" + }, + { + "name": "orchestra/testbench", + "version": "v8.17.0", + "source": { + "type": "git", + "url": "https://github.com/orchestral/testbench.git", + "reference": "3bbe0956df4b6f811ca879e2a8d69a8a8b626587" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/3bbe0956df4b6f811ca879e2a8d69a8a8b626587", + "reference": "3bbe0956df4b6f811ca879e2a8d69a8a8b626587", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "fakerphp/faker": "^1.21", + "laravel/framework": "^10.23.1", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^8.17", + "orchestra/workbench": "^1.2 || ^8.2", + "php": "^8.1", + "phpunit/phpunit": "^9.6 || ^10.1", + "symfony/process": "^6.2", + "symfony/yaml": "^6.2", + "vlucas/phpdotenv": "^5.4.1" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com", + "homepage": "https://github.com/crynobone" + } + ], + "description": "Laravel Testing Helper for Packages Development", + "homepage": "https://packages.tools/testbench/", + "keywords": [ + "BDD", + "TDD", + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/testbench/issues", + "source": "https://github.com/orchestral/testbench/tree/v8.17.0" + }, + "time": "2023-12-06T03:25:17+00:00" + }, + { + "name": "orchestra/testbench-core", + "version": "v8.17.1", + "source": { + "type": "git", + "url": "https://github.com/orchestral/testbench-core.git", + "reference": "6856e979790c18705812b2b6c3c73bb1f6d8baa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/6856e979790c18705812b2b6c3c73bb1f6d8baa8", + "reference": "6856e979790c18705812b2b6c3c73bb1f6d8baa8", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "php": "^8.1", + "symfony/polyfill-php83": "^1.28" + }, + "conflict": { + "brianium/paratest": "<6.4.0 || >=7.0.0 <7.1.4 || >=8.0.0", + "laravel/framework": "<10.23.1 || >=11.0.0", + "nunomaduro/collision": "<6.4.0 || >=7.0.0 <7.4.0 || >=8.0.0", + "orchestra/workbench": "<1.0.0", + "phpunit/phpunit": "<9.6.0 || >=10.6.0" + }, + "require-dev": { + "fakerphp/faker": "^1.21", + "laravel/framework": "^10.23", + "laravel/pint": "^1.6", + "mockery/mockery": "^1.5.1", + "phpstan/phpstan": "^1.10.7", + "phpunit/phpunit": "^10.1", + "spatie/laravel-ray": "^1.32.4", + "symfony/process": "^6.2", + "symfony/yaml": "^6.2", + "vlucas/phpdotenv": "^5.4.1" + }, + "suggest": { + "brianium/paratest": "Allow using parallel testing (^6.4 || ^7.1.4).", + "fakerphp/faker": "Allow using Faker for testing (^1.21).", + "laravel/framework": "Required for testing (^10.23).", + "mockery/mockery": "Allow using Mockery for testing (^1.5.1).", + "nunomaduro/collision": "Allow using Laravel style tests output and parallel testing (^6.4 || ^7.4).", + "orchestra/testbench-browser-kit": "Allow using legacy Laravel BrowserKit for testing (^8.0).", + "orchestra/testbench-dusk": "Allow using Laravel Dusk for testing (^8.0).", + "phpunit/phpunit": "Allow using PHPUnit for testing (^9.6 || ^10.1).", + "symfony/yaml": "Required for CLI Commander (^6.2).", + "vlucas/phpdotenv": "Required for CLI Commander (^5.4.1)." + }, + "bin": [ + "testbench" + ], + "type": "library", + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Orchestra\\Testbench\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com", + "homepage": "https://github.com/crynobone" + } + ], + "description": "Testing Helper for Laravel Development", + "homepage": "https://packages.tools/testbench", + "keywords": [ + "BDD", + "TDD", + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/testbench/issues", + "source": "https://github.com/orchestral/testbench-core" + }, + "time": "2023-12-06T08:00:50+00:00" + }, + { + "name": "orchestra/workbench", + "version": "v8.2.0", + "source": { + "type": "git", + "url": "https://github.com/orchestral/workbench.git", + "reference": "63b3961efa515abfcfd340805e6713eb540b7a39" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/workbench/zipball/63b3961efa515abfcfd340805e6713eb540b7a39", + "reference": "63b3961efa515abfcfd340805e6713eb540b7a39", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "fakerphp/faker": "^1.21", + "laravel/framework": "^10.26", + "laravel/tinker": "^2.8.2", + "orchestra/canvas": "^8.11.4", + "orchestra/testbench-core": "^8.17", + "php": "^8.1", + "spatie/laravel-ray": "^1.32.4", + "symfony/polyfill-php83": "^1.28", + "symfony/yaml": "^6.2" + }, + "require-dev": { + "laravel/pint": "^1.4", + "mockery/mockery": "^1.5.1", + "phpstan/phpstan": "^1.10.7", + "phpunit/phpunit": "^10.1", + "symfony/process": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Workbench\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Workbench Companion for Laravel Packages Development", + "keywords": [ + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/workbench/issues", + "source": "https://github.com/orchestral/workbench/tree/v8.2.0" + }, + "time": "2023-12-06T02:59:43+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "php-webdriver/webdriver", + "version": "1.15.1", + "source": { + "type": "git", + "url": "https://github.com/php-webdriver/php-webdriver.git", + "reference": "cd52d9342c5aa738c2e75a67e47a1b6df97154e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/cd52d9342c5aa738c2e75a67e47a1b6df97154e8", + "reference": "cd52d9342c5aa738c2e75a67e47a1b6df97154e8", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-zip": "*", + "php": "^7.3 || ^8.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/process": "^5.0 || ^6.0 || ^7.0" + }, + "replace": { + "facebook/webdriver": "*" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.20.0", + "ondram/ci-detector": "^4.0", + "php-coveralls/php-coveralls": "^2.4", + "php-mock/php-mock-phpunit": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^5.0 || ^6.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "autoload": { + "files": [ + "lib/Exception/TimeoutException.php" + ], + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.", + "homepage": "https://github.com/php-webdriver/php-webdriver", + "keywords": [ + "Chromedriver", + "geckodriver", + "php", + "selenium", + "webdriver" + ], + "support": { + "issues": "https://github.com/php-webdriver/php-webdriver/issues", + "source": "https://github.com/php-webdriver/php-webdriver/tree/1.15.1" + }, + "time": "2023-10-20T12:21:20+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.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "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": "account@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.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.7.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^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.7.3" + }, + "time": "2023-08-12T11:01:26+00:00" + }, + { + "name": "phpmyadmin/sql-parser", + "version": "5.8.2", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/sql-parser.git", + "reference": "f1720ae19abe6294cb5599594a8a57bc3c8cc287" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/f1720ae19abe6294cb5599594a8a57bc3c8cc287", + "reference": "f1720ae19abe6294cb5599594a8a57bc3c8cc287", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "phpmyadmin/motranslator": "<3.0" + }, + "require-dev": { + "phpbench/phpbench": "^1.1", + "phpmyadmin/coding-standard": "^3.0", + "phpmyadmin/motranslator": "^4.0 || ^5.0", + "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", + "psalm/plugin-phpunit": "^0.16.1", + "vimeo/psalm": "^4.11", + "zumba/json-serializer": "~3.0.2" + }, + "suggest": { + "ext-mbstring": "For best performance", + "phpmyadmin/motranslator": "Translate messages to your favorite locale" + }, + "bin": [ + "bin/highlight-query", + "bin/lint-query", + "bin/tokenize-query" + ], + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\SqlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "A validating SQL lexer and parser with a focus on MySQL dialect.", + "homepage": "https://github.com/phpmyadmin/sql-parser", + "keywords": [ + "analysis", + "lexer", + "parser", + "query linter", + "sql", + "sql lexer", + "sql linter", + "sql parser", + "sql syntax highlighter", + "sql tokenizer" + ], + "support": { + "issues": "https://github.com/phpmyadmin/sql-parser/issues", + "source": "https://github.com/phpmyadmin/sql-parser" + }, + "funding": [ + { + "url": "https://www.phpmyadmin.net/donate/", + "type": "other" + } + ], + "time": "2023-09-19T12:34:29+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.24.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6bd0c26f3786cd9b7c359675cb789e35a8e07496", + "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496", + "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.24.4" + }, + "time": "2023-11-26T18:29:22+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.10.47", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "84dbb33b520ea28b6cf5676a3941f4bae1c1ff39" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/84dbb33b520ea28b6cf5676a3941f4bae1c1ff39", + "reference": "84dbb33b520ea28b6cf5676a3941f4bae1c1ff39", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-12-01T15:19:17+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "a56a9ab2f680246adcf3db43f38ddf1765774735" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a56a9ab2f680246adcf3db43f38ddf1765774735", + "reference": "a56a9ab2f680246adcf3db43f38ddf1765774735", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "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" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.9" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-11-23T12:23:20+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T06:24:48+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "5aedff46afba98dddecaa12349ec044d9103d4fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5aedff46afba98dddecaa12349ec044d9103d4fe", + "reference": "5aedff46afba98dddecaa12349ec044d9103d4fe", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "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" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.2" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-12-05T14:54:33+00:00" + }, + { + "name": "pimple/pimple", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed", + "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1 || ^2.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.4@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "https://pimple.symfony.com", + "keywords": [ + "container", + "dependency injection" + ], + "support": { + "source": "https://github.com/silexphp/Pimple/tree/v3.5.0" + }, + "time": "2021-10-28T11:13:42+00:00" + }, + { + "name": "psalm/plugin-laravel", + "version": "v2.8.0", + "source": { + "type": "git", + "url": "https://github.com/psalm/psalm-plugin-laravel.git", + "reference": "0b42a51f977d216e0b5d649f68346e2f324f4a55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/psalm/psalm-plugin-laravel/zipball/0b42a51f977d216e0b5d649f68346e2f324f4a55", + "reference": "0b42a51f977d216e0b5d649f68346e2f324f4a55", + "shasum": "" + }, + "require": { + "barryvdh/laravel-ide-helper": "^2.13", + "ext-simplexml": "*", + "illuminate/config": "^9.48 || ^10.0", + "illuminate/container": "^9.48 || ^10.0", + "illuminate/contracts": "^9.48 || ^10.0", + "illuminate/database": "^9.48 || ^10.0", + "illuminate/events": "^9.48 || ^10.0", + "illuminate/http": "^9.48 || ^10.0", + "illuminate/routing": "^9.48 || ^10.0", + "illuminate/support": "^9.48 || ^10.0", + "illuminate/view": "^9.48 || ^10.0", + "nikic/php-parser": "^4.13", + "orchestra/testbench": "^7.19 || ^8.0", + "php": "^8.0.2", + "symfony/console": "^6.0", + "vimeo/psalm": "^4.30 || ^5.1" + }, + "require-dev": { + "codeception/codeception": "^5.0", + "codeception/module-asserts": "^3.0", + "codeception/module-cli": "^2.0", + "codeception/module-filesystem": "^3.0", + "codeception/module-phpbrowser": "^3.0", + "phpunit/phpunit": "^9.6 || ^10.0", + "ramsey/collection": "^1.3", + "slevomat/coding-standard": "^8.8", + "squizlabs/php_codesniffer": "*", + "symfony/http-foundation": "^6.0" + }, + "type": "psalm-plugin", + "extra": { + "psalm": { + "pluginClass": "Psalm\\LaravelPlugin\\Plugin" + } + }, + "autoload": { + "psr-4": { + "Psalm\\LaravelPlugin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown", + "email": "github@muglug.com" + } + ], + "description": "A Laravel plugin for Psalm", + "homepage": "https://github.com/psalm/psalm-plugin-laravel", + "support": { + "issues": "https://github.com/psalm/psalm-plugin-laravel/issues", + "source": "https://github.com/psalm/psalm-plugin-laravel/tree/v2.8.0" + }, + "time": "2023-02-26T18:23:48+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:15+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-14T13:18:12+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68cfb347a44871f01e33ab0ef8215966432f6957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957", + "reference": "68cfb347a44871f01e33ab0ef8215966432f6957", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-09-28T11:50:59+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-01T07:48:21+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-04-11T05:39:26+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc", + "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-09-24T13:22:09+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-07-19T07:19:23+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T09:25:50+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "spatie/array-to-xml", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/array-to-xml.git", + "reference": "96be97e664c87613121d073ea39af4c74e57a7f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/96be97e664c87613121d073ea39af4c74e57a7f8", + "reference": "96be97e664c87613121d073ea39af4c74e57a7f8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "pestphp/pest": "^1.21", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ArrayToXml\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://freek.dev", + "role": "Developer" + } + ], + "description": "Convert an array to xml", + "homepage": "https://github.com/spatie/array-to-xml", + "keywords": [ + "array", + "convert", + "xml" + ], + "support": { + "source": "https://github.com/spatie/array-to-xml/tree/3.2.2" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-11-14T14:08:51+00:00" + }, + { + "name": "spatie/backtrace", + "version": "1.5.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/backtrace.git", + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/483f76a82964a0431aa836b6ed0edde0c248e3ab", + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "ext-json": "*", + "phpunit/phpunit": "^9.3", + "spatie/phpunit-snapshot-assertions": "^4.2", + "symfony/var-dumper": "^5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Backtrace\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van de Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A better backtrace", + "homepage": "https://github.com/spatie/backtrace", + "keywords": [ + "Backtrace", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/backtrace/tree/1.5.3" + }, + "funding": [ + { + "url": "https://github.com/sponsors/spatie", + "type": "github" + }, + { + "url": "https://spatie.be/open-source/support-us", + "type": "other" + } + ], + "time": "2023-06-28T12:59:17+00:00" + }, + { + "name": "spatie/flare-client-php", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/flare-client-php.git", + "reference": "5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec", + "reference": "5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec", + "shasum": "" + }, + "require": { + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", + "nesbot/carbon": "^2.62.1", + "php": "^8.0", + "spatie/backtrace": "^1.5.2", + "symfony/http-foundation": "^5.2|^6.0|^7.0", + "symfony/mime": "^5.2|^6.0|^7.0", + "symfony/process": "^5.2|^6.0|^7.0", + "symfony/var-dumper": "^5.2|^6.0|^7.0" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.5.0", + "pestphp/pest": "^1.20|^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "spatie/phpunit-snapshot-assertions": "^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\FlareClient\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Send PHP errors to Flare", + "homepage": "https://github.com/spatie/flare-client-php", + "keywords": [ + "exception", + "flare", + "reporting", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/flare-client-php/issues", + "source": "https://github.com/spatie/flare-client-php/tree/1.4.3" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-10-17T15:54:07+00:00" + }, + { + "name": "spatie/ignition", + "version": "1.11.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/ignition.git", + "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/ignition/zipball/3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", + "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0", + "spatie/backtrace": "^1.5.3", + "spatie/flare-client-php": "^1.4.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "illuminate/cache": "^9.52|^10.0|^11.0", + "mockery/mockery": "^1.4", + "pestphp/pest": "^1.20|^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "psr/simple-cache-implementation": "*", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "simple-cache-implementation": "To cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Spatie\\Ignition\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for PHP applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/spatie/ignition/issues", + "source": "https://github.com/spatie/ignition" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-10-18T14:09:40+00:00" + }, + { + "name": "spatie/laravel-ignition", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-ignition.git", + "reference": "bf21cd15aa47fa4ec5d73bbc932005c70261efc8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/bf21cd15aa47fa4ec5d73bbc932005c70261efc8", + "reference": "bf21cd15aa47fa4ec5d73bbc932005c70261efc8", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/support": "^10.0", + "php": "^8.1", + "spatie/flare-client-php": "^1.3.5", + "spatie/ignition": "^1.9", + "symfony/console": "^6.2.3", + "symfony/var-dumper": "^6.2.3" + }, + "require-dev": { + "livewire/livewire": "^2.11", + "mockery/mockery": "^1.5.1", + "openai-php/client": "^0.3.4", + "orchestra/testbench": "^8.0", + "pestphp/pest": "^1.22.3", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.3", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "psr/simple-cache-implementation": "Needed to cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelIgnition\\IgnitionServiceProvider" + ], + "aliases": { + "Flare": "Spatie\\LaravelIgnition\\Facades\\Flare" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\LaravelIgnition\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for Laravel applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/spatie/laravel-ignition/issues", + "source": "https://github.com/spatie/laravel-ignition" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-10-09T12:55:26+00:00" + }, + { + "name": "spatie/laravel-ray", + "version": "1.33.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-ray.git", + "reference": "5028ae44a09451b26eb44490e3471998650788e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/5028ae44a09451b26eb44490e3471998650788e3", + "reference": "5028ae44a09451b26eb44490e3471998650788e3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/contracts": "^7.20|^8.19|^9.0|^10.0", + "illuminate/database": "^7.20|^8.19|^9.0|^10.0", + "illuminate/queue": "^7.20|^8.19|^9.0|^10.0", + "illuminate/support": "^7.20|^8.19|^9.0|^10.0", + "php": "^7.4|^8.0", + "spatie/backtrace": "^1.0", + "spatie/ray": "^1.37", + "symfony/stopwatch": "4.2|^5.1|^6.0", + "zbateson/mail-mime-parser": "^1.3.1|^2.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.3", + "laravel/framework": "^7.20|^8.19|^9.0|^10.0", + "orchestra/testbench-core": "^5.0|^6.0|^7.0|^8.0", + "pestphp/pest": "^1.22", + "phpstan/phpstan": "^0.12.93", + "phpunit/phpunit": "^9.3", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.29.x-dev" + }, + "laravel": { + "providers": [ + "Spatie\\LaravelRay\\RayServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelRay\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily debug Laravel apps", + "homepage": "https://github.com/spatie/laravel-ray", + "keywords": [ + "laravel-ray", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-ray/issues", + "source": "https://github.com/spatie/laravel-ray/tree/1.33.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/spatie", + "type": "github" + }, + { + "url": "https://spatie.be/open-source/support-us", + "type": "other" + } + ], + "time": "2023-09-04T10:16:53+00:00" + }, + { + "name": "spatie/macroable", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/macroable.git", + "reference": "ec2c320f932e730607aff8052c44183cf3ecb072" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/macroable/zipball/ec2c320f932e730607aff8052c44183cf3ecb072", + "reference": "ec2c320f932e730607aff8052c44183cf3ecb072", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Macroable\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A trait to dynamically add methods to a class", + "homepage": "https://github.com/spatie/macroable", + "keywords": [ + "macroable", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/macroable/issues", + "source": "https://github.com/spatie/macroable/tree/2.0.0" + }, + "time": "2021-03-26T22:39:02+00:00" + }, + { + "name": "spatie/ray", + "version": "1.40.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/ray.git", + "reference": "8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/ray/zipball/8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f", + "reference": "8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "php": "^7.3|^8.0", + "ramsey/uuid": "^3.0|^4.1", + "spatie/backtrace": "^1.1", + "spatie/macroable": "^1.0|^2.0", + "symfony/stopwatch": "^4.0|^5.1|^6.0", + "symfony/var-dumper": "^4.2|^5.1|^6.0" + }, + "require-dev": { + "illuminate/support": "6.x|^8.18|^9.0", + "nesbot/carbon": "^2.63", + "pestphp/pest": "^1.22", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5", + "spatie/phpunit-snapshot-assertions": "^4.2", + "spatie/test-time": "^1.2" + }, + "type": "library", + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\Ray\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Debug with Ray to fix problems faster", + "homepage": "https://github.com/spatie/ray", + "keywords": [ + "ray", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/ray/issues", + "source": "https://github.com/spatie/ray/tree/1.40.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/spatie", + "type": "github" + }, + { + "url": "https://spatie.be/open-source/support-us", + "type": "other" + } + ], + "time": "2023-11-20T08:20:15+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7da8ea2362a283771478c5f7729cfcb43a76b8b7", + "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.0.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": "2023-07-27T06:33:22+00:00" + }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "6de50471469b8c9afc38164452ab2b6170ee71c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/6de50471469b8c9afc38164452ab2b6170ee71c1", + "reference": "6de50471469b8c9afc38164452ab2b6170ee71c1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-iconv": "*" + }, + "suggest": { + "ext-iconv": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Iconv\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Iconv extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "iconv", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", + "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v6.4.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": "2023-02-16T10:14:28+00:00" + }, + { + "name": "symfony/yaml", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587", + "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v6.4.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": "2023-11-06T11:00:25+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2023-11-20T00:12:19+00:00" + }, + { + "name": "tightenco/duster", + "version": "v2.6.0", + "source": { + "type": "git", + "url": "https://github.com/tighten/duster.git", + "reference": "eb0e339c30abc990738f7881173f733e6520e424" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tighten/duster/zipball/eb0e339c30abc990738f7881173f733e6520e424", + "reference": "eb0e339c30abc990738f7881173f733e6520e424", + "shasum": "" + }, + "require": { + "php": "^8.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.21.1", + "laravel-zero/framework": "^10.1.1", + "laravel/pint": "^v1.11.0", + "nunomaduro/termwind": "^1.15.1", + "spatie/invade": "^1.1", + "squizlabs/php_codesniffer": "^3.7.2", + "tightenco/tlint": "^9.0" + }, + "bin": [ + "builds/duster" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Stauffer", + "email": "matt@tighten.com", + "homepage": "https://tighten.com", + "role": "Developer" + }, + { + "name": "Anthony Clark", + "email": "anthony@tighten.com", + "homepage": "https://tighten.com", + "role": "Developer" + } + ], + "description": "Automatic configuration for Laravel apps to apply Tighten's standard linting & code standards.", + "homepage": "https://github.com/tighten/duster", + "keywords": [ + "Code style", + "duster", + "laravel", + "php", + "tightenco" + ], + "support": { + "issues": "https://github.com/tighten/duster/issues", + "source": "https://github.com/tighten/duster" + }, + "time": "2023-12-01T18:43:59+00:00" + }, + { + "name": "vimeo/psalm", + "version": "5.17.0", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "c620f6e80d0abfca532b00bda366062aaedf6e5d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/c620f6e80d0abfca532b00bda366062aaedf6e5d", + "reference": "c620f6e80d0abfca532b00bda366062aaedf6e5d", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer-runtime-api": "^2", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/advanced-json-rpc": "^3.1", + "felixfbecker/language-server-protocol": "^1.5.2", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.16", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", + "sebastian/diff": "^4.0 || ^5.0", + "spatie/array-to-xml": "^2.17.0 || ^3.0", + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" + }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "amphp/phpunit-util": "^2.0", + "bamarni/composer-bin-plugin": "^1.4", + "brianium/paratest": "^6.9", + "ext-curl": "*", + "mockery/mockery": "^1.5", + "nunomaduro/mock-final-classes": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpdoc-parser": "^1.6", + "phpunit/phpunit": "^9.6", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.6", + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "project", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev", + "dev-4.x": "4.x-dev", + "dev-3.x": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\": "src/Psalm/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php", + "static analysis" + ], + "support": { + "docs": "https://psalm.dev/docs", + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm" + }, + "time": "2023-12-03T20:21:41+00:00" + }, + { + "name": "zbateson/mail-mime-parser", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/zbateson/mail-mime-parser.git", + "reference": "20b3e48eb799537683780bc8782fbbe9bc25934a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/20b3e48eb799537683780bc8782fbbe9bc25934a", + "reference": "20b3e48eb799537683780bc8782fbbe9bc25934a", + "shasum": "" + }, + "require": { + "guzzlehttp/psr7": "^1.7.0|^2.0", + "php": ">=7.1", + "pimple/pimple": "^3.0", + "zbateson/mb-wrapper": "^1.0.1", + "zbateson/stream-decorators": "^1.0.6" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "mikey179/vfsstream": "^1.6.0", + "phpstan/phpstan": "*", + "phpunit/phpunit": "<10" + }, + "suggest": { + "ext-iconv": "For best support/performance", + "ext-mbstring": "For best support/performance" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZBateson\\MailMimeParser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Zaahid Bateson" + }, + { + "name": "Contributors", + "homepage": "https://github.com/zbateson/mail-mime-parser/graphs/contributors" + } + ], + "description": "MIME email message parser", + "homepage": "https://mail-mime-parser.org", + "keywords": [ + "MimeMailParser", + "email", + "mail", + "mailparse", + "mime", + "mimeparse", + "parser", + "php-imap" + ], + "support": { + "docs": "https://mail-mime-parser.org/#usage-guide", + "issues": "https://github.com/zbateson/mail-mime-parser/issues", + "source": "https://github.com/zbateson/mail-mime-parser" + }, + "funding": [ + { + "url": "https://github.com/zbateson", + "type": "github" + } + ], + "time": "2023-02-14T22:58:03+00:00" + }, + { + "name": "zbateson/mb-wrapper", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/zbateson/mb-wrapper.git", + "reference": "faf35dddfacfc5d4d5f9210143eafd7a7fe74334" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/faf35dddfacfc5d4d5f9210143eafd7a7fe74334", + "reference": "faf35dddfacfc5d4d5f9210143eafd7a7fe74334", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-iconv": "^1.9", + "symfony/polyfill-mbstring": "^1.9" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "<=9.0" + }, + "suggest": { + "ext-iconv": "For best support/performance", + "ext-mbstring": "For best support/performance" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZBateson\\MbWrapper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Zaahid Bateson" + } + ], + "description": "Wrapper for mbstring with fallback to iconv for encoding conversion and string manipulation", + "keywords": [ + "charset", + "encoding", + "http", + "iconv", + "mail", + "mb", + "mb_convert_encoding", + "mbstring", + "mime", + "multibyte", + "string" + ], + "support": { + "issues": "https://github.com/zbateson/mb-wrapper/issues", + "source": "https://github.com/zbateson/mb-wrapper/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/zbateson", + "type": "github" + } + ], + "time": "2023-01-11T23:05:44+00:00" + }, + { + "name": "zbateson/stream-decorators", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/zbateson/stream-decorators.git", + "reference": "783b034024fda8eafa19675fb2552f8654d3a3e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/783b034024fda8eafa19675fb2552f8654d3a3e9", + "reference": "783b034024fda8eafa19675fb2552f8654d3a3e9", + "shasum": "" + }, + "require": { + "guzzlehttp/psr7": "^1.9 | ^2.0", + "php": ">=7.2", + "zbateson/mb-wrapper": "^1.0.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "<10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZBateson\\StreamDecorators\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Zaahid Bateson" + } + ], + "description": "PHP psr7 stream decorators for mime message part streams", + "keywords": [ + "base64", + "charset", + "decorators", + "mail", + "mime", + "psr7", + "quoted-printable", + "stream", + "uuencode" + ], + "support": { + "issues": "https://github.com/zbateson/stream-decorators/issues", + "source": "https://github.com/zbateson/stream-decorators/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/zbateson", + "type": "github" + } + ], + "time": "2023-05-30T22:51:52+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": { + "amirami/localizator": 15 + }, + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..9207160 --- /dev/null +++ b/config/app.php @@ -0,0 +1,188 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + 'asset_url' => env('ASSET_URL'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Faker Locale + |-------------------------------------------------------------------------- + | + | This locale will be used by the Faker PHP library when generating fake + | data for your database seeds. For example, this will be used to get + | localized telephone numbers, street address information and more. + | + */ + + 'faker_locale' => 'en_US', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => 'file', + // 'store' => 'redis', + ], + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => ServiceProvider::defaultProviders()->merge([ + /* + * Package Service Providers... + */ + + /* + * Application Service Providers... + */ + App\Providers\AppServiceProvider::class, + App\Providers\AuthServiceProvider::class, + // App\Providers\BroadcastServiceProvider::class, + App\Providers\EventServiceProvider::class, + App\Providers\RouteServiceProvider::class, + ])->toArray(), + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => Facade::defaultAliases()->merge([ + // 'Example' => App\Facades\Example::class, + ])->toArray(), + +]; diff --git a/config/auth.php b/config/auth.php new file mode 100644 index 0000000..9548c15 --- /dev/null +++ b/config/auth.php @@ -0,0 +1,115 @@ + [ + 'guard' => 'web', + 'passwords' => 'users', + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => App\Models\User::class, + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => 'password_reset_tokens', + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the amount of seconds before a password confirmation + | times out and the user is prompted to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => 10800, + +]; diff --git a/config/broadcasting.php b/config/broadcasting.php new file mode 100644 index 0000000..c9c89ca --- /dev/null +++ b/config/broadcasting.php @@ -0,0 +1,71 @@ + env('BROADCAST_DRIVER', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'secret' => env('PUSHER_APP_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'cluster' => env('PUSHER_APP_CLUSTER'), + 'host' => env('PUSHER_HOST') ?: 'api-' . env('PUSHER_APP_CLUSTER', 'mt1') . '.pusher.com', + 'port' => env('PUSHER_PORT', 443), + 'scheme' => env('PUSHER_SCHEME', 'https'), + 'encrypted' => true, + 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', + ], + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + ], + + 'ably' => [ + 'driver' => 'ably', + 'key' => env('ABLY_KEY'), + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', + ], + + ], + +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..5115f18 --- /dev/null +++ b/config/cache.php @@ -0,0 +1,111 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'cache', + 'lock_connection' => 'default', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, or DynamoDB cache + | stores there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'), + +]; diff --git a/config/cors.php b/config/cors.php new file mode 100644 index 0000000..8a39e6d --- /dev/null +++ b/config/cors.php @@ -0,0 +1,34 @@ + ['api/*', 'sanctum/csrf-cookie'], + + 'allowed_methods' => ['*'], + + 'allowed_origins' => ['*'], + + 'allowed_origins_patterns' => [], + + 'allowed_headers' => ['*'], + + 'exposed_headers' => [], + + 'max_age' => 0, + + 'supports_credentials' => false, + +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..2e731a0 --- /dev/null +++ b/config/database.php @@ -0,0 +1,176 @@ + env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DATABASE_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + 'testing' => [ + 'driver' => env('DB_TEST_DRIVER', 'mysql'), + 'host' => env('DB_TEST_HOST', 'localhost'), + 'port' => env('DB_TEST_PORT', '3306'), + 'database' => env('DB_TEST_DATABASE'), + 'username' => env('DB_TEST_USERNAME'), + 'password' => env('DB_TEST_PASSWORD'), + 'charset' => env('DB_TEST_DRIVER') === 'pgsql' ? 'utf8' : 'utf8mb4', + 'collation' => env('DB_TEST_DRIVER') === 'pgsql' ? '' : 'utf8mb4_unicode_ci', + 'prefix' => '', + 'strict' => true, + ], + + 'testing' => [ + 'driver' => env('DB_TEST_DRIVER', 'mysql'), + 'host' => env('DB_TEST_HOST', 'localhost'), + 'port' => env('DB_TEST_PORT', '3306'), + 'database' => env('DB_TEST_DATABASE'), + 'username' => env('DB_TEST_USERNAME'), + 'password' => env('DB_TEST_PASSWORD'), + 'charset' => env('DB_TEST_DRIVER') === 'pgsql' ? 'utf8' : 'utf8mb4', + 'collation' => env('DB_TEST_DRIVER') === 'pgsql' ? '' : 'utf8mb4_unicode_ci', + 'prefix' => '', + 'strict' => true, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100644 index 0000000..29f52e4 --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,81 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been set up for each driver as an example of the required values. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'throw' => false, + ], + + 'lang' => [ + 'driver' => 'local', + 'root' => lang_path(), + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL') . '/storage', + 'visibility' => 'public', + 'throw' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/config/hashing.php b/config/hashing.php new file mode 100644 index 0000000..0e8a0bb --- /dev/null +++ b/config/hashing.php @@ -0,0 +1,54 @@ + 'bcrypt', + + /* + |-------------------------------------------------------------------------- + | Bcrypt Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Bcrypt algorithm. This will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'bcrypt' => [ + 'rounds' => env('BCRYPT_ROUNDS', 12), + 'verify' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Argon Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Argon algorithm. These will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'argon' => [ + 'memory' => 65536, + 'threads' => 1, + 'time' => 4, + 'verify' => true, + ], + +]; diff --git a/config/localizator.php b/config/localizator.php new file mode 100644 index 0000000..4d409d0 --- /dev/null +++ b/config/localizator.php @@ -0,0 +1,59 @@ + [ + /** + * Short keys. This is the default for Laravel. + * They are stored in PHP files inside folders name by their locale code. + * Laravel comes with default: auth.php, pagination.php, passwords.php and validation.php. + */ + 'default' => true, + + /** + * Translations strings as key. + * They are stored in JSON file for each locale. + */ + 'json' => true, + ], + + /** + * Search criteria for files. + */ + 'search' => [ + /** + * Directories which should be looked inside. + */ + 'dirs' => ['resources/views', 'resources/js', 'app'], + + /** + * Subdirectories which will be excluded. + * The values must be relative to the included directory paths. + */ + 'exclude' => [ + // + ], + + /** + * Patterns by which files should be queried. + * The values can be a regular expression, glob, or just a string. + */ + 'patterns' => ['*.php'], + + /** + * Functions that the strings will be extracted from. + * Add here any custom defined functions. + * NOTE: The translation string should always be the first argument. + */ + 'functions' => ['__', 'trans', '@lang', 'trans_key'], + ], + + /** + * Should the localize command sort extracted strings alphabetically? + */ + 'sort' => true, + +]; diff --git a/config/localizer.php b/config/localizer.php new file mode 100644 index 0000000..455ba4d --- /dev/null +++ b/config/localizer.php @@ -0,0 +1,88 @@ + ['en', 'fr'], + + /** + * If your main locale is omitted from the URL, set it here. + * It will always be used if no supported locale is found in the URL. + * Note that no other detectors will run after the OmittedLocaleDetector! + * Setting this option to `null` will disable this detector. + */ + 'omitted_locale' => null, + + /** + * The detectors to use to find a matching locale. + * These will be executed in the order that they are added to the array! + */ + 'detectors' => [ + CodeZero\Localizer\Detectors\RouteActionDetector::class, + CodeZero\Localizer\Detectors\UrlDetector::class, + CodeZero\Localizer\Detectors\OmittedLocaleDetector::class, + CodeZero\Localizer\Detectors\UserDetector::class, + CodeZero\Localizer\Detectors\SessionDetector::class, + CodeZero\Localizer\Detectors\CookieDetector::class, + CodeZero\Localizer\Detectors\BrowserDetector::class, + CodeZero\Localizer\Detectors\AppDetector::class, + ], + + /** + * Add any of the above detector class names here to make it trusted. + * When a trusted detector returns a locale, it will be used + * as the app locale, regardless if it's a supported locale or not. + */ + 'trusted_detectors' => [ + // + ], + + /** + * The stores to store the first matching locale in. + */ + 'stores' => [ + CodeZero\Localizer\Stores\SessionStore::class, + CodeZero\Localizer\Stores\CookieStore::class, + CodeZero\Localizer\Stores\AppStore::class, + ], + + /** + * The index of the segment that has the locale, + * when using the UrlDetector. + */ + 'url_segment' => 1, + + /** + * The attribute or "action" on the route that holds the locale, + * when using the RouteActionDetector. + */ + 'route_action' => 'locale', + + /** + * The attribute on the user model that holds the locale, + * when using the UserDetector. + */ + 'user_attribute' => 'locale', + + /** + * The session key that holds the locale, + * when using the SessionDetector and SessionStore. + */ + 'session_key' => 'locale', + + /** + * The name of the cookie that holds the locale, + * when using the CookieDetector and CookieStore. + */ + 'cookie_name' => 'locale', + + /** + * The lifetime of the cookie that holds the locale, + * when using the CookieStore. + */ + 'cookie_minutes' => 60 * 24 * 365, // 1 year + +]; diff --git a/config/logging.php b/config/logging.php new file mode 100644 index 0000000..d000835 --- /dev/null +++ b/config/logging.php @@ -0,0 +1,131 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + + 'channels' => [ + 'stack' => [ + 'driver' => 'stack', + 'channels' => ['single'], + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 14, + 'replace_placeholders' => true, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Laravel Log', + 'emoji' => ':boom:', + 'level' => env('LOG_LEVEL', 'critical'), + 'replace_placeholders' => true, + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'), + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + 'facility' => LOG_USER, + 'replace_placeholders' => true, + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + ], + +]; diff --git a/config/mail.php b/config/mail.php new file mode 100644 index 0000000..d7416b1 --- /dev/null +++ b/config/mail.php @@ -0,0 +1,126 @@ + env('MAIL_MAILER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers to be used while + | sending an e-mail. You will specify which one you are using for your + | mailers below. You are free to add additional mailers as required. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", + | "postmark", "log", "array", "failover" + | + */ + + 'mailers' => [ + 'smtp' => [ + 'transport' => 'smtp', + 'url' => env('MAIL_URL'), + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'port' => env('MAIL_PORT', 587), + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'local_domain' => env('MAIL_EHLO_DOMAIN'), + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'mailgun' => [ + 'transport' => 'mailgun', + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'postmark' => [ + 'transport' => 'postmark', + // 'message_stream_id' => null, + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + ], + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), + 'name' => env('MAIL_FROM_NAME', 'Example'), + ], + + /* + |-------------------------------------------------------------------------- + | Markdown Mail Settings + |-------------------------------------------------------------------------- + | + | If you are using Markdown based email rendering, you may configure your + | theme and component paths here, allowing you to customize the design + | of the emails. Or, you may simply stick with the Laravel defaults! + | + */ + + 'markdown' => [ + 'theme' => 'default', + + 'paths' => [ + resource_path('views/vendor/mail'), + ], + ], + +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 0000000..01c6b05 --- /dev/null +++ b/config/queue.php @@ -0,0 +1,109 @@ + env('QUEUE_CONNECTION', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Laravel. You are free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + 'after_commit' => false, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + 'block_for' => 0, + 'after_commit' => false, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'after_commit' => false, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + 'block_for' => null, + 'after_commit' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/config/sanctum.php b/config/sanctum.php new file mode 100644 index 0000000..35d75b3 --- /dev/null +++ b/config/sanctum.php @@ -0,0 +1,83 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort() + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. This will override any values set in the token's + | "expires_at" attribute, but first-party sessions are not affected. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Token Prefix + |-------------------------------------------------------------------------- + | + | Sanctum can prefix new tokens in order to take advantage of numerous + | security scanning initiatives maintained by open source platforms + | that notify developers if they commit tokens into repositories. + | + | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning + | + */ + + 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, + 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, + 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, + ], + +]; diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..0ace530 --- /dev/null +++ b/config/services.php @@ -0,0 +1,34 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'scheme' => 'https', + ], + + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..1b99f22 --- /dev/null +++ b/config/session.php @@ -0,0 +1,201 @@ + env('SESSION_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => env('SESSION_LIFETIME', 120), + + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | While using one of the framework's cache driven session backends you may + | list a cache store that should be used for these sessions. This value + | must match with one of the application's configured cache "stores". + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_') . '_session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. You are free to modify this option if needed. + | + */ + + 'http_only' => true, + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" since this is a secure default value. + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => 'lax', + +]; diff --git a/config/view.php b/config/view.php new file mode 100644 index 0000000..22b8a18 --- /dev/null +++ b/config/view.php @@ -0,0 +1,36 @@ + [ + resource_path('views'), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => env( + 'VIEW_COMPILED_PATH', + realpath(storage_path('framework/views')) + ), + +]; diff --git a/database/.gitignore b/database/.gitignore new file mode 100644 index 0000000..9b19b93 --- /dev/null +++ b/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/database/factories/LevelFactory.php b/database/factories/LevelFactory.php new file mode 100644 index 0000000..66f6070 --- /dev/null +++ b/database/factories/LevelFactory.php @@ -0,0 +1,26 @@ + + */ +class LevelFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'organization_id' => Organization::factory(), + 'label' => fake()->name, + 'label_translation_key' => fake()->name, + ]; + } +} diff --git a/database/factories/OrganizationFactory.php b/database/factories/OrganizationFactory.php new file mode 100644 index 0000000..ec6dcd5 --- /dev/null +++ b/database/factories/OrganizationFactory.php @@ -0,0 +1,23 @@ + + */ +class OrganizationFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => 'Dunder Mifflin', + ]; + } +} diff --git a/database/factories/RoleFactory.php b/database/factories/RoleFactory.php new file mode 100644 index 0000000..5ba8e43 --- /dev/null +++ b/database/factories/RoleFactory.php @@ -0,0 +1,26 @@ + + */ +class RoleFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'organization_id' => Organization::factory(), + 'label' => fake()->name, + 'label_translation_key' => fake()->name, + ]; + } +} diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php new file mode 100644 index 0000000..f85bc22 --- /dev/null +++ b/database/factories/UserFactory.php @@ -0,0 +1,47 @@ + + */ +class UserFactory extends Factory +{ + protected static ?string $password; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'organization_id' => Organization::factory(), + 'first_name' => fake()->name(), + 'last_name' => fake()->name(), + 'name_for_avatar' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::$password ??= Hash::make('password'), + 'remember_token' => Str::random(10), + 'permissions' => User::ROLE_ADMINISTRATOR, + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/database/migrations/2014_04_13_002417_create_organizations_table.php b/database/migrations/2014_04_13_002417_create_organizations_table.php new file mode 100644 index 0000000..f832e1b --- /dev/null +++ b/database/migrations/2014_04_13_002417_create_organizations_table.php @@ -0,0 +1,18 @@ +id(); + $table->string('name'); + $table->string('licence_key')->nullable(); + $table->timestamps(); + }); + } +}; diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php new file mode 100644 index 0000000..0004cd6 --- /dev/null +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -0,0 +1,30 @@ +id(); + $table->unsignedBigInteger('organization_id'); + $table->string('first_name')->nullable(); + $table->string('last_name')->nullable(); + $table->string('email')->unique(); + $table->timestamp('email_verified_at')->nullable(); + $table->string('password'); + $table->string('permissions'); + $table->string('name_for_avatar'); + $table->string('locale')->default('en'); + $table->rememberToken(); + $table->timestamps(); + $table->foreign('organization_id')->references('id')->on('organizations')->onDelete('cascade'); + }); + } +}; diff --git a/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php b/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php new file mode 100644 index 0000000..cb68c9b --- /dev/null +++ b/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php @@ -0,0 +1,28 @@ +string('email')->primary(); + $table->string('token'); + $table->timestamp('created_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('password_reset_tokens'); + } +}; diff --git a/database/migrations/2019_08_19_000000_create_failed_jobs_table.php b/database/migrations/2019_08_19_000000_create_failed_jobs_table.php new file mode 100644 index 0000000..3128b95 --- /dev/null +++ b/database/migrations/2019_08_19_000000_create_failed_jobs_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php new file mode 100644 index 0000000..07c8c0e --- /dev/null +++ b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('tokenable'); + $table->string('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/database/migrations/2023_11_13_200951_create_roles_table.php b/database/migrations/2023_11_13_200951_create_roles_table.php new file mode 100644 index 0000000..1046155 --- /dev/null +++ b/database/migrations/2023_11_13_200951_create_roles_table.php @@ -0,0 +1,32 @@ +id(); + $table->unsignedBigInteger('organization_id'); + $table->string('label')->nullable(); + $table->string('label_translation_key')->nullable(); + $table->timestamps(); + $table->foreign('organization_id')->references('id')->on('organizations')->onDelete('cascade'); + }); + + Schema::create('levels', function (Blueprint $table): void { + $table->id(); + $table->unsignedBigInteger('organization_id'); + $table->string('label')->nullable(); + $table->string('label_translation_key')->nullable(); + $table->timestamps(); + $table->foreign('organization_id')->references('id')->on('organizations')->onDelete('cascade'); + }); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..a9f4519 --- /dev/null +++ b/database/seeders/DatabaseSeeder.php @@ -0,0 +1,22 @@ +create(); + + // \App\Models\User::factory()->create([ + // 'name' => 'Test User', + // 'email' => 'test@example.com', + // ]); + } +} diff --git a/lang/fr.json b/lang/fr.json new file mode 100644 index 0000000..06196eb --- /dev/null +++ b/lang/fr.json @@ -0,0 +1,110 @@ +{ + "Add": "Ajouter", + "Add a level": "Ajouter un niveau", + "Add a new level": "Ajouter un nouveau niveau", + "Add a new role": "Ajouter un nouveau rôle", + "Add a role": "Ajouter un rôle", + "A level refers to a specific position or rank that represents the seniority or authority of someone within the organization.": "Un niveau fait référence à un poste ou à un rang spécifique qui représente l'ancienneté ou l'autorité d'une personne au sein de l'organisation.", + "All the levels": "Tous les niveaux", + "All the levels in your organization": "Tous les niveaux de votre organisation", + "All the roles in your organization": "Tous les rôles dans votre organisation", + "Already registered?": "Déjà enregistré?", + "A new verification link has been sent to the email address you provided during registration.": "Un nouveau lien de vérification a été envoyé à l'adresse e-mail que vous avez fournie lors de l'inscription.", + "A new verification link has been sent to your email address.": "Un nouveau lien de vérification a été envoyé à votre adresse e-mail.", + "Are you sure you want to delete your account?": "Êtes-vous sûr de vouloir supprimer votre compte ?", + "Are you sure you want to proceed? This can not be undone.": "Êtes-vous sur de vouloir continuer? Ça ne peut pas être annulé.", + "A role refers to a specific job or position that an individual performs within your organization.": "Un rôle fait référence à un travail ou à un poste spécifique qu'une personne occupe au sein de votre organisation.", + "As an administrator, you can...": "En tant qu'administrateur, vous pouvez...", + "As a user, you can...": "En tant qu'utilisateur, vous pouvez...", + "Back": "Retour", + "Be part of something unique.": "Faites partie de quelque chose d'unique.", + "Cancel": "Annuler", + "Changes saved": "Changements sauvegardés", + "Chief Executive Officer": "Directeur général", + "Click here to re-send the verification email.": "Cliquez ici pour renvoyer l'e-mail de vérification.", + "Company": "Entreprise", + "Confirm": "Confirmer", + "Confirm Password": "Confirmez le mot de passe", + "Current Password": "Mot de passe actuel", + "Dashboard": "Tableau de bord", + "Data Analyst\/Scientist": "Analyste de données\/scientifique", + "Delete": "Supprimer", + "Delete Account": "Supprimer le compte", + "DevOps Engineer": "Ingénieur DevOps", + "Edit": "Modifier", + "Edit a level": "Modifier un niveau", + "Edit a role": "Modifier un rôle", + "Edit level": "Modifier le niveau", + "Edit role": "Modifier le rôle", + "Email": "E-mail", + "Email password reset link": "Réinitialiser le du mot de passe", + "English": "Anglais", + "Ensure your account is using a long, random password to stay secure.": "Assurez-vous que votre compte utilise un mot de passe long et aléatoire pour rester en sécurité.", + "First name": "Prénom", + "Forgot your password?": "Mot de passe oublié?", + "Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.": "Mot de passe oublié? Aucun problème. Indiquez-nous simplement votre adresse e-mail et nous vous enverrons par e-mail un lien de réinitialisation de mot de passe qui vous permettra d'en choisir un nouveau.", + "French": "Français", + "Intermediate": "Intermédiaire", + "It's great to have you back!": "C'est super de vous revoir !", + "It's great to have you back!.": "C'est super de vous revoir !", + "Junior": "Junior", + "Last name": "Nom de famille", + "Levels": "Niveaux", + "Log in": "Se connecter", + "Log out": "Déconnexion", + "Manage levels": "Gérer les niveaux", + "Manage roles": "Gérer les rôles", + "Manage your profile": "Gérer votre profil", + "Messages": "messages", + "Name": "Nom", + "Name of your organization": "Nom de votre organisation", + "New Password": "nouveau mot de passe", + "No levels have been defined yet": "Aucun niveau n'a encore été défini", + "No roles have been defined yet": "Aucun rôle n'a encore été défini", + "Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.": "Une fois votre compte supprimé, toutes ses ressources et données seront définitivement supprimées. Avant de supprimer votre compte, veuillez télécharger toutes les données ou informations que vous souhaitez conserver.", + "Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Une fois votre compte supprimé, toutes ses ressources et données seront définitivement supprimées. Veuillez saisir votre mot de passe pour confirmer que vous souhaitez supprimer définitivement votre compte.", + "Password": "Mot de passe", + "Product Manager": "Chef de produit", + "Profile": "Profil", + "Profile Information": "Informations sur le profil", + "Project Manager": "Chef de projet", + "Projects": "Projets", + "Quality Assurance Engineer": "Ingénieur Assurance Qualité", + "Register": "Créer le compte", + "Remember me": "Souviens-toi de moi", + "Resend Verification Email": "Renvoyer l'e-mail de vérification", + "Reset Password": "réinitialiser le mot de passe", + "Roles": "Rôles", + "Sales\/Account Manager": "Responsable des ventes\/comptes", + "Save": "Sauvegarder", + "Saved.": "Enregistré.", + "Scrum Master": "Maître Scrum", + "Senior": "Senior", + "Settings": "Paramètres", + "Software Engineer": "Ingénieur logiciel", + "Staff": "Principal", + "System Administrator": "Administrateur du système", + "Technical Support Engineer": "Ingénieur du Support Technique", + "Technical Writer": "Rédacteur technique", + "Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.": "Merci pour l'enregistrement! Avant de commencer, pourriez-vous vérifier votre adresse e-mail en cliquant sur le lien que nous venons de vous envoyer par e-mail ? Si vous n'avez pas reçu l'e-mail, nous vous en enverrons volontiers un autre.", + "The element has been deleted": "L'élément a été supprimé", + "The level has been created": "Le niveau a été créé", + "The role has been created": "Le rôle a été créé", + "This action can not be done": "Cette action ne peut pas être effectuée", + "This is a secure area of the application. Please confirm your password before continuing.": "Il s'agit d'une zone sécurisée de l'application. Veuillez confirmer votre mot de passe avant de continuer.", + "UI\/UX Designer": "Concepteur UI\/UX", + "Update Password": "Mettre à jour le mot de passe", + "Update your account's profile information and email address.": "Mettez à jour les informations de profil et l'adresse e-mail de votre compte.", + "Update your profile": "Mettre à jour votre profil", + "Welcome back to Shelter": "Bon retour à Shelter", + "Welcome to Shelter": "Bienvenue à Shelter", + "We will send you a verification email, and won't spam you.": "Nous vous enverrons un e-mail de vérification et ne vous enverrons pas de spam.", + "What is the name of the level?": "Quel est le nom du niveau ?", + "What is the name of the role?": "Quel est le nom du rôle ?", + "What is the name of this new level?": "Quel est le nom de ce nouveau niveau ?", + "What is the name of this new role?": "Quel est le nom de ce nouveau rôle ?", + "What is the name of this role?": "Quel est le nom de ce rôle ?", + "You're logged in!": "Vous êtes connecté !", + "You do not have permission to do this action.": "Vous n'êtes pas autorisé à effectuer cette action.", + "Your email address is unverified.": "Votre adresse e-mail n'est pas vérifiée." +} diff --git a/lang/fr/auth.php b/lang/fr/auth.php new file mode 100644 index 0000000..1936236 --- /dev/null +++ b/lang/fr/auth.php @@ -0,0 +1,7 @@ + '', + 'password' => '', + 'throttle' => '', +]; diff --git a/package.json b/package.json new file mode 100644 index 0000000..b4bbd54 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint --ext .js *.js resources", + "pretest": "DB_CONNECTION=testing php artisan migrate:fresh", + "posttest": "yarn lint --fix && ./vendor/bin/duster fix && yarn lint", + "test": "vendor/bin/phpunit" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.2", + "alpinejs": "^3.4.2", + "autoprefixer": "^10.4.2", + "axios": "^1.1.2", + "eslint": "^8.42.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "htmx.org": "^1.9.8", + "laravel-vite-plugin": "^0.8.0", + "postcss": "^8.4.6", + "tailwindcss": "^3.1.0", + "vite": "^4.0.0" + } +} diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..25f1b94 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,22 @@ +includes: + - ./vendor/nunomaduro/larastan/extension.neon + +parameters: + paths: + - app/ + # Level 9 is the highest level + level: 6 + ignoreErrors: + # larastan needs to manage ->pivot properties + #- '#Access to an undefined property App\\Models\\[^:]*::\$pivot\.#' + #- '#Method\s.+?\sreturn type has no value type specified in iterable type array\.#' + - '#\s.+?\sno value type specified in iterable type array\.#' + +# + excludePaths: +# - ./*/*/FileToBeExcluded.php + - app/Http/Controllers/Auth/VerifyEmailController.php +# +# checkMissingIterableValueType: false + checkGenericClassInNonGenericObjectType: false + treatPhpDocTypesAsCertain: false diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..4d67e22 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,33 @@ + + + + + tests/Unit + + + tests/Feature + + + + + app + + + + + + + + + + + + + + + + diff --git a/pint.json b/pint.json new file mode 100644 index 0000000..49bbbf2 --- /dev/null +++ b/pint.json @@ -0,0 +1,45 @@ +{ + "preset": "laravel", + "rules": { + "blank_line_between_import_groups": true, + "concat_space": { + "spacing": "one" + }, + "class_attributes_separation": { + "elements": { + "method": "one" + } + }, + "curly_braces_position": { + "control_structures_opening_brace": "same_line", + "functions_opening_brace": "next_line_unless_newline_at_signature_end", + "anonymous_functions_opening_brace": "same_line", + "classes_opening_brace": "next_line_unless_newline_at_signature_end", + "anonymous_classes_opening_brace": "next_line_unless_newline_at_signature_end", + "allow_single_line_empty_anonymous_classes": true, + "allow_single_line_anonymous_functions": false + }, + "explicit_string_variable": true, + "global_namespace_import": { + "import_classes": true, + "import_constants": true, + "import_functions": true + }, + "new_with_braces": { + "named_class": false, + "anonymous_class": false + }, + "ordered_imports": { + "sort_algorithm": "alpha", + "imports_order": [ + "const", + "class", + "function" + ] + }, + "php_unit_test_annotation": { + "style": "annotation" + }, + "simple_to_complex_string_variable": true + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2aa7205 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..4c8b877 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..3aec5e2 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,21 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Send Requests To Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..f3c2ebc --- /dev/null +++ b/public/index.php @@ -0,0 +1,55 @@ +make(Kernel::class); + +$response = $kernel->handle( + $request = Request::capture() +)->send(); + +$kernel->terminate($request, $response); diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/resources/css/app.css b/resources/css/app.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/resources/css/app.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/resources/js/app.js b/resources/js/app.js new file mode 100644 index 0000000..b81e1ed --- /dev/null +++ b/resources/js/app.js @@ -0,0 +1,11 @@ +import './bootstrap'; + +import Alpine from 'alpinejs'; +//import 'htmx.org/dist/ext/preload.js'; +import htmx from 'htmx.org'; + +window.Alpine = Alpine; +//window.htmx = htmx.org; +window.htmx = htmx; + +Alpine.start(); diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js new file mode 100644 index 0000000..846d350 --- /dev/null +++ b/resources/js/bootstrap.js @@ -0,0 +1,32 @@ +/** + * We'll load the axios HTTP library which allows us to easily issue requests + * to our Laravel back-end. This library automatically handles sending the + * CSRF token as a header based on the value of the "XSRF" token cookie. + */ + +import axios from 'axios'; +window.axios = axios; + +window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; + +/** + * Echo exposes an expressive API for subscribing to channels and listening + * for events that are broadcast by Laravel. Echo and event broadcasting + * allows your team to easily build robust real-time web applications. + */ + +// import Echo from 'laravel-echo'; + +// import Pusher from 'pusher-js'; +// window.Pusher = Pusher; + +// window.Echo = new Echo({ +// broadcaster: 'pusher', +// key: import.meta.env.VITE_PUSHER_APP_KEY, +// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1', +// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`, +// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, +// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, +// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https', +// enabledTransports: ['ws', 'wss'], +// }); diff --git a/resources/views/auth/confirm-password.blade.php b/resources/views/auth/confirm-password.blade.php new file mode 100644 index 0000000..8e11a01 --- /dev/null +++ b/resources/views/auth/confirm-password.blade.php @@ -0,0 +1,32 @@ + +

+ {{ __('This is a secure area of the application. Please confirm your password before continuing.') }} +
+ +
+ @csrf + + +
+ + + + + +
+ +
+ + {{ __('Confirm') }} + +
+
+ diff --git a/resources/views/auth/forgot-password.blade.php b/resources/views/auth/forgot-password.blade.php new file mode 100644 index 0000000..e3a0281 --- /dev/null +++ b/resources/views/auth/forgot-password.blade.php @@ -0,0 +1,36 @@ + + +
+ {{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }} +
+ + + + +
+ @csrf + + +
+ + + +
+ +
+ + {{ __('Email password reset link') }} + +
+
+
diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php new file mode 100644 index 0000000..64b16f7 --- /dev/null +++ b/resources/views/auth/login.blade.php @@ -0,0 +1,69 @@ + + +
+ + + + +

{{ __('Welcome back to Shelter') }}

+

{{ __('It\'s great to have you back!') }}

+
+ + + + +
+ @csrf + +
+ +
+ + + +
+ + +
+ + + + + +
+ + +
+ +
+
+ +
+ + {{ __('Log in') }} + + + + {{ __('Forgot your password?') }} + +
+
+
diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php new file mode 100644 index 0000000..b99b545 --- /dev/null +++ b/resources/views/auth/register.blade.php @@ -0,0 +1,115 @@ + + +
+ + + + +

{{ __('Welcome to Shelter') }}

+

{{ __('Be part of something unique.') }}

+
+ +
+ @csrf + +
+ +
+
+ + + +
+ +
+ + + +
+
+ + +
+ + + + + {{ __('We will send you a verification email, and won\'t spam you.') }} + + + +
+ + +
+ + + + + +
+ + +
+ + + + + +
+
+ +
+ + + + + +
+ +
+ + {{ __('Register') }} + + + + {{ __('Already registered?') }} + +
+
+
diff --git a/resources/views/auth/reset-password.blade.php b/resources/views/auth/reset-password.blade.php new file mode 100644 index 0000000..aecb8c3 --- /dev/null +++ b/resources/views/auth/reset-password.blade.php @@ -0,0 +1,63 @@ + +
+ @csrf + + + + + +
+ + + +
+ + +
+ + + +
+ + +
+ + + + + +
+ +
+ + {{ __('Reset Password') }} + +
+
+
diff --git a/resources/views/auth/verify-email.blade.php b/resources/views/auth/verify-email.blade.php new file mode 100644 index 0000000..1134d87 --- /dev/null +++ b/resources/views/auth/verify-email.blade.php @@ -0,0 +1,36 @@ + +
+
+ {{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }} +
+
+ + @if (session('status') == 'verification-link-sent') +
+ {{ __('A new verification link has been sent to the email address you provided during registration.') }} +
+ @endif + +
+
+ @csrf + +
+ + {{ __('Resend Verification Email') }} + +
+
+ +
+ @csrf + + +
+
+
diff --git a/resources/views/components/application-logo.blade.php b/resources/views/components/application-logo.blade.php new file mode 100644 index 0000000..f0cb5db --- /dev/null +++ b/resources/views/components/application-logo.blade.php @@ -0,0 +1,14 @@ +merge(['class' => '']) }} viewBox="0 0 568 394" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + + + + + + + + + + + + + diff --git a/resources/views/components/danger-button.blade.php b/resources/views/components/danger-button.blade.php new file mode 100644 index 0000000..13204d6 --- /dev/null +++ b/resources/views/components/danger-button.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/components/dropdown-link.blade.php b/resources/views/components/dropdown-link.blade.php new file mode 100644 index 0000000..6d5279d --- /dev/null +++ b/resources/views/components/dropdown-link.blade.php @@ -0,0 +1 @@ +merge(['class' => 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out']) }}>{{ $slot }} diff --git a/resources/views/components/dropdown.blade.php b/resources/views/components/dropdown.blade.php new file mode 100644 index 0000000..daedc07 --- /dev/null +++ b/resources/views/components/dropdown.blade.php @@ -0,0 +1,46 @@ +@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white dark:bg-gray-700']) + +@php + switch ($align) { + case 'left': + $alignmentClasses = 'ltr:origin-top-left rtl:origin-top-right start-0'; + break; + case 'top': + $alignmentClasses = 'origin-top'; + break; + case 'right': + default: + $alignmentClasses = 'ltr:origin-top-right rtl:origin-top-left end-0'; + break; + } + + switch ($width) { + case '48': + $width = 'w-48'; + break; + } +@endphp + +
+
+ {{ $trigger }} +
+ + +
diff --git a/resources/views/components/help.blade.php b/resources/views/components/help.blade.php new file mode 100644 index 0000000..3f1eb76 --- /dev/null +++ b/resources/views/components/help.blade.php @@ -0,0 +1,6 @@ +
merge(['class' => 'flex text-sm border border-gray-200 bg-gray-50 dark:bg-gray-900 dark:border-gray-700 dark:text-gray-300 rounded-lg p-2']) }}> +
+ +
+

{{ $slot }}

+
diff --git a/resources/views/components/htmx-link.blade.php b/resources/views/components/htmx-link.blade.php new file mode 100644 index 0000000..96bb347 --- /dev/null +++ b/resources/views/components/htmx-link.blade.php @@ -0,0 +1 @@ +merge(['class' => 'text-blue-700 underline hover:no-underline cursor-pointer dark:text-gray-400 dark:hover:text-gray-100 dark:focus:ring-offset-gray-800']) }}>{{ $slot }} diff --git a/resources/views/components/input-error.blade.php b/resources/views/components/input-error.blade.php new file mode 100644 index 0000000..907c4c1 --- /dev/null +++ b/resources/views/components/input-error.blade.php @@ -0,0 +1,9 @@ +@props(['messages']) + +@if ($messages) +
    merge(['class' => 'text-sm text-red-600 dark:text-red-400 space-y-1']) }}> + @foreach ((array) $messages as $message) +
  • {{ $message }}
  • + @endforeach +
+@endif diff --git a/resources/views/components/input-help.blade.php b/resources/views/components/input-help.blade.php new file mode 100644 index 0000000..c72c537 --- /dev/null +++ b/resources/views/components/input-help.blade.php @@ -0,0 +1,5 @@ +@props(['value']) + + diff --git a/resources/views/components/input-label.blade.php b/resources/views/components/input-label.blade.php new file mode 100644 index 0000000..ddf819b --- /dev/null +++ b/resources/views/components/input-label.blade.php @@ -0,0 +1,5 @@ +@props(['value']) + + diff --git a/resources/views/components/link.blade.php b/resources/views/components/link.blade.php new file mode 100644 index 0000000..7fdc39e --- /dev/null +++ b/resources/views/components/link.blade.php @@ -0,0 +1,3 @@ +@props(['boost' => true]) + +merge(['class' => 'text-blue-700 underline hover:no-underline dark:text-gray-400 dark:hover:text-gray-100 dark:focus:ring-offset-gray-800']) }}>{{ $slot }} diff --git a/resources/views/components/modal.blade.php b/resources/views/components/modal.blade.php new file mode 100644 index 0000000..93ae136 --- /dev/null +++ b/resources/views/components/modal.blade.php @@ -0,0 +1,67 @@ +@props(['name', 'show' => false, 'maxWidth' => '2xl']) + +@php + $maxWidth = [ + 'sm' => 'sm:max-w-sm', + 'md' => 'sm:max-w-md', + 'lg' => 'sm:max-w-lg', + 'xl' => 'sm:max-w-xl', + '2xl' => 'sm:max-w-2xl', + ][$maxWidth]; +@endphp + +
+
+
+
+ +
+ {{ $slot }} +
+
diff --git a/resources/views/components/nav-link.blade.php b/resources/views/components/nav-link.blade.php new file mode 100644 index 0000000..ae53a0d --- /dev/null +++ b/resources/views/components/nav-link.blade.php @@ -0,0 +1,9 @@ +@props(['active']) + +@php + $classes = $active ?? false ? 'inline-flex items-center px-3 bg-gray-200 dark:bg-gray-700 rounded-lg text-sm font-medium leading-5 text-gray-900 dark:text-gray-100 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out' : 'inline-flex items-center px-3 hover:bg-gray-200 dark:hover:bg-gray-500 rounded-lg text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 transition duration-150 ease-in-out'; +@endphp + +merge(['class' => $classes]) }}> + {{ $slot }} + diff --git a/resources/views/components/primary-button.blade.php b/resources/views/components/primary-button.blade.php new file mode 100644 index 0000000..0a4360b --- /dev/null +++ b/resources/views/components/primary-button.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/components/primary-link.blade.php b/resources/views/components/primary-link.blade.php new file mode 100644 index 0000000..cab0300 --- /dev/null +++ b/resources/views/components/primary-link.blade.php @@ -0,0 +1 @@ +merge(['class' => 'px-2 py-1 inline-flex items-center justify-center whitespace-nowrap rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-gray-300 bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground transition ease-in-out duration-150 hover:bg-gray-100 dark:bg-gray-700 dark:text-white dark:hover:text-gray-800']) }}>{{ $slot }} diff --git a/resources/views/components/responsive-nav-link.blade.php b/resources/views/components/responsive-nav-link.blade.php new file mode 100644 index 0000000..bf5cdc3 --- /dev/null +++ b/resources/views/components/responsive-nav-link.blade.php @@ -0,0 +1,9 @@ +@props(['active']) + +@php + $classes = $active ?? false ? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-start text-base font-medium text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out' : 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out'; +@endphp + +merge(['class' => $classes]) }}> + {{ $slot }} + diff --git a/resources/views/components/secondary-button.blade.php b/resources/views/components/secondary-button.blade.php new file mode 100644 index 0000000..f60d095 --- /dev/null +++ b/resources/views/components/secondary-button.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/components/session-status.blade.php b/resources/views/components/session-status.blade.php new file mode 100644 index 0000000..0975e01 --- /dev/null +++ b/resources/views/components/session-status.blade.php @@ -0,0 +1,7 @@ +@props(['status']) + +@if ($status) +
merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}> + {{ $status }} +
+@endif diff --git a/resources/views/components/text-input.blade.php b/resources/views/components/text-input.blade.php new file mode 100644 index 0000000..d1cea4e --- /dev/null +++ b/resources/views/components/text-input.blade.php @@ -0,0 +1,6 @@ +@props(['disabled' => false]) + +merge([ + 'class' => 'flex h-9 w-full rounded-md dark:bg-gray-900 border border-gray-300 dark:border-gray-600 bg-transparent px-3 py-1 shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', + ]) !!}> diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php new file mode 100644 index 0000000..f389e92 --- /dev/null +++ b/resources/views/dashboard.blade.php @@ -0,0 +1,17 @@ + + +

+ {{ __('Dashboard') }} +

+
+ +
+
+
+
+ {{ __("You're logged in!") }} +
+
+
+
+
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php new file mode 100644 index 0000000..6da4035 --- /dev/null +++ b/resources/views/layouts/app.blade.php @@ -0,0 +1,49 @@ + + + + + + + + + {{ config('app.name', 'Laravel') }} + + + + + @vite(['resources/css/app.css', 'resources/js/app.js']) + + + +
+ @include('layouts.navigation') + + + @if (isset($breadcrumb)) +
+
+ {{ $breadcrumb }} +
+
+ @endif + + +
+ {{ $slot }} +
+ + @if (session('status')) +
+
+
+ +
+ +

{{ session('status') }}

+
+
+ @endif +
+ + + diff --git a/resources/views/layouts/guest.blade.php b/resources/views/layouts/guest.blade.php new file mode 100644 index 0000000..47bfd19 --- /dev/null +++ b/resources/views/layouts/guest.blade.php @@ -0,0 +1,35 @@ + + + + + + + + + {{ config('app.name', 'Laravel') }} + + + @vite(['resources/css/app.css', 'resources/js/app.js']) + + + +
+
+ {{ $slot }} +
+ + +
+
    +
  • + {{ __('English') }} +
  • +
  • + {{ __('French') }} +
  • +
+
+
+ + + diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php new file mode 100644 index 0000000..ced5af3 --- /dev/null +++ b/resources/views/layouts/navigation.blade.php @@ -0,0 +1,106 @@ + diff --git a/resources/views/profile/edit.blade.php b/resources/views/profile/edit.blade.php new file mode 100644 index 0000000..6a5678b --- /dev/null +++ b/resources/views/profile/edit.blade.php @@ -0,0 +1,29 @@ + + +

+ {{ __('Profile') }} +

+
+ +
+
+
+
+ @include('profile.partials.update-profile-information-form') +
+
+ +
+
+ @include('profile.partials.update-password-form') +
+
+ +
+
+ @include('profile.partials.delete-user-form') +
+
+
+
+
diff --git a/resources/views/profile/partials/delete-user-form.blade.php b/resources/views/profile/partials/delete-user-form.blade.php new file mode 100644 index 0000000..9cad2b7 --- /dev/null +++ b/resources/views/profile/partials/delete-user-form.blade.php @@ -0,0 +1,58 @@ +
+
+

+ {{ __('Delete Account') }} +

+ +

+ {{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }} +

+
+ + {{ __('Delete Account') }} + + +
+ @csrf + @method('delete') + +

+ {{ __('Are you sure you want to delete your account?') }} +

+ +

+ {{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }} +

+ +
+ + + + + +
+ +
+ + {{ __('Cancel') }} + + + + {{ __('Delete Account') }} + +
+
+
+
diff --git a/resources/views/profile/partials/update-password-form.blade.php b/resources/views/profile/partials/update-password-form.blade.php new file mode 100644 index 0000000..62af6d2 --- /dev/null +++ b/resources/views/profile/partials/update-password-form.blade.php @@ -0,0 +1,66 @@ +
+
+

+ {{ __('Update Password') }} +

+ +

+ {{ __('Ensure your account is using a long, random password to stay secure.') }} +

+
+ +
+ @csrf + @method('put') + +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ {{ __('Save') }} + + @if (session('status') === 'password-updated') +

{{ __('Saved.') }}

+ @endif +
+
+
diff --git a/resources/views/profile/partials/update-profile-information-form.blade.php b/resources/views/profile/partials/update-profile-information-form.blade.php new file mode 100644 index 0000000..c730cc2 --- /dev/null +++ b/resources/views/profile/partials/update-profile-information-form.blade.php @@ -0,0 +1,84 @@ +
+
+

+ {{ __('Profile Information') }} +

+ +

+ {{ __("Update your account's profile information and email address.") }} +

+
+ +
+ @csrf +
+ +
+ @csrf + @method('patch') + +
+ + + +
+ +
+ + + + + @if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && !$user->hasVerifiedEmail()) +
+

+ {{ __('Your email address is unverified.') }} + + +

+ + @if (session('status') === 'verification-link-sent') +

+ {{ __('A new verification link has been sent to your email address.') }} +

+ @endif +
+ @endif +
+ +
+ {{ __('Save') }} + + @if (session('status') === 'profile-updated') +

{{ __('Saved.') }}

+ @endif +
+
+
diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php new file mode 100644 index 0000000..04cb04e --- /dev/null +++ b/resources/views/settings/index.blade.php @@ -0,0 +1,26 @@ + +
+
+
+
+

{{ __('As a user, you can...') }}

+
    +
  • + {{ __('Manage your profile') }} +
  • +
+ +

{{ __('As an administrator, you can...') }}

+
    +
  • + {{ __('Manage roles') }} +
  • +
  • + {{ __('Manage levels') }} +
  • +
+
+
+
+
+
diff --git a/resources/views/settings/level/edit.blade.php b/resources/views/settings/level/edit.blade.php new file mode 100644 index 0000000..c6b327f --- /dev/null +++ b/resources/views/settings/level/edit.blade.php @@ -0,0 +1,54 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('Levels') }} +
  • +
  • {{ __('Edit a level') }}
  • +
+
+ +
+
+
+
+ @csrf + @method('PUT') + +
+

{{ __('Edit level') }}

+
+ +
+ + + + + +
+ + +
+ {{ __('Back') }} + +
+ + {{ __('Save') }} + +
+
+
+
+
+
+
diff --git a/resources/views/settings/level/index.blade.php b/resources/views/settings/level/index.blade.php new file mode 100644 index 0000000..f37132c --- /dev/null +++ b/resources/views/settings/level/index.blade.php @@ -0,0 +1,32 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('All the levels') }} +
  • +
+
+ +
+
+
+
+

{{ __('All the levels in your organization') }}

+ + + {{ __('Add a level') }} + +
+ + + {{ __('A level refers to a specific position or rank that represents the seniority or authority of someone within the organization.') }} + + + @include('settings.level.partials.index') +
+
+
+
diff --git a/resources/views/settings/level/new.blade.php b/resources/views/settings/level/new.blade.php new file mode 100644 index 0000000..06f3730 --- /dev/null +++ b/resources/views/settings/level/new.blade.php @@ -0,0 +1,52 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('Levels') }} +
  • +
  • {{ __('Add a level') }}
  • +
+
+ +
+
+
+
+ @csrf + +
+

{{ __('Add a new level') }}

+
+ +
+ + + + + +
+ + +
+ {{ __('Back') }} + +
+ + {{ __('Add') }} + +
+
+
+
+
+
+
diff --git a/resources/views/settings/level/partials/index.blade.php b/resources/views/settings/level/partials/index.blade.php new file mode 100644 index 0000000..a5cae2c --- /dev/null +++ b/resources/views/settings/level/partials/index.blade.php @@ -0,0 +1,24 @@ +
+ @forelse ($data['levels'] as $level) +
+
{{ $level['label'] }}
+ + +
+ {{ __('Edit') }} + {{ __('Delete') }} +
+
+ @empty +
+ {{ __('No levels have been defined yet') }} +
+ @endforelse +
diff --git a/resources/views/settings/profile/index.blade.php b/resources/views/settings/profile/index.blade.php new file mode 100644 index 0000000..ffd2bd6 --- /dev/null +++ b/resources/views/settings/profile/index.blade.php @@ -0,0 +1,78 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('Profile') }} +
  • +
+
+ +
+
+
+
+ @csrf + +
+

{{ __('Update your profile') }}

+
+ +
+
+ + + +
+ +
+ + + +
+
+ +
+ + + + + +
+ + +
+ {{ __('Back') }} + +
+ + {{ __('Add') }} + +
+
+
+
+
+
+
diff --git a/resources/views/settings/role/edit.blade.php b/resources/views/settings/role/edit.blade.php new file mode 100644 index 0000000..4499fc2 --- /dev/null +++ b/resources/views/settings/role/edit.blade.php @@ -0,0 +1,54 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('Roles') }} +
  • +
  • {{ __('Edit a role') }}
  • +
+
+ +
+
+
+
+ @csrf + @method('PUT') + +
+

{{ __('Edit role') }}

+
+ +
+ + + + + +
+ + +
+ {{ __('Back') }} + +
+ + {{ __('Save') }} + +
+
+
+
+
+
+
diff --git a/resources/views/settings/role/index.blade.php b/resources/views/settings/role/index.blade.php new file mode 100644 index 0000000..8e1a099 --- /dev/null +++ b/resources/views/settings/role/index.blade.php @@ -0,0 +1,32 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('Roles') }} +
  • +
+
+ +
+
+
+
+

{{ __('All the roles in your organization') }}

+ + + {{ __('Add a role') }} + +
+ + + {{ __('A role refers to a specific job or position that an individual performs within your organization.') }} + + + @include('settings.role.partials.index') +
+
+
+
diff --git a/resources/views/settings/role/new.blade.php b/resources/views/settings/role/new.blade.php new file mode 100644 index 0000000..4f2e7f7 --- /dev/null +++ b/resources/views/settings/role/new.blade.php @@ -0,0 +1,52 @@ + + +
    +
  • + {{ __('Settings') }} +
  • +
  • + {{ __('Roles') }} +
  • +
  • {{ __('Add a role') }}
  • +
+
+ +
+
+
+
+ @csrf + +
+

{{ __('Add a new role') }}

+
+ +
+ + + + + +
+ + +
+ {{ __('Back') }} + +
+ + {{ __('Add') }} + +
+
+
+
+
+
+
diff --git a/resources/views/settings/role/partials/index.blade.php b/resources/views/settings/role/partials/index.blade.php new file mode 100644 index 0000000..edd5e2d --- /dev/null +++ b/resources/views/settings/role/partials/index.blade.php @@ -0,0 +1,24 @@ +
+ @forelse ($data['roles'] as $role) +
+
{{ $role['label'] }}
+ + +
+ {{ __('Edit') }} + {{ __('Delete') }} +
+
+ @empty +
+ {{ __('No roles have been defined yet') }} +
+ @endforelse +
diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php new file mode 100644 index 0000000..41f4570 --- /dev/null +++ b/resources/views/welcome.blade.php @@ -0,0 +1,1031 @@ + + + + + + + + Laravel + + + + + + + + + + + + + + diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 0000000..889937e --- /dev/null +++ b/routes/api.php @@ -0,0 +1,19 @@ +get('/user', function (Request $request) { + return $request->user(); +}); diff --git a/routes/auth.php b/routes/auth.php new file mode 100644 index 0000000..c10e1e9 --- /dev/null +++ b/routes/auth.php @@ -0,0 +1,59 @@ +group(function (): void { + Route::get('register', [RegisteredUserController::class, 'create']) + ->name('register'); + + Route::post('register', [RegisteredUserController::class, 'store']); + + Route::get('login', [AuthenticatedSessionController::class, 'create']) + ->name('login'); + + Route::post('login', [AuthenticatedSessionController::class, 'store']); + + Route::get('forgot-password', [PasswordResetLinkController::class, 'create']) + ->name('password.request'); + + Route::post('forgot-password', [PasswordResetLinkController::class, 'store']) + ->name('password.email'); + + Route::get('reset-password/{token}', [NewPasswordController::class, 'create']) + ->name('password.reset'); + + Route::post('reset-password', [NewPasswordController::class, 'store']) + ->name('password.store'); +}); + +Route::middleware('auth')->group(function (): void { + Route::get('verify-email', EmailVerificationPromptController::class) + ->name('verification.notice'); + + Route::get('verify-email/{id}/{hash}', VerifyEmailController::class) + ->middleware(['signed', 'throttle:6,1']) + ->name('verification.verify'); + + Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store']) + ->middleware('throttle:6,1') + ->name('verification.send'); + + Route::get('confirm-password', [ConfirmablePasswordController::class, 'show']) + ->name('password.confirm'); + + Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']); + + Route::put('password', [PasswordController::class, 'update'])->name('password.update'); + + Route::post('logout', [AuthenticatedSessionController::class, 'destroy']) + ->name('logout'); +}); diff --git a/routes/channels.php b/routes/channels.php new file mode 100644 index 0000000..5d451e1 --- /dev/null +++ b/routes/channels.php @@ -0,0 +1,18 @@ +id === (int) $id; +}); diff --git a/routes/console.php b/routes/console.php new file mode 100644 index 0000000..35b675e --- /dev/null +++ b/routes/console.php @@ -0,0 +1,19 @@ +comment(Inspiring::quote()); +})->purpose('Display an inspiring quote'); diff --git a/routes/web.php b/routes/web.php new file mode 100644 index 0000000..f467f15 --- /dev/null +++ b/routes/web.php @@ -0,0 +1,51 @@ +name('locale.update'); + +Route::get('dashboard', function () { + return view('dashboard'); +})->middleware(['auth', 'verified'])->name('dashboard'); + +Route::middleware(['auth', 'verified'])->group(function (): void { + Route::get('profile', [ProfileController::class, 'edit'])->name('profile.edit'); + Route::patch('profile', [ProfileController::class, 'update'])->name('profile.update'); + Route::delete('profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); + + // settings + Route::get('settings', [SettingsController::class, 'index'])->name('settings.index'); + + Route::middleware(['administrator'])->group(function (): void { + // profile + Route::get('settings/profile', [SettingsProfileController::class, 'index'])->name('settings.profile.index'); + + // roles + Route::get('settings/roles', [SettingsRoleController::class, 'index'])->name('settings.role.index'); + Route::get('settings/roles/new', [SettingsRoleController::class, 'new'])->name('settings.role.new'); + Route::post('settings/roles', [SettingsRoleController::class, 'store'])->name('settings.role.store'); + Route::get('settings/roles/{role}/edit', [SettingsRoleController::class, 'edit'])->name('settings.role.edit'); + Route::put('settings/roles/{role}', [SettingsRoleController::class, 'update'])->name('settings.role.update'); + Route::delete('settings/roles/{role}', [SettingsRoleController::class, 'destroy'])->name('settings.role.destroy'); + + // levels + Route::get('settings/levels', [SettingsLevelController::class, 'index'])->name('settings.level.index'); + Route::get('settings/levels/new', [SettingsLevelController::class, 'new'])->name('settings.level.new'); + Route::post('settings/levels', [SettingsLevelController::class, 'store'])->name('settings.level.store'); + Route::get('settings/levels/{level}/edit', [SettingsLevelController::class, 'edit'])->name('settings.level.edit'); + Route::put('settings/levels/{level}', [SettingsLevelController::class, 'update'])->name('settings.level.update'); + Route::delete('settings/levels/{level}', [SettingsLevelController::class, 'destroy'])->name('settings.level.destroy'); + }); +}); + +require __DIR__ . '/auth.php'; diff --git a/storage/app/.gitignore b/storage/app/.gitignore new file mode 100644 index 0000000..8f4803c --- /dev/null +++ b/storage/app/.gitignore @@ -0,0 +1,3 @@ +* +!public/ +!.gitignore diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/debugbar/.gitignore b/storage/debugbar/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/debugbar/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore new file mode 100644 index 0000000..05c4471 --- /dev/null +++ b/storage/framework/.gitignore @@ -0,0 +1,9 @@ +compiled.php +config.php +down +events.scanned.php +maintenance.php +routes.php +routes.scanned.php +schedule-* +services.json diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore new file mode 100644 index 0000000..01e4a6c --- /dev/null +++ b/storage/framework/cache/.gitignore @@ -0,0 +1,3 @@ +* +!data/ +!.gitignore diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/cache/data/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/testing/.gitignore b/storage/framework/testing/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/testing/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..85def27 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,23 @@ +import forms from '@tailwindcss/forms'; +import defaultTheme from 'tailwindcss/defaultTheme'; + +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php', + './storage/framework/views/*.php', + './resources/views/**/*.blade.php', + './vendor/wireui/wireui/resources/**/*.blade.php', + './vendor/wireui/wireui/ts/**/*.ts', + './vendor/wireui/wireui/src/View/**/*.php' + ], + theme: { + extend: { + fontFamily: { + sans: [...defaultTheme.fontFamily.sans], + }, + }, + }, + + plugins: [forms], +}; diff --git a/tests/.env.ci.mysql b/tests/.env.ci.mysql new file mode 100644 index 0000000..5449b9b --- /dev/null +++ b/tests/.env.ci.mysql @@ -0,0 +1,26 @@ +# ENV FILE FOR THE GITHUB ACTION RUNNING MYSQL +APP_NAME=Laravel +APP_ENV=testing +APP_KEY=base64:NTrXToqFZJlv48dgPc+kNpc3SBt333TfDnF1mDShsBg= +APP_DEBUG=true +APP_URL=https://shelter.test + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=bivouac +DB_USERNAME=root +DB_PASSWORD=root + +BROADCAST_DRIVER=log + +DEBUGBAR_ENABLED=false +CACHE_DRIVER=array +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +MAIL_MAILER=array + +SCOUT_DRIVER=collection + +LEMON_SQUEEZY_ACTIVATE=true +LEMON_SQUEEZY_URL=https://bivouac.lemonsqueezy.com/ diff --git a/tests/.env.ci.pgsql b/tests/.env.ci.pgsql new file mode 100644 index 0000000..baecfde --- /dev/null +++ b/tests/.env.ci.pgsql @@ -0,0 +1,26 @@ +# ENV FILE FOR THE GITHUB ACTION RUNNING MYSQL +APP_NAME=Laravel +APP_ENV=testing +APP_KEY=base64:NTrXToqFZJlv48dgPc+kNpc3SBt333TfDnF1mDShsBg= +APP_DEBUG=true +APP_URL=https://shelter.test + +DB_CONNECTION=pgsql +DB_HOST=127.0.0.1 +DB_PORT=5432 +DB_DATABASE=bivouac +DB_USERNAME=bivouac +DB_PASSWORD=secret + +BROADCAST_DRIVER=log + +DEBUGBAR_ENABLED=false +CACHE_DRIVER=array +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +MAIL_MAILER=array + +SCOUT_DRIVER=collection + +LEMON_SQUEEZY_ACTIVATE=true +LEMON_SQUEEZY_URL=https://bivouac.lemonsqueezy.com/ diff --git a/tests/Browser/ExampleTest.php b/tests/Browser/ExampleTest.php new file mode 100644 index 0000000..a2957b5 --- /dev/null +++ b/tests/Browser/ExampleTest.php @@ -0,0 +1,22 @@ +browse(function (Browser $browser): void { + $browser->visit('/') + ->assertSee('Laravel'); + }); + } +} diff --git a/tests/Browser/LocaleTest.php b/tests/Browser/LocaleTest.php new file mode 100644 index 0000000..6fac7bc --- /dev/null +++ b/tests/Browser/LocaleTest.php @@ -0,0 +1,21 @@ +browse(function (Browser $browser): void { + $browser->visit('/login') + ->click('@locale-switch-french') + ->assertSee('Se connecter') + ->click('@locale-switch-english') + ->assertSee('Log in'); + }); + } +} diff --git a/tests/Browser/Pages/HomePage.php b/tests/Browser/Pages/HomePage.php new file mode 100644 index 0000000..45d9283 --- /dev/null +++ b/tests/Browser/Pages/HomePage.php @@ -0,0 +1,36 @@ + + */ + public function elements(): array + { + return [ + '@element' => '#selector', + ]; + } +} diff --git a/tests/Browser/Pages/Page.php b/tests/Browser/Pages/Page.php new file mode 100644 index 0000000..eb9a2de --- /dev/null +++ b/tests/Browser/Pages/Page.php @@ -0,0 +1,20 @@ + + */ + public static function siteElements(): array + { + return [ + '@element' => '#selector', + ]; + } +} diff --git a/tests/Browser/SettingsRolesAndLevelsTest.php b/tests/Browser/SettingsRolesAndLevelsTest.php new file mode 100644 index 0000000..4d2e94e --- /dev/null +++ b/tests/Browser/SettingsRolesAndLevelsTest.php @@ -0,0 +1,105 @@ +create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + + $this->browse(function (Browser $browser) use ($administrator): void { + // create a new role + $browser->loginAs($administrator) + ->visit('/dashboard') + ->click('@nav-settings-link') + ->click('@manage-role-link') + ->waitFor('@add-role-cta') + ->click('@add-role-cta') + ->assertPathIs('/settings/roles/new') + ->type('label', 'Software developer') + ->waitFor('@submit-form-button') + ->click('@submit-form-button') + ->assertPathIs('/settings/roles') + ->assertSee('Software developer'); + + // edit a role + $role = Role::orderBy('updated_at', 'desc') + ->where('organization_id', $administrator->organization_id) + ->first(); + + $browser->visit('/settings/roles') + ->waitFor('@edit-role-' . $role->id) + ->click('@edit-role-' . $role->id) + ->type('label', 'Awesome developer') + ->waitFor('@submit-form-button') + ->click('@submit-form-button') + ->assertPathIs('/settings/roles') + ->assertSee('Awesome developer'); + + // delete a role + $browser->visit('/settings/roles') + ->waitFor('@delete-role-' . $role->id) + ->click('@delete-role-' . $role->id) + ->acceptDialog() + ->pause(150) + ->assertDontSee('Awesome developer'); + }); + } + + /** @test */ + public function it_lets_you_crud_a_level(): void + { + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + + $this->browse(function (Browser $browser) use ($administrator): void { + // create a level + $browser->loginAs($administrator) + ->visit('/dashboard') + ->click('@nav-settings-link') + ->waitFor('@manage-level-link') + ->click('@manage-level-link') + ->waitFor('@add-level-cta') + ->click('@add-level-cta') + ->type('label', 'Intermediate') + ->waitFor('@submit-form-button') + ->click('@submit-form-button') + ->assertPathIs('/settings/levels') + ->pause(150) + ->assertSee('Intermediate'); + + // edit a level + $level = Level::orderBy('updated_at', 'desc') + ->where('organization_id', $administrator->organization_id) + ->first(); + + $browser->visit('/settings/levels') + ->waitFor('@edit-level-' . $level->id) + ->click('@edit-level-' . $level->id) + ->type('label', 'Intermediate Senior') + ->waitFor('@submit-form-button') + ->click('@submit-form-button') + ->assertPathIs('/settings/levels') + ->assertSee('Intermediate Senior'); + + // delete a level + $browser->visit('/settings/levels') + ->waitFor('@delete-level-' . $level->id) + ->click('@delete-level-' . $level->id) + ->acceptDialog() + ->pause(150) + ->assertDontSee('Intermediate Senior'); + }); + } +} diff --git a/tests/Browser/console/.gitignore b/tests/Browser/console/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/Browser/console/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/Browser/screenshots/.gitignore b/tests/Browser/screenshots/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/Browser/screenshots/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/Browser/source/.gitignore b/tests/Browser/source/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/Browser/source/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php new file mode 100644 index 0000000..e3ad27e --- /dev/null +++ b/tests/CreatesApplication.php @@ -0,0 +1,21 @@ +make(Kernel::class)->bootstrap(); + + return $app; + } +} diff --git a/tests/DuskTestCase.php b/tests/DuskTestCase.php new file mode 100644 index 0000000..3654b42 --- /dev/null +++ b/tests/DuskTestCase.php @@ -0,0 +1,66 @@ +addArguments(collect([ + $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080', + ])->unless($this->hasHeadlessDisabled(), function (Collection $items) { + return $items->merge([ + '--disable-gpu', + '--headless=new', + ]); + })->all()); + + return RemoteWebDriver::create( + $_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515', + DesiredCapabilities::chrome()->setCapability( + ChromeOptions::CAPABILITY, $options + ) + ); + } + + /** + * Determine whether the Dusk command has disabled headless mode. + */ + protected function hasHeadlessDisabled(): bool + { + return isset($_SERVER['DUSK_HEADLESS_DISABLED']) || + isset($_ENV['DUSK_HEADLESS_DISABLED']); + } + + /** + * Determine if the browser window should start maximized. + */ + protected function shouldStartMaximized(): bool + { + return isset($_SERVER['DUSK_START_MAXIMIZED']) || + isset($_ENV['DUSK_START_MAXIMIZED']); + } +} diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php new file mode 100644 index 0000000..caa6292 --- /dev/null +++ b/tests/Feature/Auth/AuthenticationTest.php @@ -0,0 +1,67 @@ +get('/login'); + + $response->assertStatus(200); + } + + /** + * @test + */ + public function users_can_authenticate_using_the_login_screen(): void + { + $user = User::factory()->create(); + + $response = $this->post('/login', [ + 'email' => $user->email, + 'password' => 'password', + ]); + + $this->assertAuthenticated(); + $response->assertRedirect(RouteServiceProvider::HOME); + } + + /** + * @test + */ + public function users_can_not_authenticate_with_invalid_password(): void + { + $user = User::factory()->create(); + + $this->post('/login', [ + 'email' => $user->email, + 'password' => 'wrong-password', + ]); + + $this->assertGuest(); + } + + /** + * @test + */ + public function users_can_logout(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/logout'); + + $this->assertGuest(); + $response->assertRedirect('/'); + } +} diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php new file mode 100644 index 0000000..ccf8b4d --- /dev/null +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -0,0 +1,74 @@ +create([ + 'email_verified_at' => null, + ]); + + $response = $this->actingAs($user)->get('/verify-email'); + + $response->assertStatus(200); + } + + /** + * @test + */ + public function email_can_be_verified(): void + { + $user = User::factory()->create([ + 'email_verified_at' => null, + ]); + + Event::fake(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1($user->email)] + ); + + $response = $this->actingAs($user)->get($verificationUrl); + + Event::assertDispatched(Verified::class); + $this->assertTrue($user->fresh()->hasVerifiedEmail()); + $response->assertRedirect(RouteServiceProvider::HOME . '?verified=1'); + } + + /** + * @test + */ + public function email_is_not_verified_with_invalid_hash(): void + { + $user = User::factory()->create([ + 'email_verified_at' => null, + ]); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1('wrong-email')] + ); + + $this->actingAs($user)->get($verificationUrl); + + $this->assertFalse($user->fresh()->hasVerifiedEmail()); + } +} diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php new file mode 100644 index 0000000..d3b166f --- /dev/null +++ b/tests/Feature/Auth/PasswordConfirmationTest.php @@ -0,0 +1,53 @@ +create(); + + $response = $this->actingAs($user)->get('/confirm-password'); + + $response->assertStatus(200); + } + + /** + * @test + */ + public function password_can_be_confirmed(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/confirm-password', [ + 'password' => 'password', + ]); + + $response->assertRedirect(); + $response->assertSessionHasNoErrors(); + } + + /** + * @test + */ + public function password_is_not_confirmed_with_invalid_password(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/confirm-password', [ + 'password' => 'wrong-password', + ]); + + $response->assertSessionHasErrors(); + } +} diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php new file mode 100644 index 0000000..f8f8458 --- /dev/null +++ b/tests/Feature/Auth/PasswordResetTest.php @@ -0,0 +1,83 @@ +get('/forgot-password'); + + $response->assertStatus(200); + } + + /** + * @test + */ + public function reset_password_link_can_be_requested(): void + { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class); + } + + /** + * @test + */ + public function reset_password_screen_can_be_rendered(): void + { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class, function ($notification) { + $response = $this->get('/reset-password/' . $notification->token); + + $response->assertStatus(200); + + return true; + }); + } + + /** + * @test + */ + public function password_can_be_reset_with_valid_token(): void + { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) { + $response = $this->post('/reset-password', [ + 'token' => $notification->token, + 'email' => $user->email, + 'password' => 'password', + 'password_confirmation' => 'password', + ]); + + $response->assertSessionHasNoErrors(); + + return true; + }); + } +} diff --git a/tests/Feature/Auth/PasswordUpdateTest.php b/tests/Feature/Auth/PasswordUpdateTest.php new file mode 100644 index 0000000..1a2432e --- /dev/null +++ b/tests/Feature/Auth/PasswordUpdateTest.php @@ -0,0 +1,57 @@ +create(); + + $response = $this + ->actingAs($user) + ->from('/profile') + ->put('/password', [ + 'current_password' => 'password', + 'password' => 'new-password', + 'password_confirmation' => 'new-password', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/profile'); + + $this->assertTrue(Hash::check('new-password', $user->refresh()->password)); + } + + /** + * @test + */ + public function correct_password_must_be_provided_to_update_password(): void + { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->from('/profile') + ->put('/password', [ + 'current_password' => 'wrong-password', + 'password' => 'new-password', + 'password_confirmation' => 'new-password', + ]); + + $response + ->assertSessionHasErrorsIn('updatePassword', 'current_password') + ->assertRedirect('/profile'); + } +} diff --git a/tests/Feature/Auth/RegistrationTest.php b/tests/Feature/Auth/RegistrationTest.php new file mode 100644 index 0000000..58634e5 --- /dev/null +++ b/tests/Feature/Auth/RegistrationTest.php @@ -0,0 +1,40 @@ +get('/register'); + + $response->assertStatus(200); + } + + /** + * @test + */ + public function new_users_can_register(): void + { + $response = $this->post('/register', [ + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@example.com', + 'password' => 'password', + 'password_confirmation' => 'password', + 'organization_name' => 'Test Organization', + ]); + + $this->assertAuthenticated(); + $response->assertRedirect(RouteServiceProvider::HOME); + } +} diff --git a/tests/Feature/ProfileTest.php b/tests/Feature/ProfileTest.php new file mode 100644 index 0000000..0f503e9 --- /dev/null +++ b/tests/Feature/ProfileTest.php @@ -0,0 +1,89 @@ +create(); + + $response = $this + ->actingAs($user) + ->get('/profile'); + + $response->assertOk(); + } + + /** + * @test + */ + public function email_verification_status_is_unchanged_when_the_email_address_is_unchanged(): void + { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->patch('/profile', [ + 'name' => 'Test User', + 'email' => $user->email, + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/profile'); + + $this->assertNotNull($user->refresh()->email_verified_at); + } + + /** + * @test + */ + public function user_can_delete_their_account(): void + { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->delete('/profile', [ + 'password' => 'password', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/'); + + $this->assertGuest(); + $this->assertNull($user->fresh()); + } + + /** + * @test + */ + public function correct_password_must_be_provided_to_delete_account(): void + { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->from('/profile') + ->delete('/profile', [ + 'password' => 'wrong-password', + ]); + + $response + ->assertSessionHasErrorsIn('userDeletion', 'password') + ->assertRedirect('/profile'); + + $this->assertNotNull($user->fresh()); + } +} diff --git a/tests/Feature/Settings/ManageLevelTest.php b/tests/Feature/Settings/ManageLevelTest.php new file mode 100644 index 0000000..2ebcf31 --- /dev/null +++ b/tests/Feature/Settings/ManageLevelTest.php @@ -0,0 +1,104 @@ +create([ + 'label' => 'Intermediate', + ]); + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + 'organization_id' => $level->organization_id, + ]); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + 'organization_id' => $level->organization_id, + ]); + + $this->actingAs($user) + ->get('/settings/levels') + ->assertStatus(401); + + $this->actingAs($administrator) + ->get('/settings/levels') + ->assertStatus(200); + + $this->actingAs($administrator) + ->get('/settings/levels') + ->assertSee('Intermediate'); + } + + /** @test */ + public function an_administrator_can_create_a_new_level(): void + { + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + + $this->actingAs($user) + ->post('/settings/levels', [ + 'label' => fake()->name, + ]) + ->assertStatus(401); + + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + + $this->actingAs($administrator) + ->post('/settings/levels', [ + 'label' => 'Advanced', + ]) + ->assertRedirectToRoute('settings.level.index'); + + $this->actingAs($administrator) + ->get('/settings/levels') + ->assertSee('Advanced'); + } + + /** @test */ + public function a_level_can_be_edited(): void + { + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + $level = Level::factory()->create([ + 'organization_id' => $administrator->organization_id, + ]); + + $this->actingAs($administrator) + ->put('/settings/levels/' . $level->id, [ + 'label' => 'Intermediate', + ]) + ->assertStatus(302) + ->assertRedirectToRoute('settings.level.index'); + } + + // /** @test */ + public function a_level_cant_be_edited_with_the_wrong_permission(): void + { + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $level = Level::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + + $this->actingAs($user) + ->put('/settings/levels/' . $level->id, [ + 'label' => 'Intermediate', + ]) + ->assertStatus(401); + } +} diff --git a/tests/Feature/Settings/ManageRoleTest.php b/tests/Feature/Settings/ManageRoleTest.php new file mode 100644 index 0000000..a62e30e --- /dev/null +++ b/tests/Feature/Settings/ManageRoleTest.php @@ -0,0 +1,104 @@ +create([ + 'label' => 'Developer', + ]); + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + 'organization_id' => $role->organization_id, + ]); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + 'organization_id' => $role->organization_id, + ]); + + $this->actingAs($user) + ->get('/settings/roles') + ->assertStatus(401); + + $this->actingAs($administrator) + ->get('/settings/roles') + ->assertStatus(200); + + $this->actingAs($administrator) + ->get('/settings/roles') + ->assertSee('Developer'); + } + + /** @test */ + public function an_administrator_can_create_a_new_role(): void + { + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + + $this->actingAs($user) + ->post('/settings/roles', [ + 'label' => fake()->name, + ]) + ->assertStatus(401); + + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + + $this->actingAs($administrator) + ->post('/settings/roles', [ + 'label' => 'Software engineer', + ]) + ->assertRedirectToRoute('settings.role.index'); + + $this->actingAs($administrator) + ->get('/settings/roles') + ->assertSee('Software engineer'); + } + + /** @test */ + public function a_role_can_be_edited(): void + { + $administrator = User::factory()->create([ + 'permissions' => User::ROLE_ADMINISTRATOR, + ]); + $role = Role::factory()->create([ + 'organization_id' => $administrator->organization_id, + ]); + + $this->actingAs($administrator) + ->put('/settings/roles/' . $role->id, [ + 'label' => 'Software engineer', + ]) + ->assertStatus(302) + ->assertRedirectToRoute('settings.role.index'); + } + + // /** @test */ + public function a_role_cant_be_edited_with_the_wrong_permission(): void + { + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $role = Role::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + + $this->actingAs($user) + ->put('/settings/roles/' . $role->id, [ + 'label' => 'Software engineer', + ]) + ->assertStatus(401); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..2932d4a --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,10 @@ +create(); + PopulateAccount::dispatch($organization); + + $this->assertEquals( + 13, + DB::table('roles')->count() + ); + + $this->assertEquals( + 4, + DB::table('levels')->count() + ); + } +} diff --git a/tests/Unit/Models/LevelTest.php b/tests/Unit/Models/LevelTest.php new file mode 100644 index 0000000..c788cea --- /dev/null +++ b/tests/Unit/Models/LevelTest.php @@ -0,0 +1,19 @@ +create(); + $this->assertTrue($level->organization()->exists()); + } +} diff --git a/tests/Unit/Models/OrganizationTest.php b/tests/Unit/Models/OrganizationTest.php new file mode 100644 index 0000000..060c340 --- /dev/null +++ b/tests/Unit/Models/OrganizationTest.php @@ -0,0 +1,32 @@ +create(); + Role::factory()->create(['organization_id' => $organization->id]); + + $this->assertTrue($organization->roles()->exists()); + } + + /** @test */ + public function it_has_many_levels(): void + { + $organization = Organization::factory()->create(); + Level::factory()->create(['organization_id' => $organization->id]); + + $this->assertTrue($organization->levels()->exists()); + } +} diff --git a/tests/Unit/Models/RoleTest.php b/tests/Unit/Models/RoleTest.php new file mode 100644 index 0000000..13cbb33 --- /dev/null +++ b/tests/Unit/Models/RoleTest.php @@ -0,0 +1,19 @@ +create(); + $this->assertTrue($role->organization()->exists()); + } +} diff --git a/tests/Unit/Models/UserTest.php b/tests/Unit/Models/UserTest.php new file mode 100644 index 0000000..5fa2fe7 --- /dev/null +++ b/tests/Unit/Models/UserTest.php @@ -0,0 +1,24 @@ +create(); + $user = User::factory()->create([ + 'organization_id' => $organization->id, + ]); + + $this->assertTrue($user->organization()->exists()); + } +} diff --git a/tests/Unit/Services/CreateAccountTest.php b/tests/Unit/Services/CreateAccountTest.php new file mode 100644 index 0000000..9a6a75b --- /dev/null +++ b/tests/Unit/Services/CreateAccountTest.php @@ -0,0 +1,56 @@ +executeService(); + } + + private function executeService(): void + { + Queue::fake(); + + $user = (new CreateAccount( + email: 'john@email.com', + password: 'johnny', + firstName: 'johnny', + lastName: 'depp', + organizationName: 'johnny inc', + ))->execute(); + + $this->assertInstanceOf( + User::class, + $user + ); + + $this->assertDatabaseHas('users', [ + 'id' => $user->id, + 'first_name' => 'johnny', + 'last_name' => 'depp', + 'name_for_avatar' => 'johnny', + 'email' => 'john@email.com', + 'organization_id' => $user->organization_id, + 'permissions' => 'administrator', + ]); + + $this->assertDatabaseHas('organizations', [ + 'id' => $user->organization_id, + 'name' => 'johnny inc', + ]); + + Queue::assertPushed(PopulateAccount::class); + } +} diff --git a/tests/Unit/Services/CreateLevelTest.php b/tests/Unit/Services/CreateLevelTest.php new file mode 100644 index 0000000..e7f7bf1 --- /dev/null +++ b/tests/Unit/Services/CreateLevelTest.php @@ -0,0 +1,51 @@ +create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $this->executeService($user); + } + + /** @test */ + public function it_fails_if_the_user_doesnt_have_the_right_permissions(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $this->executeService($user); + } + + private function executeService(User $user): void + { + $this->actingAs($user); + $level = (new CreateLevel('intermediate'))->execute(); + + $this->assertInstanceOf( + Level::class, + $level + ); + + $this->assertDatabaseHas('levels', [ + 'id' => $level->id, + 'organization_id' => $user->organization_id, + 'label' => 'intermediate', + ]); + } +} diff --git a/tests/Unit/Services/CreateRoleTest.php b/tests/Unit/Services/CreateRoleTest.php new file mode 100644 index 0000000..bc8c778 --- /dev/null +++ b/tests/Unit/Services/CreateRoleTest.php @@ -0,0 +1,51 @@ +create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $this->executeService($user); + } + + /** @test */ + public function it_fails_if_the_user_doesnt_have_the_right_permissions(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $this->executeService($user); + } + + private function executeService(User $user): void + { + $this->actingAs($user); + $role = (new CreateRole('developer'))->execute(); + + $this->assertInstanceOf( + Role::class, + $role + ); + + $this->assertDatabaseHas('roles', [ + 'id' => $role->id, + 'organization_id' => $user->organization_id, + 'label' => 'developer', + ]); + } +} diff --git a/tests/Unit/Services/DestroyLevelTest.php b/tests/Unit/Services/DestroyLevelTest.php new file mode 100644 index 0000000..ca4548d --- /dev/null +++ b/tests/Unit/Services/DestroyLevelTest.php @@ -0,0 +1,63 @@ +create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $level = Level::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($level, $user); + } + + /** @test */ + public function it_fails_if_the_user_doesnt_have_the_right_permissions(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $level = Level::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($level, $user); + } + + /** @test */ + public function it_fails_if_the_level_doesnt_belong_to_organization(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $level = Level::factory()->create(); + $this->executeService($level, $user); + } + + private function executeService(Level $level, User $user): void + { + $this->actingAs($user); + (new DestroyLevel( + level: $level, + ))->execute(); + + $this->assertDatabaseMissing('levels', [ + 'id' => $level->id, + ]); + } +} diff --git a/tests/Unit/Services/DestroyRoleTest.php b/tests/Unit/Services/DestroyRoleTest.php new file mode 100644 index 0000000..437d400 --- /dev/null +++ b/tests/Unit/Services/DestroyRoleTest.php @@ -0,0 +1,63 @@ +create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $role = Role::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($role, $user); + } + + /** @test */ + public function it_fails_if_the_user_doesnt_have_the_right_permissions(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $role = Role::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($role, $user); + } + + /** @test */ + public function it_fails_if_the_role_doesnt_belong_to_organization(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $role = Role::factory()->create(); + $this->executeService($role, $user); + } + + private function executeService(Role $role, User $user): void + { + $this->actingAs($user); + (new DestroyRole( + role: $role, + ))->execute(); + + $this->assertDatabaseMissing('roles', [ + 'id' => $role->id, + ]); + } +} diff --git a/tests/Unit/Services/UpdateLevelTest.php b/tests/Unit/Services/UpdateLevelTest.php new file mode 100644 index 0000000..91521c7 --- /dev/null +++ b/tests/Unit/Services/UpdateLevelTest.php @@ -0,0 +1,71 @@ +create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $level = Level::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($level, $user); + } + + /** @test */ + public function it_fails_if_the_user_doesnt_have_the_right_permissions(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $level = Level::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($level, $user); + } + + /** @test */ + public function it_fails_if_the_level_doesnt_belong_to_organization(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $level = Level::factory()->create(); + $this->executeService($level, $user); + } + + private function executeService(Level $level, User $user): void + { + $this->actingAs($user); + $level = (new UpdateLevel( + level: $level, + label: 'developer' + ))->execute(); + + $this->assertInstanceOf( + Level::class, + $level + ); + + $this->assertDatabaseHas('levels', [ + 'id' => $level->id, + 'organization_id' => $user->organization_id, + 'label' => 'developer', + ]); + } +} diff --git a/tests/Unit/Services/UpdateRoleTest.php b/tests/Unit/Services/UpdateRoleTest.php new file mode 100644 index 0000000..2e52d8d --- /dev/null +++ b/tests/Unit/Services/UpdateRoleTest.php @@ -0,0 +1,71 @@ +create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $role = Role::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($role, $user); + } + + /** @test */ + public function it_fails_if_the_user_doesnt_have_the_right_permissions(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_USER, + ]); + $role = Role::factory()->create([ + 'organization_id' => $user->organization_id, + ]); + $this->executeService($role, $user); + } + + /** @test */ + public function it_fails_if_the_role_doesnt_belong_to_organization(): void + { + $this->expectException(Exception::class); + $user = User::factory()->create([ + 'permissions' => User::ROLE_ACCOUNT_MANAGER, + ]); + $role = Role::factory()->create(); + $this->executeService($role, $user); + } + + private function executeService(Role $role, User $user): void + { + $this->actingAs($user); + $role = (new UpdateRole( + role: $role, + label: 'developer' + ))->execute(); + + $this->assertInstanceOf( + Role::class, + $role + ); + + $this->assertDatabaseHas('roles', [ + 'id' => $role->id, + 'organization_id' => $user->organization_id, + 'label' => 'developer', + ]); + } +} diff --git a/tests/Unit/Traits/TranslatableTest.php b/tests/Unit/Traits/TranslatableTest.php new file mode 100644 index 0000000..dad9f84 --- /dev/null +++ b/tests/Unit/Traits/TranslatableTest.php @@ -0,0 +1,36 @@ +create([ + 'label' => 'this is the real name', + 'label_translation_key' => 'role.label', + ]); + + $this->assertEquals( + 'this is the real name', + $role->label + ); + + $role = Role::factory()->create([ + 'label' => null, + 'label_translation_key' => 'role.label', + ]); + + $this->assertEquals( + 'role.label', + $role->label + ); + } +} diff --git a/tests/Unit/ViewModels/Settings/SettingsLevelViewModelTest.php b/tests/Unit/ViewModels/Settings/SettingsLevelViewModelTest.php new file mode 100644 index 0000000..65f3410 --- /dev/null +++ b/tests/Unit/ViewModels/Settings/SettingsLevelViewModelTest.php @@ -0,0 +1,44 @@ +create(); + $this->actingAs($user); + + $array = SettingsLevelViewModel::index(); + + $this->assertCount(1, $array); + $this->assertArrayHasKey('levels', $array); + } + + /** @test */ + public function it_gets_the_level_object(): void + { + $level = Level::factory()->create([ + 'label' => 'Dunder', + ]); + $array = SettingsLevelViewModel::level($level); + + $this->assertCount(2, $array); + $this->assertEquals( + [ + 'id' => $level->id, + 'label' => 'Dunder', + ], + $array + ); + } +} diff --git a/tests/Unit/ViewModels/Settings/SettingsRoleViewModelTest.php b/tests/Unit/ViewModels/Settings/SettingsRoleViewModelTest.php new file mode 100644 index 0000000..a42b4a2 --- /dev/null +++ b/tests/Unit/ViewModels/Settings/SettingsRoleViewModelTest.php @@ -0,0 +1,44 @@ +create(); + $this->actingAs($user); + + $array = SettingsRoleViewModel::index(); + + $this->assertCount(1, $array); + $this->assertArrayHasKey('roles', $array); + } + + /** @test */ + public function it_gets_the_role_object(): void + { + $role = Role::factory()->create([ + 'label' => 'Dunder', + ]); + $array = SettingsRoleViewModel::role($role); + + $this->assertCount(2, $array); + $this->assertEquals( + [ + 'id' => $role->id, + 'label' => 'Dunder', + ], + $array + ); + } +} diff --git a/tlint.json b/tlint.json new file mode 100644 index 0000000..06419dd --- /dev/null +++ b/tlint.json @@ -0,0 +1,10 @@ +{ + "preset": "laravel", + "disabled": ["ArrayParametersOverViewWith"], + "excluded": ["tests/"], + "paths": [ + { + "controllers": ["app/Domain/Http/Controllers"] + } + ] +} diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..0299a52 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,12 @@ +import laravel from 'laravel-vite-plugin'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [ + laravel({ + input: ['resources/css/app.css', 'resources/js/app.js'], + refresh: true, + valetTls: 'shelter.test', + }), + ], +});