Skip to content

Navigation Integration

Audience: Site builders and administrators who want CRM links in the Drupal admin toolbar. For developer details on the underlying implementation, see Implementation details below.

The CRM module provides optional integration with Drupal core's Navigation module. When Navigation is enabled alongside CRM, a CRM item appears in the admin toolbar with a submenu of the main CRM administration sections.

The Navigation module is not required. CRM works fully without it; the toolbar integration activates automatically when both modules are enabled.

Requirements

  • CRM module enabled.
  • Drupal core Navigation module enabled (Admin > Extend, or drush pm:enable navigation).
  • Users must have the access navigation permission and at least one CRM permission (such as administer crm) to see the CRM toolbar links.

What You Get

CRM toolbar item

A top-level CRM link appears in the Navigation toolbar. Clicking it goes directly to the contact collection (/admin/crm/contacts).

CRM submenu

Below the top-level item, a submenu is automatically derived from the CRM administration local tasks. The default items are:

Submenu item Destination
Contacts /admin/crm/contacts
Methods /admin/crm/contact-methods
Relationships /admin/crm/relationships

The submenu is built dynamically — if a contributed module or custom code adds a local task with parent_id: crm.admin, it will appear here automatically.

Contact page tabs

When Navigation is enabled, Drupal's Navigation module suppresses the standard local-tasks block on most pages. CRM overrides this behavior on contact canonical and relationship/comment routes so the contact tabs (Summary, Relationship, Comments) continue to display as a single merged row.

Permissions

Permission Effect
access navigation Required to see and use the Navigation toolbar at all.
administer crm Grants access to the CRM toolbar item and its submenu.
view any crm contact (or bundle-specific) Required to visit the contact canonical route where tabs are shown.

Users who have access navigation but no CRM permissions will see the Navigation toolbar without any CRM-specific links.

Enabling Navigation alongside CRM

# Using Drush
ddev drush pm:enable navigation -y

Clear caches after enabling:

ddev drush cache:rebuild

No additional configuration is needed. CRM detects the presence of the Navigation module at runtime and activates the integration automatically.

Troubleshooting

  1. Verify Navigation is enabled — Go to Admin > Extend and confirm the Navigation module is checked.
  2. Check user permissions — The user needs both access navigation and a CRM permission such as administer crm. Go to Admin > People > Permissions to review.
  3. Clear caches — After enabling Navigation or changing permissions, run ddev drush cache:rebuild or use the toolbar cache-clear button.

Contact tabs show two rows or no tabs on the contact page

  • Confirm Navigation is enabled. Without it, the tab-merging behavior does not activate and tabs render using the standard Drupal layout.
  • If tabs are entirely missing, confirm the local tasks block is placed in a visible region.

Implementation details

Audience: Module developers and contributors.

The integration is implemented across three files and adds no required dependency to crm.info.yml.

Two entries in crm.links.menu.yml seed the toolbar integration. These are separate from the standard CRM admin menu links in the same file; the standard admin menu works independently of the Navigation module.

  • crm.navigation.content — the top-level CRM toolbar link, targeting the contact collection with a Navigation icon (pack_id: navigation, icon_id: entity-user-collection).
  • crm.navigation.content.items — a placeholder that points to NavigationDeriver, which replaces it with dynamic submenu links at discovery time.

Dynamic submenu (NavigationDeriver)

Drupal\crm\Plugin\Derivative\NavigationDeriver implements ContainerDeriverInterface. Its getDerivativeDefinitions() method:

  1. Loads all local task definitions via plugin.manager.menu.local_task.
  2. Filters to tasks whose parent_id is crm.admin.
  3. Sorts by weight.
  4. Emits one menu link derivative per task, all parented to crm.navigation.content.

Because it reads live plugin definitions, the submenu stays in sync with any task added by CRM or third-party modules without additional configuration.

Contact page tabs (ContactHooks)

Drupal\crm\Hook\ContactHooks implements two hooks that run after the Navigation module's own implementations (order: new OrderAfter(['navigation'])):

  • hook_block_build_local_tasks_block_alter — removes the #access FALSE that Navigation sets on the local tasks block for these routes: entity.crm_contact.canonical, crm.contact_relationship, crm.contact_comment.
  • hook_block_view_local_tasks_block_alter — attaches a #pre_render callback (ContactHooks::mergeSecondaryIntoPrimary) that folds secondary tabs into the primary row so only one tab row is rendered, without modifying task definitions for other consumers including Navigation itself.

Testing

The integration is covered by a functional test suite:

Test class What it covers
NavigationIntegrationTest::testCrmNavigationMenuLinkVisible CRM toolbar item visible to admin
NavigationIntegrationTest::testCrmNavigationDerivedSubmenuItems Contacts/Methods/Relationships submenu
NavigationIntegrationTest::testCrmNavigationRequiresPermission No CRM links without CRM permission
NavigationIntegrationTest::testContactTabsSingleRowWithNavigation Single-row tabs on contact routes
ContactHooksNavigationTest (Kernel) block_build/view_local_tasks_block_alter hook logic in isolation

To run the Navigation-specific tests:

ddev phpunit --filter=NavigationIntegrationTest
ddev phpunit --filter=ContactHooksNavigationTest