diff --git a/.env.ci b/.env.ci index 08b91e4..857f7af 100644 --- a/.env.ci +++ b/.env.ci @@ -9,13 +9,13 @@ LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=33306 +DB_HOST=mysql +DB_PORT=3306 DB_DATABASE=testing DB_USERNAME=user DB_PASSWORD=password -SCOUT_DRIVER=null +SCOUT_DRIVER=collection FILESYSTEM_DISK=local QUEUE_CONNECTION=sync CACHE_STORE=array diff --git a/.env.full b/.env.full index 556d2e9..48ef9ae 100644 --- a/.env.full +++ b/.env.full @@ -89,3 +89,11 @@ DB_HUB_COLLATION=utf8mb4_0900_ai_ci GITEA_DOMAIN= GITEA_TOKEN= + +# API key for Scribe documentation. +SCRIBE_AUTH_KEY= + +# Discord OAuth Credentials +DISCORD_CLIENT_ID= +DISCORD_CLIENT_SECRET= +DISCORD_REDIRECT_URI=${APP_URL}/login/discord/callback diff --git a/.env.light b/.env.light index 6bd4cd1..3b84afc 100644 --- a/.env.light +++ b/.env.light @@ -42,3 +42,11 @@ SCOUT_DRIVER=collection MAIL_MAILER=log MAIL_FROM_ADDRESS="no-reply@sp-tarkov.com" MAIL_FROM_NAME="${APP_NAME}" + +# API key for Scribe documentation. +SCRIBE_AUTH_KEY= + +# Discord OAuth Credentials +DISCORD_CLIENT_ID= +DISCORD_CLIENT_SECRET= +DISCORD_REDIRECT_URI=${APP_URL}/login/discord/callback diff --git a/.github/README.md b/.gitea/README.md similarity index 87% rename from .github/README.md rename to .gitea/README.md index 518895e..50f0715 100644 --- a/.github/README.md +++ b/.gitea/README.md @@ -12,7 +12,7 @@ The Forge is a Laravel-based web application that provides a platform for the Si ## Development Environment Setup -We use [Laravel Sail](https://laravel.com/docs/11.x/sail) to mirror the services that are used in our production server in a local development environment. You can see detailed instructions on how to configure the [full development environment](https://github.com/sp-tarkov/forge/wiki/Full-Windows-Dev-Env) or a [lightweight development environment](https://github.com/sp-tarkov/forge/wiki/Light-Windows-Dev-Env) on the project wiki. The full development environment is recommended. +We use [Laravel Sail](https://laravel.com/docs/11.x/sail) to mirror the services that are used in our production server in a local development environment. You can see detailed instructions on how to configure the [full development environment](https://dev.sp-tarkov.com/SPT/forge/wiki/Full-Windows-Dev-Env) or a [lightweight development environment](https://dev.sp-tarkov.com/SPT/forge/wiki/Light-Windows-Dev-Env) on the project wiki. The full development environment is recommended. ### Available Services: @@ -25,13 +25,13 @@ We use [Laravel Sail](https://laravel.com/docs/11.x/sail) to mirror the services ### Notable Routes -| Service | Authentication | Access Via Host | -|----------------------------------|----------------|-----------------------------| +| Service | Authentication | Access Via Host | +|----------------------------------|----------------|----------------------------| | Laravel Filament Admin Panel | Via User Role | | | Redis Queue Management (Horizon) | Via User Role | | | Website Status (Pulse) | Via User Role | | -| Meilisearch WebUI | Local Only | | -| Mailpit WebUI | Local Only | | +| Meilisearch WebUI | Local Only | | +| Mailpit WebUI | Local Only | | Most of these connection settings should already be configured in the `.env.full` or `.env.light` example files. Simply save one of these (depending on your environment) as `.env` and adjust settings as needed. @@ -80,12 +80,12 @@ For more information on Laravel development, please refer to the [official docum ## Development Discussion -*__Please note__, we are very early in development and will likely not accept work that is not discussed beforehand through the following channels...* - -You may propose new features or improvements of existing Forge behavior in [the repository's GitHub discussion board](https://github.com/sp-tarkov/forge/discussions). If you propose a new feature, please be willing to implement at least some of the code that would be needed to complete the feature. +*__Please note__, we are very early in development and will likely not accept work that is not discussed beforehand.* Informal discussion regarding bugs, new features, and implementation of existing features takes place in the `#website-general` channel of the [Single Player Tarkov Discord server](https://discord.com/invite/Xn9msqQZan). Refringe, the maintainer of Forge, is typically present in the channel on weekdays from 9am-5pm Eastern Time (ET), and sporadically present in the channel at other times. +If you propose a new feature, please be willing to implement at least some of the code that would be needed to complete the feature. + ## Which Branch? The `main` branch is the default branch for Forge. This branch is used for the latest stable release of the site. The `develop` branch is used for the latest development changes. All feature branches should be based on the `develop` branch. All pull requests should target the `develop` branch. diff --git a/.github/logo.spt.png b/.gitea/logo.spt.png similarity index 100% rename from .github/logo.spt.png rename to .gitea/logo.spt.png diff --git a/.github/workflows/quality.yaml b/.gitea/workflows/quality.yaml similarity index 96% rename from .github/workflows/quality.yaml rename to .gitea/workflows/quality.yaml index 739f925..4c24ed5 100644 --- a/.github/workflows/quality.yaml +++ b/.gitea/workflows/quality.yaml @@ -4,7 +4,7 @@ on: [ push, pull_request ] jobs: security-checker: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -12,66 +12,79 @@ jobs: uses: symfonycorp/security-checker-action@v5 larastan: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' extensions: mbstring, dom, fileinfo coverage: none + - name: Get Composer Cache Directory id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer dependencies uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- + - name: Install Composer Dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Prepare Laravel Environment run: | php -r "file_exists('.env') || copy('.env.ci', '.env');" php artisan key:generate php artisan optimize + - name: Execute Code Static Analysis with Larastan run: ./vendor/bin/phpstan analyse -c ./phpstan.neon --no-progress --error-format=github pint-fixer: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v4 + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' extensions: mbstring, dom, fileinfo coverage: none + - name: Get Composer Cache Directory id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer dependencies uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- + - name: Install Composer Dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Prepare Laravel Environment run: | php -r "file_exists('.env') || copy('.env.ci', '.env');" php artisan key:generate php artisan optimize + - name: Run Pint Code Style Fixer run: ./vendor/bin/pint + - uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: Pint PHP Style Fixes [no ci] diff --git a/.github/workflows/tests.yaml b/.gitea/workflows/tests.yaml similarity index 91% rename from .github/workflows/tests.yaml rename to .gitea/workflows/tests.yaml index fc8bf60..7803c49 100644 --- a/.github/workflows/tests.yaml +++ b/.gitea/workflows/tests.yaml @@ -4,7 +4,7 @@ on: [ push, pull_request ] jobs: laravel-tests: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest services: mysql: image: mysql:8.3 @@ -13,53 +13,65 @@ jobs: MYSQL_USER: user MYSQL_PASSWORD: password MYSQL_ROOT_PASSWORD: password - ports: - - 33306:3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + options: --health-cmd="mysql -u user -D testing -ppassword -h mysql -e ''" --health-interval=10s --health-timeout=5s --health-retries=3 + steps: - name: Checkout uses: actions/checkout@v4 + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' extensions: mbstring, dom, fileinfo coverage: none + - name: Get Composer Cache Directory id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer dependencies uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- + - name: Install Composer Dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Get NPM Cache Directory id: npm-cache run: echo "NPM_CACHE_DIR=$(npm config get cache)" >> $GITHUB_ENV + - name: Cache NPM Dependencies uses: actions/cache@v4 with: path: ${{ env.NPM_CACHE_DIR }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-node- + - name: Install npm dependencies run: npm ci + - name: Build Front-end Assets run: npm run build + - name: Prepare Laravel Environment run: | php -r "file_exists('.env') || copy('.env.ci', '.env');" php artisan key:generate php artisan optimize + - name: Run Database Migrations run: php artisan migrate + - name: Link Storage run: php artisan storage:link + - name: Run Tests run: php artisan test + - name: Display Laravel Log if: failure() run: cat storage/logs/laravel.log diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 4f8bc32..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 2 -updates: - # Composer dependencies (PHP) - - package-ecosystem: "composer" - directory: "/" - schedule: - interval: "daily" - time: "15:00" # 10am EST - open-pull-requests-limit: 10 - target-branch: "develop" - labels: - - "dependencies" - assignees: - - "Refringe" - - # GitHub Actions - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - time: "15:00" # 10am EST - open-pull-requests-limit: 10 - target-branch: "develop" - labels: - - "dependencies" - assignees: - - "Refringe" - - # npm modules (JavaScript) - - package-ecosystem: "npm" - directory: "/" - schedule: - interval: "daily" - time: "15:00" # 10am EST - open-pull-requests-limit: 10 - target-branch: "develop" - labels: - - "dependencies" - assignees: - - "Refringe" diff --git a/.gitignore b/.gitignore index 3ccc7e5..2855410 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,10 @@ public/build public/hot public/storage storage/*.key +storage/app/livewire-tmp +storage/app/public +!storage/app/public/cover-photos/.gitkeep +!storage/app/public/profile-photos/.gitkeep vendor auth.json frankenphp @@ -24,3 +28,4 @@ Homestead.json Homestead.yaml npm-debug.log yarn-error.log +.scribe diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index 566e51d..057f25c 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -20,7 +20,7 @@ class CreateNewUser implements CreatesNewUsers public function create(array $input): User { Validator::make($input, [ - 'name' => ['required', 'string', 'max:255'], + 'name' => ['required', 'string', 'max:36', 'unique:users'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => $this->passwordRules(), 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '', diff --git a/app/Actions/Fortify/PasswordValidationRules.php b/app/Actions/Fortify/PasswordValidationRules.php index 76b19d3..3c53605 100644 --- a/app/Actions/Fortify/PasswordValidationRules.php +++ b/app/Actions/Fortify/PasswordValidationRules.php @@ -8,8 +8,6 @@ trait PasswordValidationRules { /** * Get the validation rules used to validate passwords. - * - * @return array|string> */ protected function passwordRules(): array { diff --git a/app/Actions/Fortify/ResetUserPassword.php b/app/Actions/Fortify/ResetUserPassword.php index 7a57c50..e6bd3db 100644 --- a/app/Actions/Fortify/ResetUserPassword.php +++ b/app/Actions/Fortify/ResetUserPassword.php @@ -13,8 +13,6 @@ class ResetUserPassword implements ResetsUserPasswords /** * Validate and reset the user's forgotten password. - * - * @param array $input */ public function reset(User $user, array $input): void { diff --git a/app/Actions/Fortify/UpdateUserPassword.php b/app/Actions/Fortify/UpdateUserPassword.php index 7005639..39f2cb9 100644 --- a/app/Actions/Fortify/UpdateUserPassword.php +++ b/app/Actions/Fortify/UpdateUserPassword.php @@ -13,8 +13,6 @@ class UpdateUserPassword implements UpdatesUserPasswords /** * Validate and update the user's password. - * - * @param array $input */ public function update(User $user, array $input): void { diff --git a/app/Actions/Fortify/UpdateUserProfileInformation.php b/app/Actions/Fortify/UpdateUserProfileInformation.php index 10569dd..845647b 100644 --- a/app/Actions/Fortify/UpdateUserProfileInformation.php +++ b/app/Actions/Fortify/UpdateUserProfileInformation.php @@ -12,13 +12,11 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation { /** * Validate and update the given user's profile information. - * - * @param array $input */ public function update(User $user, array $input): void { Validator::make($input, [ - 'name' => ['required', 'string', 'max:255'], + 'name' => ['required', 'string', 'max:255', Rule::unique('users')->ignore($user->id)], 'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)], 'photo' => ['nullable', 'mimes:jpg,jpeg,png', 'max:1024'], 'cover' => ['nullable', 'mimes:jpg,jpeg,png', 'max:2048'], diff --git a/app/Console/Commands/ImportHubCommand.php b/app/Console/Commands/ImportHubCommand.php index b89bb91..1d92474 100644 --- a/app/Console/Commands/ImportHubCommand.php +++ b/app/Console/Commands/ImportHubCommand.php @@ -2,7 +2,7 @@ namespace App\Console\Commands; -use App\Jobs\ImportHubDataJob; +use App\Jobs\Import\ImportHubDataJob; use Illuminate\Console\Command; class ImportHubCommand extends Command diff --git a/app/Http/Controllers/Api/AuthController.php b/app/Http/Controllers/Api/AuthController.php index 3a4cca0..31321bb 100644 --- a/app/Http/Controllers/Api/AuthController.php +++ b/app/Http/Controllers/Api/AuthController.php @@ -9,41 +9,77 @@ use App\Traits\ApiResponses; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Knuckles\Scribe\Attributes\BodyParam; +use Knuckles\Scribe\Attributes\Response; +use Knuckles\Scribe\Attributes\ResponseField; +use Laravel\Sanctum\PersonalAccessToken; class AuthController extends Controller { use ApiResponses; + /** + * Login + * + * Authenticates the user and returns a read-only API token. This API token can then be saved and used for future + * requests that require authentication. + * + * @unauthenticated + * + * @group Authentication + */ + #[BodyParam('token_name', 'string', 'The name of the API token.', required: false, example: 'Dynamic API Token')] + #[Response(['message' => 'authenticated', 'data' => ['token' => 'YOUR_API_KEY'], 'status' => 200], status: 200, description: 'Authenticated successfully')] + #[Response(['message' => 'invalid credentials', 'status' => 401], status: 401, description: 'Invalid credentials')] + #[ResponseField('token', description: 'The newly created read-only API token to use for future authenticated requests.')] public function login(LoginUserRequest $request): JsonResponse { $request->validated($request->all()); if (! Auth::attempt($request->only('email', 'password'))) { - return $this->error(__('Invalid credentials'), 401); + return $this->error(__('invalid credentials'), 401); } $user = User::firstWhere('email', $request->email); $tokenName = $request->token_name ?? __('Dynamic API Token'); - return $this->success(__('Authenticated'), [ + return $this->success(__('authenticated'), [ // Only allowing the 'read' scope to be dynamically created. Can revisit later when writes are possible. 'token' => $user->createToken($tokenName, ['read'])->plainTextToken, ]); } + /** + * Logout + * + * Destroys the user's current API token, effectively logging them out. + * + * @group Authentication + */ + #[Response(['message' => 'success', 'status' => 200], status: 200, description: 'Token destroyed successfully')] public function logout(Request $request): JsonResponse { - /** @var \Laravel\Sanctum\PersonalAccessToken $token */ + /** @var PersonalAccessToken $token */ $token = $request->user()->currentAccessToken(); $token->delete(); - return $this->success(__('Revoked API token')); + return $this->success(__('success')); } + /** + * Logout All + * + * Destroys all the user's API tokens, effectively logging everyone out of the account. + * + * @group Authentication + */ + #[Response(['message' => 'success', 'status' => 200], status: 200, description: 'Tokens destroyed successfully')] public function logoutAll(Request $request): JsonResponse { $request->user()->tokens()->delete(); - return $this->success(__('Revoked all API tokens')); + return $this->success(__('success')); } } diff --git a/app/Http/Controllers/Api/V0/ApiController.php b/app/Http/Controllers/Api/V0/ApiController.php index 588e047..f8b8860 100644 --- a/app/Http/Controllers/Api/V0/ApiController.php +++ b/app/Http/Controllers/Api/V0/ApiController.php @@ -4,6 +4,8 @@ namespace App\Http\Controllers\Api\V0; use App\Http\Controllers\Controller; use Illuminate\Support\Str; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; class ApiController extends Controller { @@ -13,7 +15,11 @@ class ApiController extends Controller */ public static function shouldInclude(string|array $relationships): bool { - $param = request()->get('include'); + try { + $param = request()->get('include'); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + return false; + } if (! $param) { return false; diff --git a/app/Http/Controllers/Api/V0/ModController.php b/app/Http/Controllers/Api/V0/ModController.php index 9065bbc..b0f738a 100644 --- a/app/Http/Controllers/Api/V0/ModController.php +++ b/app/Http/Controllers/Api/V0/ModController.php @@ -3,50 +3,52 @@ namespace App\Http\Controllers\Api\V0; use App\Http\Filters\V1\ModFilter; -use App\Http\Requests\Api\V0\StoreModRequest; -use App\Http\Requests\Api\V0\UpdateModRequest; use App\Http\Resources\Api\V0\ModResource; use App\Models\Mod; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; +use Illuminate\Http\Resources\Json\JsonResource; +use Knuckles\Scribe\Attributes\QueryParam; +use Knuckles\Scribe\Attributes\UrlParam; class ModController extends ApiController { /** - * Display a listing of the resource. + * Get Mods + * + * List, filter, and sort basic information about mods. + * + * @group Mods */ - public function index(ModFilter $filters) + #[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'users,versions,license')] + #[QueryParam('filter[id]', 'string', 'Filter by the `id`. Select multiple by separating the IDs with a comma.', required: false, example: '5,10,15')] + #[QueryParam('filter[hub_id]', 'string', 'Filter by the `hub_id` attribute. Select multiple by separating the IDs with a comma.', required: false, example: '20')] + #[QueryParam('filter[name]', 'string', 'Filter by the `name` attribute. Use `*` as the wildcard character.', required: false, example: '*SAIN*')] + #[QueryParam('filter[slug]', 'string', 'Filter by the `slug` attribute. Use `*` as the wildcard character.', required: false, example: '*raid-times')] + #[QueryParam('filter[teaser]', 'string', 'Filter by the `teaser` attribute. Use `*` as the wildcard character.', required: false, example: '*weighted*random*times*')] + #[QueryParam('filter[source_code_link]', 'string', 'Filter by the `source_code_link` attribute. Use `*` as the wildcard character.', required: false, example: '*https*.net*')] + #[QueryParam('filter[featured]', 'boolean', 'Filter by the `featured` attribute. All "truthy" or "falsy" values are supported.', required: false, example: 'true')] + #[QueryParam('filter[contains_ads]', 'boolean', 'Filter by the `contains_ads` attribute. All "truthy" or "falsy" values are supported.', required: false, example: 'true')] + #[QueryParam('filter[contains_ai_content]', 'boolean', 'Filter by the `contains_ai_content` attribute. All "truthy" or "falsy" values are supported.', required: false, example: 'true')] + #[QueryParam('filter[created_at]', 'string', 'Filter by the `created_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')] + #[QueryParam('filter[updated_at]', 'string', 'Filter by the `updated_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')] + #[QueryParam('filter[published_at]', 'string', 'Filter by the `published_at` attribute. Ranges are possible by seperating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')] + #[QueryParam('sort', 'string', 'Sort the results by a comma seperated list of attributes. The default sort direction is ASC, append the attribute name with a minus to sort DESC.', required: false, example: '-featured,name')] + public function index(ModFilter $filters): AnonymousResourceCollection { return ModResource::collection(Mod::filter($filters)->paginate()); } /** - * Store a newly created resource in storage. + * Get Mod + * + * Display more detailed information about a specific mod. + * + * @group Mods */ - public function store(StoreModRequest $request) - { - // - } - - /** - * Display the specified resource. - */ - public function show(Mod $mod) + #[UrlParam('id', 'integer', 'The ID of the mod.', required: true, example: 558)] + #[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'users,versions,license')] + public function show(Mod $mod): JsonResource { return new ModResource($mod); } - - /** - * Update the specified resource in storage. - */ - public function update(UpdateModRequest $request, Mod $mod) - { - // - } - - /** - * Remove the specified resource from storage. - */ - public function destroy(Mod $mod) - { - // - } } diff --git a/app/Http/Controllers/Api/V0/UsersController.php b/app/Http/Controllers/Api/V0/UsersController.php index 8bf7824..69a4b56 100644 --- a/app/Http/Controllers/Api/V0/UsersController.php +++ b/app/Http/Controllers/Api/V0/UsersController.php @@ -3,50 +3,42 @@ namespace App\Http\Controllers\Api\V0; use App\Http\Filters\V1\UserFilter; -use App\Http\Requests\Api\V0\StoreUserRequest; -use App\Http\Requests\Api\V0\UpdateUserRequest; use App\Http\Resources\Api\V0\UserResource; use App\Models\User; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; +use Illuminate\Http\Resources\Json\JsonResource; +use Knuckles\Scribe\Attributes\QueryParam; class UsersController extends ApiController { /** - * Display a listing of the resource. + * Get Users + * + * List, filter, and sort basic information about users. + * + * @group Users */ - public function index(UserFilter $filters) + #[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'user_role')] + #[QueryParam('filter[id]', 'string', 'Filter by the `id`. Select multiple by separating the IDs with a comma.', required: false, example: '5,10,15')] + #[QueryParam('filter[name]', 'string', 'Filter by the `name` attribute. Use `*` as the wildcard character.', required: false, example: '*fringe')] + #[QueryParam('filter[created_at]', 'string', 'Filter by the `created_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')] + #[QueryParam('filter[updated_at]', 'string', 'Filter by the `updated_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')] + #[QueryParam('sort', 'string', 'Sort the results by a comma seperated list of attributes. The default sort direction is ASC, append the attribute name with a minus to sort DESC.', required: false, example: 'created_at,-name')] + public function index(UserFilter $filters): AnonymousResourceCollection { return UserResource::collection(User::filter($filters)->paginate()); } /** - * Store a newly created resource in storage. + * Get User + * + * Display more detailed information about a specific user. + * + * @group Users */ - public function store(StoreUserRequest $request) - { - // - } - - /** - * Display the specified resource. - */ - public function show(User $user) + #[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'user_role')] + public function show(User $user): JsonResource { return new UserResource($user); } - - /** - * Update the specified resource in storage. - */ - public function update(UpdateUserRequest $request, User $user) - { - // - } - - /** - * Remove the specified resource from storage. - */ - public function destroy(User $user) - { - // - } } diff --git a/app/Http/Controllers/ModController.php b/app/Http/Controllers/ModController.php index 939d5ae..4016d76 100644 --- a/app/Http/Controllers/ModController.php +++ b/app/Http/Controllers/ModController.php @@ -6,37 +6,36 @@ use App\Http\Requests\ModRequest; use App\Http\Resources\ModResource; use App\Models\Mod; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Illuminate\View\View; class ModController extends Controller { use AuthorizesRequests; - public function index() + public function index(): View { $this->authorize('viewAny', Mod::class); return view('mod.index'); } - public function store(ModRequest $request) + public function store(ModRequest $request): ModResource { $this->authorize('create', Mod::class); return new ModResource(Mod::create($request->validated())); } - public function show(int $modId, string $slug) + public function show(int $modId, string $slug): View { $mod = Mod::with([ 'versions', - 'versions.latestSptVersion:id,version,color_class', + 'versions.latestSptVersion', 'versions.latestResolvedDependencies', - 'versions.latestResolvedDependencies.mod:id,name,slug', - 'users:id,name', - 'license:id,name,link', - ]) - ->whereHas('latestVersion') - ->findOrFail($modId); + 'versions.latestResolvedDependencies.mod', + 'license', + 'users', + ])->findOrFail($modId); if ($mod->slug !== $slug) { abort(404); @@ -47,7 +46,7 @@ class ModController extends Controller return view('mod.show', compact(['mod'])); } - public function update(ModRequest $request, Mod $mod) + public function update(ModRequest $request, Mod $mod): ModResource { $this->authorize('update', $mod); @@ -56,12 +55,5 @@ class ModController extends Controller return new ModResource($mod); } - public function destroy(Mod $mod) - { - $this->authorize('delete', $mod); - - $mod->delete(); - - return response()->json(); - } + public function destroy(Mod $mod): void {} } diff --git a/app/Http/Controllers/ModVersionController.php b/app/Http/Controllers/ModVersionController.php new file mode 100644 index 0000000..090c0d7 --- /dev/null +++ b/app/Http/Controllers/ModVersionController.php @@ -0,0 +1,42 @@ +whereVersion($version) + ->firstOrFail(); + + if ($modVersion->mod->slug !== $slug) { + abort(404); + } + + $this->authorize('view', $modVersion); + + // Rate limit the downloads. + $rateKey = 'mod-download:'.($request->user()?->id ?: $request->ip()); + if (RateLimiter::tooManyAttempts($rateKey, maxAttempts: 5)) { // Max attempts is per minute. + abort(429); + } + + // Increment downloads counts in the background. + defer(fn () => $modVersion->incrementDownloads()); + + // Increment the rate limiter. + RateLimiter::increment($rateKey); + + // Redirect to the download link, using a 307 status code to prevent browsers from caching. + return redirect($modVersion->link, 307); + } +} diff --git a/app/Http/Controllers/SocialiteController.php b/app/Http/Controllers/SocialiteController.php new file mode 100644 index 0000000..4fa021c --- /dev/null +++ b/app/Http/Controllers/SocialiteController.php @@ -0,0 +1,152 @@ +providers)) { + return redirect()->route('login')->withErrors(__('Unsupported OAuth provider.')); + } + + $socialiteProvider = Socialite::driver($provider); + + if (method_exists($socialiteProvider, 'scopes')) { + return $socialiteProvider->scopes(['identify', 'email'])->redirect(); + } + + return $socialiteProvider->redirect(); + } + + /** + * Obtain the user information from the provider. + */ + public function callback(string $provider): RedirectResponse + { + if (! in_array($provider, $this->providers)) { + return redirect()->route('login')->withErrors(__('Unsupported OAuth provider.')); + } + + try { + $providerUser = Socialite::driver($provider)->user(); + } catch (\Exception $e) { + return redirect()->route('login')->withErrors('Unable to login using '.$provider.'. Please try again.'); + } + + $user = $this->findOrCreateUser($provider, $providerUser); + + Auth::login($user, remember: true); + + return redirect()->route('dashboard'); + } + + protected function findOrCreateUser(string $provider, ProviderUser $providerUser): User + { + $oauthConnection = OAuthConnection::whereProvider($provider) + ->whereProviderId($providerUser->getId()) + ->first(); + + if ($oauthConnection) { + $oauthConnection->update([ + 'token' => $providerUser->token ?? '', + 'refresh_token' => $providerUser->refreshToken ?? '', + 'nickname' => $providerUser->getNickname() ?? '', + 'name' => $providerUser->getName() ?? '', + 'email' => $providerUser->getEmail() ?? '', + 'avatar' => $providerUser->getAvatar() ?? '', + ]); + + return $oauthConnection->user; + } + + // If the username already exists in the database, append a random string to it to ensure uniqueness. + $username = $providerUser->getName() ?? $providerUser->getNickname(); + $random = ''; + while (User::whereName($username.$random)->exists()) { + $random = '-'.Str::random(5); + } + $username .= $random; + + // The user has not connected their account with this OAuth provider before, so a new connection needs to be + // established. Check if the user has an account with the same email address that's passed in from the provider. + // If one exists, connect that account. Otherwise, create a new one. + + return DB::transaction(function () use ($providerUser, $provider, $username) { + + $user = User::firstOrCreate(['email' => $providerUser->getEmail()], [ + 'name' => $username, + 'password' => null, + ]); + + $connection = $user->oAuthConnections()->create([ + 'provider' => $provider, + 'provider_id' => $providerUser->getId(), + 'token' => $providerUser->token ?? '', + 'refresh_token' => $providerUser->refreshToken ?? '', + 'nickname' => $providerUser->getNickname() ?? '', + 'name' => $providerUser->getName() ?? '', + 'email' => $providerUser->getEmail() ?? '', + 'avatar' => $providerUser->getAvatar() ?? '', + ]); + + $this->updateAvatar($user, $connection->avatar); + + return $user; + }); + } + + private function updateAvatar(User $user, string $avatarUrl): void + { + // Determine the disk to use based on the environment. + $disk = match (config('app.env')) { + 'production' => 'r2', // Cloudflare R2 Storage + default => 'public', // Local + }; + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_URL, $avatarUrl); + $image = curl_exec($curl); + + if ($image === false) { + Log::error('There was an error attempting to download the image. cURL error: '.curl_error($curl)); + + return; + } + + // Generate a random path for the image and ensure that it doesn't already exist. + do { + $relativePath = User::profilePhotoStoragePath().'/'.Str::random(40).'.webp'; + } while (Storage::disk($disk)->exists($relativePath)); + + // Store the image on the disk. + Storage::disk($disk)->put($relativePath, $image); + + // Update the user's profile photo path. + $user->forceFill([ + 'profile_photo_path' => $relativePath, + ])->save(); + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index a8e86d5..97eed7c 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -5,13 +5,28 @@ namespace App\Http\Controllers; use App\Models\User; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Http\Request; +use Illuminate\View\View; class UserController extends Controller { use AuthorizesRequests; - public function show(Request $request, User $user, string $username) + public function show(Request $request, int $userId, string $username): View { + $user = User::whereId($userId) + ->with(['following', 'followers']) + ->firstOrFail(); + + $mods = $user->mods() + ->with([ + 'users', + 'latestVersion', + 'latestVersion.latestSptVersion', + ]) + ->orderByDesc('created_at') + ->paginate(10) + ->fragment('mods'); + if ($user->slug() !== $username) { abort(404); } @@ -20,6 +35,6 @@ class UserController extends Controller abort(403); } - return view('user.show', compact('user')); + return view('user.show', compact('user', 'mods')); } } diff --git a/app/Http/Filters/ModFilter.php b/app/Http/Filters/ModFilter.php index 0fa8a39..ec3f493 100644 --- a/app/Http/Filters/ModFilter.php +++ b/app/Http/Filters/ModFilter.php @@ -3,7 +3,6 @@ namespace App\Http\Filters; use App\Models\Mod; -use App\Models\ModVersion; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\DB; @@ -15,14 +14,17 @@ class ModFilter protected Builder $builder; /** - * The filter that should be applied to the query. + * The filters to apply. */ protected array $filters; + /** + * Create a new ModFilter instance. + */ public function __construct(array $filters) { - $this->builder = $this->baseQuery(); $this->filters = $filters; + $this->builder = $this->baseQuery(); } /** @@ -30,21 +32,29 @@ class ModFilter */ private function baseQuery(): Builder { - return Mod::select([ - 'mods.id', - 'mods.name', - 'mods.slug', - 'mods.teaser', - 'mods.thumbnail', - 'mods.featured', - 'mods.downloads', - 'mods.created_at', - ])->with([ - 'users:id,name', - 'latestVersion' => function ($query) { - $query->with('latestSptVersion:id,version,color_class'); - }, - ]); + return Mod::query() + ->select('mods.*') + ->whereExists(function ($query) { + $query->select(DB::raw(1)) + ->from('mod_versions') + ->join('mod_version_spt_version', 'mod_versions.id', '=', 'mod_version_spt_version.mod_version_id') + ->join('spt_versions', 'mod_version_spt_version.spt_version_id', '=', 'spt_versions.id') + ->whereColumn('mod_versions.mod_id', 'mods.id') + ->where('spt_versions.version', '!=', '0.0.0'); + }) + ->with([ + 'users:id,name', + 'latestVersion', + 'latestVersion.latestSptVersion', + ]); + } + + /** + * Filter the results by the given search term. + */ + private function query(string $term): Builder + { + return $this->builder->whereLike('mods.name', "%{$term}%"); } /** @@ -58,8 +68,6 @@ class ModFilter } } - //dd($this->builder->toRawSql()); - return $this->builder; } @@ -68,34 +76,11 @@ class ModFilter */ private function order(string $type): Builder { - // We order the "recently updated" mods by the ModVersion's updated_at value. - if ($type === 'updated') { - return $this->builder - ->joinSub( - ModVersion::select('mod_id', DB::raw('MAX(updated_at) as latest_updated_at'))->groupBy('mod_id'), - 'latest_versions', - 'mods.id', - '=', - 'latest_versions.mod_id' - ) - ->orderByDesc('latest_versions.latest_updated_at'); - } - - // By default, we simply order by the column on the mods table/query. - $column = match ($type) { - 'downloaded' => 'downloads', - default => 'created_at', + return match ($type) { + 'updated' => $this->builder->orderByDesc('mods.updated_at'), + 'downloaded' => $this->builder->orderByDesc('mods.downloads'), + default => $this->builder->orderByDesc('mods.created_at'), }; - - return $this->builder->orderByDesc($column); - } - - /** - * Filter the results by the given search term. - */ - private function query(string $term): Builder - { - return $this->builder->whereLike('name', "%$term%"); } /** @@ -104,8 +89,8 @@ class ModFilter private function featured(string $option): Builder { return match ($option) { - 'exclude' => $this->builder->where('featured', false), - 'only' => $this->builder->where('featured', true), + 'exclude' => $this->builder->where('mods.featured', false), + 'only' => $this->builder->where('mods.featured', true), default => $this->builder, }; } @@ -115,28 +100,14 @@ class ModFilter */ private function sptVersions(array $versions): Builder { - // Parse the versions into major, minor, and patch arrays - $parsedVersions = array_map(fn ($version) => [ - 'major' => (int) explode('.', $version)[0], - 'minor' => (int) (explode('.', $version)[1] ?? 0), - 'patch' => (int) (explode('.', $version)[2] ?? 0), - ], $versions); - - [$majorVersions, $minorVersions, $patchVersions] = array_map('array_unique', [ - array_column($parsedVersions, 'major'), - array_column($parsedVersions, 'minor'), - array_column($parsedVersions, 'patch'), - ]); - - return $this->builder - ->join('mod_versions as mv', 'mods.id', '=', 'mv.mod_id') - ->join('mod_version_spt_version as mvsv', 'mv.id', '=', 'mvsv.mod_version_id') - ->join('spt_versions as sv', 'mvsv.spt_version_id', '=', 'sv.id') - ->whereIn('sv.version_major', $majorVersions) - ->whereIn('sv.version_minor', $minorVersions) - ->whereIn('sv.version_patch', $patchVersions) - ->where('sv.version', '!=', '0.0.0') - ->groupBy('mods.id') - ->distinct(); + return $this->builder->whereExists(function ($query) use ($versions) { + $query->select(DB::raw(1)) + ->from('mod_versions') + ->join('mod_version_spt_version', 'mod_versions.id', '=', 'mod_version_spt_version.mod_version_id') + ->join('spt_versions', 'mod_version_spt_version.spt_version_id', '=', 'spt_versions.id') + ->whereColumn('mod_versions.mod_id', 'mods.id') + ->whereIn('spt_versions.version', $versions) + ->where('spt_versions.version', '!=', '0.0.0'); + }); } } diff --git a/app/Http/Filters/V1/ModFilter.php b/app/Http/Filters/V1/ModFilter.php index dd64b11..8c5ffff 100644 --- a/app/Http/Filters/V1/ModFilter.php +++ b/app/Http/Filters/V1/ModFilter.php @@ -3,10 +3,12 @@ namespace App\Http\Filters\V1; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Str; class ModFilter extends QueryFilter { + /** + * The sortable fields. + */ protected array $sortable = [ 'name', 'slug', @@ -20,124 +22,99 @@ class ModFilter extends QueryFilter 'published_at', ]; - // TODO: Many of these are repeated across UserFilter and ModFilter. Consider refactoring into a shared trait. - // Also, consider using common filter types and making the field names dynamic. - + /** + * Filter by ID. + */ public function id(string $value): Builder { - $ids = array_map('trim', explode(',', $value)); - - return $this->builder->whereIn('id', $ids); + return $this->filterWhereIn('id', $value); } + /** + * Filter by hub ID. + */ public function hub_id(string $value): Builder { - $ids = array_map('trim', explode(',', $value)); - - return $this->builder->whereIn('hub_id', $ids); + return $this->filterWhereIn('hub_id', $value); } + /** + * Filter by name. + */ public function name(string $value): Builder { - // The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%). - $like = Str::replace('*', '%', $value); - - return $this->builder->where('name', 'like', $like); + return $this->filterByWildcardLike('name', $value); } + /** + * Filter by slug. + */ public function slug(string $value): Builder { - // The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%). - $like = Str::replace('*', '%', $value); - - return $this->builder->where('slug', 'like', $like); + return $this->filterByWildcardLike('slug', $value); } + /** + * Filter by teaser. + */ public function teaser(string $value): Builder { - // The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%). - $like = Str::replace('*', '%', $value); - - return $this->builder->where('teaser', 'like', $like); + return $this->filterByWildcardLike('teaser', $value); } + /** + * Filter by source code link. + */ public function source_code_link(string $value): Builder { - // The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%). - $like = Str::replace('*', '%', $value); - - return $this->builder->where('source_code_link', 'like', $like); + return $this->filterByWildcardLike('source_code_link', $value); } + /** + * Filter by created at date. + */ public function created_at(string $value): Builder { - // The API allows for a range of dates to be passed as a comma-separated list. - $dates = array_map('trim', explode(',', $value)); - if (count($dates) > 1) { - return $this->builder->whereBetween('created_at', $dates); - } - - return $this->builder->whereDate('created_at', $value); + return $this->filterByDate('created_at', $value); } + /** + * Filter by updated at date. + */ public function updated_at(string $value): Builder { - // The API allows for a range of dates to be passed as a comma-separated list. - $dates = array_map('trim', explode(',', $value)); - if (count($dates) > 1) { - return $this->builder->whereBetween('updated_at', $dates); - } - - return $this->builder->whereDate('updated_at', $value); + return $this->filterByDate('updated_at', $value); } + /** + * Filter by published at date. + */ public function published_at(string $value): Builder { - // The API allows for a range of dates to be passed as a comma-separated list. - $dates = array_map('trim', explode(',', $value)); - if (count($dates) > 1) { - return $this->builder->whereBetween('published_at', $dates); - } - - return $this->builder->whereDate('published_at', $value); + return $this->filterByDate('published_at', $value); } + /** + * Filter by featured. + */ public function featured(string $value): Builder { - // We need to convert the string user input to a boolean, or null if it's not a valid "truthy/falsy" value. - $value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); - - // This column is not nullable. - if ($value === null) { - return $this->builder; - } - - return $this->builder->where('featured', $value); + return $this->filterByBoolean('featured', $value); } + /** + * Filter by contains ads. + */ public function contains_ads(string $value): Builder { - // We need to convert the string user input to a boolean, or null if it's not a valid "truthy/falsy" value. - $value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); - - // This column is not nullable. - if ($value === null) { - return $this->builder; - } - - return $this->builder->where('contains_ads', $value); + return $this->filterByBoolean('contains_ads', $value); } + /** + * Filter by contains AI content. + */ public function contains_ai_content(string $value): Builder { - // We need to convert the string user input to a boolean, or null if it's not a valid "truthy/falsy" value. - $value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); - - // This column is not nullable. - if ($value === null) { - return $this->builder; - } - - return $this->builder->where('contains_ai_content', $value); + return $this->filterByBoolean('contains_ai_content', $value); } } diff --git a/app/Http/Filters/V1/QueryFilter.php b/app/Http/Filters/V1/QueryFilter.php index f636cd7..4823273 100644 --- a/app/Http/Filters/V1/QueryFilter.php +++ b/app/Http/Filters/V1/QueryFilter.php @@ -2,23 +2,57 @@ namespace App\Http\Filters\V1; +use App\Traits\V1\FilterMethods; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; -use Illuminate\Support\Str; abstract class QueryFilter { + /** + * Include general filter methods. + */ + use FilterMethods; + + /** + * The query builder instance. + */ protected Builder $builder; + /** + * The request instance. + */ protected Request $request; + /** + * The sortable fields. + */ protected array $sortable = []; + /** + * Create a new QueryFilter instance. + */ public function __construct(Request $request) { $this->request = $request; } + /** + * Iterate over each of the filter options and call the appropriate method if it exists. + */ + public function filter(array $filters): Builder + { + foreach ($filters as $attribute => $value) { + if (method_exists($this, $attribute)) { + $this->$attribute($value); + } + } + + return $this->builder; + } + + /** + * Iterate over all request data and call the appropriate method if it exists. + */ public function apply(Builder $builder): Builder { $this->builder = $builder; @@ -31,31 +65,4 @@ abstract class QueryFilter return $this->builder; } - - protected function filter(array $filters): Builder - { - foreach ($filters as $attribute => $value) { - if (method_exists($this, $attribute)) { - $this->$attribute($value); - } - } - - return $this->builder; - } - - protected function sort(string $values): Builder - { - $sortables = array_map('trim', explode(',', $values)); - - foreach ($sortables as $sortable) { - $direction = Str::startsWith($sortable, '-') ? 'desc' : 'asc'; - $column = Str::of($sortable)->remove('-')->value(); - - if (in_array($column, $this->sortable)) { - $this->builder->orderBy($column, $direction); - } - } - - return $this->builder; - } } diff --git a/app/Http/Filters/V1/UserFilter.php b/app/Http/Filters/V1/UserFilter.php index 1eec8fc..18b5ecb 100644 --- a/app/Http/Filters/V1/UserFilter.php +++ b/app/Http/Filters/V1/UserFilter.php @@ -3,53 +3,47 @@ namespace App\Http\Filters\V1; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Str; class UserFilter extends QueryFilter { + /** + * The sortable fields. + */ protected array $sortable = [ 'name', 'created_at', 'updated_at', ]; - // TODO: Many of these are repeated across UserFilter and ModFilter. Consider refactoring into a shared trait. - // Also, consider using common filter types and making the field names dynamic. - + /** + * Filter by ID. + */ public function id(string $value): Builder { - $ids = array_map('trim', explode(',', $value)); - - return $this->builder->whereIn('id', $ids); + return $this->filterWhereIn('id', $value); } + /** + * Filter by name. + */ public function name(string $value): Builder { - // The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%). - $like = Str::replace('*', '%', $value); - - return $this->builder->where('name', 'like', $like); + return $this->filterByWildcardLike('name', $value); } + /** + * Filter by created at date. + */ public function created_at(string $value): Builder { - // The API allows for a range of dates to be passed as a comma-separated list. - $dates = array_map('trim', explode(',', $value)); - if (count($dates) > 1) { - return $this->builder->whereBetween('created_at', $dates); - } - - return $this->builder->whereDate('created_at', $value); + return $this->filterByDate('created_at', $value); } + /** + * Filter by updated at date. + */ public function updated_at(string $value): Builder { - // The API allows for a range of dates to be passed as a comma-separated list. - $dates = array_map('trim', explode(',', $value)); - if (count($dates) > 1) { - return $this->builder->whereBetween('updated_at', $dates); - } - - return $this->builder->whereDate('updated_at', $value); + return $this->filterByDate('updated_at', $value); } } diff --git a/app/Http/Requests/Api/V0/StoreModRequest.php b/app/Http/Requests/Api/V0/StoreModRequest.php index 69bf403..b7a0267 100644 --- a/app/Http/Requests/Api/V0/StoreModRequest.php +++ b/app/Http/Requests/Api/V0/StoreModRequest.php @@ -19,8 +19,6 @@ class StoreModRequest extends FormRequest */ public function rules(): array { - return [ - // - ]; + return []; } } diff --git a/app/Http/Requests/Api/V0/StoreUserRequest.php b/app/Http/Requests/Api/V0/StoreUserRequest.php index 590b441..552e486 100644 --- a/app/Http/Requests/Api/V0/StoreUserRequest.php +++ b/app/Http/Requests/Api/V0/StoreUserRequest.php @@ -19,8 +19,6 @@ class StoreUserRequest extends FormRequest */ public function rules(): array { - return [ - // - ]; + return []; } } diff --git a/app/Http/Requests/Api/V0/UpdateModRequest.php b/app/Http/Requests/Api/V0/UpdateModRequest.php index e4fabca..25fed3b 100644 --- a/app/Http/Requests/Api/V0/UpdateModRequest.php +++ b/app/Http/Requests/Api/V0/UpdateModRequest.php @@ -19,8 +19,6 @@ class UpdateModRequest extends FormRequest */ public function rules(): array { - return [ - // - ]; + return []; } } diff --git a/app/Http/Requests/Api/V0/UpdateUserRequest.php b/app/Http/Requests/Api/V0/UpdateUserRequest.php index 12a1768..0200f3e 100644 --- a/app/Http/Requests/Api/V0/UpdateUserRequest.php +++ b/app/Http/Requests/Api/V0/UpdateUserRequest.php @@ -19,8 +19,6 @@ class UpdateUserRequest extends FormRequest */ public function rules(): array { - return [ - // - ]; + return []; } } diff --git a/app/Http/Requests/ModRequest.php b/app/Http/Requests/ModRequest.php index 9f483ad..816527c 100644 --- a/app/Http/Requests/ModRequest.php +++ b/app/Http/Requests/ModRequest.php @@ -6,6 +6,9 @@ use Illuminate\Foundation\Http\FormRequest; class ModRequest extends FormRequest { + /** + * Get the validation rules that apply to the request. + */ public function rules(): array { return [ @@ -18,6 +21,9 @@ class ModRequest extends FormRequest ]; } + /** + * Determine if the user is authorized to make this request. + */ public function authorize(): bool { return true; diff --git a/app/Http/Resources/Api/V0/LicenseResource.php b/app/Http/Resources/Api/V0/LicenseResource.php index a64ebe2..1ac360c 100644 --- a/app/Http/Resources/Api/V0/LicenseResource.php +++ b/app/Http/Resources/Api/V0/LicenseResource.php @@ -9,6 +9,9 @@ use Illuminate\Http\Resources\Json\JsonResource; /** @mixin License */ class LicenseResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { return [ diff --git a/app/Http/Resources/Api/V0/ModResource.php b/app/Http/Resources/Api/V0/ModResource.php index 23ed9cc..bfd5925 100644 --- a/app/Http/Resources/Api/V0/ModResource.php +++ b/app/Http/Resources/Api/V0/ModResource.php @@ -15,6 +15,8 @@ class ModResource extends JsonResource */ public function toArray(Request $request): array { + $this->load(['users', 'versions', 'license']); + return [ 'type' => 'mod', 'id' => $this->id, @@ -51,11 +53,8 @@ class ModResource extends JsonResource 'type' => 'version', 'id' => $version->id, ], - - // TODO: The download link to the version can be placed here, but I'd like to track the number of - // downloads that are made, so we'll need a new route/feature for that. #35 'links' => [ - 'self' => $version->link, + 'self' => $version->downloadUrl(absolute: true), ], ])->toArray(), diff --git a/app/Http/Resources/Api/V0/ModVersionResource.php b/app/Http/Resources/Api/V0/ModVersionResource.php index d42008d..3a5037f 100644 --- a/app/Http/Resources/Api/V0/ModVersionResource.php +++ b/app/Http/Resources/Api/V0/ModVersionResource.php @@ -28,11 +28,7 @@ class ModVersionResource extends JsonResource // $this->description //), - // TODO: The download link to the version can be placed here, but I'd like to track the number of - // downloads that are made, so we'll need a new route/feature for that. #35 - 'link' => $this->link, - - 'spt_version_id' => $this->spt_version_id, + 'link' => $this->downloadUrl(absolute: true), 'virus_total_link' => $this->virus_total_link, 'downloads' => $this->downloads, 'created_at' => $this->created_at, @@ -44,7 +40,6 @@ class ModVersionResource extends JsonResource [ 'data' => [ 'type' => 'spt_version', - 'id' => $this->spt_version_id, ], ], ], diff --git a/app/Http/Resources/Api/V0/UserResource.php b/app/Http/Resources/Api/V0/UserResource.php index 903012f..1b26c64 100644 --- a/app/Http/Resources/Api/V0/UserResource.php +++ b/app/Http/Resources/Api/V0/UserResource.php @@ -10,8 +10,13 @@ use Illuminate\Http\Resources\Json\JsonResource; /** @mixin User */ class UserResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { + $this->load('role'); + return [ 'type' => 'user', 'id' => $this->id, @@ -31,7 +36,7 @@ class UserResource extends JsonResource ], 'includes' => $this->when( ApiController::shouldInclude('user_role'), - new UserRoleResource($this->role) + new UserRoleResource($this->role), ), 'links' => [ 'self' => $this->profileUrl(), diff --git a/app/Http/Resources/Api/V0/UserRoleResource.php b/app/Http/Resources/Api/V0/UserRoleResource.php index 51d5146..0932611 100644 --- a/app/Http/Resources/Api/V0/UserRoleResource.php +++ b/app/Http/Resources/Api/V0/UserRoleResource.php @@ -9,6 +9,9 @@ use Illuminate\Http\Resources\Json\JsonResource; /** @mixin UserRole */ class UserRoleResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { return [ diff --git a/app/Http/Resources/LicenseResource.php b/app/Http/Resources/LicenseResource.php index ccc580b..773e084 100644 --- a/app/Http/Resources/LicenseResource.php +++ b/app/Http/Resources/LicenseResource.php @@ -2,12 +2,16 @@ namespace App\Http\Resources; +use App\Models\License; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; -/** @mixin \App\Models\License */ +/** @mixin License */ class LicenseResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { return [ diff --git a/app/Http/Resources/ModResource.php b/app/Http/Resources/ModResource.php index c869ee5..c5d8cde 100644 --- a/app/Http/Resources/ModResource.php +++ b/app/Http/Resources/ModResource.php @@ -2,12 +2,16 @@ namespace App\Http\Resources; +use App\Models\Mod; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; -/** @mixin \App\Models\Mod */ +/** @mixin Mod */ class ModResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { return [ diff --git a/app/Http/Resources/ModVersionResource.php b/app/Http/Resources/ModVersionResource.php index 1f4d045..831622b 100644 --- a/app/Http/Resources/ModVersionResource.php +++ b/app/Http/Resources/ModVersionResource.php @@ -2,12 +2,16 @@ namespace App\Http\Resources; +use App\Models\ModVersion; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; -/** @mixin \App\Models\ModVersion */ +/** @mixin ModVersion */ class ModVersionResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { return [ @@ -19,10 +23,7 @@ class ModVersionResource extends JsonResource 'description' => $this->description, 'virus_total_link' => $this->virus_total_link, 'downloads' => $this->downloads, - 'mod_id' => $this->mod_id, - 'spt_version_id' => $this->spt_version_id, - 'mod' => new ModResource($this->whenLoaded('mod')), 'sptVersion' => new SptVersionResource($this->whenLoaded('sptVersion')), ]; diff --git a/app/Http/Resources/SptVersionResource.php b/app/Http/Resources/SptVersionResource.php index 49ecf3a..87542c1 100644 --- a/app/Http/Resources/SptVersionResource.php +++ b/app/Http/Resources/SptVersionResource.php @@ -2,12 +2,16 @@ namespace App\Http\Resources; +use App\Models\SptVersion; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; -/** @mixin \App\Models\SptVersion */ +/** @mixin SptVersion */ class SptVersionResource extends JsonResource { + /** + * Transform the resource into an array. + */ public function toArray(Request $request): array { return [ diff --git a/app/Jobs/Import/DataTransferObjects/HubUser.php b/app/Jobs/Import/DataTransferObjects/HubUser.php new file mode 100644 index 0000000..946b1ee --- /dev/null +++ b/app/Jobs/Import/DataTransferObjects/HubUser.php @@ -0,0 +1,23 @@ +bringUserAvatarLocal(); + $this->bringUserOptionsLocal(); $this->bringFileAuthorsLocal(); $this->bringFileOptionsLocal(); $this->bringFileContentLocal(); @@ -46,6 +51,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue // Begin to import the data into the permanent local database tables. $this->importUsers(); + $this->importUserFollows(); $this->importLicenses(); $this->importSptVersions(); $this->importMods(); @@ -97,6 +103,35 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue }); } + /** + * Bring the user options table from the Hub database to the local database temporary table. + */ + private function bringUserOptionsLocal(): void + { + DB::statement('DROP TEMPORARY TABLE IF EXISTS temp_user_options_values'); + DB::statement('CREATE TEMPORARY TABLE temp_user_options_values ( + userID INT, + about LONGTEXT + ) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci'); + + DB::connection('mysql_hub') + ->table('wcf1_user_option_value') + ->orderBy('userID') + ->chunk(200, function ($options) { + $insertData = []; + foreach ($options as $option) { + $insertData[] = [ + 'userID' => (int) $option->userID, + 'about' => $option->userOption1, + ]; + } + + if ($insertData) { + DB::table('temp_user_options_values')->insert($insertData); + } + }); + } + /** * Bring the file authors from the Hub database to the local database temporary table. */ @@ -309,14 +344,29 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue $userData = $bannedUsers = $userRanks = []; foreach ($users as $user) { - $userData[] = $this->collectUserData($curl, $user); + $hubUser = new HubUser( + $user->userID, + $user->username, + $user->email, + $user->password, + $user->registrationDate, + $user->banned, + $user->banReason, + $user->banExpires, + $user->coverPhotoHash, + $user->coverPhotoExtension, + $user->rankID, + $user->rankTitle + ); - $bannedUserData = $this->collectBannedUserData($user); + $userData[] = $this->collectUserData($curl, $hubUser); + + $bannedUserData = $this->collectBannedUserData($hubUser); if ($bannedUserData) { $bannedUsers[] = $bannedUserData; } - $userRankData = $this->collectUserRankData($user); + $userRankData = $this->collectUserRankData($hubUser); if ($userRankData) { $userRanks[] = $userRankData; } @@ -331,16 +381,20 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue curl_close($curl); } - protected function collectUserData(CurlHandle $curl, object $user): array + /** + * Build an array of user data ready to be inserted into the local database. + */ + protected function collectUserData(CurlHandle $curl, HubUser $hubUser): array { return [ - 'hub_id' => (int) $user->userID, - 'name' => $user->username, - 'email' => Str::lower($user->email), - 'password' => $this->cleanPasswordHash($user->password), - 'profile_photo_path' => $this->fetchUserAvatar($curl, $user), - 'cover_photo_path' => $this->fetchUserCoverPhoto($curl, $user), - 'created_at' => $this->cleanRegistrationDate($user->registrationDate), + 'hub_id' => (int) $hubUser->userID, + 'name' => $hubUser->username, + 'email' => Str::lower($hubUser->email), + 'password' => $this->cleanPasswordHash($hubUser->password), + 'about' => $this->fetchUserAbout($hubUser->userID), + 'profile_photo_path' => $this->fetchUserAvatar($curl, $hubUser), + 'cover_photo_path' => $this->fetchUserCoverPhoto($curl, $hubUser), + 'created_at' => $this->cleanRegistrationDate($hubUser->registrationDate), 'updated_at' => now('UTC')->toDateTimeString(), ]; } @@ -358,13 +412,39 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue return str_starts_with($clean, '$2') ? $clean : ''; } + /** + * Fetch the user about text from the temporary table. + */ + private function fetchUserAbout(int $userID): string + { + $about = DB::table('temp_user_options_values') + ->where('userID', $userID) + ->limit(1) + ->value('about'); + + return $this->cleanHubContent($about ?? ''); + } + + /** + * Convert the mod description from WoltHub flavoured HTML to Markdown. + */ + protected function cleanHubContent(string $dirty): string + { + // Alright, hear me out... Shut up. + + $converter = new HtmlConverter; + $clean = Purify::clean($dirty); + + return $converter->convert($clean); + } + /** * Fetch the user avatar from the Hub and store it anew. */ - protected function fetchUserAvatar(CurlHandle $curl, object $user): string + protected function fetchUserAvatar(CurlHandle $curl, HubUser $hubUser): string { // Fetch the user's avatar data from the temporary table. - $avatar = DB::table('temp_user_avatar')->where('userID', $user->userID)->first(); + $avatar = DB::table('temp_user_avatar')->where('userID', $hubUser->userID)->first(); if (! $avatar) { return ''; @@ -373,7 +453,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue $hashShort = substr($avatar->fileHash, 0, 2); $fileName = $avatar->fileHash.'.'.$avatar->avatarExtension; $hubUrl = 'https://hub.sp-tarkov.com/images/avatars/'.$hashShort.'/'.$avatar->avatarID.'-'.$fileName; - $relativePath = 'user-avatars/'.$fileName; + $relativePath = User::profilePhotoStoragePath().'/'.$fileName; return $this->fetchAndStoreImage($curl, $hubUrl, $relativePath); } @@ -413,15 +493,15 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue /** * Fetch the user avatar from the Hub and store it anew. */ - protected function fetchUserCoverPhoto(CurlHandle $curl, object $user): string + protected function fetchUserCoverPhoto(CurlHandle $curl, HubUser $hubUser): string { - if (empty($user->coverPhotoHash) || empty($user->coverPhotoExtension)) { + if (empty($hubUser->coverPhotoHash) || empty($hubUser->coverPhotoExtension)) { return ''; } - $hashShort = substr($user->coverPhotoHash, 0, 2); - $fileName = $user->coverPhotoHash.'.'.$user->coverPhotoExtension; - $hubUrl = 'https://hub.sp-tarkov.com/images/coverPhotos/'.$hashShort.'/'.$user->userID.'-'.$fileName; + $hashShort = substr($hubUser->coverPhotoHash, 0, 2); + $fileName = $hubUser->coverPhotoHash.'.'.$hubUser->coverPhotoExtension; + $hubUrl = 'https://hub.sp-tarkov.com/images/coverPhotos/'.$hashShort.'/'.$hubUser->userID.'-'.$fileName; $relativePath = 'user-covers/'.$fileName; return $this->fetchAndStoreImage($curl, $hubUrl, $relativePath); @@ -445,13 +525,13 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue /** * Build an array of banned user data ready to be inserted into the local database. */ - protected function collectBannedUserData($user): ?array + protected function collectBannedUserData(HubUser $hubUser): ?array { - if ($user->banned) { + if ($hubUser->banned) { return [ - 'hub_id' => (int) $user->userID, - 'comment' => $user->banReason ?? '', - 'expired_at' => $this->cleanUnbannedAtDate($user->banExpires), + 'hub_id' => (int) $hubUser->userID, + 'comment' => $hubUser->banReason ?? '', + 'expired_at' => $this->cleanUnbannedAtDate($hubUser->banExpires), ]; } @@ -498,12 +578,15 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue } } - protected function collectUserRankData($user): ?array + /** + * Build an array of user rank data ready to be inserted into the local database. + */ + protected function collectUserRankData(HubUser $hubUser): ?array { - if ($user->rankID && $user->rankTitle) { + if ($hubUser->rankID && $hubUser->rankTitle) { return [ - 'hub_id' => (int) $user->userID, - 'title' => $user->rankTitle, + 'hub_id' => (int) $hubUser->userID, + 'title' => $hubUser->rankTitle, ]; } @@ -513,7 +596,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue /** * Insert or update the users in the local database. */ - protected function upsertUsers($usersData): void + protected function upsertUsers(array $usersData): void { if (! empty($usersData)) { DB::table('users')->upsert($usersData, ['hub_id'], [ @@ -529,7 +612,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue /** * Fetch the hub-banned users from the local database and ban them locally. */ - protected function handleBannedUsers($bannedUsers): void + protected function handleBannedUsers(array $bannedUsers): void { foreach ($bannedUsers as $bannedUser) { $user = User::whereHubId($bannedUser['hub_id'])->first(); @@ -543,7 +626,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue /** * Fetch or create the user ranks in the local database and assign them to the users. */ - protected function handleUserRoles($userRanks): void + protected function handleUserRoles(array $userRanks): void { foreach ($userRanks as $userRank) { $roleName = Str::ucfirst(Str::afterLast($userRank['title'], '.')); @@ -587,6 +670,37 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue ]; } + protected function importUserFollows(): void + { + $followsGroupedByFollower = []; + + DB::connection('mysql_hub') + ->table('wcf1_user_follow') + ->select(['followID', 'userID', 'followUserID', 'time']) + ->chunkById(100, function (Collection $follows) use (&$followsGroupedByFollower) { + foreach ($follows as $follow) { + $followerId = User::whereHubId($follow->userID)->value('id'); + $followingId = User::whereHubId($follow->followUserID)->value('id'); + + if (! $followerId || ! $followingId) { + continue; + } + + $followsGroupedByFollower[$followerId][$followingId] = [ + 'created_at' => Carbon::parse($follow->time, 'UTC'), + 'updated_at' => Carbon::parse($follow->time, 'UTC'), + ]; + } + }, 'followID'); + + foreach ($followsGroupedByFollower as $followerId => $followings) { + $user = User::find($followerId); + if ($user) { + $user->following()->sync($followings); + } + } + } + /** * Import the licenses from the Hub database to the local database. */ @@ -861,19 +975,6 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue curl_close($curl); } - /** - * Convert the mod description from WoltHub flavoured HTML to Markdown. - */ - protected function cleanHubContent(string $dirty): string - { - // Alright, hear me out... Shut up. - - $converter = new HtmlConverter; - $clean = Purify::clean($dirty); - - return $converter->convert($clean); - } - /** * Fetch the mod thumbnail from the Hub and store it anew. */ @@ -934,10 +1035,20 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue $sptVersionTemp = DB::table('temp_spt_version_tags')->where('hub_id', $versionLabel->labelID)->value('version'); $sptVersionConstraint = $this->extractSemanticVersion($sptVersionTemp, appendPatch: true) ?? '0.0.0'; + try { + $modVersion = new Version($version->versionNumber); + } catch (InvalidVersionNumberException $e) { + $modVersion = new Version('0.0.0'); + } + $insertData[] = [ 'hub_id' => (int) $version->versionID, 'mod_id' => $modId, - 'version' => $this->extractSemanticVersion($version->versionNumber) ?? '0.0.0', + 'version' => $modVersion, + 'version_major' => $modVersion->getMajor(), + 'version_minor' => $modVersion->getMinor(), + 'version_patch' => $modVersion->getPatch(), + 'version_pre_release' => $modVersion->getPreRelease(), 'description' => $this->cleanHubContent($versionContent->description ?? ''), 'link' => $version->downloadURL, 'spt_version_constraint' => $sptVersionConstraint, @@ -984,10 +1095,11 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue /** * The job failed to process. */ - public function failed(Exception $exception): void + public function failed(Throwable $exception): void { // Explicitly drop the temporary tables. DB::unprepared('DROP TEMPORARY TABLE IF EXISTS temp_user_avatar'); + DB::unprepared('DROP TEMPORARY TABLE IF EXISTS temp_user_options_values'); DB::unprepared('DROP TEMPORARY TABLE IF EXISTS temp_file_author'); DB::unprepared('DROP TEMPORARY TABLE IF EXISTS temp_file_option_values'); DB::unprepared('DROP TEMPORARY TABLE IF EXISTS temp_file_content'); diff --git a/app/Livewire/GlobalSearch.php b/app/Livewire/GlobalSearch.php index 991f5d1..9e0ea0c 100644 --- a/app/Livewire/GlobalSearch.php +++ b/app/Livewire/GlobalSearch.php @@ -4,8 +4,10 @@ namespace App\Livewire; use App\Models\Mod; use App\Models\User; +use Illuminate\Support\Collection; use Illuminate\Support\Str; use Illuminate\View\View; +use Livewire\Attributes\Locked; use Livewire\Component; class GlobalSearch extends Component @@ -16,20 +18,26 @@ class GlobalSearch extends Component public string $query = ''; /** - * Whether to show the search result dropdown. + * The search results. */ - public bool $showDropdown = false; + #[Locked] + public array $result = []; /** - * Whether to show the "no results found" message. + * The total number of search results. */ - public bool $noResults = false; + #[Locked] + public int $count = 0; + /** + * Render the component. + */ public function render(): View { - return view('livewire.global-search', [ - 'results' => $this->executeSearch($this->query), - ]); + $this->result = $this->executeSearch($this->query); + $this->count = $this->countTotalResults($this->result); + + return view('livewire.global-search'); } /** @@ -38,39 +46,40 @@ class GlobalSearch extends Component protected function executeSearch(string $query): array { $query = Str::trim($query); - $results = ['data' => [], 'total' => 0]; - if (Str::length($query)) { - $results['data'] = [ - 'user' => collect(User::search($query)->raw()['hits']), - 'mod' => collect(Mod::search($query)->raw()['hits']), + if (Str::length($query) > 0) { + return [ + 'user' => $this->fetchUserResults($query), + 'mod' => $this->fetchModResults($query), ]; - $results['total'] = $this->countTotalResults($results['data']); } - $this->showDropdown = Str::length($query) > 0; - $this->noResults = $results['total'] === 0 && $this->showDropdown; + return []; + } - return $results; + /** + * Fetch the user search results. + */ + protected function fetchUserResults(string $query): Collection + { + return collect(User::search($query)->raw()['hits']); + } + + /** + * Fetch the mod search results. + */ + protected function fetchModResults(string $query): Collection + { + return collect(Mod::search($query)->raw()['hits']); } /** * Count the total number of results across all models. */ - protected function countTotalResults($results): int + protected function countTotalResults(array $results): int { - return collect($results)->reduce(function ($carry, $result) { + return collect($results)->reduce(function (int $carry, Collection $result) { return $carry + $result->count(); }, 0); } - - /** - * Clear the search query and hide the dropdown. - */ - public function clearSearch(): void - { - $this->query = ''; - $this->showDropdown = false; - $this->noResults = false; - } } diff --git a/app/Livewire/Mod/Index.php b/app/Livewire/Mod/Listing.php similarity index 53% rename from app/Livewire/Mod/Index.php rename to app/Livewire/Mod/Listing.php index 5760c14..7b3e25a 100644 --- a/app/Livewire/Mod/Index.php +++ b/app/Livewire/Mod/Listing.php @@ -4,62 +4,87 @@ namespace App\Livewire\Mod; use App\Http\Filters\ModFilter; use App\Models\SptVersion; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Contracts\View\View; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Facades\Cache; use Livewire\Attributes\Computed; +use Livewire\Attributes\Locked; use Livewire\Attributes\Session; use Livewire\Attributes\Url; use Livewire\Component; use Livewire\WithPagination; -class Index extends Component +class Listing extends Component { use WithPagination; /** * The search query value. */ - #[Url] #[Session] + #[Url] public string $query = ''; /** * The sort order value. */ - #[Url] #[Session] + #[Url] public string $order = 'created'; + /** + * The number of results to show on a single page. + */ + #[Session] + #[Url] + public int $perPage = 12; + + /** + * The options that are available for the per page setting. + */ + #[Locked] + public array $perPageOptions = [6, 12, 24, 50]; + /** * The SPT versions filter value. */ - #[Url] #[Session] + #[Url] public array $sptVersions = []; /** * The featured filter value. */ - #[Url] #[Session] + #[Url] public string $featured = 'include'; /** * The available SPT versions. + * + * @var Collection */ - public Collection $availableSptVersions; + public Collection $activeSptVersions; /** * The component mount method, run only once when the component is mounted. */ public function mount(): void { - $this->availableSptVersions = $this->availableSptVersions ?? Cache::remember('available-spt-versions', 60 * 60, function () { + $this->activeSptVersions = $this->activeSptVersions ?? Cache::remember('active-spt-versions', 60 * 60, function () { return SptVersion::getVersionsForLastThreeMinors(); }); - $this->sptVersions = $this->sptVersions ?? $this->getLatestMinorVersions()->pluck('version')->toArray(); + $this->sptVersions = $this->sptVersions ?? $this->getDefaultSptVersions(); + } + + /** + * Get the default values for the SPT Versions filter. + */ + protected function getDefaultSptVersions(): array + { + return $this->getLatestMinorVersions()->pluck('version')->toArray(); } /** @@ -67,7 +92,7 @@ class Index extends Component */ public function getLatestMinorVersions(): Collection { - return $this->availableSptVersions->filter(function (SptVersion $sptVersion) { + return $this->activeSptVersions->filter(function (SptVersion $sptVersion) { return $sptVersion->isLatestMinor(); }); } @@ -77,6 +102,8 @@ class Index extends Component */ public function render(): View { + $this->validatePerPage(); + // Fetch the mods using the filters saved to the component properties. $filters = [ 'query' => $this->query, @@ -84,14 +111,40 @@ class Index extends Component 'order' => $this->order, 'sptVersions' => $this->sptVersions, ]; - $mods = (new ModFilter($filters))->apply()->paginate(16); - // Check if the current page is greater than the last page. Redirect if it is. + $mods = (new ModFilter($filters))->apply()->paginate($this->perPage); + + $this->redirectOutOfBoundsPage($mods); + + return view('livewire.mod.listing', compact('mods')); + } + + /** + * Validate that the option selected is an option that is available by setting it to the closest available version. + */ + public function validatePerPage(): void + { + $this->perPage = collect($this->perPageOptions)->pipe(function ($data) { + $closest = null; + + foreach ($data as $item) { + if ($closest === null || abs($this->perPage - $closest) > abs($item - $this->perPage)) { + $closest = $item; + } + } + + return $closest; + }); + } + + /** + * Check if the current page is greater than the last page. Redirect if it is. + */ + private function redirectOutOfBoundsPage(LengthAwarePaginator $mods): void + { if ($mods->currentPage() > $mods->lastPage()) { $this->redirectRoute('mods', ['page' => $mods->lastPage()]); } - - return view('livewire.mod.index', compact('mods')); } /** @@ -100,11 +153,8 @@ class Index extends Component public function resetFilters(): void { $this->query = ''; - $this->sptVersions = $this->getLatestMinorVersions()->pluck('version')->toArray(); + $this->sptVersions = $this->getDefaultSptVersions(); $this->featured = 'include'; - - // Clear local storage - $this->dispatch('clear-filters'); } /** diff --git a/app/Livewire/Profile/ManageOAuthConnections.php b/app/Livewire/Profile/ManageOAuthConnections.php new file mode 100644 index 0000000..cb297fd --- /dev/null +++ b/app/Livewire/Profile/ManageOAuthConnections.php @@ -0,0 +1,98 @@ +setName('profile.manage-oauth-connections'); + + $this->user = auth()->user(); + } + + /** + * Sets up the deletion confirmation. + */ + public function confirmConnectionDeletion($connectionId): void + { + $this->confirmingConnectionDeletion = true; + $this->selectedConnectionId = $connectionId; + } + + /** + * Deletes the selected OAuth connection. + */ + public function deleteConnection(): void + { + $connection = $this->user->oauthConnections()->find($this->selectedConnectionId); + + // Ensure the user is authorized to delete the connection. + $this->authorize('delete', $connection); + + // The user must have a password set before removing an OAuth connection. + if ($this->user->password === null) { + $this->addError('password_required', __('You must set a password before removing an OAuth connection.')); + $this->confirmingConnectionDeletion = false; + + return; + } + + if ($connection) { + $connection->delete(); + + $this->user->refresh(); + $this->confirmingConnectionDeletion = false; + $this->selectedConnectionId = null; + + session()->flash('status', __('OAuth connection removed successfully.')); + } else { + session()->flash('error', __('OAuth connection not found.')); + } + } + + /** + * Refreshes the user instance. + */ + #[On('saved')] + public function refreshUser(): void + { + $this->user->refresh(); + } + + /** + * Renders the component view. + */ + public function render(): View + { + return view('livewire.profile.manage-oauth-connections'); + } +} diff --git a/app/Livewire/Profile/UpdatePasswordForm.php b/app/Livewire/Profile/UpdatePasswordForm.php new file mode 100644 index 0000000..28db4eb --- /dev/null +++ b/app/Livewire/Profile/UpdatePasswordForm.php @@ -0,0 +1,52 @@ +resetErrorBag(); + + $user = Auth::user(); + + if ($user->password !== null) { + parent::updatePassword($updater); + } else { + + // User has a null password. Allow them to set a new password without their current password. + Validator::make($this->state, [ + 'password' => $this->passwordRules(), + ])->validateWithBag('updatePassword'); + + auth()->user()->forceFill([ + 'password' => Hash::make($this->state['password']), + ])->save(); + + $this->state = [ + 'current_password' => '', + 'password' => '', + 'password_confirmation' => '', + ]; + + $this->dispatch('saved'); + } + } +} diff --git a/app/Livewire/Profile/UpdateProfileForm.php b/app/Livewire/Profile/UpdateProfileForm.php index 127e34f..2408030 100644 --- a/app/Livewire/Profile/UpdateProfileForm.php +++ b/app/Livewire/Profile/UpdateProfileForm.php @@ -12,8 +12,6 @@ class UpdateProfileForm extends UpdateProfileInformationForm { /** * The new cover photo for the user. - * - * @var mixed */ public $cover; diff --git a/app/Livewire/User/FollowButtons.php b/app/Livewire/User/FollowButtons.php new file mode 100644 index 0000000..6b591d2 --- /dev/null +++ b/app/Livewire/User/FollowButtons.php @@ -0,0 +1,52 @@ +user()->follow($this->profileUserId); + $this->isFollowing = true; + + $this->dispatch('user-follow-change'); + } + + /** + * Action to unfollow a user. + */ + public function unfollow(): void + { + auth()->user()->unfollow($this->profileUserId); + $this->isFollowing = false; + + $this->dispatch('user-follow-change'); + } + + /** + * Render the component. + */ + public function render(): View + { + return view('livewire.user.follow-buttons'); + } +} diff --git a/app/Livewire/User/FollowCard.php b/app/Livewire/User/FollowCard.php new file mode 100644 index 0000000..1227aa9 --- /dev/null +++ b/app/Livewire/User/FollowCard.php @@ -0,0 +1,167 @@ + '$refresh']; + + /** + * The number of users being displayed. + */ + #[Computed] + public function followUsersCount(): int + { + return $this->followUsers->count(); + } + + /** + * Called when the component is initialized. + */ + public function mount(): void + { + $this->setTitle(); + $this->setEmptyMessage(); + $this->setDialogTitle(); + } + + /** + * Set the title of the card based on the relationship. + */ + private function setTitle(): void + { + $this->title = match ($this->relationship) { + 'followers' => __('Followers'), + 'following' => __('Following'), + default => __('Users'), + }; + } + + /** + * Set the empty message based on the relationship. + */ + private function setEmptyMessage(): void + { + $this->emptyMessage = match ($this->relationship) { + 'followers' => __('No followers yet.'), + 'following' => __('Not yet following anyone.'), + default => __('No users found.'), + }; + } + + /** + * Set the dialog title based on the relationship. + */ + private function setDialogTitle(): void + { + $this->dialogTitle = match ($this->relationship) { + 'followers' => 'User :name has these followers:', + 'following' => 'User :name is following:', + default => 'Users:', + }; + } + + /** + * Render the component. + */ + public function render(): View + { + $this->populateFollowUsers(); + + return view('livewire.user.follow-card'); + } + + /** + * Called when the user follows or unfollows a user. + */ + #[On('auth-follow-change')] + public function populateFollowUsers(): void + { + // Update the collection of profile user's followers (or following). + $this->followUsers = $this->profileUser->{$this->relationship}()->get(); + + $this->dispatch('refreshComponent'); + } + + /** + * Toggle showing the follow dialog. + */ + public function toggleFollowDialog(): void + { + $this->showFollowDialog = ! $this->showFollowDialog; + } +} diff --git a/app/Livewire/User/FollowCards.php b/app/Livewire/User/FollowCards.php new file mode 100644 index 0000000..c1847e1 --- /dev/null +++ b/app/Livewire/User/FollowCards.php @@ -0,0 +1,51 @@ +updateAuthFollowIds(); + + return view('livewire.user.follow-cards'); + } + + /** + * Called when the user follows or unfollows a user. + */ + #[On('user-follow-change')] + public function updateAuthFollowIds(): void + { + // Fetch IDs of all users the authenticated user is following. + $this->authFollowIds = collect(); + $authUser = auth()->user(); + if ($authUser) { + $this->authFollowIds = $authUser->following()->pluck('following_id'); + } + + $this->dispatch('auth-follow-change'); + } +} diff --git a/app/Models/License.php b/app/Models/License.php index c678a35..4f967ae 100644 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -9,13 +9,30 @@ use Illuminate\Database\Eloquent\SoftDeletes; class License extends Model { - use HasFactory, SoftDeletes; + use HasFactory; + use SoftDeletes; /** * The relationship between a license and mod. + * + * @return HasMany */ public function mods(): HasMany { - return $this->hasMany(Mod::class); + return $this->hasMany(Mod::class) + ->chaperone(); + } + + /** + * The attributes that should be cast to native types. + */ + protected function casts(): array + { + return [ + 'hub_id' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; } } diff --git a/app/Models/Mod.php b/app/Models/Mod.php index 030c7db..b7a9877 100644 --- a/app/Models/Mod.php +++ b/app/Models/Mod.php @@ -14,28 +14,23 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Laravel\Scout\Searchable; -/** - * @property int $id - * @property string $name - * @property string $slug - */ class Mod extends Model { - use HasFactory, Searchable, SoftDeletes; + use HasFactory; + use Searchable; + use SoftDeletes; /** * Post boot method to configure the model. */ protected static function booted(): void { - // Apply the global scope to exclude disabled mods. static::addGlobalScope(new DisabledScope); - - // Apply the global scope to exclude non-published mods. static::addGlobalScope(new PublishedScope); } @@ -48,8 +43,24 @@ class Mod extends Model $this->saveQuietly(); } + /** + * Build the URL to download the latest version of this mod. + */ + public function downloadUrl(bool $absolute = false): string + { + $this->load('latestVersion'); + + return route('mod.version.download', [ + $this->id, + $this->slug, + $this->latestVersion->version, + ], absolute: $absolute); + } + /** * The relationship between a mod and its users. + * + * @return BelongsToMany */ public function users(): BelongsToMany { @@ -58,30 +69,40 @@ class Mod extends Model /** * The relationship between a mod and its license. + * + * @return BelongsTo */ public function license(): BelongsTo { return $this->belongsTo(License::class); } + /** + * The relationship between a mod and its last updated version. + * + * @return HasOne + */ + public function latestUpdatedVersion(): HasOne + { + return $this->versions() + ->one() + ->ofMany('updated_at', 'max') + ->chaperone(); + } + /** * The relationship between a mod and its versions. + * + * @return HasMany */ public function versions(): HasMany { return $this->hasMany(ModVersion::class) - ->whereHas('latestSptVersion') - ->orderByDesc('version'); - } - - /** - * The relationship between a mod and its last updated version. - */ - public function lastUpdatedVersion(): HasOne - { - return $this->hasOne(ModVersion::class) - ->whereHas('latestSptVersion') - ->orderByDesc('updated_at'); + ->orderByDesc('version_major') + ->orderByDesc('version_minor') + ->orderByDesc('version_patch') + ->orderByDesc('version_pre_release') + ->chaperone(); } /** @@ -89,6 +110,11 @@ class Mod extends Model */ public function toSearchableArray(): array { + $this->load([ + 'latestVersion', + 'latestVersion.latestSptVersion', + ]); + return [ 'id' => $this->id, 'name' => $this->name, @@ -99,23 +125,11 @@ class Mod extends Model 'created_at' => strtotime($this->created_at), 'updated_at' => strtotime($this->updated_at), 'published_at' => strtotime($this->published_at), - 'latestVersion' => $this->latestVersion()?->first()?->latestSptVersion()?->first()?->version_formatted, - 'latestVersionColorClass' => $this->latestVersion()?->first()?->latestSptVersion()?->first()?->color_class, + 'latestVersion' => $this->latestVersion->latestSptVersion->version_formatted, + 'latestVersionColorClass' => $this->latestVersion->latestSptVersion->color_class, ]; } - /** - * The relationship to the latest mod version, dictated by the mod version number. - */ - public function latestVersion(): HasOne - { - return $this->hasOne(ModVersion::class) - ->whereHas('sptVersions') - ->orderByDesc('version') - ->orderByDesc('updated_at') - ->take(1); - } - /** * Determine if the model instance should be searchable. */ @@ -131,16 +145,27 @@ class Mod extends Model return false; } - // Fetch the latest version instance. - $latestVersion = $this->latestVersion()?->first(); + // Eager load the latest mod version, and it's latest SPT version. + $this->load([ + 'latestVersion', + 'latestVersion.latestSptVersion', + ]); // Ensure the mod has a latest version. - if (is_null($latestVersion)) { + if ($this->latestVersion()->doesntExist()) { return false; } // Ensure the latest version has a latest SPT version. - if ($latestVersion->latestSptVersion()->doesntExist()) { + if ($this->latestVersion->latestSptVersion()->doesntExist()) { + return false; + } + + // Ensure the latest SPT version is within the last three minor versions. + $activeSptVersions = Cache::remember('active-spt-versions', 60 * 60, function () { + return SptVersion::getVersionsForLastThreeMinors(); + }); + if (! in_array($this->latestVersion->latestSptVersion->version, $activeSptVersions->pluck('version')->toArray())) { return false; } @@ -148,6 +173,24 @@ class Mod extends Model return true; } + /** + * The relationship between a mod and its latest version. + * + * @return HasOne + */ + public function latestVersion(): HasOne + { + return $this->versions() + ->one() + ->ofMany([ + 'version_major' => 'max', + 'version_minor' => 'max', + 'version_patch' => 'max', + 'version_pre_release' => 'max', + ]) + ->chaperone(); + } + /** * Build the URL to the mod's thumbnail. */ @@ -197,11 +240,17 @@ class Mod extends Model 'contains_ai_content' => 'boolean', 'contains_ads' => 'boolean', 'disabled' => 'boolean', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'published_at' => 'datetime', ]; } /** * Mutate the slug attribute to always be lower case on get and slugified on set. + * + * @return Attribute */ protected function slug(): Attribute { diff --git a/app/Models/ModDependency.php b/app/Models/ModDependency.php index e147196..8ab885c 100644 --- a/app/Models/ModDependency.php +++ b/app/Models/ModDependency.php @@ -7,19 +7,14 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; -/** - * @property int $id - * @property int $mod_version_id - * @property int $dependency_mod_id - * @property string $constraint - * @property int|null $resolved_version_id - */ class ModDependency extends Model { use HasFactory; /** * The relationship between the mod dependency and the mod version. + * + * @return BelongsTo */ public function modVersion(): BelongsTo { @@ -28,17 +23,33 @@ class ModDependency extends Model /** * The relationship between the mod dependency and the resolved dependency. + * + * @return HasMany */ public function resolvedDependencies(): HasMany { - return $this->hasMany(ModResolvedDependency::class, 'dependency_id'); + return $this->hasMany(ModResolvedDependency::class, 'dependency_id') + ->chaperone(); } /** * The relationship between the mod dependency and the dependent mod. + * + * @return BelongsTo */ public function dependentMod(): BelongsTo { return $this->belongsTo(Mod::class, 'dependent_mod_id'); } + + /** + * The attributes that should be cast to native types. + */ + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + } } diff --git a/app/Models/ModResolvedDependency.php b/app/Models/ModResolvedDependency.php index ee6e747..4bdc02b 100644 --- a/app/Models/ModResolvedDependency.php +++ b/app/Models/ModResolvedDependency.php @@ -9,6 +9,8 @@ class ModResolvedDependency extends Model { /** * The relationship between the resolved dependency and the mod version. + * + * @return BelongsTo */ public function modVersion(): BelongsTo { @@ -17,6 +19,8 @@ class ModResolvedDependency extends Model /** * The relationship between the resolved dependency and the dependency. + * + * @return BelongsTo */ public function dependency(): BelongsTo { @@ -25,9 +29,22 @@ class ModResolvedDependency extends Model /** * The relationship between the resolved dependency and the resolved mod version. + * + * @return BelongsTo */ public function resolvedModVersion(): BelongsTo { return $this->belongsTo(ModVersion::class, 'resolved_mod_version_id'); } + + /** + * The attributes that should be cast to native types. + */ + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + } } diff --git a/app/Models/ModVersion.php b/app/Models/ModVersion.php index c834a41..100d99c 100644 --- a/app/Models/ModVersion.php +++ b/app/Models/ModVersion.php @@ -2,23 +2,27 @@ namespace App\Models; +use App\Exceptions\InvalidVersionNumberException; use App\Models\Scopes\DisabledScope; use App\Models\Scopes\PublishedScope; +use App\Support\Version; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Illuminate\Database\Eloquent\SoftDeletes; -/** - * @property int $id - * @property int $mod_id - * @property string $version - */ class ModVersion extends Model { - use HasFactory, SoftDeletes; + use HasFactory; + use SoftDeletes; + + /** + * Update the parent mod's updated_at timestamp when the mod version is updated. + */ + protected $touches = ['mod']; /** * Post boot method to configure the model. @@ -26,11 +30,31 @@ class ModVersion extends Model protected static function booted(): void { static::addGlobalScope(new DisabledScope); + static::addGlobalScope(new PublishedScope); + + static::saving(function (ModVersion $model) { + // Extract the version sections from the version string. + try { + $version = new Version($model->version); + + $model->version_major = $version->getMajor(); + $model->version_minor = $version->getMinor(); + $model->version_patch = $version->getPatch(); + $model->version_pre_release = $version->getPreRelease(); + } catch (InvalidVersionNumberException $e) { + $model->version_major = 0; + $model->version_minor = 0; + $model->version_patch = 0; + $model->version_pre_release = ''; + } + }); } /** * The relationship between a mod version and mod. + * + * @return BelongsTo */ public function mod(): BelongsTo { @@ -39,14 +63,19 @@ class ModVersion extends Model /** * The relationship between a mod version and its dependencies. + * + * @return HasMany */ public function dependencies(): HasMany { - return $this->hasMany(ModDependency::class); + return $this->hasMany(ModDependency::class) + ->chaperone(); } /** * The relationship between a mod version and its resolved dependencies. + * + * @return BelongsToMany */ public function resolvedDependencies(): BelongsToMany { @@ -57,6 +86,8 @@ class ModVersion extends Model /** * The relationship between a mod version and its each of it's resolved dependencies' latest versions. + * + * @return BelongsToMany */ public function latestResolvedDependencies(): BelongsToMany { @@ -71,22 +102,73 @@ class ModVersion extends Model } /** - * The relationship between a mod version and each of its SPT versions' latest version. - * Hint: Be sure to call `->first()` on this to get the actual instance. + * The relationship between a mod version and its latest SPT version. + * + * @return HasOneThrough */ - public function latestSptVersion(): BelongsToMany + public function latestSptVersion(): HasOneThrough { - return $this->belongsToMany(SptVersion::class, 'mod_version_spt_version') - ->orderBy('version', 'desc') + return $this->hasOneThrough(SptVersion::class, ModVersionSptVersion::class, 'mod_version_id', 'id', 'id', 'spt_version_id') + ->orderByDesc('spt_versions.version_major') + ->orderByDesc('spt_versions.version_minor') + ->orderByDesc('spt_versions.version_patch') + ->orderByDesc('spt_versions.version_pre_release') ->limit(1); } /** * The relationship between a mod version and its SPT versions. + * + * @return BelongsToMany */ public function sptVersions(): BelongsToMany { - return $this->belongsToMany(SptVersion::class, 'mod_version_spt_version') - ->orderByDesc('version'); + return $this->belongsToMany(SptVersion::class) + ->using(ModVersionSptVersion::class) + ->orderByDesc('version_major') + ->orderByDesc('version_minor') + ->orderByDesc('version_patch') + ->orderByDesc('version_pre_release'); + } + + /** + * Build the download URL for this mod version. + */ + public function downloadUrl(bool $absolute = false): string + { + return route('mod.version.download', [$this->mod->id, $this->mod->slug, $this->version], absolute: $absolute); + } + + /** + * Increment the download count for this mod version. + */ + public function incrementDownloads(): int + { + $this->downloads++; + $this->save(); + + // Recalculate the total download count for this mod. + $this->mod->calculateDownloads(); + + return $this->downloads; + } + + /** + * The attributes that should be cast to native types. + */ + protected function casts(): array + { + return [ + 'hub_id' => 'integer', + 'version_major' => 'integer', + 'version_minor' => 'integer', + 'version_patch' => 'integer', + 'downloads' => 'integer', + 'disabled' => 'boolean', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'published_at' => 'datetime', + ]; } } diff --git a/app/Models/ModVersionSptVersion.php b/app/Models/ModVersionSptVersion.php new file mode 100644 index 0000000..355dce7 --- /dev/null +++ b/app/Models/ModVersionSptVersion.php @@ -0,0 +1,10 @@ +belongsTo(User::class); + } + + /** + * The attributes that should be cast to native types. + */ + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + } +} diff --git a/app/Models/SptVersion.php b/app/Models/SptVersion.php index 9d0aa0f..9f97a69 100644 --- a/app/Models/SptVersion.php +++ b/app/Models/SptVersion.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Exceptions\InvalidVersionNumberException; +use App\Support\Version; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -12,7 +13,8 @@ use Illuminate\Support\Facades\Cache; class SptVersion extends Model { - use HasFactory, SoftDeletes; + use HasFactory; + use SoftDeletes; /** * Get all versions for the last three minor versions. @@ -54,7 +56,7 @@ class SptVersion extends Model ->orderByDesc('version_minor') ->limit(3) ->get() - ->map(function ($version) { + ->map(function (SptVersion $version) { return [ 'major' => (int) $version->version_major, 'minor' => (int) $version->version_minor, @@ -63,35 +65,6 @@ class SptVersion extends Model ->toArray(); } - /** - * Called when the model is booted. - */ - protected static function booted(): void - { - // Callback that runs before saving the model. - static::saving(function ($model) { - // Extract the version sections from the version string. - if (! empty($model->version)) { - // Default values in case there's an exception. - $model->version_major = 0; - $model->version_minor = 0; - $model->version_patch = 0; - $model->version_pre_release = ''; - - try { - $versionSections = self::extractVersionSections($model->version); - } catch (InvalidVersionNumberException $e) { - return; - } - - $model->version_major = $versionSections['major']; - $model->version_minor = $versionSections['minor']; - $model->version_patch = $versionSections['patch']; - $model->version_pre_release = $versionSections['pre_release']; - } - }); - } - /** * Extract the version sections from the version string. * @@ -116,6 +89,29 @@ class SptVersion extends Model ]; } + /** + * Called when the model is booted. + */ + protected static function booted(): void + { + static::saving(function (SptVersion $model) { + // Extract the version sections from the version string. + try { + $version = new Version($model->version); + + $model->version_major = $version->getMajor(); + $model->version_minor = $version->getMinor(); + $model->version_patch = $version->getPatch(); + $model->version_pre_release = $version->getPreRelease(); + } catch (InvalidVersionNumberException $e) { + $model->version_major = 0; + $model->version_minor = 0; + $model->version_patch = 0; + $model->version_pre_release = ''; + } + }); + } + /** * Update the mod count for this SptVersion. */ @@ -131,10 +127,13 @@ class SptVersion extends Model /** * The relationship between an SPT version and mod version. + * + * @return BelongsToMany */ public function modVersions(): BelongsToMany { - return $this->belongsToMany(ModVersion::class, 'mod_version_spt_version'); + return $this->belongsToMany(ModVersion::class) + ->using(ModVersionSptVersion::class); } /** @@ -173,4 +172,21 @@ class SptVersion extends Model ->first(); }); } + + /** + * The attributes that should be cast to native types. + */ + protected function casts(): array + { + return [ + 'hub_id' => 'integer', + 'version_major' => 'integer', + 'version_minor' => 'integer', + 'version_patch' => 'integer', + 'mod_count' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; + } } diff --git a/app/Models/User.php b/app/Models/User.php index 157248b..123b5e7 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,9 +8,11 @@ use App\Notifications\VerifyEmail; use App\Traits\HasCoverPhoto; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Str; @@ -42,14 +44,83 @@ class User extends Authenticatable implements MustVerifyEmail 'profile_photo_url', ]; + /** + * Get the storage path for profile photos. + */ + public static function profilePhotoStoragePath(): string + { + return 'profile-photos'; + } + /** * The relationship between a user and their mods. + * + * @return BelongsToMany */ public function mods(): BelongsToMany { return $this->belongsToMany(Mod::class); } + /** + * The relationship between a user and users that follow them. + * + * @return BelongsToMany + */ + public function followers(): BelongsToMany + { + return $this->belongsToMany(User::class, 'user_follows', 'following_id', 'follower_id') + ->withTimestamps(); + } + + /** + * Follow another user. + */ + public function follow(User|int $user): void + { + $userId = $user instanceof User ? $user->id : $user; + + if ($this->id === $userId) { + // Don't allow following yourself. + return; + } + + $this->following()->syncWithoutDetaching([$userId]); + } + + /** + * The relationship between a user and users they follow. + * + * @return BelongsToMany + */ + public function following(): BelongsToMany + { + return $this->belongsToMany(User::class, 'user_follows', 'follower_id', 'following_id') + ->withTimestamps(); + } + + /** + * Unfollow another user. + */ + public function unfollow(User|int $user): void + { + $userId = $user instanceof User ? $user->id : $user; + + if ($this->isFollowing($userId)) { + $this->following()->detach($userId); + } + } + + /** + * Check if the user is following another user. + */ + public function isFollowing(User|int $user): bool + { + $userId = $user instanceof User ? $user->id : $user; + + return $this->following()->where('following_id', $userId)->exists(); + } + /** * The data that is searchable by Scout. */ @@ -66,7 +137,9 @@ class User extends Authenticatable implements MustVerifyEmail */ public function shouldBeSearchable(): bool { - return ! is_null($this->email_verified_at); + $this->load(['bans']); + + return $this->isNotBanned(); } /** @@ -132,6 +205,8 @@ class User extends Authenticatable implements MustVerifyEmail /** * The relationship between a user and their role. + * + * @return BelongsTo */ public function role(): BelongsTo { @@ -146,6 +221,32 @@ class User extends Authenticatable implements MustVerifyEmail return $filters->apply($builder); } + /** + * The relationship between a user and their OAuth providers. + */ + public function oAuthConnections(): HasMany + { + return $this->hasMany(OAuthConnection::class); + } + + /** + * Handle the about default value if empty. Thanks, MySQL! + */ + protected function about(): Attribute + { + return Attribute::make( + set: function ($value) { + // MySQL will not allow you to set a default value of an empty string for a (LONG)TEXT column. *le sigh* + // NULL is the default. If NULL is saved, we'll swap it out for an empty string. + if (is_null($value)) { + return ''; + } + + return $value; + }, + ); + } + /** * Get the disk that profile photos should be stored on. */ @@ -160,8 +261,12 @@ class User extends Authenticatable implements MustVerifyEmail protected function casts(): array { return [ + 'id' => 'integer', + 'hub_id' => 'integer', 'email_verified_at' => 'datetime', 'password' => 'hashed', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', ]; } } diff --git a/app/Models/UserRole.php b/app/Models/UserRole.php index e27e57f..09f1906 100644 --- a/app/Models/UserRole.php +++ b/app/Models/UserRole.php @@ -12,9 +12,12 @@ class UserRole extends Model /** * The relationship between a user role and users. + * + * @return HasMany */ public function users(): HasMany { - return $this->hasMany(User::class); + return $this->hasMany(User::class) + ->chaperone(); } } diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php index 85c4838..3c61a98 100644 --- a/app/Notifications/ResetPassword.php +++ b/app/Notifications/ResetPassword.php @@ -18,6 +18,9 @@ class ResetPassword extends OriginalResetPassword implements ShouldQueue parent::__construct($token); } + /** + * Get the array representation of the notification. + */ public function toArray(object $notifiable): array { return []; diff --git a/app/Notifications/VerifyEmail.php b/app/Notifications/VerifyEmail.php index 4dde9e5..461f840 100644 --- a/app/Notifications/VerifyEmail.php +++ b/app/Notifications/VerifyEmail.php @@ -13,6 +13,9 @@ class VerifyEmail extends OriginalVerifyEmail implements ShouldQueue { use Queueable; + /** + * Get the array representation of the notification. + */ public function toArray(object $notifiable): array { return []; diff --git a/app/Observers/ModObserver.php b/app/Observers/ModObserver.php index e3b3814..fd2c926 100644 --- a/app/Observers/ModObserver.php +++ b/app/Observers/ModObserver.php @@ -20,6 +20,8 @@ class ModObserver */ public function saved(Mod $mod): void { + $mod->load('versions.sptVersions'); + foreach ($mod->versions as $modVersion) { $this->dependencyVersionService->resolve($modVersion); } @@ -44,6 +46,8 @@ class ModObserver */ public function deleted(Mod $mod): void { + $mod->load('versions.sptVersions'); + $this->updateRelatedSptVersions($mod); } } diff --git a/app/Policies/ModVersionPolicy.php b/app/Policies/ModVersionPolicy.php new file mode 100644 index 0000000..2b54cb7 --- /dev/null +++ b/app/Policies/ModVersionPolicy.php @@ -0,0 +1,68 @@ +id === $oauthConnection->user_id; + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, OAuthConnection $oauthConnection): bool + { + return $user->id === $oauthConnection->user_id && $user->password !== null; + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 5bac452..5a64f5d 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use App\Livewire\Profile\UpdatePasswordForm; use App\Models\Mod; use App\Models\ModDependency; use App\Models\ModVersion; @@ -11,11 +12,15 @@ use App\Observers\ModDependencyObserver; use App\Observers\ModObserver; use App\Observers\ModVersionObserver; use App\Observers\SptVersionObserver; -use App\Services\LatestSptVersionService; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Number; use Illuminate\Support\ServiceProvider; +use Livewire\Livewire; +use SocialiteProviders\Discord\Provider; +use SocialiteProviders\Manager\SocialiteWasCalled; class AppServiceProvider extends ServiceProvider { @@ -24,9 +29,7 @@ class AppServiceProvider extends ServiceProvider */ public function register(): void { - $this->app->singleton(LatestSptVersionService::class, function ($app) { - return new LatestSptVersionService; - }); + // } /** @@ -37,18 +40,47 @@ class AppServiceProvider extends ServiceProvider // Allow mass assignment for all models. Be careful! Model::unguard(); - // Register observers. - Mod::observe(ModObserver::class); - ModVersion::observe(ModVersionObserver::class); - ModDependency::observe(ModDependencyObserver::class); - SptVersion::observe(SptVersionObserver::class); + // Disable lazy loading in non-production environments. + Model::preventLazyLoading(! app()->isProduction()); + + // Register model observers. + $this->registerObservers(); + + // Register custom macros. + $this->registerNumberMacros(); + $this->registerCarbonMacros(); + + // Register Livewire component overrides. + $this->registerLivewireOverrides(); // This gate determines who can access the Pulse dashboard. Gate::define('viewPulse', function (User $user) { return $user->isAdmin(); }); - // Register a number macro to format download numbers. + // Register the Discord socialite provider. + Event::listen(function (SocialiteWasCalled $event) { + $event->extendSocialite('discord', Provider::class); + }); + } + + /** + * Register model observers. + */ + private function registerObservers(): void + { + Mod::observe(ModObserver::class); + ModVersion::observe(ModVersionObserver::class); + ModDependency::observe(ModDependencyObserver::class); + SptVersion::observe(SptVersionObserver::class); + } + + /** + * Register custom number macros. + */ + private function registerNumberMacros(): void + { + // Format download numbers. Number::macro('downloads', function (int|float $number) { return Number::forHumans( $number, @@ -58,4 +90,30 @@ class AppServiceProvider extends ServiceProvider ); }); } + + /** + * Register custom Carbon macros. + */ + private function registerCarbonMacros(): void + { + // Format dates dynamically based on the time passed. + Carbon::macro('dynamicFormat', function (Carbon $date) { + if ($date->diff(now())->m > 1) { + return $date->format('M jS, Y'); + } + if ($date->diff(now())->d === 0) { + return $date->diffForHumans(); + } + + return $date->format('M jS, g:i A'); + }); + } + + /** + * Register Livewire component overrides. + */ + private function registerLivewireOverrides(): void + { + Livewire::component('profile.update-password-form', UpdatePasswordForm::class); + } } diff --git a/app/Support/Version.php b/app/Support/Version.php new file mode 100644 index 0000000..b96bae3 --- /dev/null +++ b/app/Support/Version.php @@ -0,0 +1,74 @@ +version = $version; + $this->parseVersion(); + } + + /** + * Parse the version string into its components. + * + * @throws InvalidVersionNumberException + */ + protected function parseVersion(): void + { + $matches = []; + + // Regex to match semantic versioning, including pre-release identifiers + if (preg_match('/^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([\w.-]+))?$/', $this->version, $matches)) { + $this->major = (int) $matches[1]; + $this->minor = (int) ($matches[2] ?? 0); + $this->patch = (int) ($matches[3] ?? 0); + $this->preRelease = $matches[4] ?? ''; + } else { + throw new InvalidVersionNumberException('Invalid version number: '.$this->version); + } + } + + public function getMajor(): int + { + return $this->major; + } + + public function getMinor(): int + { + return $this->minor; + } + + public function getPatch(): int + { + return $this->patch; + } + + public function getPreRelease(): string + { + return $this->preRelease; + } + + public function __toString(): string + { + return $this->version; + } +} diff --git a/app/Traits/ApiResponses.php b/app/Traits/ApiResponses.php index f26781d..7117318 100644 --- a/app/Traits/ApiResponses.php +++ b/app/Traits/ApiResponses.php @@ -6,19 +6,32 @@ use Illuminate\Http\JsonResponse; trait ApiResponses { + /** + * Return a success JSON response. + */ protected function success(string $message, ?array $data = []): JsonResponse { return $this->baseResponse(message: $message, data: $data, code: 200); } + /** + * The base response. + */ private function baseResponse(?string $message = '', ?array $data = [], ?int $code = 200): JsonResponse { - return response()->json([ - 'message' => $message, - 'data' => $data, - ], $code); + $response = []; + $response['message'] = $message; + if ($data) { + $response['data'] = $data; + } + $response['status'] = $code; + + return response()->json($response, $code); } + /** + * Return an error JSON response. + */ protected function error(string $message, int $code): JsonResponse { return $this->baseResponse(message: $message, code: $code); diff --git a/app/Traits/HasCoverPhoto.php b/app/Traits/HasCoverPhoto.php index ce429e3..b366079 100644 --- a/app/Traits/HasCoverPhoto.php +++ b/app/Traits/HasCoverPhoto.php @@ -11,7 +11,7 @@ trait HasCoverPhoto /** * Update the user's cover photo. */ - public function updateCoverPhoto(UploadedFile $cover, $storagePath = 'cover-photos'): void + public function updateCoverPhoto(UploadedFile $cover, string $storagePath = 'cover-photos'): void { tap($this->cover_photo_path, function ($previous) use ($cover, $storagePath) { $this->forceFill([ @@ -51,15 +51,15 @@ trait HasCoverPhoto } /** - * Get the URL to the user's cover photo. + * Get the cover photo URL for the user. */ public function coverPhotoUrl(): Attribute { - return Attribute::get(function (): string { - return $this->cover_photo_path + return new Attribute( + get: fn (): string => $this->cover_photo_path ? Storage::disk($this->coverPhotoDisk())->url($this->cover_photo_path) - : $this->defaultCoverPhotoUrl(); - }); + : $this->defaultCoverPhotoUrl() + ); } /** diff --git a/app/Traits/V1/FilterMethods.php b/app/Traits/V1/FilterMethods.php new file mode 100644 index 0000000..d20b94c --- /dev/null +++ b/app/Traits/V1/FilterMethods.php @@ -0,0 +1,75 @@ +builder->whereIn($column, $ids); + } + + /** + * Filter using a LIKE clause with a wildcard characters. + */ + public function filterByWildcardLike(string $column, string $value): Builder + { + $like = Str::replace('*', '%', $value); + + return $this->builder->where($column, 'like', $like); + } + + /** + * Filter by date range or specific date. + */ + public function filterByDate(string $column, string $value): Builder + { + $dates = array_map('trim', explode(',', $value)); + + if (count($dates) > 1) { + return $this->builder->whereBetween($column, $dates); + } + + return $this->builder->whereDate($column, $dates[0]); + } + + /** + * Filter by boolean value. + */ + public function filterByBoolean(string $column, string $value): Builder + { + $value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + if ($value === null) { + return $this->builder; // The unmodified builder + } + + return $this->builder->where($column, $value); + } + + /** + * Apply the sort type to the query. + */ + protected function sort(string $values): Builder + { + $sortables = array_map('trim', explode(',', $values)); + + foreach ($sortables as $sortable) { + $direction = Str::startsWith($sortable, '-') ? 'desc' : 'asc'; + $column = Str::of($sortable)->remove('-')->value(); + + if (in_array($column, $this->sortable)) { + $this->builder->orderBy($column, $direction); + } + } + + return $this->builder; + } +} diff --git a/app/View/Components/HomepageMods.php b/app/View/Components/HomepageMods.php new file mode 100644 index 0000000..a0d3520 --- /dev/null +++ b/app/View/Components/HomepageMods.php @@ -0,0 +1,88 @@ + [ + 'title' => __('Featured Mods'), + 'mods' => $this->fetchFeaturedMods(), + 'link' => '/mods?featured=only', + ], + 'latest' => [ + 'title' => __('Newest Mods'), + 'mods' => $this->fetchLatestMods(), + 'link' => '/mods', + ], + 'updated' => [ + 'title' => __('Recently Updated Mods'), + 'mods' => $this->fetchUpdatedMods(), + 'link' => '/mods?order=updated', + ], + ]); + } + + /** + * Fetches the featured mods homepage listing. + */ + private function fetchFeaturedMods(): Collection + { + return Cache::flexible('homepage-featured-mods', [5, 10], function () { + return Mod::whereFeatured(true) + ->with([ + 'latestVersion', + 'latestVersion.latestSptVersion', + 'users:id,name', + 'license:id,name,link', + ]) + ->inRandomOrder() + ->limit(6) + ->get(); + }); + } + + /** + * Fetches the latest mods homepage listing. + */ + private function fetchLatestMods(): Collection + { + return Cache::flexible('homepage-latest-mods', [5, 10], function () { + return Mod::orderByDesc('created_at') + ->with([ + 'latestVersion', + 'latestVersion.latestSptVersion', + 'users:id,name', + 'license:id,name,link', + ]) + ->limit(6) + ->get(); + }); + } + + /** + * Fetches the recently updated mods homepage listing. + */ + private function fetchUpdatedMods(): Collection + { + return Cache::flexible('homepage-updated-mods', [5, 10], function () { + return Mod::orderByDesc('updated_at') + ->with([ + 'latestUpdatedVersion', + 'latestUpdatedVersion.latestSptVersion', + 'users:id,name', + 'license:id,name,link', + ]) + ->limit(6) + ->get(); + }); + } +} diff --git a/app/View/Components/ModList.php b/app/View/Components/ModList.php deleted file mode 100644 index 6d46793..0000000 --- a/app/View/Components/ModList.php +++ /dev/null @@ -1,28 +0,0 @@ -mods = $mods; - $this->versionScope = $versionScope; - } - - public function render(): View - { - return view('components.mod-list', [ - 'mods' => $this->mods, - 'versionScope' => $this->versionScope, - ]); - } -} diff --git a/app/View/Components/ModListSection.php b/app/View/Components/ModListSection.php deleted file mode 100644 index d08350e..0000000 --- a/app/View/Components/ModListSection.php +++ /dev/null @@ -1,104 +0,0 @@ -modsFeatured = $this->fetchFeaturedMods(); - $this->modsLatest = $this->fetchLatestMods(); - $this->modsUpdated = $this->fetchUpdatedMods(); - } - - private function fetchFeaturedMods(): Collection - { - return Mod::select(['id', 'name', 'slug', 'teaser', 'thumbnail', 'featured', 'downloads']) - ->with([ - 'latestVersion', - 'latestVersion.latestSptVersion:id,version,color_class', - 'users:id,name', - 'license:id,name,link', - ]) - ->whereFeatured(true) - ->inRandomOrder() - ->limit(6) - ->get(); - } - - private function fetchLatestMods(): Collection - { - return Mod::select(['id', 'name', 'slug', 'teaser', 'thumbnail', 'featured', 'created_at', 'downloads']) - ->with([ - 'latestVersion', - 'latestVersion.latestSptVersion:id,version,color_class', - 'users:id,name', - 'license:id,name,link', - ]) - ->latest() - ->limit(6) - ->get(); - } - - private function fetchUpdatedMods(): Collection - { - return Mod::select(['id', 'name', 'slug', 'teaser', 'thumbnail', 'featured', 'downloads']) - ->with([ - 'lastUpdatedVersion', - 'lastUpdatedVersion.latestSptVersion:id,version,color_class', - 'users:id,name', - 'license:id,name,link', - ]) - ->joinSub( - ModVersion::select('mod_id', DB::raw('MAX(updated_at) as latest_updated_at'))->groupBy('mod_id'), - 'latest_versions', - 'mods.id', - '=', - 'latest_versions.mod_id' - ) - ->orderByDesc('latest_versions.latest_updated_at') - ->limit(6) - ->get(); - } - - public function render(): View - { - return view('components.mod-list-section', [ - 'sections' => $this->getSections(), - ]); - } - - public function getSections(): array - { - return [ - [ - 'title' => __('Featured Mods'), - 'mods' => $this->modsFeatured, - 'versionScope' => 'latestVersion', - ], - [ - 'title' => __('Newest Mods'), - 'mods' => $this->modsLatest, - 'versionScope' => 'latestVersion', - ], - [ - 'title' => __('Recently Updated Mods'), - 'mods' => $this->modsUpdated, - 'versionScope' => 'lastUpdatedVersion', - ], - ]; - } -} diff --git a/app/View/Components/ModListStats.php b/app/View/Components/ModListStats.php deleted file mode 100644 index a267d7c..0000000 --- a/app/View/Components/ModListStats.php +++ /dev/null @@ -1,19 +0,0 @@ -withExceptions(function (Exceptions $exceptions) { // - })->create(); + }) + ->create(); diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 95d193c..843676d 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -6,4 +6,5 @@ return [ App\Providers\HorizonServiceProvider::class, App\Providers\JetstreamServiceProvider::class, App\Providers\Filament\AdminPanelProvider::class, + \SocialiteProviders\Manager\ServiceProvider::class, ]; diff --git a/composer.json b/composer.json index 714d954..cb2d7b8 100644 --- a/composer.json +++ b/composer.json @@ -19,24 +19,26 @@ "laravel/pulse": "^1.2", "laravel/sanctum": "^4.0", "laravel/scout": "^10.10", + "laravel/socialite": "^5.16", "laravel/tinker": "^2.9", "league/flysystem-aws-s3-v3": "^3.28", "league/html-to-markdown": "^5.1", "livewire/livewire": "^3.5", "mchev/banhammer": "^2.3", "meilisearch/meilisearch-php": "^1.8", + "socialiteproviders/discord": "^4.2", "stevebauman/purify": "^6.2" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.13", "fakerphp/faker": "^1.23", - "larastan/larastan": "^2.9", + "knuckleswtf/scribe": "^4.37", + "larastan/larastan": "^3.0", "laravel/pint": "^1.16", "laravel/sail": "^1.29", "mockery/mockery": "^1.6", - "nunomaduro/collision": "^8.1", - "pestphp/pest": "^2.34", - "pestphp/pest-plugin-stressless": "^2.2", + "nunomaduro/collision": "^8.4", + "pestphp/pest": "^3.0", "spatie/laravel-ignition": "^2.8" }, "autoload": { diff --git a/composer.lock b/composer.lock index e20bcda..3075582 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "920d8caa63c8b0da280a78c05d5983a8", + "content-hash": "90ab265f1717010daee00464169720ac", "packages": [ { "name": "anourvalar/eloquent-serialize", - "version": "1.2.23", + "version": "1.2.26", "source": { "type": "git", "url": "https://github.com/AnourValar/eloquent-serialize.git", - "reference": "fd7bc1dc2c98fe705647ab4b81d13ea3d599ea1f" + "reference": "756c1232ff0d02321fd90f4fe3c221d6a7b8d697" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/fd7bc1dc2c98fe705647ab4b81d13ea3d599ea1f", - "reference": "fd7bc1dc2c98fe705647ab4b81d13ea3d599ea1f", + "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/756c1232ff0d02321fd90f4fe3c221d6a7b8d697", + "reference": "756c1232ff0d02321fd90f4fe3c221d6a7b8d697", "shasum": "" }, "require": { @@ -68,22 +68,22 @@ ], "support": { "issues": "https://github.com/AnourValar/eloquent-serialize/issues", - "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.2.23" + "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.2.26" }, - "time": "2024-07-12T10:52:26+00:00" + "time": "2024-11-16T12:29:47+00:00" }, { "name": "aws/aws-crt-php", - "version": "v1.2.6", + "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "a63485b65b6b3367039306496d49737cf1995408" + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/a63485b65b6b3367039306496d49737cf1995408", - "reference": "a63485b65b6b3367039306496d49737cf1995408", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", "shasum": "" }, "require": { @@ -122,22 +122,22 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.6" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" }, - "time": "2024-06-13T17:21:28+00:00" + "time": "2024-10-18T22:15:13+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.321.2", + "version": "3.330.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "c04f8f30891cee8480c132778cd4cc486467e77a" + "reference": "136749f15d1dbff07064ef5ba1c2f08b96cf78ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c04f8f30891cee8480c132778cd4cc486467e77a", - "reference": "c04f8f30891cee8480c132778cd4cc486467e77a", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/136749f15d1dbff07064ef5ba1c2f08b96cf78ff", + "reference": "136749f15d1dbff07064ef5ba1c2f08b96cf78ff", "shasum": "" }, "require": { @@ -167,7 +167,7 @@ "paragonie/random_compat": ">= 2", "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", "psr/cache": "^1.0", - "psr/simple-cache": "^1.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "sebastian/comparator": "^1.2.3 || ^4.0", "yoast/phpunit-polyfills": "^1.0" }, @@ -220,22 +220,22 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.321.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.330.1" }, - "time": "2024-08-30T18:14:40+00:00" + "time": "2024-11-25T19:20:00+00:00" }, { "name": "bacon/bacon-qr-code", - "version": "v3.0.0", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "510de6eca6248d77d31b339d62437cc995e2fb41" + "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/510de6eca6248d77d31b339d62437cc995e2fb41", - "reference": "510de6eca6248d77d31b339d62437cc995e2fb41", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/f9cc1f52b5a463062251d666761178dbdb6b544f", + "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f", "shasum": "" }, "require": { @@ -274,22 +274,22 @@ "homepage": "https://github.com/Bacon/BaconQrCode", "support": { "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.0" + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.1" }, - "time": "2024-04-18T11:16:25+00:00" + "time": "2024-10-01T13:55:55+00:00" }, { "name": "blade-ui-kit/blade-heroicons", - "version": "2.4.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/blade-ui-kit/blade-heroicons.git", - "reference": "a7c377a4ef88cd54712e3e15cbed30446820da0b" + "reference": "4ed3ed08e9ac192d0d126b2f12711d6fb6576a48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/a7c377a4ef88cd54712e3e15cbed30446820da0b", - "reference": "a7c377a4ef88cd54712e3e15cbed30446820da0b", + "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/4ed3ed08e9ac192d0d126b2f12711d6fb6576a48", + "reference": "4ed3ed08e9ac192d0d126b2f12711d6fb6576a48", "shasum": "" }, "require": { @@ -333,7 +333,7 @@ ], "support": { "issues": "https://github.com/blade-ui-kit/blade-heroicons/issues", - "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/2.4.0" + "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/2.5.0" }, "funding": [ { @@ -345,20 +345,20 @@ "type": "paypal" } ], - "time": "2024-07-16T07:00:01+00:00" + "time": "2024-11-18T19:59:07+00:00" }, { "name": "blade-ui-kit/blade-icons", - "version": "1.7.1", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/blade-ui-kit/blade-icons.git", - "reference": "8f787baf09d88cdfd6ec4dbaba11ebfa885f0595" + "reference": "75a54a3f5a2810fcf6574ab23e91b6cc229a1b53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/8f787baf09d88cdfd6ec4dbaba11ebfa885f0595", - "reference": "8f787baf09d88cdfd6ec4dbaba11ebfa885f0595", + "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/75a54a3f5a2810fcf6574ab23e91b6cc229a1b53", + "reference": "75a54a3f5a2810fcf6574ab23e91b6cc229a1b53", "shasum": "" }, "require": { @@ -426,7 +426,7 @@ "type": "paypal" } ], - "time": "2024-08-14T14:25:11+00:00" + "time": "2024-10-17T17:38:00+00:00" }, { "name": "brick/math", @@ -559,24 +559,24 @@ }, { "name": "composer/semver", - "version": "3.4.2", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", - "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", "extra": { @@ -620,7 +620,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.2" + "source": "https://github.com/composer/semver/tree/3.4.3" }, "funding": [ { @@ -636,7 +636,7 @@ "type": "tidelift" } ], - "time": "2024-07-12T11:35:52+00:00" + "time": "2024-09-19T14:15:21+00:00" }, { "name": "danharrin/date-format-converter", @@ -870,16 +870,16 @@ }, { "name": "doctrine/dbal", - "version": "4.1.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "2377cd41609aa51bee822c8d207317a3f363a558" + "reference": "dadd35300837a3a2184bd47d403333b15d0a9bd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/2377cd41609aa51bee822c8d207317a3f363a558", - "reference": "2377cd41609aa51bee822c8d207317a3f363a558", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/dadd35300837a3a2184bd47d403333b15d0a9bd0", + "reference": "dadd35300837a3a2184bd47d403333b15d0a9bd0", "shasum": "" }, "require": { @@ -892,16 +892,16 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.2", - "phpstan/phpstan": "1.11.7", + "phpstan/phpstan": "1.12.6", "phpstan/phpstan-phpunit": "1.4.0", "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "10.5.28", + "phpunit/phpunit": "10.5.30", "psalm/plugin-phpunit": "0.19.0", "slevomat/coding-standard": "8.13.1", "squizlabs/php_codesniffer": "3.10.2", "symfony/cache": "^6.3.8|^7.0", "symfony/console": "^5.4|^6.3|^7.0", - "vimeo/psalm": "5.24.0" + "vimeo/psalm": "5.25.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -958,7 +958,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.1.0" + "source": "https://github.com/doctrine/dbal/tree/4.2.1" }, "funding": [ { @@ -974,7 +974,7 @@ "type": "tidelift" } ], - "time": "2024-08-15T07:37:07+00:00" + "time": "2024-10-10T18:01:27+00:00" }, { "name": "doctrine/deprecations", @@ -1193,16 +1193,16 @@ }, { "name": "doctrine/sql-formatter", - "version": "1.4.1", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "7f83911cc5eba870de7ebb11283972483f7e2891" + "reference": "b784cbde727cf806721451dde40eff4fec3bbe86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/7f83911cc5eba870de7ebb11283972483f7e2891", - "reference": "7f83911cc5eba870de7ebb11283972483f7e2891", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/b784cbde727cf806721451dde40eff4fec3bbe86", + "reference": "b784cbde727cf806721451dde40eff4fec3bbe86", "shasum": "" }, "require": { @@ -1210,6 +1210,7 @@ }, "require-dev": { "doctrine/coding-standard": "^12", + "ergebnis/phpunit-slow-test-detector": "^2.14", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.24" @@ -1242,22 +1243,22 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.4.1" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.1" }, - "time": "2024-08-05T20:32:22+00:00" + "time": "2024-10-21T18:21:57+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.3", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { @@ -1270,10 +1271,14 @@ "require-dev": { "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", - "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -1297,7 +1302,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, "funding": [ { @@ -1305,7 +1310,7 @@ "type": "github" } ], - "time": "2023-08-10T19:36:49+00:00" + "time": "2024-10-09T13:47:03+00:00" }, { "name": "egulias/email-validator", @@ -1376,20 +1381,20 @@ }, { "name": "ezyang/htmlpurifier", - "version": "v4.17.0", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" + "reference": "cb56001e54359df7ae76dc522d08845dc741621b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", - "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -1431,22 +1436,22 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" }, - "time": "2023-11-17T15:01:25+00:00" + "time": "2024-11-01T03:51:45+00:00" }, { "name": "filament/actions", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "5d6e4fe444f1ef04d373518248a445bbcc3ca272" + "reference": "631b38a36f5209a3884182acee60a0db682c6d24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/5d6e4fe444f1ef04d373518248a445bbcc3ca272", - "reference": "5d6e4fe444f1ef04d373518248a445bbcc3ca272", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/631b38a36f5209a3884182acee60a0db682c6d24", + "reference": "631b38a36f5209a3884182acee60a0db682c6d24", "shasum": "" }, "require": { @@ -1486,20 +1491,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-08-26T07:22:35+00:00" + "time": "2024-11-13T16:35:31+00:00" }, { "name": "filament/filament", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "130636e90e821154e0ce60dcbc7b358d2a1a716f" + "reference": "3f170b1c57033ad8e9e6bd71f3dc3f0665bf3ae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/130636e90e821154e0ce60dcbc7b358d2a1a716f", - "reference": "130636e90e821154e0ce60dcbc7b358d2a1a716f", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/3f170b1c57033ad8e9e6bd71f3dc3f0665bf3ae9", + "reference": "3f170b1c57033ad8e9e6bd71f3dc3f0665bf3ae9", "shasum": "" }, "require": { @@ -1551,20 +1556,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-08-30T01:52:09+00:00" + "time": "2024-11-13T16:35:35+00:00" }, { "name": "filament/forms", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "02fe2e211993f6291b719a093ed6f63e17125e9a" + "reference": "c73351c086036bd8de24e8671fd97018942d6d61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/02fe2e211993f6291b719a093ed6f63e17125e9a", - "reference": "02fe2e211993f6291b719a093ed6f63e17125e9a", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/c73351c086036bd8de24e8671fd97018942d6d61", + "reference": "c73351c086036bd8de24e8671fd97018942d6d61", "shasum": "" }, "require": { @@ -1607,20 +1612,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-08-30T18:04:06+00:00" + "time": "2024-11-13T16:35:31+00:00" }, { "name": "filament/infolists", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "96403f2842e4c485f32110e4456b7a3bbcb1e835" + "reference": "7946035f47746e69ff9d98bfed04b0248000ee2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/96403f2842e4c485f32110e4456b7a3bbcb1e835", - "reference": "96403f2842e4c485f32110e4456b7a3bbcb1e835", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/7946035f47746e69ff9d98bfed04b0248000ee2e", + "reference": "7946035f47746e69ff9d98bfed04b0248000ee2e", "shasum": "" }, "require": { @@ -1658,20 +1663,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-08-14T16:52:44+00:00" + "time": "2024-11-13T16:35:31+00:00" }, { "name": "filament/notifications", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "03ea56e0729c98c65831ab0215285a7cb1c4117f" + "reference": "c19df07c801c5550de0d30957c5a316f53019533" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/03ea56e0729c98c65831ab0215285a7cb1c4117f", - "reference": "03ea56e0729c98c65831ab0215285a7cb1c4117f", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/c19df07c801c5550de0d30957c5a316f53019533", + "reference": "c19df07c801c5550de0d30957c5a316f53019533", "shasum": "" }, "require": { @@ -1710,20 +1715,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-07-31T11:53:11+00:00" + "time": "2024-10-23T07:36:14+00:00" }, { "name": "filament/support", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "78e25428c754fcbb30c321d5dda439c760de9837" + "reference": "13b1e485d3bc993950c9e61a3f6a8cb05efd2b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/78e25428c754fcbb30c321d5dda439c760de9837", - "reference": "78e25428c754fcbb30c321d5dda439c760de9837", + "url": "https://api.github.com/repos/filamentphp/support/zipball/13b1e485d3bc993950c9e61a3f6a8cb05efd2b96", + "reference": "13b1e485d3bc993950c9e61a3f6a8cb05efd2b96", "shasum": "" }, "require": { @@ -1733,7 +1738,7 @@ "illuminate/contracts": "^10.45|^11.0", "illuminate/support": "^10.45|^11.0", "illuminate/view": "^10.45|^11.0", - "kirschbaum-development/eloquent-power-joins": "^3.0", + "kirschbaum-development/eloquent-power-joins": "^3.0|^4.0", "livewire/livewire": "^3.4.10", "php": "^8.1", "ryangjchandler/blade-capture-directive": "^0.2|^0.3|^1.0", @@ -1769,20 +1774,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-08-26T07:22:57+00:00" + "time": "2024-11-13T16:35:51+00:00" }, { "name": "filament/tables", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "129943d1b4e6c1edeef53e804eb56ef78a932a6c" + "reference": "5f1b04952080e71f3f72bae3801f2757619722e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/129943d1b4e6c1edeef53e804eb56ef78a932a6c", - "reference": "129943d1b4e6c1edeef53e804eb56ef78a932a6c", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/5f1b04952080e71f3f72bae3801f2757619722e7", + "reference": "5f1b04952080e71f3f72bae3801f2757619722e7", "shasum": "" }, "require": { @@ -1821,20 +1826,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-08-30T01:52:14+00:00" + "time": "2024-11-13T16:35:47+00:00" }, { "name": "filament/widgets", - "version": "v3.2.110", + "version": "v3.2.124", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "909fc82bae2cf41d70b3cd7dda8982245b2ea723" + "reference": "59a907af93c9027180e2bac5879f35b5fb11c96f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/909fc82bae2cf41d70b3cd7dda8982245b2ea723", - "reference": "909fc82bae2cf41d70b3cd7dda8982245b2ea723", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/59a907af93c9027180e2bac5879f35b5fb11c96f", + "reference": "59a907af93c9027180e2bac5879f35b5fb11c96f", "shasum": "" }, "require": { @@ -1865,7 +1870,70 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-07-31T11:53:30+00:00" + "time": "2024-11-13T16:35:48+00:00" + }, + { + "name": "firebase/php-jwt", + "version": "v6.10.2", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/30c19ed0f3264cb660ea496895cfb6ef7ee3653b", + "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.10.2" + }, + "time": "2024-11-24T11:22:49+00:00" }, { "name": "fruitcake/php-cors", @@ -2128,16 +2196,16 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { @@ -2191,7 +2259,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.3" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -2207,7 +2275,7 @@ "type": "tidelift" } ], - "time": "2024-07-18T10:29:17+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", @@ -2471,27 +2539,28 @@ }, { "name": "kirschbaum-development/eloquent-power-joins", - "version": "3.5.7", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", - "reference": "3f57b398117d97bae4dfd5c37ea0f8f48f296c97" + "reference": "c6c42a52c5a097cc11761e72782b2d0215692caf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/3f57b398117d97bae4dfd5c37ea0f8f48f296c97", - "reference": "3f57b398117d97bae4dfd5c37ea0f8f48f296c97", + "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/c6c42a52c5a097cc11761e72782b2d0215692caf", + "reference": "c6c42a52c5a097cc11761e72782b2d0215692caf", "shasum": "" }, "require": { - "illuminate/database": "^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^8.0|^9.0|^10.0|^11.0", - "php": "^8.0" + "illuminate/database": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "php": "^8.1" }, "require-dev": { + "friendsofphp/php-cs-fixer": "dev-master", "laravel/legacy-factories": "^1.0@dev", - "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0", - "phpunit/phpunit": "^8.0|^9.0|^10.0" + "orchestra/testbench": "^8.0|^9.0", + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { @@ -2527,31 +2596,34 @@ ], "support": { "issues": "https://github.com/kirschbaum-development/eloquent-power-joins/issues", - "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/3.5.7" + "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.0.0" }, - "time": "2024-06-26T13:09:29+00:00" + "time": "2024-10-06T12:28:14+00:00" }, { "name": "laminas/laminas-diactoros", - "version": "3.3.1", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "74cfb9a7522ffd2a161d1ebe10db2fc2abb9df45" + "reference": "143a16306602ce56b8b092a7914fef03c37f9ed2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/74cfb9a7522ffd2a161d1ebe10db2fc2abb9df45", - "reference": "74cfb9a7522ffd2a161d1ebe10db2fc2abb9df45", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/143a16306602ce56b8b092a7914fef03c37f9ed2", + "reference": "143a16306602ce56b8b092a7914fef03c37f9ed2", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0", - "psr/http-factory": "^1.0.2", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "psr/http-factory": "^1.1", "psr/http-message": "^1.1 || ^2.0" }, + "conflict": { + "amphp/amp": "<2.6.4" + }, "provide": { - "psr/http-factory-implementation": "^1.1 || ^2.0", + "psr/http-factory-implementation": "^1.0", "psr/http-message-implementation": "^1.1 || ^2.0" }, "require-dev": { @@ -2559,12 +2631,12 @@ "ext-dom": "*", "ext-gd": "*", "ext-libxml": "*", - "http-interop/http-factory-tests": "^0.9.0", + "http-interop/http-factory-tests": "^2.2.0", "laminas/laminas-coding-standard": "~2.5.0", - "php-http/psr7-integration-tests": "^1.3", - "phpunit/phpunit": "^9.6.16", - "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.22.1" + "php-http/psr7-integration-tests": "^1.4.0", + "phpunit/phpunit": "^10.5.36", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.26.1" }, "type": "library", "extra": { @@ -2614,20 +2686,20 @@ "type": "community_bridge" } ], - "time": "2024-02-16T16:06:16+00:00" + "time": "2024-10-14T11:59:49+00:00" }, { "name": "laravel/fortify", - "version": "v1.24.0", + "version": "v1.24.5", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "fbe67f018c1fe26d00913de56a6d60589b4be9b2" + "reference": "bba8c2ecc3fcc78e8632e0d719ae10bef6343eef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/fbe67f018c1fe26d00913de56a6d60589b4be9b2", - "reference": "fbe67f018c1fe26d00913de56a6d60589b4be9b2", + "url": "https://api.github.com/repos/laravel/fortify/zipball/bba8c2ecc3fcc78e8632e0d719ae10bef6343eef", + "reference": "bba8c2ecc3fcc78e8632e0d719ae10bef6343eef", "shasum": "" }, "require": { @@ -2679,20 +2751,20 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2024-08-20T14:43:56+00:00" + "time": "2024-11-12T14:51:12+00:00" }, { "name": "laravel/framework", - "version": "v11.21.0", + "version": "v11.33.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9d9d36708d56665b12185493f684abce38ad2d30" + "reference": "6b9832751cf8eed18b3c73df5071f78f0682aa5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9d9d36708d56665b12185493f684abce38ad2d30", - "reference": "9d9d36708d56665b12185493f684abce38ad2d30", + "url": "https://api.github.com/repos/laravel/framework/zipball/6b9832751cf8eed18b3c73df5071f78f0682aa5d", + "reference": "6b9832751cf8eed18b3c73df5071f78f0682aa5d", "shasum": "" }, "require": { @@ -2711,8 +2783,8 @@ "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1.18", - "laravel/serializable-closure": "^1.3", + "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", "league/commonmark": "^2.2.1", "league/flysystem": "^3.8.0", "monolog/monolog": "^3.0", @@ -2754,6 +2826,7 @@ "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", "illuminate/conditionable": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", @@ -2794,9 +2867,9 @@ "league/flysystem-path-prefixing": "^3.3", "league/flysystem-read-only": "^3.3", "league/flysystem-sftp-v3": "^3.0", - "mockery/mockery": "^1.6", + "mockery/mockery": "^1.6.10", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^9.1.5", + "orchestra/testbench-core": "^9.6", "pda/pheanstalk": "^5.0", "phpstan/phpstan": "^1.11.5", "phpunit/phpunit": "^10.5|^11.0", @@ -2854,6 +2927,8 @@ "src/Illuminate/Events/functions.php", "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], "psr-4": { @@ -2885,20 +2960,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-08-20T15:00:52+00:00" + "time": "2024-11-19T22:47:13+00:00" }, { "name": "laravel/horizon", - "version": "v5.27.1", + "version": "v5.29.3", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "184449be3eb296ab16c13a69ce22049f32d0fc2c" + "reference": "a48d242759704e598242074daf0060bbeb6ed46d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/184449be3eb296ab16c13a69ce22049f32d0fc2c", - "reference": "184449be3eb296ab16c13a69ce22049f32d0fc2c", + "url": "https://api.github.com/repos/laravel/horizon/zipball/a48d242759704e598242074daf0060bbeb6ed46d", + "reference": "a48d242759704e598242074daf0060bbeb6ed46d", "shasum": "" }, "require": { @@ -2913,6 +2988,7 @@ "ramsey/uuid": "^4.0", "symfony/console": "^6.0|^7.0", "symfony/error-handler": "^6.0|^7.0", + "symfony/polyfill-php83": "^1.28", "symfony/process": "^6.0|^7.0" }, "require-dev": { @@ -2962,22 +3038,22 @@ ], "support": { "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.27.1" + "source": "https://github.com/laravel/horizon/tree/v5.29.3" }, - "time": "2024-08-05T14:23:30+00:00" + "time": "2024-11-07T21:51:45+00:00" }, { "name": "laravel/jetstream", - "version": "v5.1.5", + "version": "v5.3.3", "source": { "type": "git", "url": "https://github.com/laravel/jetstream.git", - "reference": "653a422fe65278c1c4f319e99d5cb700c4117ea0" + "reference": "16859ea11a0bbce631c19d95ca0e172322e52e30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/jetstream/zipball/653a422fe65278c1c4f319e99d5cb700c4117ea0", - "reference": "653a422fe65278c1c4f319e99d5cb700c4117ea0", + "url": "https://api.github.com/repos/laravel/jetstream/zipball/16859ea11a0bbce631c19d95ca0e172322e52e30", + "reference": "16859ea11a0bbce631c19d95ca0e172322e52e30", "shasum": "" }, "require": { @@ -3031,26 +3107,26 @@ "issues": "https://github.com/laravel/jetstream/issues", "source": "https://github.com/laravel/jetstream" }, - "time": "2024-08-08T13:28:23+00:00" + "time": "2024-11-13T13:59:38+00:00" }, { "name": "laravel/octane", - "version": "v2.5.4", + "version": "v2.5.9", "source": { "type": "git", "url": "https://github.com/laravel/octane.git", - "reference": "d7b8991270eb57eef83be7de62ba04c1289dd65b" + "reference": "d8d432eb1e51a8ab2575854963d94e70d4592e15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/octane/zipball/d7b8991270eb57eef83be7de62ba04c1289dd65b", - "reference": "d7b8991270eb57eef83be7de62ba04c1289dd65b", + "url": "https://api.github.com/repos/laravel/octane/zipball/d8d432eb1e51a8ab2575854963d94e70d4592e15", + "reference": "d8d432eb1e51a8ab2575854963d94e70d4592e15", "shasum": "" }, "require": { "laminas/laminas-diactoros": "^3.0", "laravel/framework": "^10.10.1|^11.0", - "laravel/prompts": "^0.1.24", + "laravel/prompts": "^0.1.24|^0.2.0|^0.3.0", "laravel/serializable-closure": "^1.3.0", "nesbot/carbon": "^2.66.0|^3.0", "php": "^8.1.0", @@ -3121,25 +3197,25 @@ "issues": "https://github.com/laravel/octane/issues", "source": "https://github.com/laravel/octane" }, - "time": "2024-08-09T12:25:04+00:00" + "time": "2024-10-06T21:09:20+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.25", + "version": "v0.3.2", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "7b4029a84c37cb2725fc7f011586e2997040bc95" + "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/7b4029a84c37cb2725fc7f011586e2997040bc95", - "reference": "7b4029a84c37cb2725fc7f011586e2997040bc95", + "url": "https://api.github.com/repos/laravel/prompts/zipball/0e0535747c6b8d6d10adca8b68293cf4517abb0f", + "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f", "shasum": "" }, "require": { + "composer-runtime-api": "^2.2", "ext-mbstring": "*", - "illuminate/collections": "^10.0|^11.0", "php": "^8.1", "symfony/console": "^6.2|^7.0" }, @@ -3148,8 +3224,9 @@ "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { + "illuminate/collections": "^10.0|^11.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3", + "pestphp/pest": "^2.3|^3.4", "phpstan/phpstan": "^1.11", "phpstan/phpstan-mockery": "^1.1" }, @@ -3159,7 +3236,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "0.1.x-dev" + "dev-main": "0.3.x-dev" } }, "autoload": { @@ -3177,26 +3254,26 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.25" + "source": "https://github.com/laravel/prompts/tree/v0.3.2" }, - "time": "2024-08-12T22:06:33+00:00" + "time": "2024-11-12T14:59:47+00:00" }, { "name": "laravel/pulse", - "version": "v1.2.4", + "version": "v1.2.6", "source": { "type": "git", "url": "https://github.com/laravel/pulse.git", - "reference": "2e7699a602e13bada4c64e3bc7c148ddcaec81bc" + "reference": "6bde670e71155c969d7a9f42ba0e6465291faa0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pulse/zipball/2e7699a602e13bada4c64e3bc7c148ddcaec81bc", - "reference": "2e7699a602e13bada4c64e3bc7c148ddcaec81bc", + "url": "https://api.github.com/repos/laravel/pulse/zipball/6bde670e71155c969d7a9f42ba0e6465291faa0d", + "reference": "6bde670e71155c969d7a9f42ba0e6465291faa0d", "shasum": "" }, "require": { - "doctrine/sql-formatter": "^1.2", + "doctrine/sql-formatter": "^1.4.1", "guzzlehttp/promises": "^1.0|^2.0", "illuminate/auth": "^10.48.4|^11.0.8", "illuminate/cache": "^10.48.4|^11.0.8", @@ -3266,20 +3343,20 @@ "issues": "https://github.com/laravel/pulse/issues", "source": "https://github.com/laravel/pulse" }, - "time": "2024-07-08T15:09:50+00:00" + "time": "2024-11-12T14:57:16+00:00" }, { "name": "laravel/sanctum", - "version": "v4.0.2", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "9cfc0ce80cabad5334efff73ec856339e8ec1ac1" + "reference": "819782c75aaf2b08da1765503893bd2b8023d3b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/9cfc0ce80cabad5334efff73ec856339e8ec1ac1", - "reference": "9cfc0ce80cabad5334efff73ec856339e8ec1ac1", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/819782c75aaf2b08da1765503893bd2b8023d3b3", + "reference": "819782c75aaf2b08da1765503893bd2b8023d3b3", "shasum": "" }, "require": { @@ -3330,20 +3407,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2024-04-10T19:39:58+00:00" + "time": "2024-11-15T14:47:23+00:00" }, { "name": "laravel/scout", - "version": "v10.11.1", + "version": "v10.11.7", "source": { "type": "git", "url": "https://github.com/laravel/scout.git", - "reference": "b31056d49ae0540a475947391d7ea8617d779aee" + "reference": "d4c0bbc41f52b4bf315914cfc7046fd485e8d92d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/scout/zipball/b31056d49ae0540a475947391d7ea8617d779aee", - "reference": "b31056d49ae0540a475947391d7ea8617d779aee", + "url": "https://api.github.com/repos/laravel/scout/zipball/d4c0bbc41f52b4bf315914cfc7046fd485e8d92d", + "reference": "d4c0bbc41f52b4bf315914cfc7046fd485e8d92d", "shasum": "" }, "require": { @@ -3357,8 +3434,11 @@ "php": "^8.0", "symfony/console": "^6.0|^7.0" }, + "conflict": { + "algolia/algoliasearch-client-php": "<3.2.0|>=5.0.0" + }, "require-dev": { - "algolia/algoliasearch-client-php": "^3.2", + "algolia/algoliasearch-client-php": "^3.2|^4.0", "meilisearch/meilisearch-php": "^1.0", "mockery/mockery": "^1.0", "orchestra/testbench": "^7.31|^8.11|^9.0", @@ -3408,20 +3488,20 @@ "issues": "https://github.com/laravel/scout/issues", "source": "https://github.com/laravel/scout" }, - "time": "2024-08-06T15:13:57+00:00" + "time": "2024-11-13T09:41:16+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.3.4", + "version": "v1.3.7", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81" + "reference": "4f48ade902b94323ca3be7646db16209ec76be3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/61b87392d986dc49ad5ef64e75b1ff5fee24ef81", - "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d", + "reference": "4f48ade902b94323ca3be7646db16209ec76be3d", "shasum": "" }, "require": { @@ -3469,20 +3549,92 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-08-02T07:48:17+00:00" + "time": "2024-11-14T18:34:49+00:00" }, { - "name": "laravel/tinker", - "version": "v2.9.0", + "name": "laravel/socialite", + "version": "v5.16.0", "source": { "type": "git", - "url": "https://github.com/laravel/tinker.git", - "reference": "502e0fe3f0415d06d5db1f83a472f0f3b754bafe" + "url": "https://github.com/laravel/socialite.git", + "reference": "40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/502e0fe3f0415d06d5db1f83a472f0f3b754bafe", - "reference": "502e0fe3f0415d06d5db1f83a472f0f3b754bafe", + "url": "https://api.github.com/repos/laravel/socialite/zipball/40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf", + "reference": "40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf", + "shasum": "" + }, + "require": { + "ext-json": "*", + "firebase/php-jwt": "^6.4", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "league/oauth1-client": "^1.10.1", + "php": "^7.2|^8.0", + "phpseclib/phpseclib": "^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.0|^9.3|^10.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2024-09-03T09:46:57+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/ba4d51eb56de7711b3a37d63aa0643e99a339ae5", + "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5", "shasum": "" }, "require": { @@ -3533,9 +3685,9 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.9.0" + "source": "https://github.com/laravel/tinker/tree/v2.10.0" }, - "time": "2024-01-04T16:10:04+00:00" + "time": "2024-09-23T13:32:56+00:00" }, { "name": "league/commonmark", @@ -3727,16 +3879,16 @@ }, { "name": "league/csv", - "version": "9.16.0", + "version": "9.18.0", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "998280c6c34bd67d8125fdc8b45bae28d761b440" + "reference": "b02d010e4055ae992247f6ffd1e7b103ef2a0790" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/998280c6c34bd67d8125fdc8b45bae28d761b440", - "reference": "998280c6c34bd67d8125fdc8b45bae28d761b440", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/b02d010e4055ae992247f6ffd1e7b103ef2a0790", + "reference": "b02d010e4055ae992247f6ffd1e7b103ef2a0790", "shasum": "" }, "require": { @@ -3744,17 +3896,16 @@ "php": "^8.1.2" }, "require-dev": { - "doctrine/collections": "^2.2.2", "ext-dom": "*", "ext-xdebug": "*", - "friendsofphp/php-cs-fixer": "^3.57.1", - "phpbench/phpbench": "^1.2.15", - "phpstan/phpstan": "^1.11.1", - "phpstan/phpstan-deprecation-rules": "^1.2.0", + "friendsofphp/php-cs-fixer": "^3.64.0", + "phpbench/phpbench": "^1.3.1", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-deprecation-rules": "^1.2.1", "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.0", - "phpunit/phpunit": "^10.5.16 || ^11.1.3", - "symfony/var-dumper": "^6.4.6 || ^7.0.7" + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^10.5.16 || ^11.4.1", + "symfony/var-dumper": "^6.4.8 || ^7.1.5" }, "suggest": { "ext-dom": "Required to use the XMLConverter and the HTMLConverter classes", @@ -3772,7 +3923,7 @@ "src/functions_include.php" ], "psr-4": { - "League\\Csv\\": "src" + "League\\Csv\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3811,20 +3962,20 @@ "type": "github" } ], - "time": "2024-05-24T11:04:54+00:00" + "time": "2024-10-18T08:14:48+00:00" }, { "name": "league/flysystem", - "version": "3.28.0", + "version": "3.29.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c" + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c", - "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", "shasum": "" }, "require": { @@ -3892,22 +4043,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.28.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" }, - "time": "2024-05-22T10:09:12+00:00" + "time": "2024-10-08T08:58:34+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.28.0", + "version": "3.29.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "22071ef1604bc776f5ff2468ac27a752514665c8" + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/22071ef1604bc776f5ff2468ac27a752514665c8", - "reference": "22071ef1604bc776f5ff2468ac27a752514665c8", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9", "shasum": "" }, "require": { @@ -3947,22 +4098,22 @@ "storage" ], "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.28.0" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0" }, - "time": "2024-05-06T20:05:52+00:00" + "time": "2024-08-17T13:10:48+00:00" }, { "name": "league/flysystem-local", - "version": "3.28.0", + "version": "3.29.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40" + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/13f22ea8be526ea58c2ddff9e158ef7c296e4f40", - "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", "shasum": "" }, "require": { @@ -3996,9 +4147,9 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.28.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" }, - "time": "2024-05-06T20:05:52+00:00" + "time": "2024-08-09T21:24:39+00:00" }, { "name": "league/html-to-markdown", @@ -4091,16 +4242,16 @@ }, { "name": "league/mime-type-detection", - "version": "1.15.0", + "version": "1.16.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301" + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301", - "reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", "shasum": "" }, "require": { @@ -4131,7 +4282,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.15.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" }, "funding": [ { @@ -4143,7 +4294,83 @@ "type": "tidelift" } ], - "time": "2024-01-28T23:22:08+00:00" + "time": "2024-09-21T08:32:55+00:00" + }, + { + "name": "league/oauth1-client", + "version": "v1.10.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "guzzlehttp/psr7": "^1.7|^2.0", + "php": ">=7.1||>=8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "friendsofphp/php-cs-fixer": "^2.17", + "mockery/mockery": "^1.3.3", + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5||9.5" + }, + "suggest": { + "ext-simplexml": "For decoding XML-based responses." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.1" + }, + "time": "2022-04-15T14:02:14+00:00" }, { "name": "league/uri", @@ -4321,16 +4548,16 @@ }, { "name": "livewire/livewire", - "version": "v3.5.6", + "version": "v3.5.12", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "597a2808d8d3001cc3ed5ce89a6ebab00f83b80f" + "reference": "3c8d1f9d7d9098aaea663093ae168f2d5d2ae73d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/597a2808d8d3001cc3ed5ce89a6ebab00f83b80f", - "reference": "597a2808d8d3001cc3ed5ce89a6ebab00f83b80f", + "url": "https://api.github.com/repos/livewire/livewire/zipball/3c8d1f9d7d9098aaea663093ae168f2d5d2ae73d", + "reference": "3c8d1f9d7d9098aaea663093ae168f2d5d2ae73d", "shasum": "" }, "require": { @@ -4338,7 +4565,7 @@ "illuminate/routing": "^10.0|^11.0", "illuminate/support": "^10.0|^11.0", "illuminate/validation": "^10.0|^11.0", - "laravel/prompts": "^0.1.24", + "laravel/prompts": "^0.1.24|^0.2|^0.3", "league/mime-type-detection": "^1.9", "php": "^8.1", "symfony/console": "^6.0|^7.0", @@ -4385,7 +4612,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.5.6" + "source": "https://github.com/livewire/livewire/tree/v3.5.12" }, "funding": [ { @@ -4393,7 +4620,7 @@ "type": "github" } ], - "time": "2024-08-19T11:52:18+00:00" + "time": "2024-10-15T19:35:06+00:00" }, { "name": "masterminds/html5", @@ -4464,16 +4691,16 @@ }, { "name": "mchev/banhammer", - "version": "v2.3.1", + "version": "v2.3.2", "source": { "type": "git", "url": "https://github.com/mchev/banhammer.git", - "reference": "6193903d46294bf39869747939fad7ad7cc7ce10" + "reference": "5a792d0d0dde6751c829c89a9331bcad7bdbd344" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mchev/banhammer/zipball/6193903d46294bf39869747939fad7ad7cc7ce10", - "reference": "6193903d46294bf39869747939fad7ad7cc7ce10", + "url": "https://api.github.com/repos/mchev/banhammer/zipball/5a792d0d0dde6751c829c89a9331bcad7bdbd344", + "reference": "5a792d0d0dde6751c829c89a9331bcad7bdbd344", "shasum": "" }, "require": { @@ -4520,7 +4747,7 @@ ], "support": { "issues": "https://github.com/mchev/banhammer/issues", - "source": "https://github.com/mchev/banhammer/tree/v2.3.1" + "source": "https://github.com/mchev/banhammer/tree/v2.3.2" }, "funding": [ { @@ -4528,20 +4755,20 @@ "type": "github" } ], - "time": "2024-08-23T16:47:51+00:00" + "time": "2024-09-20T18:16:07+00:00" }, { "name": "meilisearch/meilisearch-php", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/meilisearch/meilisearch-php.git", - "reference": "110be455194fda42ae3a3b8b6a9243479c3a6d19" + "reference": "4dd127cb87848f7a7b28e83bb355b4b86d329867" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/110be455194fda42ae3a3b8b6a9243479c3a6d19", - "reference": "110be455194fda42ae3a3b8b6a9243479c3a6d19", + "url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/4dd127cb87848f7a7b28e83bb355b4b86d329867", + "reference": "4dd127cb87848f7a7b28e83bb355b4b86d329867", "shasum": "" }, "require": { @@ -4593,9 +4820,9 @@ ], "support": { "issues": "https://github.com/meilisearch/meilisearch-php/issues", - "source": "https://github.com/meilisearch/meilisearch-php/tree/v1.10.0" + "source": "https://github.com/meilisearch/meilisearch-php/tree/v1.11.0" }, - "time": "2024-08-26T23:09:54+00:00" + "time": "2024-10-28T14:04:37+00:00" }, { "name": "mobiledetect/mobiledetectlib", @@ -4663,16 +4890,16 @@ }, { "name": "monolog/monolog", - "version": "3.7.0", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8" + "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8", - "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/32e515fdc02cdafbe4593e30a9350d486b125b67", + "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67", "shasum": "" }, "require": { @@ -4692,12 +4919,14 @@ "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.5.17", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -4748,7 +4977,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.7.0" + "source": "https://github.com/Seldaek/monolog/tree/3.8.0" }, "funding": [ { @@ -4760,20 +4989,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:40:51+00:00" + "time": "2024-11-12T13:57:08+00:00" }, { "name": "mtdowling/jmespath.php", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b" + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/bbb69a935c2cbb0c03d7f481a238027430f6440b", - "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", "shasum": "" }, "require": { @@ -4790,7 +5019,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -4824,26 +5053,26 @@ ], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.7.0" + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" }, - "time": "2023-08-25T10:54:48+00:00" + "time": "2024-09-04T18:46:31+00:00" }, { "name": "nesbot/carbon", - "version": "3.8.0", + "version": "3.8.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "bbd3eef89af8ba66a3aa7952b5439168fbcc529f" + "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bbd3eef89af8ba66a3aa7952b5439168fbcc529f", - "reference": "bbd3eef89af8ba66a3aa7952b5439168fbcc529f", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e1268cdbc486d97ce23fef2c666dc3c6b6de9947", + "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947", "shasum": "" }, "require": { - "carbonphp/carbon-doctrine-types": "*", + "carbonphp/carbon-doctrine-types": "<100.0", "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", @@ -4932,28 +5161,28 @@ "type": "tidelift" } ], - "time": "2024-08-19T06:22:39+00:00" + "time": "2024-11-07T17:46:48+00:00" }, { "name": "nette/schema", - "version": "v1.3.0", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188" + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", - "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.3" + "php": "8.1 - 8.4" }, "require-dev": { - "nette/tester": "^2.4", + "nette/tester": "^2.5.2", "phpstan/phpstan-nette": "^1.0", "tracy/tracy": "^2.8" }, @@ -4992,9 +5221,9 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.0" + "source": "https://github.com/nette/schema/tree/v1.3.2" }, - "time": "2023-12-11T11:54:22+00:00" + "time": "2024-10-06T23:10:23+00:00" }, { "name": "nette/utils", @@ -5084,16 +5313,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.1.0", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { @@ -5136,38 +5365,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-07-01T20:03:41+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.0.1", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "58c4c58cf23df7f498daeb97092e34f5259feb6a" + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/58c4c58cf23df7f498daeb97092e34f5259feb6a", - "reference": "58c4c58cf23df7f498daeb97092e34f5259feb6a", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.0.4" + "symfony/console": "^7.1.8" }, "require-dev": { - "ergebnis/phpstan-rules": "^2.2.0", - "illuminate/console": "^11.0.0", - "laravel/pint": "^1.14.0", - "mockery/mockery": "^1.6.7", - "pestphp/pest": "^2.34.1", - "phpstan/phpstan": "^1.10.59", - "phpstan/phpstan-strict-rules": "^1.5.2", - "symfony/var-dumper": "^7.0.4", + "illuminate/console": "^11.33.2", + "laravel/pint": "^1.18.2", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.11", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.8", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -5210,7 +5438,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.0.1" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" }, "funding": [ { @@ -5226,20 +5454,20 @@ "type": "github" } ], - "time": "2024-03-06T16:17:14+00:00" + "time": "2024-11-21T10:39:51+00:00" }, { "name": "openspout/openspout", - "version": "v4.24.5", + "version": "v4.27.0", "source": { "type": "git", "url": "https://github.com/openspout/openspout.git", - "reference": "393299ae21153f042f48b185f2adeb4b157d1d93" + "reference": "1841a6047b4d23d1d353821b8a03f8d599a94143" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/openspout/openspout/zipball/393299ae21153f042f48b185f2adeb4b157d1d93", - "reference": "393299ae21153f042f48b185f2adeb4b157d1d93", + "url": "https://api.github.com/repos/openspout/openspout/zipball/1841a6047b4d23d1d353821b8a03f8d599a94143", + "reference": "1841a6047b4d23d1d353821b8a03f8d599a94143", "shasum": "" }, "require": { @@ -5249,17 +5477,17 @@ "ext-libxml": "*", "ext-xmlreader": "*", "ext-zip": "*", - "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { "ext-zlib": "*", - "friendsofphp/php-cs-fixer": "^3.60.0", - "infection/infection": "^0.29.6", + "friendsofphp/php-cs-fixer": "^3.65.0", + "infection/infection": "^0.29.8", "phpbench/phpbench": "^1.3.1", - "phpstan/phpstan": "^1.11.8", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.0", - "phpunit/phpunit": "^10.5.20 || ^11.2.8" + "phpstan/phpstan": "^2.0.2", + "phpstan/phpstan-phpunit": "^2.0.1", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^11.4.3" }, "suggest": { "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", @@ -5307,7 +5535,7 @@ ], "support": { "issues": "https://github.com/openspout/openspout/issues", - "source": "https://github.com/openspout/openspout/tree/v4.24.5" + "source": "https://github.com/openspout/openspout/tree/v4.27.0" }, "funding": [ { @@ -5319,28 +5547,28 @@ "type": "github" } ], - "time": "2024-07-26T05:48:04+00:00" + "time": "2024-11-25T10:23:43+00:00" }, { "name": "paragonie/constant_time_encoding", - "version": "v2.7.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105" + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105", - "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", "shasum": "" }, "require": { - "php": "^7|^8" + "php": "^8" }, "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^1|^2|^3|^4" + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4|^5" }, "type": "library", "autoload": { @@ -5386,20 +5614,70 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2024-05-08T12:18:48+00:00" + "time": "2024-05-08T12:36:18+00:00" }, { - "name": "php-http/discovery", - "version": "1.19.4", + "name": "paragonie/random_compat", + "version": "v9.99.100", "source": { "type": "git", - "url": "https://github.com/php-http/discovery.git", - "reference": "0700efda8d7526335132360167315fdab3aeb599" + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/0700efda8d7526335132360167315fdab3aeb599", - "reference": "0700efda8d7526335132360167315fdab3aeb599", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.20.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", "shasum": "" }, "require": { @@ -5463,9 +5741,9 @@ ], "support": { "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.19.4" + "source": "https://github.com/php-http/discovery/tree/1.20.0" }, - "time": "2024-03-29T13:00:05+00:00" + "time": "2024-10-02T11:20:13+00:00" }, { "name": "phpoption/phpoption", @@ -5543,25 +5821,135 @@ "time": "2024-07-20T21:41:07+00:00" }, { - "name": "pragmarx/google2fa", - "version": "v8.0.1", + "name": "phpseclib/phpseclib", + "version": "3.0.42", "source": { "type": "git", - "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3" + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/80c3d801b31fe165f8fe99ea085e0a37834e1be3", - "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98", "shasum": "" }, "require": { - "paragonie/constant_time_encoding": "^1.0|^2.0", + "paragonie/constant_time_encoding": "^1|^2|^3", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.42" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2024-09-16T03:06:04+00:00" + }, + { + "name": "pragmarx/google2fa", + "version": "v8.0.3", + "source": { + "type": "git", + "url": "https://github.com/antonioribeiro/google2fa.git", + "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", + "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1.0|^2.0|^3.0", "php": "^7.1|^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.18", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^7.5.15|^8.5|^9.0" }, "type": "library", @@ -5590,9 +5978,9 @@ ], "support": { "issues": "https://github.com/antonioribeiro/google2fa/issues", - "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.1" + "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.3" }, - "time": "2022-06-13T21:57:56+00:00" + "time": "2024-09-05T11:56:40+00:00" }, { "name": "psr/cache", @@ -5956,16 +6344,16 @@ }, { "name": "psr/log", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "79dff0b268932c640297f5208d6298f71855c03e" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e", - "reference": "79dff0b268932c640297f5208d6298f71855c03e", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -6000,9 +6388,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.1" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2024-08-21T13:31:24+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "psr/simple-cache", @@ -6438,17 +6826,141 @@ "time": "2024-02-26T18:08:49+00:00" }, { - "name": "spatie/color", - "version": "1.5.3", + "name": "socialiteproviders/discord", + "version": "4.2.0", "source": { "type": "git", - "url": "https://github.com/spatie/color.git", - "reference": "49739265900cabce4640cd26c3266fd8d2cca390" + "url": "https://github.com/SocialiteProviders/Discord.git", + "reference": "c71c379acfdca5ba4aa65a3db5ae5222852a919c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/color/zipball/49739265900cabce4640cd26c3266fd8d2cca390", - "reference": "49739265900cabce4640cd26c3266fd8d2cca390", + "url": "https://api.github.com/repos/SocialiteProviders/Discord/zipball/c71c379acfdca5ba4aa65a3db5ae5222852a919c", + "reference": "c71c379acfdca5ba4aa65a3db5ae5222852a919c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.4 || ^8.0", + "socialiteproviders/manager": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "SocialiteProviders\\Discord\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christopher Eklund", + "email": "eklundchristopher@gmail.com" + } + ], + "description": "Discord OAuth2 Provider for Laravel Socialite", + "keywords": [ + "discord", + "laravel", + "oauth", + "provider", + "socialite" + ], + "support": { + "docs": "https://socialiteproviders.com/discord", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" + }, + "time": "2023-07-24T23:28:47+00:00" + }, + { + "name": "socialiteproviders/manager", + "version": "v4.7.0", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Manager.git", + "reference": "ab0691b82cec77efd90154c78f1854903455c82f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/ab0691b82cec77efd90154c78f1854903455c82f", + "reference": "ab0691b82cec77efd90154c78f1854903455c82f", + "shasum": "" + }, + "require": { + "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "laravel/socialite": "^5.5", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "SocialiteProviders\\Manager\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "SocialiteProviders\\Manager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andy Wendt", + "email": "andy@awendt.com" + }, + { + "name": "Anton Komarev", + "email": "a.komarev@cybercog.su" + }, + { + "name": "Miguel Piedrafita", + "email": "soy@miguelpiedrafita.com" + }, + { + "name": "atymic", + "email": "atymicq@gmail.com", + "homepage": "https://atymic.dev" + } + ], + "description": "Easily add new or override built-in providers in Laravel Socialite.", + "homepage": "https://socialiteproviders.com", + "keywords": [ + "laravel", + "manager", + "oauth", + "providers", + "socialite" + ], + "support": { + "issues": "https://github.com/socialiteproviders/manager/issues", + "source": "https://github.com/socialiteproviders/manager" + }, + "time": "2024-11-10T01:56:18+00:00" + }, + { + "name": "spatie/color", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/color.git", + "reference": "4c540ffbef68a3df3d209718ae06deaab081e708" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/color/zipball/4c540ffbef68a3df3d209718ae06deaab081e708", + "reference": "4c540ffbef68a3df3d209718ae06deaab081e708", "shasum": "" }, "require": { @@ -6486,7 +6998,7 @@ ], "support": { "issues": "https://github.com/spatie/color/issues", - "source": "https://github.com/spatie/color/tree/1.5.3" + "source": "https://github.com/spatie/color/tree/1.6.1" }, "funding": [ { @@ -6494,7 +7006,7 @@ "type": "github" } ], - "time": "2022-12-18T12:58:32+00:00" + "time": "2024-11-18T15:00:47+00:00" }, { "name": "spatie/invade", @@ -6557,16 +7069,16 @@ }, { "name": "spatie/laravel-package-tools", - "version": "1.16.5", + "version": "1.16.6", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2" + "reference": "1f26942dc1e5c49eacfced34fdbc29ed234bd7b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/c7413972cf22ffdff97b68499c22baa04eddb6a2", - "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/1f26942dc1e5c49eacfced34fdbc29ed234bd7b3", + "reference": "1f26942dc1e5c49eacfced34fdbc29ed234bd7b3", "shasum": "" }, "require": { @@ -6605,7 +7117,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.5" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.6" }, "funding": [ { @@ -6613,20 +7125,20 @@ "type": "github" } ], - "time": "2024-08-27T18:56:10+00:00" + "time": "2024-11-18T15:02:02+00:00" }, { "name": "stevebauman/purify", - "version": "v6.2.1", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/stevebauman/purify.git", - "reference": "083a8bd4c956652196272ac4ece294e50df64d8c" + "reference": "a449299a3d5f5f8ef177e626721b3f69143890a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stevebauman/purify/zipball/083a8bd4c956652196272ac4ece294e50df64d8c", - "reference": "083a8bd4c956652196272ac4ece294e50df64d8c", + "url": "https://api.github.com/repos/stevebauman/purify/zipball/a449299a3d5f5f8ef177e626721b3f69143890a4", + "reference": "a449299a3d5f5f8ef177e626721b3f69143890a4", "shasum": "" }, "require": { @@ -6677,22 +7189,22 @@ ], "support": { "issues": "https://github.com/stevebauman/purify/issues", - "source": "https://github.com/stevebauman/purify/tree/v6.2.1" + "source": "https://github.com/stevebauman/purify/tree/v6.2.2" }, - "time": "2024-08-26T16:21:45+00:00" + "time": "2024-09-24T12:27:10+00:00" }, { "name": "symfony/clock", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "3dfc8b084853586de51dd1441c6242c76a28cbe7" + "reference": "97bebc53548684c17ed696bc8af016880f0f098d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/3dfc8b084853586de51dd1441c6242c76a28cbe7", - "reference": "3dfc8b084853586de51dd1441c6242c76a28cbe7", + "url": "https://api.github.com/repos/symfony/clock/zipball/97bebc53548684c17ed696bc8af016880f0f098d", + "reference": "97bebc53548684c17ed696bc8af016880f0f098d", "shasum": "" }, "require": { @@ -6737,7 +7249,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.1.1" + "source": "https://github.com/symfony/clock/tree/v7.1.6" }, "funding": [ { @@ -6753,20 +7265,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/console", - "version": "v7.1.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111" + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111", - "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111", + "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", "shasum": "" }, "require": { @@ -6830,7 +7342,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.4" + "source": "https://github.com/symfony/console/tree/v7.1.8" }, "funding": [ { @@ -6846,20 +7358,20 @@ "type": "tidelift" } ], - "time": "2024-08-15T22:48:53+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/css-selector", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "1c7cee86c6f812896af54434f8ce29c8d94f9ff4" + "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/1c7cee86c6f812896af54434f8ce29c8d94f9ff4", - "reference": "1c7cee86c6f812896af54434f8ce29c8d94f9ff4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", + "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", "shasum": "" }, "require": { @@ -6895,7 +7407,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.1.1" + "source": "https://github.com/symfony/css-selector/tree/v7.1.6" }, "funding": [ { @@ -6911,7 +7423,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6982,16 +7494,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.1.3", + "version": "v7.1.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "432bb369952795c61ca1def65e078c4a80dad13c" + "reference": "010e44661f4c6babaf8c4862fe68c24a53903342" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/432bb369952795c61ca1def65e078c4a80dad13c", - "reference": "432bb369952795c61ca1def65e078c4a80dad13c", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/010e44661f4c6babaf8c4862fe68c24a53903342", + "reference": "010e44661f4c6babaf8c4862fe68c24a53903342", "shasum": "" }, "require": { @@ -7037,7 +7549,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.1.3" + "source": "https://github.com/symfony/error-handler/tree/v7.1.7" }, "funding": [ { @@ -7053,20 +7565,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T13:02:51+00:00" + "time": "2024-11-05T15:34:55+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7" + "reference": "87254c78dd50721cfd015b62277a8281c5589702" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", - "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87254c78dd50721cfd015b62277a8281c5589702", + "reference": "87254c78dd50721cfd015b62277a8281c5589702", "shasum": "" }, "require": { @@ -7117,7 +7629,7 @@ "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.1.1" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.6" }, "funding": [ { @@ -7133,7 +7645,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -7213,16 +7725,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", "shasum": "" }, "require": { @@ -7257,7 +7769,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.4" + "source": "https://github.com/symfony/finder/tree/v7.1.6" }, "funding": [ { @@ -7273,20 +7785,20 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/html-sanitizer", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/html-sanitizer.git", - "reference": "737cbaa8082b696d0574afd91b9f471eca67fc65" + "reference": "a25620fc6407e14331f3c0c5668eb4f35c392d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/737cbaa8082b696d0574afd91b9f471eca67fc65", - "reference": "737cbaa8082b696d0574afd91b9f471eca67fc65", + "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/a25620fc6407e14331f3c0c5668eb4f35c392d4a", + "reference": "a25620fc6407e14331f3c0c5668eb4f35c392d4a", "shasum": "" }, "require": { @@ -7326,7 +7838,7 @@ "sanitizer" ], "support": { - "source": "https://github.com/symfony/html-sanitizer/tree/v7.1.1" + "source": "https://github.com/symfony/html-sanitizer/tree/v7.1.6" }, "funding": [ { @@ -7342,20 +7854,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:55:39+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.1.3", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f602d5c17d1fa02f8019ace2687d9d136b7f4a1a" + "reference": "f4419ec69ccfc3f725a4de7c20e4e57626d10112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f602d5c17d1fa02f8019ace2687d9d136b7f4a1a", - "reference": "f602d5c17d1fa02f8019ace2687d9d136b7f4a1a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f4419ec69ccfc3f725a4de7c20e4e57626d10112", + "reference": "f4419ec69ccfc3f725a4de7c20e4e57626d10112", "shasum": "" }, "require": { @@ -7365,12 +7877,12 @@ }, "conflict": { "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -7403,7 +7915,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.1.3" + "source": "https://github.com/symfony/http-foundation/tree/v7.1.8" }, "funding": [ { @@ -7419,20 +7931,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-11-09T09:16:45+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.1.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "6efcbd1b3f444f631c386504fc83eeca25963747" + "reference": "33fef24e3dc79d6d30bf4936531f2f4bd2ca189e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6efcbd1b3f444f631c386504fc83eeca25963747", - "reference": "6efcbd1b3f444f631c386504fc83eeca25963747", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/33fef24e3dc79d6d30bf4936531f2f4bd2ca189e", + "reference": "33fef24e3dc79d6d30bf4936531f2f4bd2ca189e", "shasum": "" }, "require": { @@ -7517,7 +8029,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.4" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.8" }, "funding": [ { @@ -7533,20 +8045,20 @@ "type": "tidelift" } ], - "time": "2024-08-30T17:02:28+00:00" + "time": "2024-11-13T14:25:32+00:00" }, { "name": "symfony/mailer", - "version": "v7.1.2", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "8fcff0af9043c8f8a8e229437cea363e282f9aee" + "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/8fcff0af9043c8f8a8e229437cea363e282f9aee", - "reference": "8fcff0af9043c8f8a8e229437cea363e282f9aee", + "url": "https://api.github.com/repos/symfony/mailer/zipball/69c9948451fb3a6a4d47dc8261d1794734e76cdd", + "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd", "shasum": "" }, "require": { @@ -7597,7 +8109,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.1.2" + "source": "https://github.com/symfony/mailer/tree/v7.1.6" }, "funding": [ { @@ -7613,20 +8125,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T08:00:31+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/mime", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "ccaa6c2503db867f472a587291e764d6a1e58758" + "reference": "caa1e521edb2650b8470918dfe51708c237f0598" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/ccaa6c2503db867f472a587291e764d6a1e58758", - "reference": "ccaa6c2503db867f472a587291e764d6a1e58758", + "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", + "reference": "caa1e521edb2650b8470918dfe51708c237f0598", "shasum": "" }, "require": { @@ -7681,7 +8193,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.4" + "source": "https://github.com/symfony/mime/tree/v7.1.6" }, "funding": [ { @@ -7697,24 +8209,24 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2024-10-25T15:11:02+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -7760,7 +8272,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -7776,24 +8288,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -7838,7 +8350,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -7854,26 +8366,25 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c" + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a6e83bdeb3c84391d1dfe16f42e40727ce524a5c", - "reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" @@ -7922,7 +8433,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -7938,24 +8449,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -8003,7 +8514,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -8019,24 +8530,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -8083,7 +8594,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -8099,97 +8610,24 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "10112722600777e02d2745716b70c5db4ca70442" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/10112722600777e02d2745716b70c5db4ca70442", - "reference": "10112722600777e02d2745716b70c5db4ca70442", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "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.30.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -8236,7 +8674,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -8252,24 +8690,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -8312,7 +8750,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -8328,24 +8766,24 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:35:24+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "2ba1f33797470debcda07fe9dce20a0003df18e9" + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/2ba1f33797470debcda07fe9dce20a0003df18e9", - "reference": "2ba1f33797470debcda07fe9dce20a0003df18e9", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -8391,7 +8829,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" }, "funding": [ { @@ -8407,20 +8845,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v7.1.3", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca" + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca", - "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca", + "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", "shasum": "" }, "require": { @@ -8452,7 +8890,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.3" + "source": "https://github.com/symfony/process/tree/v7.1.8" }, "funding": [ { @@ -8468,20 +8906,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:44:47+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "405a7bcd872f1563966f64be19f1362d94ce71ab" + "reference": "f16471bb19f6685b9ccf0a2c03c213840ae68cd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/405a7bcd872f1563966f64be19f1362d94ce71ab", - "reference": "405a7bcd872f1563966f64be19f1362d94ce71ab", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/f16471bb19f6685b9ccf0a2c03c213840ae68cd6", + "reference": "f16471bb19f6685b9ccf0a2c03c213840ae68cd6", "shasum": "" }, "require": { @@ -8535,7 +8973,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.1.4" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.1.6" }, "funding": [ { @@ -8551,20 +8989,20 @@ "type": "tidelift" } ], - "time": "2024-08-15T22:48:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/routing", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7" + "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", - "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", + "url": "https://api.github.com/repos/symfony/routing/zipball/66a2c469f6c22d08603235c46a20007c0701ea0a", + "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a", "shasum": "" }, "require": { @@ -8616,7 +9054,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.4" + "source": "https://github.com/symfony/routing/tree/v7.1.6" }, "funding": [ { @@ -8632,7 +9070,7 @@ "type": "tidelift" } ], - "time": "2024-08-29T08:16:25+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/service-contracts", @@ -8719,16 +9157,16 @@ }, { "name": "symfony/string", - "version": "v7.1.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b" + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b", - "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b", + "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", "shasum": "" }, "require": { @@ -8786,7 +9224,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.4" + "source": "https://github.com/symfony/string/tree/v7.1.8" }, "funding": [ { @@ -8802,20 +9240,20 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:59:40+00:00" + "time": "2024-11-13T13:31:21+00:00" }, { "name": "symfony/translation", - "version": "v7.1.3", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "8d5e50c813ba2859a6dfc99a0765c550507934a1" + "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/8d5e50c813ba2859a6dfc99a0765c550507934a1", - "reference": "8d5e50c813ba2859a6dfc99a0765c550507934a1", + "url": "https://api.github.com/repos/symfony/translation/zipball/b9f72ab14efdb6b772f85041fa12f820dee8d55f", + "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f", "shasum": "" }, "require": { @@ -8880,7 +9318,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.1.3" + "source": "https://github.com/symfony/translation/tree/v7.1.6" }, "funding": [ { @@ -8896,7 +9334,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-09-28T12:35:13+00:00" }, { "name": "symfony/translation-contracts", @@ -8978,16 +9416,16 @@ }, { "name": "symfony/uid", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "82177535395109075cdb45a70533aa3d7a521cdf" + "reference": "65befb3bb2d503bbffbd08c815aa38b472999917" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/82177535395109075cdb45a70533aa3d7a521cdf", - "reference": "82177535395109075cdb45a70533aa3d7a521cdf", + "url": "https://api.github.com/repos/symfony/uid/zipball/65befb3bb2d503bbffbd08c815aa38b472999917", + "reference": "65befb3bb2d503bbffbd08c815aa38b472999917", "shasum": "" }, "require": { @@ -9032,7 +9470,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.4" + "source": "https://github.com/symfony/uid/tree/v7.1.6" }, "funding": [ { @@ -9048,20 +9486,20 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:59:40+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa" + "reference": "7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a5fa7481b199090964d6fd5dab6294d5a870c7aa", - "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8", + "reference": "7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8", "shasum": "" }, "require": { @@ -9115,7 +9553,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.4" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.8" }, "funding": [ { @@ -9131,7 +9569,7 @@ "type": "tidelift" } ], - "time": "2024-08-30T16:12:47+00:00" + "time": "2024-11-08T15:46:42+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -9272,16 +9710,16 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b56450eed252f6801410d810c8e1727224ae0743" + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", - "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", "shasum": "" }, "require": { @@ -9306,7 +9744,7 @@ "authors": [ { "name": "Lars Moelleken", - "homepage": "http://www.moelleken.org/" + "homepage": "https://www.moelleken.org/" } ], "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", @@ -9318,7 +9756,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" }, "funding": [ { @@ -9342,7 +9780,7 @@ "type": "tidelift" } ], - "time": "2022-03-08T17:03:00+00:00" + "time": "2024-11-21T01:49:47+00:00" }, { "name": "webmozart/assert", @@ -9406,23 +9844,23 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.13.5", + "version": "v3.14.9", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "92d86be45ee54edff735e46856f64f14b6a8bb07" + "reference": "2e805a6bd4e1aa83774316bb062703c65d0691ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/92d86be45ee54edff735e46856f64f14b6a8bb07", - "reference": "92d86be45ee54edff735e46856f64f14b6a8bb07", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/2e805a6bd4e1aa83774316bb062703c65d0691ef", + "reference": "2e805a6bd4e1aa83774316bb062703c65d0691ef", "shasum": "" }, "require": { "illuminate/routing": "^9|^10|^11", "illuminate/session": "^9|^10|^11", "illuminate/support": "^9|^10|^11", - "maximebf/debugbar": "~1.22.0", + "maximebf/debugbar": "~1.23.0", "php": "^8.0", "symfony/finder": "^6|^7" }, @@ -9435,7 +9873,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.13-dev" + "dev-master": "3.14-dev" }, "laravel": { "providers": [ @@ -9474,7 +9912,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.13.5" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.9" }, "funding": [ { @@ -9486,20 +9924,20 @@ "type": "github" } ], - "time": "2024-04-12T11:20:37+00:00" + "time": "2024-11-25T14:51:20+00:00" }, { "name": "brianium/paratest", - "version": "v7.4.3", + "version": "v7.6.0", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "64fcfd0e28a6b8078a19dbf9127be2ee645b92ec" + "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/64fcfd0e28a6b8078a19dbf9127be2ee645b92ec", - "reference": "64fcfd0e28a6b8078a19dbf9127be2ee645b92ec", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/68ff89a8de47d086588e391a516d2a5b5fde6254", + "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254", "shasum": "" }, "require": { @@ -9507,31 +9945,30 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-simplexml": "*", - "fidry/cpu-core-counter": "^1.1.0", - "jean85/pretty-package-versions": "^2.0.5", - "php": "~8.2.0 || ~8.3.0", - "phpunit/php-code-coverage": "^10.1.11 || ^11.0.0", - "phpunit/php-file-iterator": "^4.1.0 || ^5.0.0", - "phpunit/php-timer": "^6.0.0 || ^7.0.0", - "phpunit/phpunit": "^10.5.9 || ^11.0.3", - "sebastian/environment": "^6.0.1 || ^7.0.0", - "symfony/console": "^6.4.3 || ^7.0.3", - "symfony/process": "^6.4.3 || ^7.0.3" + "fidry/cpu-core-counter": "^1.2.0", + "jean85/pretty-package-versions": "^2.0.6", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-timer": "^7.0.1", + "phpunit/phpunit": "^11.4.1", + "sebastian/environment": "^7.2.0", + "symfony/console": "^6.4.11 || ^7.1.5", + "symfony/process": "^6.4.8 || ^7.1.5" }, "require-dev": { "doctrine/coding-standard": "^12.0.0", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^1.10.58", - "phpstan/phpstan-deprecation-rules": "^1.1.4", - "phpstan/phpstan-phpunit": "^1.3.15", - "phpstan/phpstan-strict-rules": "^1.5.2", - "squizlabs/php_codesniffer": "^3.9.0", - "symfony/filesystem": "^6.4.3 || ^7.0.3" + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "squizlabs/php_codesniffer": "^3.10.3", + "symfony/filesystem": "^6.4.9 || ^7.1.5" }, "bin": [ "bin/paratest", - "bin/paratest.bat", "bin/paratest_for_phpstorm" ], "type": "library", @@ -9568,7 +10005,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.4.3" + "source": "https://github.com/paratestphp/paratest/tree/v7.6.0" }, "funding": [ { @@ -9580,20 +10017,70 @@ "type": "paypal" } ], - "time": "2024-02-20T07:24:02+00:00" + "time": "2024-10-15T12:38:31+00:00" }, { - "name": "fakerphp/faker", - "version": "v1.23.1", + "name": "erusev/parsedown", + "version": "1.7.4", "source": { "type": "git", - "url": "https://github.com/FakerPHP/Faker.git", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" + "url": "https://github.com/erusev/parsedown.git", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, + "time": "2019-12-30T22:54:17+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", "shasum": "" }, "require": { @@ -9641,9 +10128,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" }, - "time": "2024-01-02T13:46:09+00:00" + "time": "2024-11-21T13:46:39+00:00" }, { "name": "fidry/cpu-core-counter", @@ -9708,26 +10195,26 @@ }, { "name": "filp/whoops", - "version": "2.15.4", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", - "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", + "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", + "php": "^7.1 || ^8.0", "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { - "mockery/mockery": "^0.9 || ^1.0", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", - "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", @@ -9767,7 +10254,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.15.4" + "source": "https://github.com/filp/whoops/tree/2.16.0" }, "funding": [ { @@ -9775,7 +10262,7 @@ "type": "github" } ], - "time": "2023-11-03T12:00:00+00:00" + "time": "2024-09-25T12:00:00+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -9830,28 +10317,28 @@ }, { "name": "jean85/pretty-package-versions", - "version": "2.0.6", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", "shasum": "" }, "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.1|^8.0" + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^7.5|^8.5|^9.4", - "vimeo/psalm": "^4.3" + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "vimeo/psalm": "^4.3 || ^5.0" }, "type": "library", "extra": { @@ -9883,43 +10370,141 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0" }, - "time": "2024-03-08T09:58:59+00:00" + "time": "2024-11-18T16:19:46+00:00" }, { - "name": "larastan/larastan", - "version": "v2.9.8", + "name": "knuckleswtf/scribe", + "version": "4.38.0", "source": { "type": "git", - "url": "https://github.com/larastan/larastan.git", - "reference": "340badd89b0eb5bddbc503a4829c08cf9a2819d7" + "url": "https://github.com/knuckleswtf/scribe.git", + "reference": "da667aafb6804b4b599ac6506bb178bfa5434802" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/340badd89b0eb5bddbc503a4829c08cf9a2819d7", - "reference": "340badd89b0eb5bddbc503a4829c08cf9a2819d7", + "url": "https://api.github.com/repos/knuckleswtf/scribe/zipball/da667aafb6804b4b599ac6506bb178bfa5434802", + "reference": "da667aafb6804b4b599ac6506bb178bfa5434802", + "shasum": "" + }, + "require": { + "erusev/parsedown": "1.7.4", + "ext-fileinfo": "*", + "ext-json": "*", + "ext-pdo": "*", + "fakerphp/faker": "^1.9.1", + "illuminate/console": "^8.0|^9.0|^10.0|^11.0", + "illuminate/routing": "^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "^8.0|^9.0|^10.0|^11.0", + "league/flysystem": "^1.1.4|^2.1.1|^3.0", + "mpociot/reflection-docblock": "^1.0.1", + "nikic/php-parser": "^5.0", + "nunomaduro/collision": "^5.10|^6.0|^7.0|^8.0", + "php": ">=8.0", + "ramsey/uuid": "^4.2.2", + "shalvah/clara": "^3.1.0", + "shalvah/upgrader": ">=0.6.0", + "spatie/data-transfer-object": "^2.6|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "replace": { + "mpociot/laravel-apidoc-generator": "*" + }, + "require-dev": { + "brianium/paratest": "^6.0", + "dms/phpunit-arraysubset-asserts": "^0.4", + "laravel/legacy-factories": "^1.3.0", + "laravel/lumen-framework": "^8.0|^9.0|^10.0", + "league/fractal": "^0.20", + "nikic/fast-route": "^1.3", + "orchestra/testbench": "^6.0|^7.0|^8.0", + "pestphp/pest": "^1.21", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^9.0|^10.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dom-crawler": "^5.4|^6.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Knuckles\\Scribe\\ScribeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Knuckles\\Camel\\": "camel/", + "Knuckles\\Scribe\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shalvah" + } + ], + "description": "Generate API documentation for humans from your Laravel codebase.✍", + "homepage": "http://github.com/knuckleswtf/scribe", + "keywords": [ + "api", + "dingo", + "documentation", + "laravel" + ], + "support": { + "issues": "https://github.com/knuckleswtf/scribe/issues", + "source": "https://github.com/knuckleswtf/scribe/tree/4.38.0" + }, + "funding": [ + { + "url": "https://patreon.com/shalvah", + "type": "patreon" + } + ], + "time": "2024-10-18T20:16:40+00:00" + }, + { + "name": "larastan/larastan", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/larastan/larastan.git", + "reference": "88f46e3f2cd9d2a14dba13ef293b822a75832e62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/larastan/larastan/zipball/88f46e3f2cd9d2a14dba13ef293b822a75832e62", + "reference": "88f46e3f2cd9d2a14dba13ef293b822a75832e62", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0", - "php": "^8.0.2", + "illuminate/console": "^11.15.0", + "illuminate/container": "^11.15.0", + "illuminate/contracts": "^11.15.0", + "illuminate/database": "^11.15.0", + "illuminate/http": "^11.15.0", + "illuminate/pipeline": "^11.15.0", + "illuminate/support": "^11.15.0", + "php": "^8.2", "phpmyadmin/sql-parser": "^5.9.0", - "phpstan/phpstan": "^1.11.2" + "phpstan/phpstan": "^2.0.0" }, "require-dev": { "doctrine/coding-standard": "^12.0", - "nikic/php-parser": "^4.19.1", - "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.2", - "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.3", - "phpunit/phpunit": "^9.6.13 || ^10.5.16" + "laravel/framework": "^11.15.0", + "mockery/mockery": "^1.6", + "nikic/php-parser": "^5.3", + "orchestra/canvas": "^v9.1.3", + "orchestra/testbench-core": "^9.5.2", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpunit/phpunit": "^10.5.16" }, "suggest": { "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" @@ -9967,40 +10552,28 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.9.8" + "source": "https://github.com/larastan/larastan/tree/v3.0.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" } ], - "time": "2024-07-06T17:46:02+00:00" + "time": "2024-11-15T09:38:34+00:00" }, { "name": "laravel/pint", - "version": "v1.17.2", + "version": "v1.18.2", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "e8a88130a25e3f9d4d5785e6a1afca98268ab110" + "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/e8a88130a25e3f9d4d5785e6a1afca98268ab110", - "reference": "e8a88130a25e3f9d4d5785e6a1afca98268ab110", + "url": "https://api.github.com/repos/laravel/pint/zipball/f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64", + "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64", "shasum": "" }, "require": { @@ -10011,13 +10584,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.61.1", - "illuminate/view": "^10.48.18", + "friendsofphp/php-cs-fixer": "^3.64.0", + "illuminate/view": "^10.48.20", "larastan/larastan": "^2.9.8", "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.0" + "pestphp/pest": "^2.35.1" }, "bin": [ "builds/pint" @@ -10053,20 +10626,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-08-06T15:11:54+00:00" + "time": "2024-11-20T09:33:46+00:00" }, { "name": "laravel/sail", - "version": "v1.31.1", + "version": "v1.38.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "3d06dd18cee8059baa7b388af00ba47f6d96bd85" + "reference": "d17abae06661dd6c46d13627b1683a2924259145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/3d06dd18cee8059baa7b388af00ba47f6d96bd85", - "reference": "3d06dd18cee8059baa7b388af00ba47f6d96bd85", + "url": "https://api.github.com/repos/laravel/sail/zipball/d17abae06661dd6c46d13627b1683a2924259145", + "reference": "d17abae06661dd6c46d13627b1683a2924259145", "shasum": "" }, "require": { @@ -10116,20 +10689,20 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2024-08-02T07:45:47+00:00" + "time": "2024-11-11T20:16:51+00:00" }, { "name": "maximebf/debugbar", - "version": "v1.22.3", + "version": "v1.23.3", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96" + "reference": "687400043d77943ef95e8417cb44e1673ee57844" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96", - "reference": "7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/687400043d77943ef95e8417cb44e1673ee57844", + "reference": "687400043d77943ef95e8417cb44e1673ee57844", "shasum": "" }, "require": { @@ -10151,7 +10724,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.22-dev" + "dev-master": "1.23-dev" } }, "autoload": { @@ -10182,9 +10755,9 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.22.3" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.23.3" }, - "time": "2024-04-03T19:39:26+00:00" + "time": "2024-10-29T12:24:25+00:00" }, { "name": "mockery/mockery", @@ -10270,17 +10843,70 @@ "time": "2024-05-16T03:13:13+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.12.0", + "name": "mpociot/reflection-docblock", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "url": "https://github.com/mpociot/reflection-docblock.git", + "reference": "c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/mpociot/reflection-docblock/zipball/c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587", + "reference": "c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mpociot": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "support": { + "issues": "https://github.com/mpociot/reflection-docblock/issues", + "source": "https://github.com/mpociot/reflection-docblock/tree/master" + }, + "time": "2016-06-20T20:53:12+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -10319,7 +10945,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -10327,27 +10953,27 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.4.0", + "version": "v8.5.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a" + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/e7d1aa8ed753f63fa816932bbc89678238843b4a", - "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", "shasum": "" }, "require": { - "filp/whoops": "^2.15.4", - "nunomaduro/termwind": "^2.0.1", + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", "php": "^8.2.0", - "symfony/console": "^7.1.3" + "symfony/console": "^7.1.5" }, "conflict": { "laravel/framework": "<11.0.0 || >=12.0.0", @@ -10355,14 +10981,14 @@ }, "require-dev": { "larastan/larastan": "^2.9.8", - "laravel/framework": "^11.19.0", - "laravel/pint": "^1.17.1", - "laravel/sail": "^1.31.0", - "laravel/sanctum": "^4.0.2", - "laravel/tinker": "^2.9.0", - "orchestra/testbench-core": "^9.2.3", - "pestphp/pest": "^2.35.0 || ^3.0.0", - "sebastian/environment": "^6.1.0 || ^7.0.0" + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", "extra": { @@ -10424,40 +11050,42 @@ "type": "patreon" } ], - "time": "2024-08-03T15:32:23+00:00" + "time": "2024-10-15T16:06:32+00:00" }, { "name": "pestphp/pest", - "version": "v2.35.1", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "b13acb630df52c06123588d321823c31fc685545" + "reference": "179d46ce97d52bcb3f791449ae94025c3f32e3e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/b13acb630df52c06123588d321823c31fc685545", - "reference": "b13acb630df52c06123588d321823c31fc685545", + "url": "https://api.github.com/repos/pestphp/pest/zipball/179d46ce97d52bcb3f791449ae94025c3f32e3e3", + "reference": "179d46ce97d52bcb3f791449ae94025c3f32e3e3", "shasum": "" }, "require": { - "brianium/paratest": "^7.3.1", - "nunomaduro/collision": "^7.10.0|^8.4.0", - "nunomaduro/termwind": "^1.15.1|^2.0.1", - "pestphp/pest-plugin": "^2.1.1", - "pestphp/pest-plugin-arch": "^2.7.0", - "php": "^8.1.0", - "phpunit/phpunit": "^10.5.17" + "brianium/paratest": "^7.6.0", + "nunomaduro/collision": "^8.5.0", + "nunomaduro/termwind": "^2.2.0", + "pestphp/pest-plugin": "^3.0.0", + "pestphp/pest-plugin-arch": "^3.0.0", + "pestphp/pest-plugin-mutate": "^3.0.5", + "php": "^8.2.0", + "phpunit/phpunit": "^11.4.3" }, "conflict": { - "phpunit/phpunit": ">10.5.17", - "sebastian/exporter": "<5.1.0", + "filp/whoops": "<2.16.0", + "phpunit/phpunit": ">11.4.3", + "sebastian/exporter": "<6.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { - "pestphp/pest-dev-tools": "^2.16.0", - "pestphp/pest-plugin-type-coverage": "^2.8.5", - "symfony/process": "^6.4.0|^7.1.3" + "pestphp/pest-dev-tools": "^3.3.0", + "pestphp/pest-plugin-type-coverage": "^3.1.0", + "symfony/process": "^7.1.6" }, "bin": [ "bin/pest" @@ -10466,6 +11094,8 @@ "extra": { "pest": { "plugins": [ + "Pest\\Mutate\\Plugins\\Mutate", + "Pest\\Plugins\\Configuration", "Pest\\Plugins\\Bail", "Pest\\Plugins\\Cache", "Pest\\Plugins\\Coverage", @@ -10520,7 +11150,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v2.35.1" + "source": "https://github.com/pestphp/pest/tree/v3.5.1" }, "funding": [ { @@ -10532,34 +11162,34 @@ "type": "github" } ], - "time": "2024-08-20T21:41:50+00:00" + "time": "2024-10-31T16:12:45+00:00" }, { "name": "pestphp/pest-plugin", - "version": "v2.1.1", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin.git", - "reference": "e05d2859e08c2567ee38ce8b005d044e72648c0b" + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e05d2859e08c2567ee38ce8b005d044e72648c0b", - "reference": "e05d2859e08c2567ee38ce8b005d044e72648c0b", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e79b26c65bc11c41093b10150c1341cc5cdbea83", + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83", "shasum": "" }, "require": { "composer-plugin-api": "^2.0.0", "composer-runtime-api": "^2.2.2", - "php": "^8.1" + "php": "^8.2" }, "conflict": { - "pestphp/pest": "<2.2.3" + "pestphp/pest": "<3.0.0" }, "require-dev": { - "composer/composer": "^2.5.8", - "pestphp/pest": "^2.16.0", - "pestphp/pest-dev-tools": "^2.16.0" + "composer/composer": "^2.7.9", + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.0" }, "type": "composer-plugin", "extra": { @@ -10586,7 +11216,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin/tree/v2.1.1" + "source": "https://github.com/pestphp/pest-plugin/tree/v3.0.0" }, "funding": [ { @@ -10602,31 +11232,30 @@ "type": "patreon" } ], - "time": "2023-08-22T08:40:06+00:00" + "time": "2024-09-08T23:21:41+00:00" }, { "name": "pestphp/pest-plugin-arch", - "version": "v2.7.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-arch.git", - "reference": "d23b2d7498475354522c3818c42ef355dca3fcda" + "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/d23b2d7498475354522c3818c42ef355dca3fcda", - "reference": "d23b2d7498475354522c3818c42ef355dca3fcda", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/0a27e55a270cfe73d8cb70551b91002ee2cb64b0", + "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0", "shasum": "" }, "require": { - "nunomaduro/collision": "^7.10.0|^8.1.0", - "pestphp/pest-plugin": "^2.1.1", - "php": "^8.1", + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", "ta-tikoma/phpunit-architecture-test": "^0.8.4" }, "require-dev": { - "pestphp/pest": "^2.33.0", - "pestphp/pest-dev-tools": "^2.16.0" + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.0" }, "type": "library", "extra": { @@ -10661,7 +11290,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-arch/tree/v2.7.0" + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.0.0" }, "funding": [ { @@ -10673,55 +11302,54 @@ "type": "github" } ], - "time": "2024-01-26T09:46:42+00:00" + "time": "2024-09-08T23:23:55+00:00" }, { - "name": "pestphp/pest-plugin-stressless", - "version": "v2.2.0", + "name": "pestphp/pest-plugin-mutate", + "version": "v3.0.5", "source": { "type": "git", - "url": "https://github.com/pestphp/pest-plugin-stressless.git", - "reference": "7494c7d9fab9649a0f85f9f04a179f20f1405501" + "url": "https://github.com/pestphp/pest-plugin-mutate.git", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-stressless/zipball/7494c7d9fab9649a0f85f9f04a179f20f1405501", - "reference": "7494c7d9fab9649a0f85f9f04a179f20f1405501", + "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/e10dbdc98c9e2f3890095b4fe2144f63a5717e08", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08", "shasum": "" }, "require": { - "ext-curl": "*", - "ext-zip": "*", - "pestphp/pest": "^2.28", - "pestphp/pest-plugin": "^2.1.1", - "php": "^8.2" + "nikic/php-parser": "^5.2.0", + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "psr/simple-cache": "^3.0.0" }, "require-dev": { - "pestphp/pest-dev-tools": "^2.16" + "pestphp/pest": "^3.0.8", + "pestphp/pest-dev-tools": "^3.0.0", + "pestphp/pest-plugin-type-coverage": "^3.0.0" }, "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pest\\Stressless\\Plugin" - ] - } - }, "autoload": { - "files": [ - "src/Autoload.php" - ], "psr-4": { - "Pest\\Stressless\\": "src/" + "Pest\\Mutate\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Stressless plugin for Pest", + "authors": [ + { + "name": "Sandro Gehri", + "email": "sandrogehri@gmail.com" + } + ], + "description": "Mutates your code to find untested cases", "keywords": [ "framework", + "mutate", + "mutation", "pest", "php", "plugin", @@ -10730,24 +11358,23 @@ "unit" ], "support": { - "issues": "https://github.com/pestphp/pest-plugin-stressless/issues", - "source": "https://github.com/pestphp/pest-plugin-stressless/tree/v2.2.0" + "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v3.0.5" }, "funding": [ { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "url": "https://www.paypal.com/paypalme/enunomaduro", "type": "custom" }, + { + "url": "https://github.com/gehrisandro", + "type": "github" + }, { "url": "https://github.com/nunomaduro", "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" } ], - "time": "2023-12-06T14:33:21+00:00" + "time": "2024-09-22T07:54:40+00:00" }, { "name": "phar-io/manifest", @@ -10922,16 +11549,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.4.1", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f3558a4c23426d12bffeaab463f8a8d8b681193c", + "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c", "shasum": "" }, "require": { @@ -10940,17 +11567,17 @@ "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.5", + "mockery/mockery": "~1.3.5 || ~1.6.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.8", "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" + "psalm/phar": "^5.26" }, "type": "library", "extra": { @@ -10980,29 +11607,29 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.0" }, - "time": "2024-05-21T05:55:05+00:00" + "time": "2024-11-12T11:25:25+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.2", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "phpstan/phpdoc-parser": "^1.18|^2.0" }, "require-dev": { "ext-tokenizer": "*", @@ -11038,22 +11665,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" }, - "time": "2024-02-23T11:10:43+00:00" + "time": "2024-11-09T15:12:26+00:00" }, { "name": "phpmyadmin/sql-parser", - "version": "5.10.0", + "version": "5.10.1", "source": { "type": "git", "url": "https://github.com/phpmyadmin/sql-parser.git", - "reference": "91d980ab76c3f152481e367f62b921adc38af451" + "reference": "b14fd66496a22d8dd7f7e2791edd9e8674422f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/91d980ab76c3f152481e367f62b921adc38af451", - "reference": "91d980ab76c3f152481e367f62b921adc38af451", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/b14fd66496a22d8dd7f7e2791edd9e8674422f17", + "reference": "b14fd66496a22d8dd7f7e2791edd9e8674422f17", "shasum": "" }, "require": { @@ -11127,34 +11754,34 @@ "type": "other" } ], - "time": "2024-08-29T20:56:34+00:00" + "time": "2024-11-10T04:10:31+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.30.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f" + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/5ceb0e384997db59f38774bf79c2a6134252c08f", - "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "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", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -11172,26 +11799,26 @@ "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.30.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" }, - "time": "2024-08-29T09:54:52+00:00" + "time": "2024-10-13T11:29:49+00:00" }, { "name": "phpstan/phpstan", - "version": "1.12.0", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "384af967d35b2162f69526c7276acadce534d0e1" + "reference": "6c98c7600fc717b2c78c11ef60040d5b1e359c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/384af967d35b2162f69526c7276acadce534d0e1", - "reference": "384af967d35b2162f69526c7276acadce534d0e1", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6c98c7600fc717b2c78c11ef60040d5b1e359c82", + "reference": "6c98c7600fc717b2c78c11ef60040d5b1e359c82", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "php": "^7.4|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -11232,39 +11859,39 @@ "type": "github" } ], - "time": "2024-08-27T09:18:05+00:00" + "time": "2024-11-17T14:17:00+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.16", + "version": "11.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^11.4.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -11273,7 +11900,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1.x-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -11302,7 +11929,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" }, "funding": [ { @@ -11310,32 +11937,32 @@ "type": "github" } ], - "time": "2024-08-22T04:31:57+00:00" + "time": "2024-10-09T06:21:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -11363,7 +11990,7 @@ "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" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -11371,28 +11998,28 @@ "type": "github" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", - "version": "4.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -11400,7 +12027,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -11426,7 +12053,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -11434,32 +12062,32 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -11486,7 +12114,7 @@ "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" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -11494,32 +12122,32 @@ "type": "github" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "6.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -11545,7 +12173,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -11553,20 +12182,20 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "10.5.17", + "version": "11.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c1f736a473d21957ead7e94fcc029f571895abf5" + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1f736a473d21957ead7e94fcc029f571895abf5", - "reference": "c1f736a473d21957ead7e94fcc029f571895abf5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", "shasum": "" }, "require": { @@ -11576,26 +12205,25 @@ "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" + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.1.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.2" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -11606,7 +12234,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "11.4-dev" } }, "autoload": { @@ -11638,7 +12266,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.17" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" }, "funding": [ { @@ -11654,32 +12282,32 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:39:01+00:00" + "time": "2024-10-28T13:07:50+00:00" }, { "name": "sebastian/cli-parser", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -11703,7 +12331,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -11711,32 +12339,32 @@ "type": "github" } ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "2.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -11759,7 +12387,8 @@ "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" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" }, "funding": [ { @@ -11767,32 +12396,32 @@ "type": "github" } ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2024-07-03T04:44:28+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -11814,7 +12443,8 @@ "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" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -11822,36 +12452,36 @@ "type": "github" } ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "5.0.2", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.4" + "phpunit/phpunit": "^11.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.2-dev" } }, "autoload": { @@ -11891,7 +12521,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" }, "funding": [ { @@ -11899,33 +12529,33 @@ "type": "github" } ], - "time": "2024-08-12T06:03:08+00:00" + "time": "2024-10-31T05:30:08+00:00" }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -11949,7 +12579,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -11957,33 +12587,33 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -12016,7 +12646,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -12024,27 +12654,27 @@ "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "6.1.0", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-posix": "*" @@ -12052,7 +12682,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -12080,7 +12710,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { @@ -12088,34 +12718,34 @@ "type": "github" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2024-07-03T04:54:44+00:00" }, { "name": "sebastian/exporter", - "version": "5.1.2", + "version": "6.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -12158,7 +12788,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" }, "funding": [ { @@ -12166,35 +12796,35 @@ "type": "github" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2024-07-03T04:56:19+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.2", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -12220,7 +12850,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -12228,33 +12858,33 @@ "type": "github" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -12278,7 +12908,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -12286,34 +12916,34 @@ "type": "github" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "5.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -12335,7 +12965,8 @@ "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" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -12343,32 +12974,32 @@ "type": "github" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -12390,7 +13021,8 @@ "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" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -12398,32 +13030,32 @@ "type": "github" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -12453,7 +13085,8 @@ "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" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { @@ -12461,32 +13094,32 @@ "type": "github" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", - "version": "4.0.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -12509,7 +13142,8 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" }, "funding": [ { @@ -12517,29 +13151,29 @@ "type": "github" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2024-09-17T13:12:04+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -12562,7 +13196,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -12570,20 +13205,125 @@ "type": "github" } ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { - "name": "spatie/backtrace", - "version": "1.6.2", + "name": "shalvah/clara", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/spatie/backtrace.git", - "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9" + "url": "https://github.com/shalvah/clara.git", + "reference": "cdbb5737cbdd101756d97dd2279a979a1af7710b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/1a9a145b044677ae3424693f7b06479fc8c137a9", - "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9", + "url": "https://api.github.com/repos/shalvah/clara/zipball/cdbb5737cbdd101756d97dd2279a979a1af7710b", + "reference": "cdbb5737cbdd101756d97dd2279a979a1af7710b", + "shasum": "" + }, + "require": { + "php": ">=7.4", + "symfony/console": "^4.0|^5.0|^6.0|^7.0" + }, + "require-dev": { + "eloquent/phony-phpunit": "^7.0", + "phpunit/phpunit": "^9.1" + }, + "type": "library", + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Shalvah\\Clara\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "🔊 Simple, pretty, testable console output for CLI apps.", + "keywords": [ + "cli", + "log", + "logging" + ], + "support": { + "issues": "https://github.com/shalvah/clara/issues", + "source": "https://github.com/shalvah/clara/tree/3.2.0" + }, + "time": "2024-02-27T20:30:59+00:00" + }, + { + "name": "shalvah/upgrader", + "version": "0.6.0", + "source": { + "type": "git", + "url": "https://github.com/shalvah/upgrader.git", + "reference": "d95ed17fe9f5e1ee7d47ad835595f1af080a867f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shalvah/upgrader/zipball/d95ed17fe9f5e1ee7d47ad835595f1af080a867f", + "reference": "d95ed17fe9f5e1ee7d47ad835595f1af080a867f", + "shasum": "" + }, + "require": { + "illuminate/support": ">=8.0", + "nikic/php-parser": "^5.0", + "php": ">=8.0" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.2.0", + "pestphp/pest": "^1.21", + "phpstan/phpstan": "^1.0", + "spatie/ray": "^1.33" + }, + "type": "library", + "autoload": { + "psr-4": { + "Shalvah\\Upgrader\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shalvah", + "email": "hello@shalvah.me" + } + ], + "description": "Create automatic upgrades for your package.", + "homepage": "http://github.com/shalvah/upgrader", + "keywords": [ + "upgrade" + ], + "support": { + "issues": "https://github.com/shalvah/upgrader/issues", + "source": "https://github.com/shalvah/upgrader/tree/0.6.0" + }, + "funding": [ + { + "url": "https://patreon.com/shalvah", + "type": "patreon" + } + ], + "time": "2024-02-20T11:51:46+00:00" + }, + { + "name": "spatie/backtrace", + "version": "1.6.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/backtrace.git", + "reference": "7c18db2bc667ac84e5d7c18e33f16c38ff2d8838" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/7c18db2bc667ac84e5d7c18e33f16c38ff2d8838", + "reference": "7c18db2bc667ac84e5d7c18e33f16c38ff2d8838", "shasum": "" }, "require": { @@ -12621,7 +13361,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.6.2" + "source": "https://github.com/spatie/backtrace/tree/1.6.3" }, "funding": [ { @@ -12633,7 +13373,71 @@ "type": "other" } ], - "time": "2024-07-22T08:21:24+00:00" + "time": "2024-11-18T14:58:58+00:00" + }, + { + "name": "spatie/data-transfer-object", + "version": "3.9.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/data-transfer-object.git", + "reference": "1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/data-transfer-object/zipball/1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8", + "reference": "1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "illuminate/collections": "^8.36", + "jetbrains/phpstorm-attributes": "^1.0", + "larapack/dd": "^1.1", + "phpunit/phpunit": "^9.5.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\DataTransferObject\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brent Roose", + "email": "brent@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Data transfer objects with batteries included", + "homepage": "https://github.com/spatie/data-transfer-object", + "keywords": [ + "data-transfer-object", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/data-transfer-object/issues", + "source": "https://github.com/spatie/data-transfer-object/tree/3.9.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "abandoned": "spatie/laravel-data", + "time": "2022-09-16T13:34:38+00:00" }, { "name": "spatie/error-solutions", @@ -12953,17 +13757,93 @@ "time": "2024-06-12T15:01:18+00:00" }, { - "name": "symfony/yaml", - "version": "v7.1.4", + "name": "symfony/var-exporter", + "version": "v7.1.6", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "92e080b851c1c655c786a2da77f188f2dccd0f4b" + "url": "https://github.com/symfony/var-exporter.git", + "reference": "90173ef89c40e7c8c616653241048705f84130ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/92e080b851c1c655c786a2da77f188f2dccd0f4b", - "reference": "92e080b851c1c655c786a2da77f188f2dccd0f4b", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/90173ef89c40e7c8c616653241048705f84130ef", + "reference": "90173ef89c40e7c8c616653241048705f84130ef", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "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": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", + "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", "shasum": "" }, "require": { @@ -13005,7 +13885,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.1.4" + "source": "https://github.com/symfony/yaml/tree/v7.1.6" }, "funding": [ { @@ -13021,7 +13901,7 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:59:40+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", diff --git a/config/app.php b/config/app.php index f467267..b253ab2 100644 --- a/config/app.php +++ b/config/app.php @@ -1,5 +1,7 @@ env('APP_MAINTENANCE_STORE', 'database'), ], + /* + |-------------------------------------------------------------------------- + | 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([ + 'Carbon' => \Carbon\Carbon::class, + ])->toArray(), + ]; diff --git a/config/livewire.php b/config/livewire.php index c8bd1cd..c7b1649 100644 --- a/config/livewire.php +++ b/config/livewire.php @@ -114,7 +114,7 @@ return [ | */ - 'inject_assets' => true, + 'inject_assets' => false, /* |--------------------------------------------------------------------------- diff --git a/config/scribe.php b/config/scribe.php new file mode 100644 index 0000000..98547d3 --- /dev/null +++ b/config/scribe.php @@ -0,0 +1,269 @@ + for the generated documentation. If this is empty, Scribe will infer it from config('app.name'). + 'title' => 'The Forge API Documentation', + + // A short description of your API. Will be included in the docs webpage, Postman collection and OpenAPI spec. + 'description' => '', + + // The base URL displayed in the docs. If this is empty, Scribe will use the value of config('app.url') at generation time. + // If you're using `laravel` type, you can set this to a dynamic string, like '{{ config("app.tenant_url") }}' to get a dynamic base URL. + 'base_url' => null, + + 'routes' => [ + [ + // Routes that match these conditions will be included in the docs + 'match' => [ + // Match only routes whose paths match this pattern (use * as a wildcard to match any characters). Example: 'users/*'. + 'prefixes' => ['api/*'], + + // Match only routes whose domains match this pattern (use * as a wildcard to match any characters). Example: 'api.*'. + 'domains' => ['*'], + + // [Dingo router only] Match only routes registered under this version. Wildcards are NOT supported. + 'versions' => ['v0'], + ], + + // Include these routes even if they did not match the rules above. + 'include' => [ + // 'users.index', 'POST /new', '/auth/*' + ], + + // Exclude these routes even if they matched the rules above. + 'exclude' => [ + // 'GET /health', 'admin.*' + ], + ], + ], + + // The type of documentation output to generate. + // - "static" will generate a static HTMl page in the /public/docs folder, + // - "laravel" will generate the documentation as a Blade view, so you can add routing and authentication. + // - "external_static" and "external_laravel" do the same as above, but generate a basic template, + // passing the OpenAPI spec as a URL, allowing you to easily use the docs with an external generator + 'type' => 'static', + + // See https://scribe.knuckles.wtf/laravel/reference/config#theme for supported options + 'theme' => 'default', + + 'static' => [ + // HTML documentation, assets and Postman collection will be generated to this folder. + // Source Markdown will still be in resources/docs. + 'output_path' => 'public/docs', + ], + + 'laravel' => [ + // Whether to automatically create a docs endpoint for you to view your generated docs. + // If this is false, you can still set up routing manually. + 'add_routes' => true, + + // URL path to use for the docs endpoint (if `add_routes` is true). + // By default, `/docs` opens the HTML page, `/docs.postman` opens the Postman collection, and `/docs.openapi` the OpenAPI spec. + 'docs_url' => '/docs', + + // Directory within `public` in which to store CSS and JS assets. + // By default, assets are stored in `public/vendor/scribe`. + // If set, assets will be stored in `public/{{assets_directory}}` + 'assets_directory' => null, + + // Middleware to attach to the docs endpoint (if `add_routes` is true). + 'middleware' => [], + ], + + 'external' => [ + 'html_attributes' => [], + ], + + 'try_it_out' => [ + // Add a Try It Out button to your endpoints so consumers can test endpoints right from their browser. + // Don't forget to enable CORS headers for your endpoints. + 'enabled' => true, + + // The base URL for the API tester to use (for example, you can set this to your staging URL). + // Leave as null to use the current app URL when generating (config("app.url")). + 'base_url' => null, + + // [Laravel Sanctum] Fetch a CSRF token before each request, and add it as an X-XSRF-TOKEN header. + 'use_csrf' => false, + + // The URL to fetch the CSRF token from (if `use_csrf` is true). + 'csrf_url' => '/sanctum/csrf-cookie', + ], + + // How is your API authenticated? This information will be used in the displayed docs, generated examples and response calls. + 'auth' => [ + // Set this to true if ANY endpoints in your API use authentication. + 'enabled' => true, + + // Set this to true if your API should be authenticated by default. If so, you must also set `enabled` (above) to true. + // You can then use @unauthenticated or @authenticated on individual endpoints to change their status from the default. + 'default' => true, + + // Where is the auth value meant to be sent in a request? + // Options: query, body, basic, bearer, header (for custom header) + 'in' => 'bearer', + + // The name of the auth parameter (eg token, key, apiKey) or header (eg Authorization, Api-Key). + 'name' => 'Authorization', + + // The value of the parameter to be used by Scribe to authenticate response calls. + // This will NOT be included in the generated documentation. If empty, Scribe will use a random value. + 'use_value' => env('SCRIBE_AUTH_KEY'), + + // Placeholder your users will see for the auth parameter in the example requests. + // Set this to null if you want Scribe to use a random value as placeholder instead. + 'placeholder' => 'YOUR_API_KEY', + + // Any extra authentication-related info for your users. Markdown and HTML are supported. + 'extra_info' => 'You can generate your own API token by logging into The Forge, clicking your profile picture, and clicking API Tokens.', + ], + + // Text to place in the "Introduction" section, right after the `description`. Markdown and HTML are supported. + 'intro_text' => <<<'INTRO' +This documentation aims to provide all the information you need to work with our API. + + +INTRO + , + + // Example requests for each endpoint will be shown in each of these languages. + // Supported options are: bash, javascript, php, python + // To add a language of your own, see https://scribe.knuckles.wtf/laravel/advanced/example-requests + 'example_languages' => [ + 'javascript', + 'php', + 'python', + ], + + // Generate a Postman collection (v2.1.0) in addition to HTML docs. + // For 'static' docs, the collection will be generated to public/docs/collection.json. + // For 'laravel' docs, it will be generated to storage/app/scribe/collection.json. + // Setting `laravel.add_routes` to true (above) will also add a route for the collection. + 'postman' => [ + 'enabled' => true, + 'overrides' => [ + // 'info.version' => '2.0.0', + ], + ], + + // Generate an OpenAPI spec (v3.0.1) in addition to docs webpage. + // For 'static' docs, the collection will be generated to public/docs/openapi.yaml. + // For 'laravel' docs, it will be generated to storage/app/scribe/openapi.yaml. + // Setting `laravel.add_routes` to true (above) will also add a route for the spec. + 'openapi' => [ + 'enabled' => true, + 'overrides' => [ + // 'info.version' => '2.0.0', + ], + ], + + 'groups' => [ + // Endpoints which don't have a @group will be placed in this default group. + 'default' => 'Endpoints', + + // By default, Scribe will sort groups alphabetically, and endpoints in the order their routes are defined. + // You can override this by listing the groups, subgroups and endpoints here in the order you want them. + // See https://scribe.knuckles.wtf/blog/laravel-v4#easier-sorting and https://scribe.knuckles.wtf/laravel/reference/config#order for details + 'order' => [], + ], + + // Custom logo path. This will be used as the value of the src attribute for the tag, + // so make sure it points to an accessible URL or path. Set to false to not use a logo. + // For example, if your logo is in public/img: + // - 'logo' => '../img/logo.png' // for `static` type (output folder is public/docs) + // - 'logo' => 'img/logo.png' // for `laravel` type + 'logo' => false, + + // Customize the "Last updated" value displayed in the docs by specifying tokens and formats. + // Examples: + // - {date:F j Y} => March 28, 2022 + // - {git:short} => Short hash of the last Git commit + // Available tokens are `{date:}` and `{git:}`. + // The format you pass to `date` will be passed to PHP's `date()` function. + // The format you pass to `git` can be either "short" or "long". + 'last_updated' => 'Last updated: {date:F j, Y}', + + 'examples' => [ + // Set this to any number (eg. 1234) to generate the same example values for parameters on each run, + 'faker_seed' => null, + + // With API resources and transformers, Scribe tries to generate example models to use in your API responses. + // By default, Scribe will try the model's factory, and if that fails, try fetching the first from the database. + // You can reorder or remove strategies here. + 'models_source' => ['factoryCreate', 'factoryMake', 'databaseFirst'], + ], + + // The strategies Scribe will use to extract information about your routes at each stage. + // If you create or install a custom strategy, add it here. + 'strategies' => [ + 'metadata' => [ + Strategies\Metadata\GetFromDocBlocks::class, + Strategies\Metadata\GetFromMetadataAttributes::class, + ], + 'urlParameters' => [ + Strategies\UrlParameters\GetFromLaravelAPI::class, + Strategies\UrlParameters\GetFromUrlParamAttribute::class, + Strategies\UrlParameters\GetFromUrlParamTag::class, + ], + 'queryParameters' => [ + Strategies\QueryParameters\GetFromFormRequest::class, + Strategies\QueryParameters\GetFromInlineValidator::class, + Strategies\QueryParameters\GetFromQueryParamAttribute::class, + Strategies\QueryParameters\GetFromQueryParamTag::class, + ], + 'headers' => [ + Strategies\Headers\GetFromHeaderAttribute::class, + Strategies\Headers\GetFromHeaderTag::class, + [ + 'override', + [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ], + ], + ], + 'bodyParameters' => [ + Strategies\BodyParameters\GetFromFormRequest::class, + Strategies\BodyParameters\GetFromInlineValidator::class, + Strategies\BodyParameters\GetFromBodyParamAttribute::class, + Strategies\BodyParameters\GetFromBodyParamTag::class, + ], + 'responses' => [ + Strategies\Responses\UseResponseAttributes::class, + Strategies\Responses\UseTransformerTags::class, + Strategies\Responses\UseApiResourceTags::class, + Strategies\Responses\UseResponseTag::class, + Strategies\Responses\UseResponseFileTag::class, + [ + Strategies\Responses\ResponseCalls::class, + [ + 'only' => ['GET *'], + // Disable debug mode when generating response calls to avoid error stack traces in responses + 'config' => [ + 'app.debug' => false, + ], + ], + ], + ], + 'responseFields' => [ + Strategies\ResponseFields\GetFromResponseFieldAttribute::class, + Strategies\ResponseFields\GetFromResponseFieldTag::class, + ], + ], + + // For response calls, API resource responses and transformer responses, + // Scribe will try to start database transactions, so no changes are persisted to your database. + // Tell Scribe which connections should be transacted here. If you only use one db connection, you can leave this as is. + 'database_connections_to_transact' => [config('database.default')], + + 'fractal' => [ + // If you are using a custom serializer with league/fractal, you can specify it here. + 'serializer' => null, + ], + + 'routeMatcher' => \Knuckles\Scribe\Matching\RouteMatcher::class, +]; diff --git a/config/services.php b/config/services.php index beca5d4..8fe5103 100644 --- a/config/services.php +++ b/config/services.php @@ -40,4 +40,12 @@ return [ 'token' => env('GITEA_TOKEN', ''), ], + 'discord' => [ + 'client_id' => env('DISCORD_CLIENT_ID'), + 'client_secret' => env('DISCORD_CLIENT_SECRET'), + 'redirect' => env('DISCORD_REDIRECT_URI'), + 'allow_gif_avatars' => (bool) env('DISCORD_AVATAR_GIF', true), + 'avatar_default_extension' => env('DISCORD_EXTENSION_DEFAULT', 'webp'), + ], + ]; diff --git a/database/factories/LicenseFactory.php b/database/factories/LicenseFactory.php index 0bb8660..42d7fbb 100644 --- a/database/factories/LicenseFactory.php +++ b/database/factories/LicenseFactory.php @@ -6,6 +6,9 @@ use App\Models\License; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Carbon; +/** + * @extends Factory + */ class LicenseFactory extends Factory { protected $model = License::class; diff --git a/database/factories/ModDependencyFactory.php b/database/factories/ModDependencyFactory.php index b3318ac..22a0508 100644 --- a/database/factories/ModDependencyFactory.php +++ b/database/factories/ModDependencyFactory.php @@ -8,6 +8,9 @@ use App\Models\ModVersion; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Carbon; +/** + * @extends Factory + */ class ModDependencyFactory extends Factory { protected $model = ModDependency::class; diff --git a/database/factories/ModFactory.php b/database/factories/ModFactory.php index a3167b4..c818a49 100644 --- a/database/factories/ModFactory.php +++ b/database/factories/ModFactory.php @@ -7,25 +7,23 @@ use App\Models\Mod; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Carbon; use Illuminate\Support\Str; -use Random\RandomException; +/** + * @extends Factory + */ class ModFactory extends Factory { protected $model = Mod::class; - /** - * @throws RandomException - */ public function definition(): array { - - $name = fake()->catchPhrase(); + $name = fake()->sentence(rand(3, 5)); return [ 'name' => $name, 'slug' => Str::slug($name), 'teaser' => fake()->sentence(), - 'description' => fake()->paragraphs(random_int(4, 20), true), + 'description' => fake()->paragraphs(rand(4, 20), true), 'license_id' => License::factory(), 'source_code_link' => fake()->url(), 'featured' => fake()->boolean(), diff --git a/database/factories/ModVersionFactory.php b/database/factories/ModVersionFactory.php index 716fd20..e3684a6 100644 --- a/database/factories/ModVersionFactory.php +++ b/database/factories/ModVersionFactory.php @@ -8,6 +8,9 @@ use App\Models\SptVersion; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Carbon; +/** + * @extends Factory + */ class ModVersionFactory extends Factory { protected $model = ModVersion::class; @@ -16,7 +19,7 @@ class ModVersionFactory extends Factory { return [ 'mod_id' => Mod::factory(), - 'version' => fake()->numerify('#.#.#'), + 'version' => $this->faker->numerify('#.#.#'), 'description' => fake()->text(), 'link' => fake()->url(), diff --git a/database/factories/OAuthConnectionFactory.php b/database/factories/OAuthConnectionFactory.php new file mode 100644 index 0000000..a391720 --- /dev/null +++ b/database/factories/OAuthConnectionFactory.php @@ -0,0 +1,29 @@ + User::factory(), + 'provider_name' => $this->faker->randomElement(['discord', 'google', 'facebook']), + 'provider_id' => (string) $this->faker->unique()->numberBetween(100000, 999999), + 'token' => Str::random(40), + 'refresh_token' => Str::random(40), + 'created_at' => now(), + 'updated_at' => now(), + ]; + } +} diff --git a/database/factories/SptVersionFactory.php b/database/factories/SptVersionFactory.php index 5adf33a..707ed46 100644 --- a/database/factories/SptVersionFactory.php +++ b/database/factories/SptVersionFactory.php @@ -6,6 +6,9 @@ use App\Models\SptVersion; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Carbon; +/** + * @extends Factory + */ class SptVersionFactory extends Factory { protected $model = SptVersion::class; diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 75f3298..5830a4b 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -2,10 +2,15 @@ namespace Database\Factories; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; +use Random\RandomException; +/** + * @extends Factory + */ class UserFactory extends Factory { /** @@ -13,8 +18,12 @@ class UserFactory extends Factory */ protected static ?string $password; + protected $model = User::class; + /** * Define the user's default state. + * + * @throws RandomException */ public function definition(): array { @@ -23,6 +32,10 @@ class UserFactory extends Factory 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => static::$password ??= Hash::make('password'), + + // TODO: Does Faker have a markdown plugin? + 'about' => fake()->paragraphs(random_int(1, 10), true), + 'two_factor_secret' => null, 'two_factor_recovery_codes' => null, 'remember_token' => Str::random(10), diff --git a/database/factories/UserRoleFactory.php b/database/factories/UserRoleFactory.php index 0e7d165..20b0a2b 100644 --- a/database/factories/UserRoleFactory.php +++ b/database/factories/UserRoleFactory.php @@ -6,6 +6,9 @@ use App\Models\UserRole; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Carbon; +/** + * @extends Factory + */ class UserRoleFactory extends Factory { protected $model = UserRole::class; diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 5d26cb2..5238821 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -14,14 +14,13 @@ return new class extends Migration { Schema::create('users', function (Blueprint $table) { $table->id(); - $table->bigInteger('hub_id') - ->nullable() - ->default(null) - ->unique(); + $table->bigInteger('hub_id')->nullable()->default(null)->unique(); + $table->unsignedBigInteger('discord_id')->nullable()->default(null)->unique(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); + $table->string('password')->nullable(); + $table->longText('about')->nullable()->default(null); $table->foreignIdFor(UserRole::class) ->nullable() ->default(null) diff --git a/database/migrations/2024_05_14_040126_create_pulse_tables.php b/database/migrations/2024_05_14_040126_create_pulse_tables.php index 5d194e2..3335394 100644 --- a/database/migrations/2024_05_14_040126_create_pulse_tables.php +++ b/database/migrations/2024_05_14_040126_create_pulse_tables.php @@ -23,7 +23,7 @@ return new class extends PulseMigration match ($this->driver()) { 'mariadb', 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'), 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'), - 'sqlite' => $table->string('key_hash'), + default => $table->string('key_hash'), }; $table->mediumText('value'); @@ -40,7 +40,7 @@ return new class extends PulseMigration match ($this->driver()) { 'mariadb', 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'), 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'), - 'sqlite' => $table->string('key_hash'), + default => $table->string('key_hash'), }; $table->bigInteger('value')->nullable(); @@ -59,7 +59,7 @@ return new class extends PulseMigration match ($this->driver()) { 'mariadb', 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'), 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'), - 'sqlite' => $table->string('key_hash'), + default => $table->string('key_hash'), }; $table->string('aggregate'); $table->decimal('value', 20, 2); diff --git a/database/migrations/2024_05_15_023430_create_spt_versions_table.php b/database/migrations/2024_05_15_023430_create_spt_versions_table.php index 1c6a0a0..15c9cf8 100644 --- a/database/migrations/2024_05_15_023430_create_spt_versions_table.php +++ b/database/migrations/2024_05_15_023430_create_spt_versions_table.php @@ -15,18 +15,17 @@ return new class extends Migration ->default(null) ->unique(); $table->string('version'); - $table->unsignedInteger('version_major'); - $table->unsignedInteger('version_minor'); - $table->unsignedInteger('version_patch'); - $table->string('version_pre_release'); + $table->unsignedInteger('version_major')->default(0); + $table->unsignedInteger('version_minor')->default(0); + $table->unsignedInteger('version_patch')->default(0); + $table->string('version_pre_release')->default(''); $table->unsignedInteger('mod_count')->default(0); $table->string('link'); $table->string('color_class'); $table->softDeletes(); $table->timestamps(); - $table->index(['version', 'deleted_at', 'id'], 'spt_versions_filtering_index'); - $table->index(['version_major', 'version_minor', 'version_patch', 'version_pre_release', 'deleted_at'], 'spt_versions_lookup_index'); + $table->index(['version', 'version_major', 'version_minor', 'version_patch', 'version_pre_release'], 'spt_versions_lookup_index'); }); } diff --git a/database/migrations/2024_05_15_023705_create_mod_versions_table.php b/database/migrations/2024_05_15_023705_create_mod_versions_table.php index 0301ead..565716c 100644 --- a/database/migrations/2024_05_15_023705_create_mod_versions_table.php +++ b/database/migrations/2024_05_15_023705_create_mod_versions_table.php @@ -20,6 +20,10 @@ return new class extends Migration ->cascadeOnDelete() ->cascadeOnUpdate(); $table->string('version'); + $table->unsignedInteger('version_major')->default(0); + $table->unsignedInteger('version_minor')->default(0); + $table->unsignedInteger('version_patch')->default(0); + $table->string('version_pre_release')->default(''); $table->longText('description'); $table->string('link'); $table->string('spt_version_constraint'); @@ -32,6 +36,7 @@ return new class extends Migration $table->index(['version']); $table->index(['mod_id', 'deleted_at', 'disabled', 'published_at'], 'mod_versions_filtering_index'); + $table->index(['version_major', 'version_minor', 'version_patch', 'version_pre_release'], 'mod_versions_version_components_index'); $table->index(['id', 'deleted_at'], 'mod_versions_id_deleted_at_index'); }); } diff --git a/database/migrations/2024_05_15_023710_create_mod_version_spt_version_table.php b/database/migrations/2024_05_15_023710_create_mod_version_spt_version_table.php index 2848d91..1084253 100644 --- a/database/migrations/2024_05_15_023710_create_mod_version_spt_version_table.php +++ b/database/migrations/2024_05_15_023710_create_mod_version_spt_version_table.php @@ -12,7 +12,6 @@ return new class extends Migration $table->id(); $table->foreignId('mod_version_id')->constrained('mod_versions')->cascadeOnDelete()->cascadeOnUpdate(); $table->foreignId('spt_version_id')->constrained('spt_versions')->cascadeOnDelete()->cascadeOnUpdate(); - $table->timestamps(); $table->index(['mod_version_id', 'spt_version_id'], 'mod_version_spt_version_index'); $table->index(['spt_version_id', 'mod_version_id'], 'spt_version_mod_version_index'); diff --git a/database/migrations/2024_08_28_141058_create_user_follows_table.php b/database/migrations/2024_08_28_141058_create_user_follows_table.php new file mode 100644 index 0000000..c8e07db --- /dev/null +++ b/database/migrations/2024_08_28_141058_create_user_follows_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('follower_id')->references('id')->on('users')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('following_id')->references('id')->on('users')->cascadeOnDelete()->cascadeOnUpdate(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_follows'); + } +}; diff --git a/database/migrations/2024_09_26_164844_create_oauth_providers_table.php b/database/migrations/2024_09_26_164844_create_oauth_providers_table.php new file mode 100644 index 0000000..66a1e32 --- /dev/null +++ b/database/migrations/2024_09_26_164844_create_oauth_providers_table.php @@ -0,0 +1,42 @@ +id(); + $table->foreignIdFor(User::class) + ->constrained('users') + ->cascadeOnDelete() + ->cascadeOnUpdate(); + $table->string('provider'); + $table->string('provider_id'); + $table->string('token')->default(''); + $table->string('refresh_token')->default(''); + $table->string('nickname')->default(''); + $table->string('name')->default(''); + $table->string('email')->default(''); + $table->string('avatar')->default(''); + $table->timestamps(); + + $table->unique(['provider', 'provider_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('oauth_providers'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 1cfedfb..d8358f7 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -6,10 +6,13 @@ use App\Models\License; use App\Models\Mod; use App\Models\ModDependency; use App\Models\ModVersion; -use App\Models\SptVersion; use App\Models\User; use App\Models\UserRole; use Illuminate\Database\Seeder; +use Illuminate\Support\Facades\Artisan; +use Laravel\Prompts\Progress; + +use function Laravel\Prompts\progress; class DatabaseSeeder extends Seeder { @@ -18,46 +21,114 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // Create a few SPT versions. - $spt_versions = SptVersion::factory(30)->create(); + // How many of each entity to create. + $counts = [ + 'license' => 10, + 'administrator' => 5, + 'moderator' => 5, + 'user' => 100, + 'mod' => 200, + 'modVersion' => 1500, + ]; - // Create some code licenses. - $licenses = License::factory(10)->create(); + // Licenses + $licenses = License::factory($counts['license'])->create(); - // Add 5 administrators. - $administrator = UserRole::factory()->administrator()->create(); - User::factory()->for($administrator, 'role')->create([ + // Administrator Users + $administratorRole = UserRole::factory()->administrator()->create(); + $testAccount = User::factory()->for($administratorRole, 'role')->create([ 'email' => 'test@example.com', ]); - User::factory(4)->for($administrator, 'role')->create(); + User::factory($counts['administrator'] - 1)->for($administratorRole, 'role')->create(); - // Add 10 moderators. - $moderator = UserRole::factory()->moderator()->create(); - User::factory(5)->for($moderator, 'role')->create(); + $this->command->outputComponents()->info("Test account created: {$testAccount->email}"); - // Add 100 users. - $users = User::factory(100)->create(); + // Moderator Users + $moderatorRole = UserRole::factory()->moderator()->create(); + User::factory($counts['moderator'])->for($moderatorRole, 'role')->create(); - // Add 300 mods, assigning them to the users we just created. - $allUsers = $users->merge([$administrator, $moderator]); - $mods = Mod::factory(300)->recycle([$licenses])->create(); - foreach ($mods as $mod) { - $userIds = $allUsers->random(rand(1, 3))->pluck('id')->toArray(); - $mod->users()->attach($userIds); - } + // Users + progress( + label: 'Adding Users...', + steps: $counts['user'], + callback: fn () => User::factory()->create() + ); - // Add 3000 mod versions, assigning them to the mods we just created. - $modVersions = ModVersion::factory(3000)->recycle([$mods, $spt_versions])->create(); + // All Users + $allUsers = User::all(); - // Add ModDependencies to a subset of ModVersions. - foreach ($modVersions as $modVersion) { - $hasDependencies = rand(0, 100) < 30; // 30% chance to have dependencies - if ($hasDependencies) { - $dependencyMods = $mods->random(rand(1, 3)); // 1 to 3 dependencies + // User Follows + progress( + label: 'adding user follows ...', + steps: $allUsers, + callback: function ($user) use ($allUsers) { + $hasFollowers = rand(0, 100) < 70; // 70% chance to have followers + $isFollowing = rand(0, 100) < 70; // 70% chance to be following other users + + if ($hasFollowers) { + $followers = $allUsers->random(rand(1, 10))->pluck('id')->toArray(); + $user->followers()->attach($followers); + } + + if ($isFollowing) { + $following = $allUsers->random(rand(1, 10))->pluck('id')->toArray(); + $user->following()->attach($following); + } + }); + + // Mods + $mods = collect(progress( + label: 'Adding Mods...', + steps: $counts['mod'], + callback: fn () => Mod::factory()->recycle([$licenses])->create() + )); + + // Attach users to mods + progress( + label: 'Attaching users to mods...', + steps: $mods, + callback: function (Mod $mod, Progress $progress) use ($allUsers) { + $userIds = $allUsers->random(rand(1, 3))->pluck('id')->toArray(); + $mod->users()->attach($userIds); + } + ); + + // Add mod versions, assigning them to the mods we just created. + $modVersions = collect(progress( + label: 'Adding Mod Versions...', + steps: $counts['modVersion'], + callback: fn () => ModVersion::factory()->recycle([$mods])->create() + )); + + // Add mod dependencies to *some* mod versions. + progress( + label: 'Adding Mod Dependencies...', + steps: $modVersions, + callback: function (ModVersion $modVersion, Progress $progress) use ($mods) { + // 70% chance to not have dependencies + if (rand(0, 9) >= 3) { + return; + } + + // Choose 1-3 random mods to be dependencies. + $dependencyMods = $mods->random(rand(1, 3)); foreach ($dependencyMods as $dependencyMod) { ModDependency::factory()->recycle([$modVersion, $dependencyMod])->create(); } } - } + ); + + $this->command->outputComponents()->success('Initial seeding complete'); + + Artisan::call('app:search-sync'); + Artisan::call('app:resolve-versions'); + Artisan::call('app:count-mods'); + Artisan::call('app:update-downloads'); + $this->command->outputComponents()->warn('Jobs added to queue. Ensure Horizon is running!'); + + Artisan::call('cache:clear'); + $this->command->outputComponents()->info('Cache cleared'); + + $this->command->outputComponents()->success('Database seeding complete'); } } diff --git a/package-lock.json b/package-lock.json index f9cb11c..98e8603 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,24 @@ { - "name": "html", + "name": "forge", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { - "@alpinejs/focus": "^3.14.1" + "@alpinejs/focus": "^3.14.3" }, "devDependencies": { "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "^0.5.10", "autoprefixer": "^10.4.16", "axios": "^1.6.4", - "chokidar": "^3.6.0", + "chokidar": "^4.0.1", "laravel-vite-plugin": "^1.0", - "postcss": "^8.4.32", + "postcss": "^8.4.49", "prettier": "^3.2.5", - "prettier-plugin-tailwindcss": "^0.6.5", - "tailwindcss": "^3.4.0", - "vite": "^5.0" + "prettier-plugin-tailwindcss": "^0.6.9", + "tailwindcss": "^3.4.15", + "vite": "^5.4" } }, "node_modules/@alloc/quick-lru": { @@ -35,9 +35,9 @@ } }, "node_modules/@alpinejs/focus": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.14.1.tgz", - "integrity": "sha512-z4xdpK6X1LB2VitsWbL61tmABoOORuEhE5v2tnUX/be6/nAygXyeDxZ1x9s1u+bOEYlIOXXLmjdmTlhchUVWxw==", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.14.3.tgz", + "integrity": "sha512-ZBL6HziMXhQIuta3PQjpYaMb5Ro9VPqh0mkP+d1uefJnhliBMWUfQXOnobV/0zJUB9pDxzd78diDX3ywewoJ3g==", "license": "MIT", "dependencies": { "focus-trap": "^6.9.4", @@ -556,9 +556,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz", - "integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", + "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", "cpu": [ "arm" ], @@ -570,9 +570,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz", - "integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", + "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", "cpu": [ "arm64" ], @@ -584,9 +584,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz", - "integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", + "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", "cpu": [ "arm64" ], @@ -598,9 +598,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz", - "integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", "cpu": [ "x64" ], @@ -611,10 +611,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", + "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", + "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz", - "integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", + "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", "cpu": [ "arm" ], @@ -626,9 +654,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz", - "integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", + "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", "cpu": [ "arm" ], @@ -640,9 +668,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz", - "integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", + "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", "cpu": [ "arm64" ], @@ -654,9 +682,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz", - "integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", + "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", "cpu": [ "arm64" ], @@ -668,9 +696,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz", - "integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", + "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", "cpu": [ "ppc64" ], @@ -682,9 +710,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz", - "integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", + "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", "cpu": [ "riscv64" ], @@ -696,9 +724,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz", - "integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", + "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", "cpu": [ "s390x" ], @@ -710,9 +738,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz", - "integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", + "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", "cpu": [ "x64" ], @@ -724,9 +752,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz", - "integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", + "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", "cpu": [ "x64" ], @@ -738,9 +766,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz", - "integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", + "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", "cpu": [ "arm64" ], @@ -752,9 +780,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz", - "integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", + "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", "cpu": [ "ia32" ], @@ -766,9 +794,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz", - "integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", + "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", "cpu": [ "x64" ], @@ -780,9 +808,9 @@ ] }, "node_modules/@tailwindcss/forms": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.8.tgz", - "integrity": "sha512-DJs7B7NPD0JH7BVvdHWNviWmunlFhuEkz7FyFxE4japOWYMLl9b1D6+Z9mivJJPWr6AEbmlPqgiFRyLwFB1SgQ==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", + "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==", "dev": true, "license": "MIT", "dependencies": { @@ -809,16 +837,16 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -915,9 +943,9 @@ } }, "node_modules/axios": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.6.tgz", - "integrity": "sha512-Ekur6XDwhnJ5RgOCaxFnXyqlPALI3rVeukZMwOdfghW7/wGz784BYKiQq+QD8NPcr91KRo30KfHOchyijwWw7g==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -970,9 +998,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -990,10 +1018,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1013,9 +1041,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001655", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", - "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", + "version": "1.0.30001684", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", + "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==", "dev": true, "funding": [ { @@ -1034,28 +1062,19 @@ "license": "CC-BY-4.0" }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" } }, "node_modules/color-convert": { @@ -1102,9 +1121,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -1161,9 +1180,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", + "version": "1.5.65", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", + "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==", "dev": true, "license": "ISC" }, @@ -1240,6 +1259,19 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -1273,9 +1305,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -1311,9 +1343,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "license": "MIT", "dependencies": { @@ -1386,16 +1418,16 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/hasown": { @@ -1517,9 +1549,9 @@ } }, "node_modules/laravel-vite-plugin": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.5.tgz", - "integrity": "sha512-Zv+to82YLBknDCZ6g3iwOv9wZ7f6EWStb9pjSm7MGe9Mfoy5ynT2ssZbGsMr1udU6rDg9HOoYEVGw5Qf+p9zbw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.6.tgz", + "integrity": "sha512-B34OqmZc/rV1KvSjst8SsUm/LKHsuDusw8jiZCIhlnTHXbXnK89JUM9pTJuk6E/Vc/1DT2gX7qNfhipak1WS8w==", "dev": true, "license": "MIT", "dependencies": { @@ -1743,9 +1775,9 @@ } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, @@ -1784,9 +1816,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -1824,9 +1856,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -1845,8 +1877,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -2017,9 +2049,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.6.tgz", - "integrity": "sha512-OPva5S7WAsPLEsOuOWXATi13QrCKACCiIonFgIR6V4lYv4QLp++UXVhZSzRbZxXGimkQtQT86CC6fQqTOybGng==", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.9.tgz", + "integrity": "sha512-r0i3uhaZAXYP0At5xGfJH876W3HHGHDp+LCRUJrs57PBeQ6mYHMwr25KH8NPX44F2yGTvdnH7OqCshlQx183Eg==", "dev": true, "license": "MIT", "engines": { @@ -2134,16 +2166,17 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/resolve": { @@ -2176,13 +2209,13 @@ } }, "node_modules/rollup": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", - "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", + "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -2192,22 +2225,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.2", - "@rollup/rollup-android-arm64": "4.21.2", - "@rollup/rollup-darwin-arm64": "4.21.2", - "@rollup/rollup-darwin-x64": "4.21.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", - "@rollup/rollup-linux-arm-musleabihf": "4.21.2", - "@rollup/rollup-linux-arm64-gnu": "4.21.2", - "@rollup/rollup-linux-arm64-musl": "4.21.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", - "@rollup/rollup-linux-riscv64-gnu": "4.21.2", - "@rollup/rollup-linux-s390x-gnu": "4.21.2", - "@rollup/rollup-linux-x64-gnu": "4.21.2", - "@rollup/rollup-linux-x64-musl": "4.21.2", - "@rollup/rollup-win32-arm64-msvc": "4.21.2", - "@rollup/rollup-win32-ia32-msvc": "4.21.2", - "@rollup/rollup-win32-x64-msvc": "4.21.2", + "@rollup/rollup-android-arm-eabi": "4.27.4", + "@rollup/rollup-android-arm64": "4.27.4", + "@rollup/rollup-darwin-arm64": "4.27.4", + "@rollup/rollup-darwin-x64": "4.27.4", + "@rollup/rollup-freebsd-arm64": "4.27.4", + "@rollup/rollup-freebsd-x64": "4.27.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", + "@rollup/rollup-linux-arm-musleabihf": "4.27.4", + "@rollup/rollup-linux-arm64-gnu": "4.27.4", + "@rollup/rollup-linux-arm64-musl": "4.27.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", + "@rollup/rollup-linux-riscv64-gnu": "4.27.4", + "@rollup/rollup-linux-s390x-gnu": "4.27.4", + "@rollup/rollup-linux-x64-gnu": "4.27.4", + "@rollup/rollup-linux-x64-musl": "4.27.4", + "@rollup/rollup-win32-arm64-msvc": "4.27.4", + "@rollup/rollup-win32-ia32-msvc": "4.27.4", + "@rollup/rollup-win32-x64-msvc": "4.27.4", "fsevents": "~2.3.2" } }, @@ -2272,9 +2307,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -2428,34 +2463,34 @@ "license": "MIT" }, "node_modules/tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", + "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.0", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.0", + "jiti": "^1.21.6", "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -2465,17 +2500,42 @@ "node": ">=14.0.0" } }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 6" } }, "node_modules/tailwindcss/node_modules/postcss-selector-parser": { @@ -2492,6 +2552,19 @@ "node": ">=4" } }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -2536,9 +2609,9 @@ "license": "Apache-2.0" }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -2556,8 +2629,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -2574,14 +2647,14 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", - "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.41", + "postcss": "^8.4.43", "rollup": "^4.20.0" }, "bin": { @@ -2759,9 +2832,9 @@ } }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 5b5e9fa..4ba1884 100644 --- a/package.json +++ b/package.json @@ -10,15 +10,15 @@ "@tailwindcss/typography": "^0.5.10", "autoprefixer": "^10.4.16", "axios": "^1.6.4", - "chokidar": "^3.6.0", + "chokidar": "^4.0.1", "laravel-vite-plugin": "^1.0", - "postcss": "^8.4.32", + "postcss": "^8.4.49", "prettier": "^3.2.5", - "prettier-plugin-tailwindcss": "^0.6.5", - "tailwindcss": "^3.4.0", - "vite": "^5.0" + "prettier-plugin-tailwindcss": "^0.6.9", + "tailwindcss": "^3.4.15", + "vite": "^5.4" }, "dependencies": { - "@alpinejs/focus": "^3.14.1" + "@alpinejs/focus": "^3.14.3" } } diff --git a/phpstan.neon b/phpstan.neon index 9cc52bf..57de978 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,7 +1,7 @@ includes: - ./vendor/larastan/larastan/extension.neon parameters: - level: 6 + level: 5 paths: - app - bootstrap diff --git a/public/docs/collection.json b/public/docs/collection.json new file mode 100644 index 0000000..45faaeb --- /dev/null +++ b/public/docs/collection.json @@ -0,0 +1,486 @@ +{ + "variable": [ + { + "id": "baseUrl", + "key": "baseUrl", + "type": "string", + "name": "string", + "value": "http:\/\/forge.test" + } + ], + "info": { + "name": "The Forge API Documentation", + "_postman_id": "111f14f0-1551-4ff3-a8c0-1301df26b9c2", + "description": "", + "schema": "https:\/\/schema.getpostman.com\/json\/collection\/v2.1.0\/collection.json" + }, + "item": [ + { + "name": "Authentication", + "description": "", + "item": [ + { + "name": "Login", + "request": { + "url": { + "host": "{{baseUrl}}", + "path": "api\/login", + "query": [], + "raw": "{{baseUrl}}\/api\/login" + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application\/json" + }, + { + "key": "Accept", + "value": "application\/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"email\":\"olson.margret@example.net\",\"password\":\"j\\\/.0^{~eOsyx^\",\"token_name\":\"Dynamic API Token\"}" + }, + "description": "Authenticates the user and returns a read-only API token. This API token can then be saved and used for future\nrequests that require authentication.