VOOZH about

URL: https://deepwiki.com/mathsgod/light/8.3-menu-system

⇱ Menu System | mathsgod/light | DeepWiki


Loading...
Last indexed: 31 January 2026 (cf9511)
Menu

Menu System

Purpose and Scope

This document describes the menu system in the Light framework, which provides a hierarchical, permission-based navigation structure for applications. The menu system supports multiple configuration sources, role-based filtering, and dynamic feature flags. For information about the underlying configuration storage, see Config Model and Settings. For details on the RBAC system used for permission checking, see RBAC System.


Menu Configuration Architecture

The menu system aggregates menus from three sources: a system default YAML file, custom menus stored in the database, and dynamically-generated menus based on enabled features.


Menu Loading Flow

Sources: src/App.php174-191 src/App.php586-592


Menu Structure and Properties

Menus are represented as nested arrays with the following structure:

PropertyTypeRequiredDescription
labelstringYesDisplay text for the menu item
tostringNoRoute path (e.g., /FileManager)
iconstringNoIcon identifier (defaults to sym_o_circle)
permissionstring|arrayNoRequired permission(s) to view this menu
childrenarrayNoNested menu items

Permission Specification

Permissions can be specified in two formats:

  1. Role reference: String starting with # (e.g., #administrators) - checks if user has this role
  2. Permission string: Regular permission (e.g., fs, user.list) - checks via RBAC system

Multiple permissions can be specified as an array. If any permission matches, access is granted.

Sources: src/Type/App.php203-260


Menu Loading Process

The menu loading process occurs during App initialization and follows this sequence:


Menu Initialization Sequence

System Default Menus

System menus are defined in menus.yml at the project root. During initialization, the App class loads this file:

src/App.php176


Custom Menus

Custom menus are stored in the Config model with name='menus' as a JSON-encoded array. These are loaded after system menus:

src/App.php178


The getCustomMenus() method retrieves and decodes the JSON:

src/App.php586-592


Feature-Based Dynamic Menus

Certain menus are conditionally added based on feature flags:

File Manager Menu

src/App.php181-190


The File Manager menu is only added if the file_manager config value is truthy (see Application Settings).

Sources: src/App.php174-191 src/App.php586-592 src/App.php594-600


Menu Storage and Manipulation

The App class maintains menus in a protected array and provides methods for access and manipulation:

Storage

src/App.php55


Access Methods

MethodDescriptionReturn Type
getMenus()Returns full hierarchical menu structurearray
getFlatMenus()Returns flattened menu list (no hierarchy)array
getCustomMenus()Returns only custom menus from Configarray
addMenus(array)Appends menus to the menu arrayvoid

Flattened Menu Structure

The getFlatMenus() method traverses the menu tree and returns a flat array, useful for permission extraction:

src/App.php194-209


This method uses a stack-based traversal to flatten the hierarchy while preserving all menu items.

Sources: src/App.php55 src/App.php194-221


Permission-Based Menu Filtering

Menus are filtered based on the current user's roles and permissions when accessed via GraphQL. This ensures users only see menus they have access to.


Permission Filtering Logic

GraphQL Endpoint

The getMenus() field in the Type\App class returns filtered menus:

src/Type/App.php196-201


This method requires authentication (#[Logged]) and injects the current user and RBAC system.

Filtering Algorithm

The filterMenus() method implements recursive permission checking:

src/Type/App.php203-260

Key filtering rules:

  1. Icon default: If no icon is specified, defaults to sym_o_circle src/Type/App.php207-209

  2. Feature-based filtering: The CustomField menu is excluded if custom_field_models config is not set src/Type/App.php211-215

  3. Recursive children filtering: Child menus are recursively filtered, and parent menus without to routes are removed if all children are filtered out src/Type/App.php218-224

  4. Permission checking:

  5. Multiple permissions: When multiple permissions are specified (as array), access is granted if ANY permission matches src/Type/App.php233-249

Permission Extraction

The getMenusPermission() method extracts all permissions from the menu structure for use in the permission discovery system:

src/App.php368-390


This method is called by getPermissions() to include menu permissions in the system-wide permission list src/App.php453-455

Sources: src/Type/App.php196-260 src/App.php368-390


GraphQL API

The menu system exposes two GraphQL queries for accessing menu data:

Query: getMenus

Returns the filtered menu hierarchy for the current user.

Schema:


Annotations:

  • #[Logged] - Requires authentication
  • #[Field(outputType: "mixed")] - Returns mixed/dynamic structure

Implementation: src/Type/App.php196-201

Example Response:


Query: getCustomMenus

Returns only the custom menus stored in the database, without filtering or system menus.

Schema:


Annotations:

  • #[Logged] - Requires authentication
  • #[Field(outputType: "mixed")] - Returns mixed/dynamic structure

Implementation: src/Type/App.php354-357

This query is useful for menu configuration UIs that need to display only user-defined menus.

Sources: src/Type/App.php196-201 src/Type/App.php354-357


Menu Configuration Management

Custom menus are managed through the Config model with mutations provided by AppController.

Storage Format

Custom menus are stored in the Config table:

  • name: "menus"
  • value: JSON-encoded array of menu objects

Configuration Mutations

The AppController provides GraphQL mutations for managing custom menus. See AppController for details on configuration mutations.

Example Custom Menu Configuration


This configuration demonstrates:

  • Hierarchical menus with children
  • Icon customization
  • Mixed permission types (role-based and named permissions)
  • Multiple permission options (array)

Sources: src/App.php586-592 src/Type/App.php354-357


Integration with Permission System

The menu system integrates tightly with the RBAC permission system for both enforcement and discovery.


Permission System Integration

Permission Discovery

Menu permissions are automatically discovered and included in the system-wide permission list returned by getPermissions():

src/App.php453-455


This ensures that:

  1. Menu permissions are included in the permission management UI
  2. Administrators can assign menu-specific permissions to roles
  3. Permission consistency is maintained across the system

Permission Filtering

Role-based permissions (prefixed with #) are filtered out from the final permission list:

src/App.php462-465


This is because role references are handled differently from named permissions in the RBAC system.

Sources: src/App.php392-472 src/App.php368-390


Menu Examples

System Default Menu Structure

The menus.yml file at the project root defines system default menus. While the file content is not shown in the provided code, it follows the same structure as custom menus and is loaded during app initialization.

Conditional Feature Menus

File Manager Menu (conditionally added):


This menu appears only when Config::Value("file_manager") returns a truthy value src/App.php181-190

CustomField Menu (conditionally filtered):

  • Menu items with to="/CustomField" are excluded if custom_field_models config is not set
  • This occurs during filtering, not during loading src/Type/App.php211-215

Permission Patterns

Single Permission:


Role-Based Permission:


Multiple Permissions (OR logic):


This menu is accessible to users who either have the "Administrators" role OR have the "reports.view" permission.

Sources: src/App.php181-190 src/Type/App.php211-215 src/Type/App.php226-250