Vue d'ensemble
- Module
websourcenewproducts, classeWebsourceNewProducts, espace de nomsWebsource\NewProducts(PSR-4 danssrc/,vendor/autoload.php). - Implémente
WidgetInterface. Configuration dans la page Configurer du module (listeviews/templates/admin/list.tpl, formulaireconfigure.tpl), sans contrôleur d'administration dédié. - Les vignettes sont rendues par le présentateur natif (
ProductListingPresenter,PriceFormatter) et le partial du thèmecatalog/_partials/miniatures/product.tpl(ITEM_TEMPLATEdu module en repli). - Cache court des identifiants de produits (
Query\ProductIdCache, fichiers, 5 minutes ; clé boutique + langue + groupe de clients + devise + période + produit/panier). Prix et stocks ne sont jamais mis en cache.
Hooks
Hooks fixes (WebsourceNewProducts::HOOKS)
| Hook | Rôle |
|---|---|
actionFrontControllerSetMedia | Ajoute views/css/front.css et, si un carrousel s'affiche, views/js/carousel.js (bas de page, defer) — seulement quand un bloc s'affichera sur la page. |
actionProductSave, actionProductAdd, actionProductDelete, actionObjectProductUpdateAfter, actionOrderStatusPostUpdate | Vident le cache des identifiants (toutes boutiques). |
actionWebsourceBuilderRegisterBlocks | Déclare le bloc « Nouveautés » au Websource Builder. |
actionObjectShopAddAfter, actionShopDataDuplication, actionObjectShopDeleteAfter | Multiboutique : branchement d'une nouvelle boutique, copie des réglages, nettoyage. |
actionWebsourceThemeExport / actionWebsourceThemeImport | Section newproducts (version 1) des paquets .wsxtheme : blocs, textes par ISO, catégorie category:slug, produits product:référence. |
Hooks d'affichage (greffés par boutique selon les blocs actifs, Hook\HookSynchronizer)
| Clé | Libellé | Hook | Page naturelle |
|---|---|---|---|
home | Page d'accueil | displayHome | home |
under_header | Sous l'en-tête (pleine largeur) | displayNavFullWidth | au choix |
category_footer | Pages catégories, sous la liste des produits | displayFooterCategory | category |
product_footer | Fiche produit, sous la description | displayFooterProduct | product |
cart | Panier, sous la liste des articles | displayShoppingCartFooter | cart |
before_footer | Juste au-dessus du pied de page | displayFooterBefore | au choix |
footer | Dans le pied de page | displayFooter | au choix |
custom | Autre emplacement | tout display* saisi | au choix |
Les méthodes hookDisplayXxx sont servies par __call(). Pages : all, home, category, product, cart, checkout (order, orderopc), cms, search (détection par php_self).
Sources de produits (Settings\SourceCatalog)
| Clé | Libellé | Options utilisées | Contexte | Lien du bouton |
|---|---|---|---|---|
native | Nouveautés | tri | — | page new-products |
featured | Produits à la une | catégorie, tri | — | catégorie |
bestsellers | Meilleures ventes | période | — | page best-sales |
specials | Promotions | tri | — | page prices-drop |
viewed | Produits déjà vus | — (pas de cache, cookie de session) | — | — |
related | Produits associés | tri | fiche produit | — |
crosssell | Ventes croisées | période (365 j par défaut) | produit ou panier | — |
category | Une catégorie | catégorie, tri | — | catégorie |
manual | Ma sélection | produits choisis | — | — |
Tris : position, newest, oldest, name_asc, price_asc, price_desc. Périodes : 7, 30, 90, 180, 365, 0 (depuis toujours). Pastilles : new, discount, on-sale, pack, online-only, out_of_stock (Render\FlagFilter).
Widget Smarty
{widget name='websourcenewproducts'} {* premier bloc actif, ou blocs du hook courant *}
{widget name='websourcenewproducts' block=2} {* un bloc précis, par numéro *}
{widget name='websourcenewproducts' block=2 count=6 columns=3 layout='carousel' title='Nos nouveautés'}
Surcharges acceptées : title, count (1 à 24), columns (2 à 6), layout (grid, carousel). CSS et JS sont alors insérés une seule fois dans la page.
API PHP
$module = Module::getInstanceByName('websourcenewproducts');
echo $module->renderForBlock(['block' => 2, 'title' => '', 'count' => 8, 'columns' => 4, 'layout' => 'grid'], (int) $languageId);
Classes principales : Settings\BlockRepository (WSNP_BLOCKS, portées Configuration), Settings\BlockCollection (find, sanitizeAll), Settings\SettingsSanitizer (applyBlockData), Settings\Defaults (MAX_BLOCKS 30, MIN_COUNT 1, MAX_COUNT 24, MIN_COLUMNS 2, MAX_COLUMNS 6), Query\ProductListProvider, Query\ProductIdSource, Render\SectionViewBuilder, Render\JsonLdBuilder, Admin\ProductSearch.
Bloc Websource Builder
Classe Builder\NewProductsBlock (catégorie « Boutique »), enregistrée seulement si Websource\Builder\Block\BlockInterface existe.
| Champ | Valeurs |
|---|---|
| Bloc à afficher | liste des blocs du module |
| Titre | vide = titre du bloc |
| Nombre de produits | 1 à 24 (défaut 8) |
| Colonnes (sur grand écran) | 2 à 6 (défaut 4) |
| Présentation | grid Grille, carousel Carrousel |
Page de configuration
Formulaire POST sur index.php?controller=AdminModules&configure=websourcenewproducts&token=… :
| Paramètre | Rôle |
|---|---|
submitWsnp + champs du bloc (id, name, active, title[id_lang], subtitle[id_lang], button_label[id_lang], show_button, source, category_id, product_ids[], period_days, count, sort, position, hook, page, layout, columns, show_badges, badges_on[], badges_order[], lazy_images, json_ld, use_theme_design, bg_color, title_color, borders, radius) | Enregistre un bloc (création si id = 0). |
wsnpDo = toggle, duplicate, delete, up, down + wsnp_id | Actions de la liste. |
wsnp_edit = N (0 = nouveau, avec wsnp_source) | Ouvre le formulaire. |
resetWsnp | Remet un seul bloc « Nouveautés » d'origine. |
inheritWsnp | Supprime la liste propre à la boutique (contexte boutique). |
wsnp_action=search&q=… (GET) | Recherche de produits : JSON [{"id":19,"name":"Mug personnalisable","reference":"demo_14"}, …] (nom, référence ou identifiant, bornée par product_shop). |
Réglages
| Clé de configuration | Portée | Contenu |
|---|---|---|
WSNP_BLOCKS | commune, groupe ou boutique (héritage Configuration) | JSON {"v":2,"blocks":[{id, name, active, position, hook, page, title{}, subtitle{}, button_label{}, show_button, count, source, category_id, product_ids[], sort, period_days, layout, columns, show_badges, badges[], lazy_images, json_ld, use_theme_design, bg_color, title_color, borders, radius}]} |
WSNP_SETTINGS | héritage 1.1 | Migré en premier bloc par upgrade-1.2.0.php (Settings\LegacyMigrator). |
Mises à niveau : upgrade-1.1.0.php (multiboutique), upgrade-1.2.0.php (blocs multiples), upgrade-1.2.1.php (JSON-LD activé), upgrade-1.3.0.php (hooks de paquet de thème).
Données structurées
Par bloc affiché et si json_ld est actif : un ItemList (@id<url de la page>#itemlist-newproducts-<n>, une seule fois par liste de produits et par page) dont chaque élément porte @id<url>#product, nom, adresse sans fragment et une offre dans la devise du visiteur avec disponibilité (InStock, OutOfStock, BackOrder, LimitedAvailability) et vendeur {base}#organization.
Template et CSS
Templates views/templates/hook/section.tpl (section) et item.tpl (vignette de repli), surchargeables dans themes/<theme>/modules/websourcenewproducts/views/templates/hook/. Variable Smarty $wsnp : uid, class, style, title, subtitle, products[] (présentés), item_template, is_carousel, show_button, button_label, button_url, labels, json_ld.
Classes : .wsnp, .wsnp--custom, .wsnp__head, .wsnp__heading, .wsnp__title, .wsnp__subtitle, .wsnp__nav, .wsnp__track, .wsnp__more, .wsnp__btn, .wsnp__link.
| Variable CSS | Rôle |
|---|---|
--wsnp-cols, --wsnp-cols-md | Colonnes sur grand écran et tablette. |
--wsnp-gap | Espacement des cartes. |
--wsnp-bg, --wsnp-title | Fond de section et couleur du titre personnalisés. |
Variables du thème reprises avec repli : --color-brand-600, --color-brand-50, --color-ink, --color-line, --color-surface, --font-head, --radius-xl, --radius-2xl, --wst-card-shadow. CSS mobile d'abord (2 colonnes dès 320 px, 3 en tablette), propriétés logiques (RTL : flèches du carrousel inversées), prefers-reduced-motion, contraste élevé.
Tests
php tests/run.php (logique pure, sans PrestaShop).