Vue d'ensemble
- Espace de noms
Websource\Builder, classes danssrc/(chargeur PSR-4 maison, pas de Composer). Fichier principalwebsource-builder.php: constantesWEBSOURCE_BUILDER_VERSION,WEBSOURCE_BUILDER_DIR,WEBSOURCE_BUILDER_URL, fonctionswebsource_builder()etwebsource_builder_render_composition(). - Un seul catalogue de blocs (
Block\BlockRegistry) alimente trois façades : blocs Gutenbergwebsource/<type>(rendu serveur,block.jsondansblocks/<type>/), shortcodes[wsb_<type>], et le modèle JSON{type, data, style}utilisé par l'API PHP, l'export et le connecteur Websource MCP. C'est le même modèle que le module PrestaShop Websource Builder 1.13. - Type de contenu
wsb_composition(« Compositions Websource », non public,show_in_rest), métadonnées_wsb_placements(liste d'emplacements),_wsb_lang,_wsb_pending_content(brouillon en attente d'une composition publiée). - Options :
wsb_product_layout(disposition de la fiche produit),wsb_contact_page,wsb_placement_index(index des emplacements, reconstruit à chaque enregistrement). - Aucune table, aucun JavaScript public. CSS :
assets/css/base.css+ une feuille par bloc, chargées seulement si le bloc est présent (Assets::typesIn()analyse le contenu et les compositions retenues avant l'en-tête).
| Classe | Rôle |
|---|---|
Plugin, Api, Assets | Démarrage, API publique, feuilles de style. |
Block\* | Catalogue, champs (Field), apparence (Appearance), validation (BlockSanitizer), couleurs (ColorValue), layouts (Layout\LayoutCatalog), types (Block\Type\*Block). |
Gutenberg\* | Enregistrement des blocs et données de l'éditeur (Blocks), shortcodes, gabarits (Patterns), conversion JSON ↔ contenu Gutenberg (Serializer). |
Composition\* | Type de contenu (PostType), catalogue des emplacements (Placements), affichage par hooks (Display). |
Render\* | Rendu (BlockRenderer, Html), icônes SVG (Icons), jetons (TokenResolver), contexte (RenderContext). |
Product\* | Dispositions de la fiche produit WooCommerce. |
Seo\JsonLd | FAQPage (fusionnée, une par page), VideoObject, ItemList. |
ThemePackage\Package | Export / import JSON, section builder du paquet de thème. |
Rest\Routes, Admin\Admin, I18n\Translator | Routes REST, écrans, traduction des libellés de catalogue. |
Blocs
Nom Gutenberg websource/<type>, shortcode [wsb_<type>]. Tous ont l'attribut appearance (objet : apparence + style avancé) et className. Les attributs portent le nom du champ ; les noms réservés par Gutenberg (style, align, layout…) sont préfixés wsb_ (wsb_style pour le bouton, wsb_align pour l'appel à l'action).
| Type | Champs (data) |
|---|---|
hero | title, subtitle, button_label, button_url, image, height (m, l) |
heading | title, subtitle, level (h2, h3) |
text | content (HTML riche ; dans l'éditeur, blocs imbriqués) |
image | src, alt, caption, link |
button | label, url, style (solid, outline) |
spacer | size (s, m, l), line (booléen) |
features | columns (2–4), items[] : icon, title, text |
cards | columns (2–4), items[] : image, title, text, link |
split | image, side (left, right), title, text (riche), button_label, button_url |
cta | variant (gradient, brand, split, floating, dark, minimal, icon, image), title, text, button_label, button_url, button2_label, button2_url, align (auto, left, center, right), size (s, m, l), icon, accent (blue, green, orange, pink, purple, red, black ou vide), accent_color (#rrggbb), image |
faq | items[] : question, answer |
testimonials | columns (1–3), items[] : quote, author, role, photo, rating (1–5), date |
stats | items[] : value, label |
video | url (YouTube ou Vimeo), title, description, upload_date (AAAA-MM-JJ), thumbnail |
announcement | text, link |
products | title, category (identifiant product_cat, 0 = nouveautés), limit (1–12), columns (2–4). WooCommerce requis. |
html | code (HTML filtré par wp_kses_post) |
pagecontent | title, lead, content (riche ; blocs imbriqués dans l'éditeur) |
columns | gap (s, m, l, none), valign (top, center, bottom, stretch), cols[] : w (1–6), blocks[] (modèle JSON) ; dans l'éditeur, blocs enfants websource/column (attribut w) |
Apparence (style, commune à tous les blocs) :
| Clé | Valeurs | Rôle |
|---|---|---|
bg | none, soft, surface, brand, dark | Fond. |
pad | s, m, l | Espace autour. |
width | container, wide, full | Dans le cadre, fond pleine largeur, bord à bord. |
align | left, center | Alignement du texte. |
| Style avancé | c_bg, c_bg2, g_angle, c_text, c_accent, c_overlay, c_btn_bg, c_btn_text, c_btn_hover, c_card, b_style, b_width, b_color, b_radius, shadow, sh_color, p_top|right|bottom|left, m_top|right|bottom|left, f_family, f_size, f_weight | Couleurs (#rrggbb, #rrggbbaa, rgb()/rgba()), tailles en px, listes fermées. Une valeur invalide est retirée. |
layout | clé d'un layout du type (LayoutCatalog) | Layout appliqué ; les clés de style qu'il fixe sont écrites dans style. |
Icônes (icon) : icon:<nom> parmi truck, bag, chat, home, hand, rocket, sparkles, bolt, heart, shield, phone, tag, list, alert, return, star, bell, megaphone, mountain, quote, leaf, pin, cart, fire, thumb, link, check, lock… (Render\Icons::PATHS), ou un emoji, un court texte, une adresse d'image.
Jetons dans les textes et liens (Render\TokenResolver) : {price:N}, {link:home}, {link:contact}, {link:shop}, {link:cart}, {link:account}, {link:page:ID} (alias {link:cms:ID}), {link:post:ID}, {link:product:ID}, {link:category:ID}. Les identifiants sont traduits par Polylang / WPML.
Balisage produit : <section class="wsb-block wsb-b-<type> wsb-bg-<bg> wsb-pad-<pad> wsb-w-<width> wsb-al-<align> [wsb-l-<layout>]">, contenu dans .wsb-inner. Une composition est enveloppée dans <div class="wsb-composition wsb-at-<position>" data-wsb-composition="ID">.
Shortcodes
[wsb_hero title="Bienvenue" subtitle="…" button_label="Voir" button_url="{link:shop}" image="https://…/photo.jpg" height="l" style_bg="dark" style_pad="l"]
[wsb_features columns="3" style_bg="soft"]
[wsb_item icon="icon:truck" title="Livraison rapide" text="Sous 48 h."]
[wsb_item icon="icon:shield" title="Paiement sécurisé" text="3D Secure."]
[/wsb_features]
[wsb_text]<p>Texte riche : <strong>le contenu du shortcode</strong>.</p>[/wsb_text]
[wsb_columns gap="l" valign="center"][wsb_column w="2"]…[/wsb_column][wsb_column w="1"]…[/wsb_column][/wsb_columns]
[wsb_composition id="12"]
- Un attribut par champ ;
style_<clé>pour l'apparence et le style avancé ;classajoute une classe CSS. - Listes (
features,cards,faq,testimonials,stats) : un[wsb_item …]par élément, attributs = sous-champs. - Texte riche (
text,split,pagecontent) : le contenu du shortcode remplace le champ riche. [wsb_composition id="N"]affiche une composition publiée (vide sinon).
Modèle JSON
[
{"type": "hero", "data": {"title": "Bienvenue", "button_url": "{link:shop}"}, "style": {"bg": "dark", "pad": "l"}},
{"type": "columns", "data": {"cols": [
{"w": 2, "blocks": [{"type": "heading", "data": {"title": "Colonne A"}}]},
{"w": 1, "blocks": [{"type": "button", "data": {"label": "Voir", "style": "outline"}}]}
]}},
{"type": "gutenberg", "data": {"ref": "a3f9…"}}
]
- Un champ absent prend sa valeur par défaut ; une valeur hors liste revient à la valeur par défaut ; les types inconnus sont retirés ; 80 blocs au plus ; un seul niveau de colonnes.
gutenberg: un bloc natif de l'éditeur présent dans la composition, référencé par une empreinteref.Serializerle conserve tel quel ; l'API refuse une référence inconnue (aucun bloc natif ne peut être créé par ce modèle).Gutenberg\Serializer::toContent()/fromContent()convertissent dans les deux sens avec le contenu Gutenberg sérialisé.
API PHP
websource_builder() renvoie Websource\Builder\Api :
| Méthode | Rôle |
|---|---|
version(): string | Version de l'extension. |
registry(): BlockRegistry, describeBlocks(): array | Catalogue ; description par type : type, name, shortcode, label, description, category, icon, fields, defaults, layouts. |
styleFields(): array, advancedStyleGroups(): array | Champs d'apparence et groupes du style avancé. |
sanitizeBlocks($blocks): array | Valide une liste de blocs (modèle JSON). |
renderBlocks(array $blocks): string | HTML public d'une liste de blocs. |
describePlacements(): array | pages (clé => libellé), positions (key, label, pages), targetable. |
sanitizePlacement($placement): ?array | Emplacement validé (page, position, object_id, hook, priority, native) ou null. |
languages(): array | Codes des langues du site (Polylang, WPML, sinon la locale). |
listCompositions(): array | Compositions hors corbeille : id, name, lang, status, is_published, has_changes, placements, date_upd, edit_url, shortcode. |
findComposition(int $id): ?array | Idem + blocks_live, blocks_draft. |
createComposition(string $name, string $lang, array $placement, array $blocks): int | Crée un brouillon ; 0 en cas d'échec. |
saveDraft(int $id, string $name, array $blocks): bool | Remplace le brouillon. Composition publiée : écrit _wsb_pending_content, la version en ligne ne change pas. |
publish(int $id): bool | Publie (le brouillon en attente devient le contenu). |
setActive(int $id, bool $active): bool | Met en ligne / hors ligne (statut draft), sans rien supprimer. |
pendingContent(int $id): string, discardPending(int $id): bool | Brouillon en attente. |
websource_builder_render_composition(int $id): string : HTML d'une composition publiée.
Déclarer un bloc externe (il devient bloc Gutenberg, shortcode et type du connecteur MCP) :
add_action('websource_builder_register_blocks', function (Websource\Builder\Block\BlockRegistry $registry) {
$registry->add(new Mon_Bloc()); // implémente Websource\Builder\Block\BlockInterface
});
add_filter('websource_builder_block_styles', fn(array $styles) => $styles + ['mon_bloc' => plugins_url('mon-bloc.css', __FILE__)]);
BlockInterface : getType(), getLabel(), getDescription(), getCategory(), getIcon(), getFields() (tableau de Block\Field::text(), textarea(), richText(), url(), image(), icon(), color(), select(), number(), toggle(), category(), repeater()), getDefaults(), render(array $data, RenderContext $context). Étendre Block\AbstractBlock fournit l'essentiel ; InnerContentBlock (innerField()) déclare un champ riche édité par blocs imbriqués.
Routes REST
Espace websource-builder/v1. Authentification WordPress (cookie + nonce X-WP-Nonce, ou mot de passe d'application).
| Méthode | Chemin | Droit | Rôle |
|---|---|---|---|
| GET | /blocks | edit_pages | { "blocks": [...], "style": [...], "advanced_style": [...] } |
| GET | /placements | edit_pages | { "pages": {...}, "positions": [...], "targetable": [...], "languages": [...] } |
| GET | /compositions/{id}/pending | edit_post | { "content": "<!-- wp:websource/hero … -->" } (chaîne vide sans brouillon) |
| DELETE | /compositions/{id}/pending | edit_post | { "deleted": true } |
| GET | /export | manage_options | Paquet JSON (voir Export / import). |
| POST | /import | manage_options | Corps { "package": {...}, "mode": "merge"|"replace", "dry_run": false } ; réponse = rapport. |
Les compositions elles-mêmes passent par la route native wp/v2/websource-compositions (métas _wsb_placements, _wsb_lang exposées en REST).
curl -u admin:xxxx-xxxx-xxxx-xxxx https://exemple.fr/wp-json/websource-builder/v1/placements
{
"pages": {"all": "Toutes les pages du site", "home": "Page d'accueil", "product": "Fiches produit", "cms": "Pages de contenu (CMS)"},
"positions": [{"key": "top", "label": "Tout en haut, sous l'en-tête (pleine largeur)", "pages": null},
{"key": "product_info", "label": "Dans la fiche produit, sous le bouton d'achat", "pages": ["product"]}],
"targetable": ["cms", "post", "product", "category"],
"languages": ["fr"]
}
Emplacements
Un emplacement : { "page": "product", "position": "product_info", "object_id": 0, "hook": "", "priority": 10, "native": "" } (12 au plus par composition).
Pages : all, home, shop, category, product, cms, post, blog, login, registration, password, account, orders, cart, checkout, contact, search, notfound. object_id est accepté pour cms (page), post, product, category (product_cat).
| Position | Pages | Hooks écoutés (thème Websource, WooCommerce, repli) |
|---|---|---|
top | toutes | websource_wrapper_top ; woocommerce_before_main_content (5) ; thème à blocs : après l'en-tête (render_block_core/template-part) ; sinon loop_start |
before_content | toutes | websource_content_top ; woocommerce_before_single_product / woocommerce_before_shop_loop (5) ; the_content (20) sur un contenu seul ; loop_start |
after_content | toutes | websource_content_bottom ; woocommerce_after_single_product / woocommerce_after_shop_loop (50) ; the_content ; loop_end |
home | home, all | websource_home (section de l'accueil du thème Websource), sinon comme after_content |
bottom | toutes | websource_wrapper_bottom ; woocommerce_after_main_content (50) ; thème à blocs : avant le pied de page ; sinon get_footer |
footer | toutes | websource_footer ; sinon wp_footer (1) |
cms_page | cms, post | the_content ; native = hidden, above, below |
category_top | category, shop | woocommerce_archive_description (15) |
product_info | product | woocommerce_single_product_summary (35) ; zone « Réassurance » d'une disposition de fiche produit |
product_footer | product | woocommerce_after_single_product_summary (25) |
after_login_form | login | woocommerce_login_form_end (20) |
registration_top, registration_bottom | registration, login | woocommerce_register_form_start (5), woocommerce_register_form_end (20) |
account_block | account | woocommerce_account_dashboard (20) |
cart_top | cart | woocommerce_before_cart (5) |
checkout_top | checkout | woocommerce_before_checkout_form (5) |
custom | toutes | le hook donné dans hook (^[A-Za-z_][A-Za-z0-9_\/.:-]{2,80}$), à la priorité priority |
Les thèmes à blocs sont pris en charge via render_block_core/template-part, render_block_core/query et render_block_woocommerce/product-collection.
Hooks
| Filtre | Paramètres | Rôle |
|---|---|---|
websource_builder_blocks | BlockInterface[] | Autre façon de déclarer des blocs externes. |
websource_builder_block_styles | array type => URL | Feuille de style d'un bloc externe. |
websource_builder_templates | array définitions | Gabarits (clé => label, description, icon, placement, blocks). |
websource_builder_current_pages | string[] | Clés de page de la requête en cours. |
websource_builder_composition_html | string $html, int $id, string $position | HTML d'une composition avant affichage. |
websource_builder_is_editing | bool | Contexte éditeur (aperçus). |
websource_builder_link | string $url, string $kind, int $id | Adresse résolue d'un jeton {link:…}. |
websource_builder_contact_page | int $pageId | Page de contact. |
websource_builder_price_amount, websource_builder_format_price | float ; string $text, float $amount | Jeton {price:N}. |
websource_builder_products_query | array $args, int $categoryId | Arguments de wc_get_products() du bloc Produits. |
websource_builder_show_prices | bool, WC_Product | Prix dans le bloc Produits. |
websource_builder_page_url | string | URL de la page dans le JSON-LD. |
websource_builder_product_layout | array $layout | Disposition de la fiche produit après lecture (preset, details_mode, zones, blocks). |
websource_builder_apply_product_layout | bool | Désactive l'application de la disposition. |
websource_theme_export, websource_theme_import | voir ci-dessous | Section builder du paquet de thème (Websource Theme Config). |
| Action | Paramètres | Rôle |
|---|---|---|
websource_builder_register_blocks | BlockRegistry $registry | Déclarer des blocs externes. |
websource_builder_attach_position | string $position, callable $echo, array $placement | Brancher une position sur un hook supplémentaire (add_action('mon_hook', $echo)). |
Le thème Websource expose aussi websource_theme_product_layout : la disposition enregistrée ici y est injectée (Product\ProductLayouts::forTheme()).
Export / import
GET /export, bouton Exporter les compositions, ou ThemePackage\Package::export() :
{
"format": "websource-builder",
"version": 1,
"generator": "websource-builder/1.0.0 (wordpress)",
"sections": {
"builder": [
{"key": "wsb-bandeau", "title": "Bandeau de promotion", "status": "publish", "lang": "",
"placements": [{"page": "all", "position": "top", "hook": "", "priority": 10, "native": ""}],
"content": "<!-- wp:websource/announcement {\"link\":\"{link:shop}\",\"appearance\":{\"bg\":\"brand\",\"pad\":\"s\",\"width\":\"wide\",\"align\":\"center\"}} /-->",
"pending": ""}
],
"builder_library": [{"key": "…", "title": "…", "content": "…"}],
"product_layout": null
}
}
key: clé stable de la composition (slug), utilisée pour la fusion. Un emplacement ciblant un contenu porteobject_ref(slug) à la place deobject_id; les adresses du site dans les contenus sont réécrites à l'import. Les références introuvables sont listées dansmissinget remplacées par l'accueil.builder_library: sections réutilisables (wp_block) contenant des blocs Websource ;product_layout: disposition de la fiche produit (nullsi jamais enregistrée).Package::import(array $package, string $mode = 'merge', bool $dryRun = false)renvoiedry_run,mode,created,updated,trashed,library,product_layout,missing,errors. Un paquet d'unformatdifférent ou d'uneversionsupérieure est refusé.- Le paquet complet du thème (Websource Theme Config) inclut les sections
builder,builder_libraryetproduct_layoutviawebsource_theme_export/websource_theme_import.
Variables CSS
Les feuilles de style lisent les variables du thème Websource avec repli :
| Variable lue | Repli | Usage |
|---|---|---|
--color-brand-600, --color-brand-50, --color-brand-on (alias --wst-brand…) | couleur de lien du thème ou #0f766e, #eef7f6, #ffffff | Boutons, fonds brand, soft, icônes. |
--color-ink, --wst-muted | #14282b, encre à 65 % | Textes. |
--color-line, --color-surface, --color-page | #d9e6e4, #ffffff | Bordures, cartes, fond surface. |
--radius-xl, --radius-2xl (--wst-radius) | 1rem, 1.5rem | Boutons, cartes. |
--wst-card-shadow | none | Ombre des cartes. |
--font-sans, --font-head | pile système | Polices. |
--container-page | 80rem | Largeur container / wide. |
Variables posées par l'extension sur .wsb-block quand une valeur est fixée (apparence, layout ou style avancé) : --wsb-brand, --wsb-brand-soft, --wsb-ink, --wsb-line, --wsb-surface, --wsb-text, --wsb-overlay, --wsb-btn-bg, --wsb-btn-fg, --wsb-btn-hover, --wsb-card-bg, --wsb-r, --wsb-r2 (arrondis), --wsb-shadow, --wsb-font, --wsb-weight, --wsb-k (facteur de taille).
Données structurées
Seo\JsonLd imprime dans wp_footer : FAQPage (toutes les questions des blocs FAQ de la page, fusionnées en un seul nœud), VideoObject (bloc Vidéo avec titre, description, date, miniature), ItemList + Product / Offer (bloc Produits). Rien n'est imprimé dans l'éditeur ni sur une page sans ces blocs.
Multilingue
- Composition : méta
_wsb_lang(vide = toutes les langues) comparée àpll_current_language/wpml_current_language, sinon à la locale. wpml-config.xml: typewsb_compositiontraduisible, métas copiées ou ignorées, champs texte des blocs déclarés pour l'éditeur de traduction avancé.- Jetons
{link:…}: identifiants traduits parpll_get_post/wpml_object_id.
Désinstallation
uninstall.php supprime les compositions (wsb_composition, corbeille comprise, avec leurs métas) et les options wsb_placement_index, wsb_product_layout, wsb_contact_page. Les blocs présents dans les pages restent du contenu Gutenberg ordinaire (affichés comme des blocs inconnus, texte conservé).