Build rsvp_community_navigator sub-module and companion recipe

Submitted by StephenGroundwater on
Status
Priority
High

Implement the Community Context Navigator per ADR-0025. A programmatic block plugin that surfaces community identity and role-appropriate actions on every community page.

Sub-module: rsvp_community_navigator (in rsvp_system_module/modules/)

Services

  • CommunityContextResolver — resolves community + community_type from URL path (/{community_type}/{community}/), falls back to field_community_owner on current node. Also detects page type: calendar|resource|event|reservations|community_landing|generic.
  • UserAccessResolver — reads current user's community_* roles and position role, derives effectiveAccessLevel for the resolved community: none|member|contributor|editor|coordinator|manager|admin.

Value Objects

  • CommunityContext — community term, community_type term, page_type, current_ym (YYYY-MM)
  • UserContext — position_role, community_roles[], effective_level, is_member bool

Block Plugin: CommunityNavigatorBlock

Three render zones:

  1. Context Header — community name + community type label (read-only, no switcher)
  2. Calendar View Switcher — built-in: Event Calendar + Reservations. Active tab detected by URL match. Extensible via hook_rsvp_community_calendar_views_alter().
  3. Quick Actions — role-gated. URL params pass community TID + current YYYY-MM to node/add forms for zero-friction pre-fill. Extensible via hook_rsvp_community_quick_actions_alter().

Block renders nothing (no HTML) if no community context resolves or user has effectiveAccessLevel = none.

Built-in Quick Actions

  • Add Event (min: editor)
  • Book a Resource (min: member)
  • Reservation Queue (min: coordinator)
  • Manage Resources (min: coordinator)
  • Moderation Queue (min: manager)

Cache contexts

user.roles + url.path — sufficient to vary correctly per user per community page.

Companion Recipe: rsvp_community_navigator (in rsvp-recipes)

  • Enables sub-module
  • Places block in theme region
  • Block visibility: URL path matches /{community_type}/{community}/
  • Not included in rsvp_full_stack — opt-in

Extension Points (for future rsvp_community_schedule)

  • hook_rsvp_community_calendar_views_alter(array &$views, CommunityContext $context)
  • hook_rsvp_community_quick_actions_alter(array &$actions, CommunityContext $context, UserContext $user_context)

Definition of Done

  • Sub-module installed, services injectable
  • Block placed on a community calendar page, renders correct community name and access-appropriate zones
  • Calendar view switcher highlights active view by URL match
  • "Add Event" from calendar page opens node/add/rsvp_event pre-filled with correct community TID and current month
  • Anonymous users and non-members see no block output
  • Coordinator+ sees Reservation Queue and Manage Resources actions
  • Alter hooks documented with examples in module README
  • Companion recipe applies cleanly on fresh install

ADR: ADR-0025
Depends on: ADR-0023 role sync (community_ role → community term mapping already in place)