Skip to content

chore: upgrade to PHP 8.5 and Laravel 13#406

Open
herpaderpaldent wants to merge 88 commits into
3.xfrom
chore/php-8.5-laravel-13-upgrade
Open

chore: upgrade to PHP 8.5 and Laravel 13#406
herpaderpaldent wants to merge 88 commits into
3.xfrom
chore/php-8.5-laravel-13-upgrade

Conversation

@herpaderpaldent
Copy link
Copy Markdown
Contributor

Summary

Upgrade the auth package to PHP 8.5 and Laravel 13.

Changes

Runtime

  • php ^8.3 → ^8.5
  • laravel/framework ^11.0 → ^13.0

Dev dependencies

  • orchestra/testbench ^9.0 → ^11.0 (follows Laravel versioning)
  • pestphp/pest ^3.0 → ^4.0
  • pestphp/pest-plugin-laravel ^3.0 → ^4.1 (Laravel 13 support)
  • pestphp/pest-plugin-type-coverage 3.5.1 → ^4.0
  • phpstan/phpstan 1.12.24 → ^2.0
  • rector/rector ^1.2 → ^2.0
  • driftingly/rector-laravel ^1.2 → ^2.0
  • larastan/larastan ^2.9 → ^3.0

Other

  • Added VCS repos for seatplus/eveapi and seatplus/esi-client pointing to their Laravel 13 upgrade branches
  • Regenerated PHPStan baseline (same 12 pre-existing errors, now properly tracked)
  • Added typed PHP 8.3 class constants (const array) to satisfy pest-plugin-type-coverage v4 stricter checks

Test status

✅ 278 tests passed (620 assertions)
✅ Type coverage: 100%
✅ PHPStan: 0 errors
✅ Pint: clean

- Added RoleAffiliatedIdsServiceTest to test RoleAffiliatedIdsService functionality
- Implemented test cases for allowed, inverse, forbidden, allowed and inverse, allowed and forbidden, inverse and forbidden, allowed, inverse and forbidden scenarios
- Created dataset for entity types and helper functions to retrieve entity ids
- Updated RoleAffiliatedIdsService to load missing relationships and build affiliated ids array based on affiliations
- Added RolePermissionObjectService class to handle role permissions
- Created RolePermissionObjectServiceTest to test the functionality
- Mocked RoleAffiliatedIdsService for testing purposes
…validation remove old middleware and pipelines etc
Refactor the SSO routes and controllers to improve code structure and readability. Update the routes for SSO authentication and callback handling. Also, rename the MainCharacterController to SwitchMainCharacterController for better clarity. Add a new LogoutAction to handle user logout functionality. Update the StepUpController to return a RedirectResponse. Update corresponding test files for the changes made.
…nd methods

Added the AutomaticRoleServiceTest.php file to test the AutomaticRoleService class and its methods for assigning roles to corporations, alliances, and users. Also added the AutomaticRoleService.php file with methods for automatically assigning roles to corporations and alliances, syncing members, and handling users.
Refactor the `for` method in the `BaseRoleService` class to utilize the match expression for better readability and maintainability. Also, update the constructor in the `ManageAutomaticRoleAction` class to use the null coalescing operator for default parameter assignment. Additionally, update the exception expectation in the `BaseRoleServiceTest` to match the correct exception class. Add unit tests for the `ManageAutomaticRoleAction` class in the `ManageAutomaticRoleActionTest.php` file.
- Updated the scope building logic in the `BuildScopesArrayService.php` file to retrieve the corporation IDs and alliance IDs from the user's characters using the new structure.
- Updated the pluck method to access the corporation and alliance IDs directly from the relationships.
- Updated the tests in `CheckRequiredScopesTest.php` to only run the specific test case.
…s; add strict mode to Model in tests; update getAuthPassword method in User model
…cationable types

- Added a match statement to determine the user_id based on applicationable_type
- Removed the default case as it is unnecessary and can be handled by returning null directly
- Added cache invalidation for user permissions after determining user_id
- Added a new method `updateMemberStatusBasedOnUserCompliance` to `AbstractRoleService` to update member status based on user compliance
- Updated the `syncMembers` method in `AutomaticRoleService` to call `updateMemberStatusBasedOnUserCompliance` after adding assigned members
- Filter role memberships based on entity type being CorporationInfo or AllianceInfo
- Handle case where character_ids are empty, return early
- Refactor each method in AbstractRoleService to specify type for role_membership parameter
- Add id column to role_memberships table in migration file
- Create OnRequestRoleService class with methods for role applications and approvals
- Implement validation logic for entity types in OnRequestRoleService
- Add syncMembers method to remove unassigned members and update member status based on user compliance
- Reset criteria in OnRequestRoleService by deleting role memberships with specific entity types
- Remove primaryKey from RoleMembership model and update casts property
- Added ManualRoleService class with methods to set moderator, add member, remove member, and sync members
- Added corresponding tests for ManualRoleService functionality
- Added OptInRoleService class to handle opt-in roles
- Implemented addCriteriaForRole method to add criteria for role
- Implemented joinRole method to allow users to join the role
- Implemented leaveRole method to allow users to leave the role
- Implemented syncMembers method to sync members and update their status based on user compliance
- Added OptInRoleServiceTest to test the functionality of the OptInRoleService class
- Added methods for handling different role types such as automatic, on request, manual, and opt-in
- Updated the getTypeService method to use a match expression for selecting the appropriate service
- Added a new method handleMembers to call the appropriate type service for handling members
…liance

Implemented methods for automatically assigning roles to corporations and alliances in the AutomaticRoleService class. Removed unnecessary methods for clarity and improved code structure.
Refactor the getRoleMembers method in the AbstractRoleService class to improve code readability and maintainability. Remove unnecessary parameters and simplify the logic for retrieving role members based on assigned character IDs. Update the method to only fetch role members without considering moderators.
herpaderpaldent and others added 29 commits September 13, 2024 21:34
* Update UserFactory.php

* add use Illuminate\Support\Str;

* ```
Reorganize imports in UserFactory for consistency

Adjusted the order of import statements in UserFactory to align with coding standards and improve readability. This change has no functional impact but enhances code maintainability.
```
* Add RoleType enum casting and refactor type handling logic

This commit introduces a cast for the 'type' property in the Role model using the RoleType enum to enforce type safety. It also refactors the BaseRoleService to use the getType() method, improving clarity and reducing reliance on raw value matching. These changes ensure better maintainability and stricter type adherence.

* remove math arm, that never can be reached

* Update role type comparison and assignment logic

Simplify the role type comparison by directly using the roleType object instead of its value property. This change ensures consistency and reduces unnecessary property access. Adjust the update method accordingly to reflect this modification.

* Simplify `getType` method in BaseRoleService

Replaced the redundant variable assignment in the `getType` method with a direct return statement. This improves code readability and eliminates unnecessary lines without changing functionality.

* Fix moderation check in OptInRoleService

Replaced the hardcoded `false` with a call to `isModerator`. This ensures the method correctly evaluates whether a user has moderation privileges.

* Adjust Role model property docblock type hint

Updated the `Role` model's docblock type hint for `$type` to reflect its usage as `RoleType`. This ensures consistency and clarity in type definitions within the codebase.
Added configuration for custom permission and role models within the authentication service provider. This ensures the proper models are used for permission handling, improving extensibility and consistency.
The web package overrides redirectTo() to return an Inertia response,
which is not a subtype of RedirectResponse. Change to Symfony's base
Response type so overrides in downstream packages can return any HTTP
response type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ta, CriteriaData) (#403)

* fix: correct tuple format and ordering in Manage*RoleActions

- Convert affiliated arrays to [entity_id, entity_type, affiliation_type]
  tuples before passing to syncAffiliateManyEntities(), which validates
  via *.0 / *.1 / *.2 numeric keys
- Convert assigned arrays to [entity_id, entity_type] tuples for
  automaticallyAssignRoleTo() / addCriteriaForRoleApplication() /
  addCriteriaForRole()
- Move setRoleType() before criteria writes so type-change resets
  (resetRoleMemberships) don't wipe newly written criteria
- Add handleMembers() call after all writes to sync memberships
- Remove affiliated handling from ManageManualRoleAction (manual roles
  have no affiliation criteria by design)
- Add declare(strict_types=1) to all four action files
- Update unit tests: fix mock chains (for()->andReturn($mock)),
  correct expected tuple arguments, add handleMembers expectations,
  remove now-deleted affiliated-entities test for manual action

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: replace tuple arrays with readonly DTOs (AffiliationData, CriteriaData)

- Add AffiliationData and CriteriaData readonly DTOs in Services/Roles/DTO/
- Update AbstractRoleService::syncAffiliateManyEntities() and addCriteria() to accept variadic DTOs
- Update RoleServiceInterface to match new signature
- Update AutomaticRoleService, OnRequestRoleService, OptInRoleService to use CriteriaData variadics
- Update all 4 Manage*RoleAction classes to construct DTOs from request data
- Update all tests to use new DTO-based call signatures
- Remove validateAffiliationEntities() and validateCriteria() validators (DTOs provide static analysis coverage)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove accidentally committed .phpunit.cache directory

The .phpunit.cache/ directory was already in .gitignore but got
committed in the previous commit. Remove from tracking.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add .phpunit.cache to .gitignore

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: move entity type → class resolution into DTOs via entityClass()

Add entityClass() method to AffiliationData and CriteriaData so callers
don't need to repeat the match expression. AbstractRoleService now just
calls $entity->entityClass() instead of inlining the match. Invalid
entity types throw \ValueError with a descriptive message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: rename abbreviated closure params $e to descriptive names

Replace fn (array $e) with fn (array $affiliationData) and
fn (array $criteriaData) in all Manage*RoleAction classes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore affiliated handling in ManageManualRoleAction

Manual roles support syncAffiliateManyEntities() (inherited from
AbstractRoleService) for visibility scoping. The affiliated array
was inadvertently removed in the DTO refactor.

Also restores the 'affiliates many entities' test with withArgs()
DTO-based assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: handle empty arrays in role actions to allow clearing affiliations/criteria

Previously, is_truthy check on arrays meant passing affiliated: [] or
assigned: [] was a no-op. Now is_array() correctly distinguishes 'key
absent' (no change) from 'key present with empty array' (reset to empty).

Also updates ManageAutomaticRoleActionTest to expect 0-arg calls when
affiliated or assigned are provided as empty arrays.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: update actions/checkout to v4 and paambaati/codeclimate-action to v9

paambaati/codeclimate-action@v2.6.0 used Node.js 12 which is no longer
supported on GitHub Actions runners. Updated to v9 (Node.js 20) which is
the current stable release. Also updated actions/checkout from v2 to v4.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: replace fragile two-workflow setup with a single consolidated laravel.yml

- Delete tests.yml (used paambaati/codeclimate-action@v2.6.0 which runs
  Node.js 12, long since removed from GitHub Actions runners)
- Delete check-coding-standards.yml (ran composer update with floating
  deps, inconsistent with tests.yml which used composer install)
- Add laravel.yml modelled on seatplus/web workflow:
  - concurrency group with cancel-in-progress: true to conserve resources
  - fail-early step order: lint → types → type-coverage → tests
  - XDEBUG_MODE=coverage + --coverage --min=100 enforces 100% code coverage
    via Pest exit code — no external service needed
  - actions/cache@v4 for Composer dependency caching
  - pgsql, pdo_pgsql, redis PHP extensions (previously missing)
  - actions/checkout@v4 (consistent with recent fixes)
- Update README: add CI badge, expand with package overview (role types,
  affiliation system, SSO compliance, permission checking, dev setup)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: pin phpstan/phpstan to 1.12.24 and pest-plugin-type-coverage to 3.5.1

pest-plugin-type-coverage v3.6.1 passes [] (array) to PHPStan's
RuleErrorTransformer::transform() which expects a string for $nodeType.
PHPStan 1.12.25+ added strict native type enforcement that turns this
into a TypeError, crashing type-coverage analysis.

Pin to the same versions used by seatplus/web (phpstan 1.12.24,
pest-plugin-type-coverage 3.5.1) where this bug does not occur.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: clear stale character_roles before permission checks in test

The 'checks owned character ids' test was intermittently failing with 200
instead of 403. Root cause: CharacterRole rows from previous test runs
(committed outside any transaction, e.g. from eveapi package tests) are
visible in the current test's LazilyRefreshDatabase transaction. When
CharacterInfo factory's afterCreating hook tries to save a CharacterRole
with the same character_id as a stale committed row, the PK UPDATE fails,
leaving the stale row (with withRandomRoles() data including 'Director') in
place. The middleware then grants corporation access that should be denied.

Fix: call CharacterRole::query()->delete() at the start of the test body to
remove any stale rows within the transaction before the middleware runs.
The transaction rollback at the end of the test restores all stale records.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…iance (#404)

* fix: correct tuple format and ordering in Manage*RoleActions

- Convert affiliated arrays to [entity_id, entity_type, affiliation_type]
  tuples before passing to syncAffiliateManyEntities(), which validates
  via *.0 / *.1 / *.2 numeric keys
- Convert assigned arrays to [entity_id, entity_type] tuples for
  automaticallyAssignRoleTo() / addCriteriaForRoleApplication() /
  addCriteriaForRole()
- Move setRoleType() before criteria writes so type-change resets
  (resetRoleMemberships) don't wipe newly written criteria
- Add handleMembers() call after all writes to sync memberships
- Remove affiliated handling from ManageManualRoleAction (manual roles
  have no affiliation criteria by design)
- Add declare(strict_types=1) to all four action files
- Update unit tests: fix mock chains (for()->andReturn($mock)),
  correct expected tuple arguments, add handleMembers expectations,
  remove now-deleted affiliated-entities test for manual action

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: replace tuple arrays with readonly DTOs (AffiliationData, CriteriaData)

- Add AffiliationData and CriteriaData readonly DTOs in Services/Roles/DTO/
- Update AbstractRoleService::syncAffiliateManyEntities() and addCriteria() to accept variadic DTOs
- Update RoleServiceInterface to match new signature
- Update AutomaticRoleService, OnRequestRoleService, OptInRoleService to use CriteriaData variadics
- Update all 4 Manage*RoleAction classes to construct DTOs from request data
- Update all tests to use new DTO-based call signatures
- Remove validateAffiliationEntities() and validateCriteria() validators (DTOs provide static analysis coverage)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove accidentally committed .phpunit.cache directory

The .phpunit.cache/ directory was already in .gitignore but got
committed in the previous commit. Remove from tracking.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add .phpunit.cache to .gitignore

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: move entity type → class resolution into DTOs via entityClass()

Add entityClass() method to AffiliationData and CriteriaData so callers
don't need to repeat the match expression. AbstractRoleService now just
calls $entity->entityClass() instead of inlining the match. Invalid
entity types throw \ValueError with a descriptive message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: rename abbreviated closure params $e to descriptive names

Replace fn (array $e) with fn (array $affiliationData) and
fn (array $criteriaData) in all Manage*RoleAction classes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore affiliated handling in ManageManualRoleAction

Manual roles support syncAffiliateManyEntities() (inherited from
AbstractRoleService) for visibility scoping. The affiliated array
was inadvertently removed in the DTO refactor.

Also restores the 'affiliates many entities' test with withArgs()
DTO-based assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: handle empty arrays in role actions to allow clearing affiliations/criteria

Previously, is_truthy check on arrays meant passing affiliated: [] or
assigned: [] was a no-op. Now is_array() correctly distinguishes 'key
absent' (no change) from 'key present with empty array' (reset to empty).

Also updates ManageAutomaticRoleActionTest to expect 0-arg calls when
affiliated or assigned are provided as empty arrays.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: update actions/checkout to v4 and paambaati/codeclimate-action to v9

paambaati/codeclimate-action@v2.6.0 used Node.js 12 which is no longer
supported on GitHub Actions runners. Updated to v9 (Node.js 20) which is
the current stable release. Also updated actions/checkout from v2 to v4.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: replace fragile two-workflow setup with a single consolidated laravel.yml

- Delete tests.yml (used paambaati/codeclimate-action@v2.6.0 which runs
  Node.js 12, long since removed from GitHub Actions runners)
- Delete check-coding-standards.yml (ran composer update with floating
  deps, inconsistent with tests.yml which used composer install)
- Add laravel.yml modelled on seatplus/web workflow:
  - concurrency group with cancel-in-progress: true to conserve resources
  - fail-early step order: lint → types → type-coverage → tests
  - XDEBUG_MODE=coverage + --coverage --min=100 enforces 100% code coverage
    via Pest exit code — no external service needed
  - actions/cache@v4 for Composer dependency caching
  - pgsql, pdo_pgsql, redis PHP extensions (previously missing)
  - actions/checkout@v4 (consistent with recent fixes)
- Update README: add CI badge, expand with package overview (role types,
  affiliation system, SSO compliance, permission checking, dev setup)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: pin phpstan/phpstan to 1.12.24 and pest-plugin-type-coverage to 3.5.1

pest-plugin-type-coverage v3.6.1 passes [] (array) to PHPStan's
RuleErrorTransformer::transform() which expects a string for $nodeType.
PHPStan 1.12.25+ added strict native type enforcement that turns this
into a TypeError, crashing type-coverage analysis.

Pin to the same versions used by seatplus/web (phpstan 1.12.24,
pest-plugin-type-coverage 3.5.1) where this bug does not occur.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: clear stale character_roles before permission checks in test

The 'checks owned character ids' test was intermittently failing with 200
instead of 403. Root cause: CharacterRole rows from previous test runs
(committed outside any transaction, e.g. from eveapi package tests) are
visible in the current test's LazilyRefreshDatabase transaction. When
CharacterInfo factory's afterCreating hook tries to save a CharacterRole
with the same character_id as a stale committed row, the PK UPDATE fails,
leaving the stale row (with withRandomRoles() data including 'Director') in
place. The middleware then grants corporation access that should be denied.

Fix: call CharacterRole::query()->delete() at the start of the test body to
remove any stale rows within the transaction before the middleware runs.
The transaction rollback at the end of the test restores all stale records.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: eager load entity relation in updateMemberStatusBasedOnUserCompliance

Accessing $role_membership->entity inside a collection->each() callback
triggers lazy loading which fails when Model::shouldBeStrict() is active
(all test suites). Add ->with('entity') to the query before ->get() to
ensure the User is eager loaded.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add setModerator() to OptInRoleService (same pattern as ManualRoleService/OnRequestRoleService)
- Update SetModeratorAction::validateRoleType() to accept OptInRoleService

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ated during SSO

Previously throw_if() raised an exception causing a 500 on the
initial SSO callback when a user was already logged in. Now we
redirect to '/' silently, keeping the user where they should be.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Bump php ^8.3 → ^8.5
- Bump laravel/framework ^11.0 → ^13.0
- Bump orchestra/testbench ^9.0 → ^11.0 (follows Laravel versioning)
- Bump pestphp/pest ^3.0 → ^4.0
- Bump pestphp/pest-plugin-laravel ^3.0 → ^4.1 (Laravel 13 support)
- Bump pestphp/pest-plugin-type-coverage 3.5.1 → ^4.0
- Bump phpstan/phpstan 1.12.24 → ^2.0
- Bump rector/rector ^1.2 → ^2.0
- Bump driftingly/rector-laravel ^1.2 → ^2.0
- Bump larastan/larastan ^2.9 → ^3.0
- Add VCS repos for seatplus/eveapi and seatplus/esi-client
  pointing to their upgrade branches (dev-chore/*-upgrade)
- Regenerate PHPStan baseline (pre-existing errors unchanged)
- Add typed PHP 8.3 class constants (BuildScopesArrayService) for
  pest-plugin-type-coverage v4 compliance

All 278 tests pass, type coverage 100%, PHPStan clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@herpaderpaldent herpaderpaldent force-pushed the chore/php-8.5-laravel-13-upgrade branch from 7964546 to 4cdd9b2 Compare May 12, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant