Tiger_Model_Menu

@api · extends Tiger_Model_Table

Menu — custom navigation menus (see migration 0017).

One flat, self-referential table; a menu = the rows sharing (org_id, menu_key). This model is the data gateway: it owns the queries (tenant cascade, tree assembly, reorder, the admin list) and knows nothing about rendering — turning a tree into HTML is Tiger_Menu's job (via Zend_Navigation).

TENANT CASCADE is menu-level: if the current org has any rows for a menu_key, that whole menu is used; otherwise the global ('') menu. Menus don't merge item-by-item.

Methods

tree()

tree($menuKey, $orgId = '', $onlyPublished = true)

The assembled item TREE for a menu, honoring the tenant cascade. Each node is the row's columns as an array plus a children array (recursively). Ordered by sort_order within each level. Front-end callers get published-only; the admin editor passes $onlyPublished = false to see drafts.

  • $menuKey string — the menu's key
  • $orgId string — tenant scope ('' = global)
  • $onlyPublished bool — exclude drafts (front-end); false for the admin editor

Returns array<int,array<string,mixed>>

flat()

flat($menuKey, $orgId = '', $onlyPublished = true)

Flat, ordered rows for a menu after the tenant cascade (the org's menu wins whole, else global). Returned as plain arrays.

  • $menuKey string — the menu's key
  • $orgId string — tenant scope ('' = global)
  • $onlyPublished bool — exclude drafts (front-end); false for the admin editor

Returns array<int,array<string,mixed>>

reorder()

reorder(array $items, $menuKey, $orgId = '')

Reorder / re-parent a batch of items in one transaction (drag-drop persistence). Each entry: ['menu_id' => …, 'parent_id' => …|null, 'sort_order' => int]. Only items already in the given menu (scope) are touched — a guard against a client moving foreign rows.

  • $items array
  • $menuKey string — the menu's key (the scope guard)
  • $orgId string — tenant scope ('' = global)

Returns int — rows updated

Throws Throwable — on a DB failure (the transaction is rolled back and rethrown)

datatable()

datatable(array $opts)

The list of distinct menus for the admin index: one entry per (org_id, menu_key) with the item count. Optional search on the key. Server-side DataTables shape.

  • $opts array — query options (search, limit, offset, orderCol, orderDir)

Returns array{total:int,filtered:int,rows:array}

itemsForEditor()

itemsForEditor($menuKey, $orgId = '')

Every live item for a menu scope, flat + ordered — the admin editor's working set.

  • $menuKey string — the menu's key
  • $orgId string — tenant scope ('' = global)

Returns array<int,array<string,mixed>> — flat, ordered rows

nextSort()

nextSort($menuKey, $orgId, $parentId)

The next sort_order to append a new item at the end of its level.

  • $menuKey string — the menu's key
  • $orgId string — tenant scope ('' = global)
  • $parentId string|null — the parent item id, or null/'' for a top-level item

Returns int — the next sort_order value

deleteItem()

deleteItem($menuId)

Soft-delete an item AND all its descendants (deleting a parent removes its subtree).

  • $menuId string — the item id to delete

Returns int — the number of rows soft-deleted (the item plus its descendants)

keys()

keys($orgId = null)

Distinct menu_keys that already have rows (feeds the "add item to menu" pickers).

  • $orgId string|null — restrict to a tenant scope, or null for all scopes

Returns array<int,string> — the distinct menu keys