Add evo_megamenu_json extension and seed the megamenu

- new project-neutral extension evo_megamenu_json (Evomedien): a Megamenu
  plugin holding entries, columns, items, teaser cards and a featured slot
  as nested records; presentation settings travel with the payload so the
  front end reads behaviour instead of hard-coding it; published as
  page.10.fields.megaMenu, driven by the site settings megamenu.contentUid
  and megamenu.storagePid
- vitec:seed-megamenu fills one element from the live structure: 5 entries,
  26 columns, 95 items, 4 story cards; items without a page yet are flagged
  pending so the front end falls back to the column link
- vitec:debug-sets prints the resolved site set order
- read-only diagnostics: check_megamenu_schema.php, check_typoscript_templates.php
- docs: schema updates run via extension:setup (database:updateschema no
  longer exists in v14), and a JSON Accept header activates headless-mixed,
  which strips every set-added page field
This commit is contained in:
orasche committed 2026-09-11 11:44:20 +02:00
1 parent e9eaa62d89
commit 5bb4e374b4
31 files changed
+2251 -4

No files matched your search

@@ -0,0 +1,9 @@
name: evomedien/megamenu
label: EVO Megamenu (JSON)
# headless has to be loaded before this set: it resets the whole page object
# (`page < lib.headlessPage`), which would drop the page-level field added
# here. Declaring the dependency keeps that order without the site
# configuration having to care about the listing position.
dependencies:
- friendsoftypo3/headless
@@ -0,0 +1,19 @@
categories:
megamenu:
label: 'Megamenu'
description: 'Which megamenu element is published at page level'
settings:
megamenu.contentUid:
label: 'Megamenu element (uid)'
description: 'Uid of the "Megamenu" content element to publish on every page as `megaMenu`. 0 = do not publish at page level.'
category: megamenu
type: int
default: 0
megamenu.storagePid:
label: 'Megamenu folder (pid)'
description: 'Alternative to the uid above: the first megamenu element found on this folder is published. Ignored when an element uid is set.'
category: megamenu
type: int
default: 0
@@ -0,0 +1,41 @@
# =============================================================================
# EVO Megamenu JSON
#
# Two wiring points, one renderer:
# 1. the plugin element renders itself, so the menu can be previewed on the
# page it sits on (content.megamenu),
# 2. the site header needs the menu on every page - set `megamenu.contentUid`
# (or `megamenu.storagePid`) and it is published at page level as
# `megaMenu`.
#
# Two things are deliberate here:
#
# * No TypoScript condition around the page-level field. A condition that
# cannot be evaluated swallows every include that follows it and silently
# disables the TypoScript of all later sets. The renderer returns an empty
# value when nothing is configured - same result, no risk.
#
# * The JSON key is written out literally. Since TYPO3 v12 the TypoScript
# parser substitutes constants only on the VALUE side, so a `{$...}` in
# the object path produces no field at all (found the hard way,
# 2026-09-11). A project that needs another key copies these five lines
# into its own set.
#
# The USER function returns a JSON string; the headless JSON content object
# decodes it, so the menu arrives as a real object, not an escaped string.
# =============================================================================
tt_content.evomegamenujson_megamenu =< lib.contentElement
tt_content.evomegamenujson_megamenu {
fields {
megamenu = USER
megamenu.userFunc = Evomedien\EvoMegamenuJson\UserFunc\MegamenuJsonRenderer->render
}
}
page.10.fields.megaMenu = USER
page.10.fields.megaMenu {
userFunc = Evomedien\EvoMegamenuJson\UserFunc\MegamenuJsonRenderer->render
contentUid = {$megamenu.contentUid}
storagePid = {$megamenu.storagePid}
}