Spaces Actions
10 unique action hooks currently map to this category, across 22 call sites.
Hook Inventory
| Hook | Edition | Call Sites | First Source |
|---|---|---|---|
fluent_community/space | Core | 3 | fluent-community/app/Hooks/Handlers/PortalHandler.php:420 |
fluent_community/space/before_delete | Core | 1 | fluent-community/app/Http/Controllers/SpaceController.php:567 |
fluent_community/space/created | Core | 1 | fluent-community/app/Http/Controllers/SpaceController.php:142 |
fluent_community/space/deleted | Core | 1 | fluent-community/app/Http/Controllers/SpaceController.php:584 |
fluent_community/space/join_requested | Core | 1 | fluent-community/app/Http/Controllers/SpaceController.php:518 |
fluent_community/space/joined | Core (also fired by Pro) | 6 | fluent-community-pro/app/Services/Integrations/FluentCRM/ContactAdvancedFilter.php:245 |
fluent_community/space/member/role_updated | Core | 2 | fluent-community/app/Http/Controllers/SpaceController.php:637 |
fluent_community/space/update_meta_settings_{metaProvider} | Core | 1 | fluent-community/app/Http/Controllers/SpaceController.php:372 |
fluent_community/space/updated | Core | 2 | fluent-community/app/Http/Controllers/SpaceController.php:366 |
fluent_community/space/user_left | Core (also fired by Pro) | 4 | fluent-community-pro/app/Services/Integrations/FluentCRM/ContactAdvancedFilter.php:365 |
fluent_community/space
- Type: action
- Edition: Core
- Call sites: 3
- When it fires: Passes a formatted space by reference so its payload can be extended before it reaches the portal.
Fired with do_action_ref_array(), so declare the parameter as &$space and mutate the model in place. It runs on three paths — the single-space fetch, the all-spaces listing, and the sidebar build during portal render — always immediately after formatSpaceData(), which is what attaches permissions, membership, topics, header_links and, for non-admins, lockscreen_config. Because it is a listing hook as well, it can run dozens of times per request; keep callbacks free of queries.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The formatted space, passed by reference. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Hooks/Handlers/PortalHandler.php:420 | &$space (Space) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:242 | &$space (Space) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:267 | &$space (Space) |
Example
add_action('fluent_community/space', function ($space) {
}, 10, 1);Related: fluent_community/space_api_response · fluent_community/space_header_links
fluent_community/space/before_delete
- Type: action
- Edition: Core
- Call sites: 1
- When it fires: Runs immediately before a space and its content are deleted.
The last point at which the space, its posts, comments, reactions and membership rows are all still queryable — the controller deletes them in bulk straight afterwards. Those bulk deletes bypass the per-item controllers, so no fluent_community/feed/deleted or fluent_community/comment_deleted fires for the content that goes with the space. Attached media is not cleaned up here either.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The space about to be deleted. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:567 | $space (Space) |
Example
add_action('fluent_community/space/before_delete', function ($space) {
}, 10, 1);Related: fluent_community/space/deleted
fluent_community/space/created
- Type: action
- Edition: Core
- Call sites: 1
- When it fires: Runs after a new space is created, its images claimed, its creator attached as admin and its topics synced.
Only fires for spaces created through SpaceController::create(); spaces produced by migrations, seeders or direct model writes do not reach it. The second argument is the sanitised request payload, which carries fields such as topic_ids and image URLs that are not columns on the model.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The newly created space. |
| 2 | $data | array | The sanitised creation payload from the request. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:142 | $space (Space)$data (mixed) |
Example
add_action('fluent_community/space/created', function ($space, $data) {
}, 10, 2);Related: fluent_community/space/updated
fluent_community/space/deleted
- Type: action
- Edition: Core
- Call sites: 1
- When it fires: Runs after a space row has been deleted, with only its ID.
The model and all its content are gone, so capture anything you need from fluent_community/space/before_delete. Deleting by ID delegates to the slug endpoint, so both routes fire it exactly once.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $spaceId | int | ID of the deleted space. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:584 | $spaceId (int) |
Example
add_action('fluent_community/space/deleted', function ($spaceId) {
}, 10, 1);Related: fluent_community/space/before_delete
fluent_community/space/join_requested
- Type: action
- Edition: Core
- Call sites: 1
- When it fires: Fires when a member's request to join a non-public space is left pending approval.
The membership row already exists with status = pending, so the member is attached but not yet active. Only self-service joins reach it: an admin adding a member creates an active row and fires fluent_community/space/joined instead, as does the later approval of this request. Secret spaces reject the join outright before the hook. Core emails the space admins from here. The third argument is always self at the only call site.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The space that was requested. |
| 2 | $userId | int | WordPress user ID of the requester. |
| 3 | $by | string | How the request came about; self at the only current call site. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:518 | $space (Space)$user->ID (int)'self' (string) |
Example
add_action('fluent_community/space/join_requested', function ($space, $userId, $by) {
}, 10, 3);Related: fluent_community/space/joined · fluent_community/space/join_status_for_private
fluent_community/space/joined
- Type: action
- Edition: Core (also fired by Pro)
- Call sites: 6
- When it fires: Fires once a user holds an active membership row in a community space.
Course-type spaces never reach this hook — Helper::addToSpace() routes them to fluent_community/course/enrolled instead. It also does not fire for join requests that land in pending; those fire fluent_community/space/join_requested, and the later approval fires this hook. Only the Helper::addToSpace() path supplies the fourth argument, and only when a membership row was genuinely created, so treat $created as optional.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The space that was joined. |
| 2 | $userId | int | WordPress user ID of the new member. |
| 3 | $by | string | How the membership came about: self, by_admin, automation, or an integration key. |
| 4 | $created | \FluentCommunity\App\Models\SpaceUserPivot | The newly created membership row. Optional — omitted when an existing pending or inactive row was reactivated. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| PRO | fluent-community-pro/app/Services/Integrations/FluentCRM/ContactAdvancedFilter.php:245 | $space (Space)$userId (int)'by_admin' (string) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:520 | $space (Space)$user->ID (int)'self' (string) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:651 | $space (Space)$userId (int)'by_admin' (string) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:669 | $space (Space)$userId (int)'by_admin' (string) |
| Core | fluent-community/app/Services/Helper.php:1757 | $space (Space)$userId (int)$by (mixed) |
| Core | fluent-community/app/Services/Helper.php:1781 | $space (Space)$userId (int)$by (mixed)$created (mixed) |
Example
add_action('fluent_community/space/joined', function ($space, $userId, $by, $created) {
}, 10, 4);Related: fluent_community/space/user_left · fluent_community/course/enrolled
fluent_community/space/member/role_updated
- Type: action
- Edition: Core
- Call sites: 2
- When it fires: Runs after an existing member's role within a space has been changed and saved.
Fires from the admin member-management endpoint only. When a pending member is approved with a non-default role, it fires straight after fluent_community/space/joined for the same user, so a promotion-on-approval reaches both hooks. The pivot is passed rather than the user, so read $pivot->user_id and $pivot->role.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The space whose membership changed. |
| 2 | $pivot | \FluentCommunity\App\Models\SpaceUserPivot | The membership row, already saved with the new role. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:637 | $space (Space)$pivot (mixed) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:654 | $space (Space)$pivot (mixed) |
Example
add_action('fluent_community/space/member/role_updated', function ($space, $pivot) {
}, 10, 2);Related: fluent_community/space/joined
fluent_community/space/update_meta_settings_{metaProvider}
- Type: action
- Edition: Core
- Call sites: 1
- When it fires: Delivers the submitted values for one extra settings section on a space.
The suffix is the provider slug used when the section was registered through fluent_community/space/meta_fields, and the two must match or the values are never delivered. It fires once per provider present in the request, after the space itself has been saved and fluent_community/space/updated has run. The values arrive exactly as submitted — sanitise them yourself. FluentExtendApi::addMetaBox() wires both halves up for you.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $metaData | array | The submitted values for this provider's section, unsanitised. |
| 2 | $space | \FluentCommunity\App\Models\Space | The space that was updated. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:372 | $metaData (mixed)$space (Space) |
Example
add_action('fluent_community/space/update_meta_settings_{metaProvider}', function ($metaData, $space) {
}, 10, 2);Related: fluent_community/space/meta_fields · fluent_community/course/update_meta_settings_{metaProvider}
fluent_community/space/updated
- Type: action
- Edition: Core
- Call sites: 2
- When it fires: Runs after a space is saved with changed values.
Two call sites with different second arguments: SpaceController::update() passes the filtered request payload, while BaseSpace::updateCustomData() passes the dirty attribute map. The model-level call is additionally gated on type == 'community', so custom-data updates to courses, space groups and sidebar links stay silent. Check what you actually received before reading keys off the second argument.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The space after saving. |
| 2 | $data | array | Either the request payload or the changed attributes, depending on the call site. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| Core | fluent-community/app/Http/Controllers/SpaceController.php:366 | $space (Space)$data (mixed) |
| Core | fluent-community/app/Models/BaseSpace.php:370 | $this (mixed)$dirty (mixed) |
Example
add_action('fluent_community/space/updated', function ($space, $data) {
}, 10, 2);Related: fluent_community/space/created
fluent_community/space/user_left
- Type: action
- Edition: Core (also fired by Pro)
- Call sites: 4
- When it fires: Fires after a membership row has been removed from a community space.
Covers self-leaves, admin removals and CRM-driven removals alike; the $by argument tells them apart. As with joining, course-type spaces are routed elsewhere — they fire fluent_community/course/student_left. The pivot row is already deleted and the user's cached space list rebuilt by the time callbacks run.
Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $space | \FluentCommunity\App\Models\Space | The space the user left. |
| 2 | $userId | int | WordPress user ID of the departing member. |
| 3 | $by | string | What triggered the removal: self, by_admin, or automation. |
Call Sites
| Edition | Source | Parameters |
|---|---|---|
| PRO | fluent-community-pro/app/Services/Integrations/FluentCRM/ContactAdvancedFilter.php:365 | $space (Space)$userId (int)'by_admin' (string) |
| PRO | fluent-community-pro/app/Services/Integrations/FluentCRM/RemoveFromSpaceAction.php:87 | $space (Space)$user->ID (int)'automation' (string) |
| Core | fluent-community/app/Http/Controllers/SpaceController.php:706 | $space (Space)$userId (int)'by_admin' (string) |
| Core | fluent-community/app/Services/Helper.php:1831 | $space (Space)$userId (int)$by (mixed) |
Example
add_action('fluent_community/space/user_left', function ($space, $userId, $by) {
}, 10, 3);Related: fluent_community/space/joined