feat: add bulk workspace invitation support #78

Open
Charon wants to merge 3 commits from feat/bulk-workspace-invitations into dev
Member

Summary

  • Add Workspace::inviteMany(array $emails, string $role, ?User $invitedBy, int $expiresInDays) method for sending multiple invitations in one call
  • Deduplicates input emails (case-insensitive, trimmed) before processing
  • Skips emails belonging to existing workspace members (returns already_member status)
  • Delegates to existing invite() method per email, inheriting re-send/update behaviour for pending invitations
  • Returns a Collection of result arrays with email, status, and invitation keys

Fixes #36

Test plan

  • test_invite_many_sends_multiple_invitations — verifies 3 emails produce 3 invitations and 3 notifications
  • test_invite_many_skips_existing_members — verifies existing workspace members are skipped
  • test_invite_many_deduplicates_emails — verifies case-insensitive and whitespace deduplication
  • test_invite_many_with_empty_array — verifies empty input returns empty collection, no notifications sent
  • test_invite_many_assigns_correct_role — verifies the role parameter is passed through
  • test_invite_many_handles_resend_for_pending_invitations — verifies re-inviting a pending email updates the role
  • test_invite_many_skips_existing_member_case_insensitive — verifies case-insensitive member matching

🤖 Generated with Claude Code

## Summary - Add `Workspace::inviteMany(array $emails, string $role, ?User $invitedBy, int $expiresInDays)` method for sending multiple invitations in one call - Deduplicates input emails (case-insensitive, trimmed) before processing - Skips emails belonging to existing workspace members (returns `already_member` status) - Delegates to existing `invite()` method per email, inheriting re-send/update behaviour for pending invitations - Returns a `Collection` of result arrays with `email`, `status`, and `invitation` keys Fixes #36 ## Test plan - [x] `test_invite_many_sends_multiple_invitations` — verifies 3 emails produce 3 invitations and 3 notifications - [x] `test_invite_many_skips_existing_members` — verifies existing workspace members are skipped - [x] `test_invite_many_deduplicates_emails` — verifies case-insensitive and whitespace deduplication - [x] `test_invite_many_with_empty_array` — verifies empty input returns empty collection, no notifications sent - [x] `test_invite_many_assigns_correct_role` — verifies the role parameter is passed through - [x] `test_invite_many_handles_resend_for_pending_invitations` — verifies re-inviting a pending email updates the role - [x] `test_invite_many_skips_existing_member_case_insensitive` — verifies case-insensitive member matching 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Charon added 3 commits 2026-03-24 13:51:32 +00:00
Add larastan/larastan ^3.0 to require-dev and create phpstan.neon
config at level 5 covering all source directories. Adds a
`composer analyse` script shortcut.

Fixes #26

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change Core\Mod\Tenant\Services to Core\Tenant\Services to match
the actual namespace used in source files.

Fixes #28

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Workspace::inviteMany() method that sends multiple invitations in
one call. Handles duplicates gracefully by skipping already-invited
members and deduplicating input emails (case-insensitive). Returns a
collection of results with status per email.

Fixes #36

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/bulk-workspace-invitations:feat/bulk-workspace-invitations
git checkout feat/bulk-workspace-invitations

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git checkout dev
git merge --no-ff feat/bulk-workspace-invitations
git checkout feat/bulk-workspace-invitations
git rebase dev
git checkout dev
git merge --ff-only feat/bulk-workspace-invitations
git checkout feat/bulk-workspace-invitations
git rebase dev
git checkout dev
git merge --no-ff feat/bulk-workspace-invitations
git checkout dev
git merge --squash feat/bulk-workspace-invitations
git checkout dev
git merge --ff-only feat/bulk-workspace-invitations
git checkout dev
git merge feat/bulk-workspace-invitations
git push origin dev
Sign in to join this conversation.
No description provided.