Vue d'ensemble
- Espace de noms PHP :
Websource\MegaMenu(classes danssrc/, PSR-4, chargeursrc/Autoloader.php). - Domaine de traduction :
websource-megamenu(languages/). - Table :
{prefix}wsx_megamenu(un menu par ligne, brouillon et version en ligne en JSON). - Options :
wsx_megamenu_db_version,wsx_megamenu_cache_version. - Fichiers envoyés depuis l'éditeur :
wp-content/uploads/websource-megamenu/. - Capacité requise pour l'administration et l'API :
edit_theme_options.
Bloc
websource/megamenu — rendu côté serveur (blocks/menu/block.json, éditeur sans étape de build).
| Attribut | Type | Défaut | Rôle |
|---|---|---|---|
menu | string | "" | Identifiant ou nom du menu. Vide : tous les menus en ligne dont l'emplacement est « Je le place moi-même ». |
align | string | — | wide ou full (support natif). |
className | string | — | Classe CSS supplémentaire (support natif). |
<!-- wp:websource/megamenu {"menu":"2","align":"full"} /-->
Le bloc n'affiche rien sur le site si le menu n'est pas en ligne.
Code court
[websource_megamenu]
| Attribut | Défaut | Rôle |
|---|---|---|
menu | "" | Identifiant ou nom du menu (insensible à la casse). |
location | "" | Clé d'emplacement : affiche les menus placés sur cet emplacement. Sans menu ni location : emplacement widget. |
[websource_megamenu menu="2"]
[websource_megamenu menu="Pied de page"]
[websource_megamenu location="widget"]
Fonction PHP
websource_megamenu( int|string $menu = '', string $location = '' ): string
Renvoie le HTML du menu demandé (identifiant ou nom), sinon celui des menus placés sur $location. La feuille de style et le script sont mis en file d'attente par l'appel.
// Dans un gabarit de thème classique.
if ( function_exists( 'websource_megamenu' ) ) {
echo websource_megamenu( 'Menu principal' ); // HTML déjà échappé par l'extension.
}
Emplacements
Réglage hook d'un menu.
| Clé | Affichage |
|---|---|
wp_body_open | Action wp_body_open (haut de page). |
header_navigation | Remplace le premier bloc core/navigation du gabarit d'en-tête (zone header). |
footer_navigation | Remplace le premier bloc core/navigation du gabarit de pied de page (zone footer). |
location:<slug> | Remplace wp_nav_menu( [ 'theme_location' => '<slug>' ] ) (filtre pre_wp_nav_menu). Une clé par emplacement enregistré par le thème. |
wp_footer | Action wp_footer, priorité 5. |
widget | Aucun affichage automatique : bloc, code court ou fonction PHP. |
| nom d'une action | Toute clé ajoutée par le filtre websource_megamenu_locations et qui est le nom d'une action : le menu est imprimé quand cette action s'exécute. |
Routes REST
Espace de noms : websource-megamenu/v1. Toutes les routes exigent la capacité edit_theme_options (cookie + en-tête X-WP-Nonce, ou mot de passe d'application). Sans authentification : 401.
Les erreurs métier sont renvoyées sous la forme {"error":"message"} avec le code HTTP indiqué.
| Méthode | Chemin | Paramètres | Réponse |
|---|---|---|---|
| GET | /menus | — | {"menus":[{id,name,active,published,has_changes,location,updated}]} |
| POST | /menus | name, hook (clé d'emplacement), source : empty, example, nav:<id du menu classique> ou navpost:<id du wp_navigation> | 201 {"id":3,"url":"…"} ; 404 si la source n'existe pas |
| POST | /menus/<id>/sync | payload (JSON : name, settings, tree), lang (code de langue de l'aperçu) | {"html":"…","saved_at":"18:05:25","has_changes":true} ; 404 si le menu n'existe pas |
| POST | /menus/<id>/publish | — | {"ok":true} |
| POST | /menus/<id>/discard | — | {"ok":true} (le brouillon reprend la version en ligne) |
| POST | /menus/<id>/toggle | active (booléen) | {"ok":true} |
| POST | /menus/<id>/duplicate | — | 201 {"id":4,"url":"…"} |
| DELETE | /menus/<id> | — | {"ok":true} |
| POST | /menus/<id>/delete | — | {"ok":true} (équivalent pour les hébergements qui bloquent DELETE) |
| GET, POST | /products | q (nom, référence ou identifiant) | {"products":[{"id":40,"name":"T-shirt Ardoise"}]} |
| POST | /upload | file (multipart ; JPG, PNG, WebP, GIF, AVIF ; 5 Mo) | {"url":"…"} ; 400 si refusé |
| POST | /upload-icon | file (multipart ; SVG, PNG, JPG, WebP, GIF, AVIF ; 1 Mo) | {"url":"…"} ; 400 si refusé. Un SVG est réécrit par SvgSanitizer. |
| GET | /export | — | Paquet JSON (voir plus bas) |
| POST | /import | data (paquet JSON), mode : merge (défaut) ou replace, dry_run (booléen) | {"action":"merge","counts":{"create":1,"update":0,"delete":0,"skip":0},"messages":[]} ; 400 si le fichier n'est pas un export |
Exemple de requête :
curl -u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \
-X POST "https://exemple.fr/wp-json/websource-megamenu/v1/menus" \
-d "name=Menu principal" -d "hook=widget" -d "source=example"
Exemple de réponse :
{"id":3,"url":"https://exemple.fr/wp-admin/themes.php?page=websource-megamenu&edit=3"}
Enregistrer un brouillon puis le publier :
curl -u "admin:xxxx…" -X POST "https://exemple.fr/wp-json/websource-megamenu/v1/menus/3/sync" \
--data-urlencode 'payload={"name":"Menu principal","settings":{"hook":"widget","layout":"bar"},"tree":[{"type":"link","label":{"fr":"Contact"},"url":{"fr":"/contact"}}]}'
curl -u "admin:xxxx…" -X POST "https://exemple.fr/wp-json/websource-megamenu/v1/menus/3/publish"
Format des données
Réglages d'un menu (settings)
| Clé | Valeurs |
|---|---|
hook | Clé d'emplacement (voir Emplacements). |
layout | bar, columns. |
theme | light, dark, brand. |
panel | auto, content, full. |
align | start, center. |
mobile | push, accordion. |
aria_label | { "<code de langue>": "texte" }. |
max_depth | Entier de 2 à 6. |
Élément de l'arbre (tree)
Chaque élément : id (3 à 24 caractères a-z0-9_, régénéré s'il manque), type, children (tableau), puis les champs du type. Les textes sont des tables { "<code de langue>": "texte" } ; les adresses libres acceptent une chaîne ou une table par langue.
| Type | Champs propres |
|---|---|
category | id_category (terme product_cat), label, include_children, depth (1–3) |
brand | id_manufacturer (terme product_brand), label |
brands | label, limit (1–50) |
product | id_product, label |
products | source (new, best, category, manual), id_category, ids, label, limit (1–20) |
page | page (home, blog, shop, new-products, best-sales, cart, checkout, my-account, login, privacy, terms), label |
cms_page | id_cms (identifiant de page), label |
cms_category | id_cms_category (identifiant de la page parente), label |
term | id_term, label, include_children, depth |
link | label, url |
group | label, url |
promo | image, label, text, button_label, button_url, blank, visibility |
Champs communs (sauf promo) : icon (clé de la bibliothèque, adresse d'image ou emoji), display (both, icon, text), icon_pos (before, after), icon_size (xs–xl), badge, badge_pos (float, inline), badge_variant (accent, brand, dark, light, success, danger, auto, custom), badge_bg, badge_fg (hex 3/4/6/8 chiffres ou rgb()/rgba()), badge_shape (pill, rounded, square), blank, nofollow, align (start, center, end), visibility (all, desktop, mobile).
Limites : 400 éléments par menu, 100 éléments par niveau, textes de 120 caractères (400 pour text), adresses de 500 caractères. Schémas d'adresse acceptés : http, https, mailto, tel, adresses relatives et ancres.
Paquet d'export
{
"format": "websource-megamenu",
"version": 1,
"site": "https://exemple.fr/",
"menus": [
{
"name": "Menu principal", "active": true, "published": true,
"settings": {}, "tree": [], "settings_live": {}, "tree_live": []
}
]
}
Dans un paquet, chaque élément relié à un contenu porte _refs : term:<taxonomie>:<slug> ou post:<type>:<chemin>. À l'import, ces références sont résolues sur le site d'arrivée ; une référence introuvable est signalée dans messages.
Filtres
| Filtre | Paramètres | Rôle |
|---|---|---|
websource_megamenu_locations | array $hooks (clé => libellé) | Ajouter ou retirer des emplacements. Une clé qui est le nom d'une action affiche le menu sur cette action. |
websource_megamenu_node_types | array $definitions | Modifier le catalogue des types d'éléments. |
websource_megamenu_sources | SourceInterface[] $sources | Ajouter une source de données pour un type personnalisé. |
websource_megamenu_shop_available | bool $available | Forcer la disponibilité des types « boutique ». |
websource_megamenu_brands_url | string $url, string $language | Adresse de la page « toutes les marques » (vide par défaut : le titre n'est pas un lien). |
websource_megamenu_resolved_tree | array $tree, array $menu | Arbre prêt à afficher, juste avant le rendu. |
websource_megamenu_json_ld | bool $enabled, array $menu | Désactiver les données structurées SiteNavigationElement. |
websource_megamenu_html | string $html, string $menu, string $location | HTML final du ou des menus. |
websource_megamenu_preview_head | string $head | <head> du cadre d'aperçu de l'éditeur. |
// Afficher les menus placés sur un hook du thème.
add_filter( 'websource_megamenu_locations', function ( $hooks ) {
$hooks['mon_theme_sous_entete'] = 'Sous l\'en-tête de mon thème';
return $hooks;
} );
Variables CSS
Le menu lit les variables du thème Websource sous la forme var(--wst-x, var(--color-x, repli)).
| Variable | Repli | Usage |
|---|---|---|
--wst-surface / --color-surface | #fff | Fond du menu et des panneaux. |
--wst-ink / --color-ink | #14282b | Texte ; fond du menu foncé et du tiroir. |
--wst-line / --color-line | #d9e6e4 | Filets et bordures. |
--wst-brand-600 / --color-brand-600 | #0f766e | Couleur d'accent, menu « couleur principale ». |
--wst-brand-700 / --color-brand-700 | #0b5f58 | Dégradé du tiroir mobile. |
--wst-brand-50 / --color-brand-50 | #effaf8 | Fond doux (survol, visuel). |
--wst-brand-fill, --wst-brand-on | #0f766e, #fff | Pastille « couleur principale ». |
--wst-accent-fill, --wst-accent-600, --wst-accent-on | #0f766e, #fff | Pastille « couleur d'accent ». |
--wst-radius-xl / --radius-xl | 1rem | Arrondi des languettes et visuels. |
--wst-radius-2xl / --radius-2xl | 1.5rem | Arrondi bas des grands panneaux. |
--wst-container-max / --container-max | 80rem | Largeur maximale de la barre et des panneaux. |
--wst-card-shadow | none | Ombre des panneaux et visuels. |
Variables internes, surchargeables sur .wsmm : --wsmm-bg, --wsmm-fg, --wsmm-line, --wsmm-accent, --wsmm-soft, --wsmm-pbg, --wsmm-max, --wsmm-bd-bg, --wsmm-bd-fg, --wsmm-push-w.
.wsmm { --wsmm-accent: #b45309; --wsmm-max: 72rem; }
Balisage et JavaScript
<nav class="wsmm wsmm--bar|wsmm--columns wsmm--theme-* …" aria-label="…">, listesul.wsmm__list > li.wsmm__item, panneauxdiv.wsmm__panel, liens.wsmm__link, pastilles.wsmm__badge.- Boutons d'ouverture :
button.wsmm__toggle(flèche à côté d'un lien) oubutton.wsmm__trigger(titre sans lien), avecaria-expandedetaria-controls. - Point de bascule ordinateur / mobile : 992 px.
- Script
assets/js/menu.js(sans jQuery,defer, chargé seulement si un menu en barre est rendu). API :window.WSMegaMenu.init(root),.openNode(id),.openDrawer(),.closeDrawer(). - Tout élément portant l'attribut
data-wsmm-openouvre le tiroir mobile du premier menu « push » de la page.
Classes PHP utiles
| Classe | Rôle |
|---|---|
Plugin::instance() | Services : display(), repository(), cache(), presenter(), createDefaultMenu(). |
Repository\MenuRepository | all(), find(), create(), saveDraft(), publish(), discardDraft(), setActive(), delete(), findLive(). |
Cache\MenuCache | remember(), invalidate() (cache d'objets persistant si présent, sinon transients, 15 minutes). |
Menu\TreeSanitizer, Menu\MenuSettings, Menu\FieldSanitizer, Menu\ColorSanitizer, Menu\SvgSanitizer | Nettoyage des données reçues. |
Source\SourceInterface | types(): array, resolve( array $node, ResolveContext $context ): ?array (label, url, children). |
Package\MenuPackage | export(), import(). |
// Vider le cache des menus après une opération maison.
Websource\MegaMenu\Plugin::instance()->cache()->invalidate();
Multilingue
- Les textes sont enregistrés par code de langue (Polylang, WPML, sinon la langue du site).
- Repli : langue du visiteur, puis langue par défaut traduite par la traduction de chaînes (Polylang : groupe « Websource Mega Menu » ; WPML : domaine
websource-megamenu), puis premier texte disponible. - Les catégories, pages et produits sont remplacés par leur traduction (
pll_get_post,pll_get_term, filtrewpml_object_id). wpml-config.xmldéclare le bloc et le code court comme n'ayant rien à traduire dans le contenu des pages.