Le Origini dei contenuti consentono a un plugin abilitato di esporre dati di dominio tipizzati ai blocchi CMS esistenti senza possedere il markup pubblico. Un plugin di catalogo, commercio, eventi o notizie fornisce i record; le pagine CMS mantengono il controllo di layout, composizione dei blocchi, traduzione, anteprima e rendering.

Il confine è intenzionale:

  • un'origine del plugin risponde a quali dati sono disponibili;
  • un blocco CMS risponde a come vengono presentati i dati;
  • l'albero di pagine e slot risponde a dove appaiono.

I plugin non devono ricreare i renderer principali di Header, Rich Text, Card, Grid, Slider o Slide soltanto per mostrare record di proprietà del plugin.

Contratto dell’origine entità

Un plugin abilitato registra un'origine entità nella propria definizione:

PluginDefinition::make('plugin-catalog')
  ->contentSources([
    ContentSourceDefinition::entity('plugin-catalog::plugin')
      ->label('Plugin')
      ->resolver(PluginSource::class)
      ->fields([
        'name' => ['type' => 'text', 'label' => 'Name'],
        'description' => ['type' => 'rich_text', 'label' => 'Description'],
        'download_url' => ['type' => 'url', 'label' => 'Download URL'],
      ]),
  ]);

Il resolver implementa ContentSourceResolver. options() fornisce all'editor di blocchi scelte di anteprima sicure e leggibili; resolve() restituisce un record per la chiave stabile richiesta e per il contesto corrente di sito, pagina, locale e anteprima.

Il plugin rimane l'unico proprietario delle proprie tabelle e dei modelli di dominio. Il CMS memorizza soltanto l'handle dell'origine, la chiave stabile del record, il campo selezionato e il normale valore editoriale di riserva del blocco.

Accesso e cache

Un'origine che contiene dati riservati collega tramite ContentSourceAccessPolicy una classe che implementa accessPolicy(...). La policy riceve sito, pagina, locale, stato dell'anteprima e attore autenticato prima della chiamata a qualsiasi resolver. Un'origine negata si comporta come non disponibile e il blocco pubblico conserva il proprio valore editoriale di riserva.

I plugin possono attivare la cache limitata dei risultati con cacheFor($seconds). Le chiavi della cache includono origine, sito, pagina, locale, argomenti di record/query e impostazioni dell'origine. Le richieste di anteprima ignorano la cache, così gli editor controllano sempre dati aggiornati. Dopo una scrittura nel dominio, i plugin possono chiamare app(ContentSourceRuntime::class)->invalidate('plugin-handle::source') per rendere immediatamente obsolete tutte le varianti memorizzate di quell'origine. Una durata pari a zero, il valore predefinito, disabilita la cache.

Comportamento dell’editor

I blocchi esistenti supportati mostrano un controllo Origine del contenuto nella scheda Impostazioni. L'editor può mantenere il valore letterale inserito nei Campi del blocco oppure selezionare un record dell'origine e un campo di tipo compatibile. Nessuna espressione di associazione viene digitata manualmente.

Le associazioni di campo supportate includono:

  • title di Header da un campo origine text;
  • content di Plain Text da un campo origine text;
  • content di Rich Text da un campo origine text o rich_text.
  • Origine dell'immagine, didascalia, testo alternativo e collegamento da campi compatibili.
  • Etichette e URL di Button e Button Link.
  • Titolo, testo secondario, descrizione e URL di Link List Item.

Durante il rendering pubblico, l'associazione prevale quando si risolve in un valore non vuoto. Record mancanti, plugin disabilitati, origini non disponibili e valori vuoti mantengono in sicurezza il valore editoriale del blocco. Gli errori del resolver vengono segnalati senza rendere indisponibile la pagina.

Le associazioni si trovano in settings.content_bindings, quindi i comportamenti esistenti di duplicazione, revisione, esportazione e importazione delle pagine le conservano senza una colonna di database specifica del dominio.

Origini delle raccolte

Un plugin può registrare ContentSourceDefinition::collection(...) con un resolver che implementa ContentCollectionSourceResolver. I contenitori compatibili con le raccolte possono selezionare tale raccolta e un figlio diretto esistente come modello ripetuto. Durante il rendering, il CMS clona quel sottoalbero per ogni record, fornisce il record come elemento corrente della raccolta e risolve su di esso le associazioni dei campi discendenti.

Il supporto delle raccolte è una capacità del contratto del blocco, non un elenco CMS di nomi di blocchi speciali. I tipi principali Section, Container, Stack, Cluster, Grid e Slide accettano qualsiasi modello figlio diretto altrimenti valido. Slider accetta Slide; Columns accetta Column Item; Feature Grid accetta Feature Item o Column Item; Link List accetta Link List Item. Split e i contenitori semantici come Card non dichiarano tale capacità, perché ripetere i loro figli strutturali violerebbe il contratto di layout.

I tipi di blocco dei plugin possono aderire con ->contentCollectionTemplate() per qualsiasi tipo figlio valido, oppure passare un elenco di slug di catalogo figli consentiti. I manifest installati esprimono lo stesso contratto con content_collection.enabled e l'eventuale content_collection.child_types. La vista pubblica del contenitore del plugin esegue il rendering dei figli risolti tramite ContentCollectionRenderer::children($block), come le viste dei contenitori principali.

Gli altri figli restano contenuto editoriale ordinario e mantengono la loro posizione. Il modello selezionato viene sostituito sul posto dai record risolti, così un contenitore può combinare intenzionalmente contenuti manuali e dinamici senza un renderer carousel, grid o card di proprietà del plugin. Gli editor possono visualizzare in anteprima fino a tre record, limitare i record, filtrare per un campo e valore dell'origine, ordinare per un campo dell'origine in entrambe le direzioni e impaginare i risultati di Grid o Stack. La risoluzione è limitata a 50 record. Un'origine mancante, un plugin disabilitato, un modello non valido o un errore del resolver ripristina in sicurezza il normale albero di blocchi memorizzato.

Per origini piccole, ContentCollectionSourceResolver è sufficiente e il CMS applica filtro, ordinamento e impaginazione all'iterabile. Le origini grandi dovrebbero implementare QueryableContentCollectionSourceResolver. Il CMS passa quindi al plugin una ContentCollectionQuery tipizzata e utilizza un ContentCollectionResult, consentendo filtro database/API, ordinamento, limiti, totali e finestre di pagina senza caricare l'intera raccolta.

Gli editor scelgono separatamente se un risultato valido ma vuoto e un errore del resolver nascondono il modello ripetuto o mostrano il suo valore editoriale di riserva. Le origini negate o rimosse conservano il contenuto memorizzato. Il pannello Impostazioni segnala le associazioni il cui plugin, origine o campo dichiarato è scomparso, affinché aggiornamenti e rimozioni dei plugin non lascino silenziosamente contenuti orfani.

Le associazioni e la configurazione della raccolta risiedono nel normale payload settings del blocco. Le revisioni delle pagine e l'esportazione/importazione del sito copiano già tale payload alla lettera; nessuna tabella di proprietà del plugin né output eseguibile del resolver entra in una revisione CMS o in un pacchetto di trasferimento.

API interna dei contenuti

I client API individuano soltanto le origini abilitate e accessibili con GET /webadmin/api/content-sources. Il passaggio di block_id aggiunge le destinazioni di associazione compatibili e indica se il blocco può ospitare la raccolta. Le origini entità includono le proprie scelte sicure di record; i campi provengono sempre dal contratto dichiarato del plugin.

POST /webadmin/api/content-sources/{source}/preview risolve un record entità o fino a cinque record di raccolta senza modificare il contenuto. Le risposte di anteprima scartano ogni valore non dichiarato dall'origine e usano come contesto il blocco richiesto, il locale, l'attore autenticato e la policy di accesso all'origine.

Un blocco strutturato esistente accetta content_bindings e content_collection al livello principale di PATCH /webadmin/api/blocks/{block}; gli stessi oggetti sono accettati anche sotto settings. Ogni oggetto sostituisce la configurazione corrispondente e null la cancella. Prima della scrittura, l'API convalida destinazioni dei blocchi, tipi di campo, accesso all'origine, scelte dei record, proprietà dei figli diretti e tipi di modello di raccolta consentiti dal contratto del blocco. Una configurazione non valida restituisce 422 invalid_content_source_configuration. Dopo la scrittura, eseguire il rendering della bozza o della pagina di aggiornamento proprietaria per verificare il risultato composto.