Skip to content

MelisCmsBlog

Sistema di blog per i siti Melis, con un back-office React nativo per la gestione degli articoli e tre plugin di visualizzazione front-office. Pacchetto melisplatform/melis-cms-blog.

Scopo

MelisCmsBlog fornisce uno strumento Blog nel back-office dove i redattori creano e gestiscono articoli di blog multilingua (titoli, sottotitolo, fino a quattro paragrafi in testo formattato, immagini, documenti, pianificazione di pubblicazione/rimozione, uno slider opzionale e URL SEO + meta). Gli articoli vengono esposti sul front office tramite tre plugin di templating pronti all'uso: un'anteprima degli ultimi articoli, un elenco di articoli paginato e filtrabile, e una vista di dettaglio del singolo articolo. Gli URL ottimizzati per la SEO, i meta tag per articolo e i redirect 301 automatici verso l'URL canonico sono gestiti da listener di eventi dedicati.

Nel back-office React v6 (/melis-react) il modulo include un brick React nativo completo — una vera interfaccia React per elencare e modificare gli articoli, supportata da un livello JSON react-api — con un toggle New / Old che può ricadere sullo strumento legacy in un iframe. È il gemello architetturale di MelisCmsNews. Il framework, i servizi, il modello dati, il routing SEO e i plugin front sono invariati rispetto alla v5; è nuovo solo il livello di visualizzazione del back-office.

Attivazione

Aggiungere a config/melis.module.load.php:

php
return [
    'MelisCmsBlog',
];

Richiede melis-core e melis-cms, PHP ^8.1|^8.3|^8.4. Le integrazioni opzionali si attivano quando sono installati anche MelisCmsComments, MelisCmsSlider, MelisSmallBusiness o MelisCmsUserAccount. Il brick compare nella barra laterale React solo se il modulo è presente (rilevamento modulare dei brick tramite GET /melis/react-api/react-modules).

Servizi principali

Registrati come alias service_manager in config/module.config.php. Il controller React riutilizza queste stesse regole di business lato server, mantenendo la parità con lo strumento legacy.

Alias del servizioRuolo
MelisCmsBlogServiceServizio principale CRUD/query. Legge, crea, aggiorna ed elimina gli articoli; interroga per sito, lingua, intervallo di date, stato, autore. Ogni metodo scatena eventi *_start / *_end tramite MelisEngineGeneralService.

Alias dei table gateway: MelisCmsBlogTable, MelisCmsBlogTextsTable.

Tabelle del database

Struttura di base in install/sql/setup_structure.sql; migrazioni in install/dbdeploy/.

TabellaContenuto
melis_cms_blogRiga principale dell'articolo: stato, date di pubblicazione/rimozione, id del sito, image1-3, documents1-3, id dello slider
melis_cms_blog_textsTesti per lingua: titolo, sottotitolo, paragrafi 1-4, id lingua, URL SEO, meta title/description SEO, account autore

A differenza di MelisCmsNews, il blog non ha né categorie né tag — nessuna tabella di collegamento e nessun supporto per melis_cms_tag*.

Back-office React

Barra laterale → gruppo MelisCmsBlog (fa-rss). Il brick si apre come scheda principale denominata Blog e disegna la propria barra di sotto-schede interna allo strumento: una sotto-scheda per ogni articolo aperto, più un ritorno all'elenco. Ogni articolo aperto rimane montato, così il passaggio tra articoli è istantaneo.

L'elenco degli articoli

L'elenco React mostra ogni articolo della piattaforma, con schede KPI (Totale articoli, Pubblicati, Non pubblicati), una casella di ricerca con filtri All / Active / Inactive, un gestore di Colonne (nascondi/riordina), un pulsante di Esportazione (xlsx/csv), paginazione keyset e modifica / elimina per riga. Fare clic sull'intestazione di una colonna per ordinare. + New post avvia un editor vuoto.

L'elenco Blog React: schede KPI (Totale articoli / Pubblicati / Non pubblicati), una casella di ricerca con filtri All / Active / Inactive, un gestore di Colonne, un pulsante di Esportazione, il toggle New/Old e il pulsante "+ New post", con azioni di modifica ed eliminazione per riga

Un toggle New / Old (in alto a destra) commuta l'elenco — e solo l'elenco — tra l'interfaccia React e lo strumento legacy renderizzato in un iframe (/melis/react-tool-page?key=meliscmsblog_left_menu), così da poter confrontare le due interfacce affiancate.

L'editor degli articoli

Dove lo strumento legacy usava schede principali separate (Properties / Texts / Medias), l'editor React è una singola pagina scorrevole: un'ampia colonna dei contenuti a sinistra e una barra laterale delle impostazioni comprimibile a destra. Un selettore di lingua in alto contiene tutte le traduzioni contemporaneamente — tutte le lingue vengono salvate insieme in un'unica chiamata.

Colonna dei contenuti

  • Titolo / Sottotitolo — testo semplice, per lingua.

Il selettore di lingua dell'editor degli articoli (English / Français / Español), i campi Titolo e Sottotitolo e il BODY con fino a 4 paragrafi in testo formattato (TinyMCE) — ciascuno nella propria scheda riordinabile tramite trascinamento con un contatore di paragrafi

  • Body — fino a 4 paragrafi in testo formattato (TinyMCE) (cblog_paragraph1..4), riordinabili tramite trascinamento, con + Add paragraph (max. 4).
  • Media — fino a 3 immagini (Replace / Remove per slot) e fino a 3 file allegati. Compare solo dopo il primo salvataggio, poiché i caricamenti richiedono che l'articolo esista già.

L'area Media — Immagini (max. 3, con Replace/Remove per slot) e file allegati (max. 3, "Click to attach a file")

  • Comments — un pannello di moderazione nativo (aggiungi/modifica, approva/rifiuta/elimina, paginato), mostrato solo quando MelisCmsComments è installato.

Barra laterale delle impostazioni (sezioni comprimibili)

  • Status — un toggle Published / Unpublished, più un pulsante Workflow (validazione) quando MelisSmallBusiness è attivo.

La parte superiore della barra laterale delle impostazioni — il toggle Published con un pulsante Workflow, i selettori di data e ora Publish on / Unpublish on e il selettore del sito

  • Publication — selettori di data e ora Publish on / Unpublish on.
  • Site — il sito a cui appartiene l'articolo (obbligatorio).
  • Author — un selettore di autore, mostrato solo quando MelisCmsUserAccount fornisce la colonna cblog_author_account.
  • Comments validation — un toggle "i commenti front-office restano nascosti fino all'approvazione" più un interruttore specifico del blog "Account required to comment", mostrato quando MelisCmsComments è attivo.
  • SEO — Meta title, Meta description e URL semplificato, per lingua (memorizzati nella tabella dei testi, non in una tabella SEO dedicata).
  • Slider — uno slider da mostrare con l'articolo, mostrato solo quando MelisCmsSlider è attivo.

Le sezioni opzionali vengono rilevate a runtime tramite feature detection (gli endpoint companion rispondono 404 in modo controllato; lo stato del modulo viene letto da /melis/react-api/react-modules), così un modulo companion mancante non interrompe mai un salvataggio. Save (in alto a destra) persiste ogni traduzione, SEO, date, collegamenti media, slider e autore in un'unica chiamata. Un'area di Preview renderizza poi l'articolo salvato sulla sua pagina di dettaglio in un iframe.

La barra laterale delle impostazioni ampliata — un toggle Comments validation, il toggle "Account required to comment" specifico del blog, poi le sezioni comprimibili SEO e Slider

API React

Le rotte si trovano in config/react-api.php (unite tramite MelisCmsBlog\Module::getConfig()), montate sotto /melis/react-api/…. Controller: MelisCmsBlog\Controller\MelisCmsBlogReactApiController. Contratto { success, data, error }; ogni fetch invia X-Requested-With: XMLHttpRequest e credentials:'include'.

Metodo e URLScopo
GET /blogElenca gli articoli (keyset: limit, search, status, siteId, sort, dir, after) → {items,total,nextCursor}
GET /blog/statsKPI {total, published, draft}
GET /blog/:idUn articolo (?langId= → quella traduzione; campi base + paragrafi + media + SEO + slider/autore)
POST /blog/saveCrea / aggiorna (tutte le traduzioni, status, siteId, date, sliderId, authorId, flag dei commenti, seo)
DELETE /blog/delete/:idElimina un articolo e i suoi testi
GET /blog/preview/:idURL di anteprima + elenco delle pagine BLOG_DETAIL per il sito dell'articolo
GET /blog/usersUtenti front-office come autori (MelisCmsUserAccount)
GET /blog/:id/commentsCommenti di un articolo (404 se MelisCmsComments è disattivato)
POST /blog/comments/saveAggiunge/modifica un commento
POST /blog/comments/approve/:cid · /refuse/:cidModera un commento
DELETE /blog/comments/delete/:cidElimina un commento
GET /blog-sitesElenco dei siti
GET /blog-languagesLingue CMS (melis_cms_lang)

Non esistono rotte /blog/categories o /blog/tags. Gli slider provengono dalla rotta GET /melis/react-api/sliders del brick MelisCmsSlider. Il caricamento/rimozione dei media e la ricerca dell'autore dei commenti riutilizzano gli endpoint legacy (nessuna modifica al backend):

  • POST /melis/MelisCmsBlog/MelisCmsBlog/saveFileForm — caricamento multipart di immagini/file
  • POST /melis/MelisCmsBlog/MelisCmsBlog/removeAttachFile — svuota la colonna ed elimina il file

Capacità

Dichiarate in config/react.capabilities.php sotto il nodo dei diritti meliscmsblog_left_menu:

meliscmsblog_left_menu
└─ actions: list · create · edit · delete · export

React regola l'interfaccia tramite window.__melisUseCaps('meliscmsblog_left_menu').can(cap) (New post → create, Export → export, azioni di riga → edit/delete, corpo dell'elenco → list). Lato server, ogni azione del controller è protetta da denyUnlessAccess() (auth + canAccess) e poi da denyUnlessCan(cap).

Manifest del brick

public/ui-react/brick.manifest.json (bundle Vite IIFE, React/ReactDOM esternalizzati verso i global host):

json
{ "id": "blog", "route": "/melis-cms/blog", "label": "Blog",
  "forwardKey": "MelisCmsBlog/MelisCmsBlogList", "melisKey": "meliscmsblog_left_menu",
  "entry": "brick.js", "persistent": true, "subTabs": true }

forwardKey mappa il nodo del menu di sinistra legacy sulla rotta ad albero /melis-cms/blog (deep-linkabile come /melis-cms/blog/:id, usata dall'occhio Workflow). subTabs: true significa che il brick disegna la propria barra di sotto-schede interna allo strumento. Quando MelisSmallBusiness è attivo, la sezione Status renderizza il window.__melisWorkflowModal mutualizzato con ctx.wfType = 'BLOG'. Un modulo opzionale può aggiungere azioni per paragrafo tramite window.__melisBlogExtensions.renderParagraphActions(...).

Front office

Tre plugin di templating estendono MelisTemplatingPlugin, ciascuno con un controller plugin e un file di configurazione sotto config/plugins/. Tutti leggono l'id dell'articolo attivo dal parametro di query ?blogId. Nell'editor di pagina React vengono trascinati dal gruppo Melis Cms Blog nel pannello dei plugin, e ciascuno apre la classica finestra modale di configurazione a schede.

L'editor di pagina React con il pannello dei plugin aperto — il gruppo "Melis Cms Blog": Latest blog posts, Blog post list, Blog post details

Classe del pluginChiave di configVistaSchede di config
MelisCmsBlogLatestBlogPluginMelisCmsBlogLatestBlogMelisCmsBlog/latest-blogProperties, Filters
MelisCmsBlogListBlogPluginMelisCmsBlogListBlogMelisCmsBlog/blog-listProperties, Pagination, Filters
MelisCmsBlogShowBlogPluginMelisCmsBlogShowBlogMelisCmsBlog/blog-detailsProperties

Parametri di configurazione dei plugin: template_path, site_id, pageIdBlog (link alla pagina di dettaglio), column, order, limit, date_min, date_max, search; più nbPerPage / nbPageBeforeAfter (solo Blog list). Il plugin Blog list filtra anche per ?authorId. Il plugin Blog details ricade sull'articolo pubblicato più recente quando nella richiesta non è presente alcun blogId, e supporta la modalità di anteprima (renderMode === 'previewtab').

Colonne di ordinamento disponibili: cblog_id, cblog_title, cblog_publish_date, cblog_creation_date.

Plugin Blog list → Properties — Template MelisCmsBlog/blog-list, sito e pagina di dettaglio del blog

Plugin Latest blog → Filters — Sort (Blog publish date), Order, Limit, data From/To e Default search

Plugin Blog details → Properties — Template MelisCmsBlog/blog-details e un selettore Default post

Routing SEO

Gli articoli vengono serviti tramite una pagina di tipo BLOG_DETAIL che ospita il plugin Blog details, all'URL cblog_seo_url dell'articolo. Quattro listener implementano l'intera pipeline SEO:

ListenerEventoRuolo
MelisCmsBlogSEOReformatToRoutePageUrlListenerEVENT_ROUTEFa corrispondere l'URL SEO e costruisce una rotta verso la pagina BLOG_DETAIL
MelisBlogSEODispatchRouterRegularUrlListenerEVENT_DISPATCHReindirizza con 301 un URL non canonico verso il cblog_seo_url dell'articolo
MelisCmsBlogRedirect301Listenermeliscmsblog_redirect_pageImposta i meta SEO della pagina dai campi meta dell'articolo
MelisCmsBlogSEOMetaPageListenerEVENT_FINISHRiscrive i <title> / <meta description> renderizzati con i meta SEO dell'articolo

MelisCmsBlogPreviewTypeListener registra il tipo di pagina BLOG_DETAIL nel form delle proprietà di pagina (evento modify_page_properties_form_config).

Esempio

php
$blog = $this->getServiceManager()->get('MelisCmsBlogService');

// Latest 10 published posts for site 1, newest first:
$list = $blog->getBlogList([
    'siteId'   => 1,
    'langId'   => 1,
    'limit'    => 10,
    'orderBy'  => 'cblog_publish_date',
    'orderDir' => 'DESC',
]);

// Fetch one post (with its texts for a given language):
$post = $blog->getBlogById($blogId, $langId);
$txt  = $blog->getPostText($blogId);

// Create / update / delete:
$id = $blog->saveBlog(['cblog_site_id' => 1, 'cblog_status' => 1, ...], $blogId); // null → create
$blog->deleteBlogById($blogId);  // also removes its texts

// Utility:
$pages  = $blog->getBlogDetailsPagesBySite($siteId);       // BLOG_DETAIL-type pages for a site
$isDupe = $blog->checkSeoUrlDuplication($seoUrl, $blogId); // SEO URL uniqueness check
$slug   = $blog->cleanURL($title);                         // slugify (handles accents)

// Posts by a front-account author:
$posts  = $blog->getBlogListByAuthorId($authorId);

Altri listener

ListenerEventoScopo
MelisCmsBlogSliderDeletedListenermeliscmsslider_delete_slider_endRimuove dagli articoli uno slider eliminato (cblog_slider_id)
MelisCmsBlogGdprAutoDeleteActionDeleteListenermelis_cms_user_account_gdpr_auto_delete_action_deleteGDPR: azzera cblog_author_account per un account utente eliminato
MelisCmsBlogServiceMicroServiceListenermelis_core_microservice_amend_dataTrasforma i percorsi delle immagini in URL assoluti nei risultati di getBlogList per l'output API/microservizio
SiteMenuBlogDataListenerMelisFrontMenuPlugin_melistemplating_plugin_endAlimenta gli articoli (raggruppati per mese/anno) nel plugin del menu front
MelisCmsBlogFlashMessengerListenermeliscmsblog_delete_blog_end, meliscmsblog_save_blog_*_endFeedback flash-messenger per le azioni del blog

File principali

AmbitoPercorso
Config del modulo (servizi, gateway, plugin)vendor/melisplatform/melis-cms-blog/config/module.config.php
Rotte API Reactvendor/melisplatform/melis-cms-blog/config/react-api.php
Capacità Reactvendor/melisplatform/melis-cms-blog/config/react.capabilities.php
Albero dello strumento di backoffice (legacy / vista Old)vendor/melisplatform/melis-cms-blog/config/app.interface.php
Iniezione della scheda dei commentivendor/melisplatform/melis-cms-blog/config/comments.config.php
Config dei pluginvendor/melisplatform/melis-cms-blog/config/plugins/
Servizio principalevendor/melisplatform/melis-cms-blog/src/Service/MelisCmsBlogService.php
Controller API Reactvendor/melisplatform/melis-cms-blog/src/Controller/MelisCmsBlogReactApiController.php
Plugin frontvendor/melisplatform/melis-cms-blog/src/Controller/Plugin/
Listener (SEO, GDPR, slider, menu, flash)vendor/melisplatform/melis-cms-blog/src/Listener/
Sorgente del brick Reactvendor/melisplatform/melis-cms-blog/ui-react/src/
Brick compilato + manifestvendor/melisplatform/melis-cms-blog/public/ui-react/
SQL di installazionevendor/melisplatform/melis-cms-blog/install/sql/setup_structure.sql

Vedere anche: melis-cms, melis-front, melis-engine, melis-core, melis-cms-slider, melis-small-business