Simple content blocks system. Nothing fancy, easy to implement.
See composer.json
Add the following to your config.yml (optional):
PageController:
extensions:
- Toast\Blocks\Extensions\PageControllerExtensionUse Page or other class that extends SiteTree.
In your Layout/Page.ss template, add the following:
<% loop $ContentBlocks %>
$ForTemplate
<% end_loop %>
Toast\Blocks\Extensions\PageExtension:
available_blocks:
- Toast\Blocks\TextBlockYour\Page\Class:
extensions:
- Toast\Blocks\Extensions\PageContentBlockPageExtension<% loop $ContentBlocks.Sort('SortOrder') %>
<% if $IsPageContentBlock %>
<% with $Top %>
<%-- Your page content code here --%>
<% end_with %>
<% else %>
{$ForTemplate}
<% end_if %>
<% end_loop %>
"layout_src": directory that holds folders of different layouts with .ss templates "layout_icon_src": directory that holds all the layout icons "layout_dist_dir": specificed the css for block layouts
CSS file will only be included with the syntax of 'theme/themename/dist/styles/$LayoutName-$BlockType.css"
Toast\Blocks\Extensions\PageExtension:
layout_src: 'app/templates/Toast/Blocks'
layout_icon_src: 'app/client/images/layout-icons'
layout_dist_dir: 'theme/themename/dist/styles'
Ensure there are at least one CustomBlock.ss and 'customblock.svg' icon in each of the specified directory. Layout will be available for all subsites.
You may have multiple layouts, please ensure you have the block.ss created under a new layout folder in the src directory. e.g. 'app/templates/Toast/Blocks/CustomLayoutNameOne/ImageBlock.ss' or 'app/templates/Toast/Blocks/CustomLayoutNameTwo/ImageBlock.ss'
Please ensure the layout icon are named after the block name are all in lowercase, e.g. customblock.svg. e.g. 'app/client/images/layout-icons/customlayoutone/customblock.svg' or 'app/templates/Toast/Blocks/customlayouttwo/customblock.svg'
Allowed extension: 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'
Use layout_config on any block class to customise the label or icon shown in the CMS layout picker, or to disable a layout entirely. Keys are short layout folder names (e.g. Default, Split).
View the available icon classes here: client/fonts/layout-icons/font/preview.html
Toast\Blocks\TextBlock:
layout_config:
Default:
label: 'Default'
layout_icon_path: '[resources]/app/client/images/layout-icons/default/textblock.svg'
Split:
label: 'Split'
layout_icon_class: 'layout-icons-text-columns'
disabled: trueSupported keys per layout entry:
| Key | Type | Description |
|---|---|---|
label |
string | Display label shown beneath the icon in the CMS picker |
layout_icon_path |
string | Path to an SVG file. Supports the [resources] token. Highest priority. |
layout_icon_class |
string | CSS class for an icon font or sprite. Overrides directory discovery. |
disabled |
bool | Set true to hide this layout from the CMS picker |
Icon resolution priority: layout_icon_path → layout_icon_class → auto-discovered SVG from layout_icon_src directory.
Full class-name keys (e.g.
Toast\Blocks\Default\TextBlock) are still supported for backward compatibility.
Use exclude_layouts alongside layout_config to hide one or more layouts from the picker without specifying full config entries. This is the quickest way to remove a layout.
Toast\Blocks\MediaTextBlock:
exclude_layouts:
- ShortRoundedPrecedence rules:
layout_config.<Layout>.disabled: truetakes precedence overexclude_layouts.exclude_layoutsonly hides layouts from the CMS picker — the.sstemplate file must still exist for the block to render correctly if a record already holds that layout value.- YAML cannot create layouts. A
.sstemplate file must exist for a layout to appear.
If a block record has a previously saved layout that is later excluded or disabled, the block will automatically fall back to the Default layout at render time and on next save. If Default is also unavailable, the first available layout is used instead.
When a content editor opens such a block in the CMS, a warning notice will appear above the layout picker advising them that the previous layout is no longer available and prompting them to select a replacement and save.
Extend Block to create a new block type.
<?php
class MyBlock extends Toast\Blocks\Block
{
private static $singular_name = 'My Block';
private static $plural_name = 'My Blocks';
private static $icon = 'mysite/images/blocks/custom.png';
private static $db = [
'Content' => 'HTMLText'
];
}/themes/default/templates/Toast/Blocks/MyBlock.ss:
<%-- Your block template here --%>
<h2>$Title</h2>
$Content
The Toast\Blocks\Block class exposes the following methods.
forTemplate(): string- Resolve and render the active template with fallback.getCMSFields()- Build CMS fields for block editing.getAvailableLayouts($className = null)- Return discovered/allowed layouts.getOptionsForLayouts($layouts = [])- Build icon/label options for layout selectors.getTemplateOptionsField()- Return selector field (OptionsetField,DropdownField, or hidden fallback).getCSSFile()- Resolve the CSS file for the current layout/template.onBeforeWrite()- Enforce template fallback and persist CSS file path.getTemplateClass()- Return default template class name.populateDefaults()- Set default/fallback template on new records.
getContentSummary()- CMS summary for content/heading.getIconForCMS()- Block icon HTML shown in CMS.IconForCMS()- Alias forgetIconForCMS().getTitle()- Display title fallback to block singular name.getApiURL()- API endpoint URL for this block.getBlockTemplateName()- Short class name used as template base.getHtmlID()- Deterministic HTML id value for this block.getDisplayTitle()- Title with parent page context.getImageFocusPosition($imageid = null)- Return focus point CSS position for an image.getBlockID()- Anchor-friendly block id (fromAnchorNameor fallback).getExtraRequirements()- Extra frontend requirements injected by extensions.getBlockSpecificExtraClasses()- Extra CSS classes injected by extensions.
getLink($action = null)- Relative URL to this block anchor.Link($action = null)- Alias forgetLink().getBlockLink($parent)- Block link for a specific parent page.getBlockPreviewURL($anchor = null)- CMS preview URL including stage/subsite params.getAbsoluteLink($action = null)- Absolute stage URL to this block anchor.AbsoluteLink($action = null)- Alias forgetAbsoluteLink().
getLinkedPagesList()- Comma-separated linked page titles.getAllPages()- Unique pages (main + subsites) using this block.getPagesFromSiteTree()- Pages using this block in current context.getPagesFromMainSite()- Pages using this block in main site context.getPagesFromSubsites()- Pages using this block across all subsites.getParentPage()- Attempt to resolve current parent page.getPage()- Resolve page owning this block in current controller context.getCMSParentPage()- Current CMS parent page.getCMSEditLink(): ?string- Direct CMS edit URL for this block.getCMSSiblingBlocks()- Sibling blocks on the same page.getCMSSiblingBlocksLinks()- HTML list of sibling block links.
canView($member = null)canEdit($member = null)canDelete($member = null)canCreate($member = null, $context = [])canDeleteFromLive($member = null)canPublish($member = null)canArchive($member = null)isPublished()isNew()doArchive()
These are not part of the public API, but are useful if you extend Block and override behavior.
- Layout config and filtering:
getLayoutConfig(),getExcludedLayouts(),getLayoutConfigEntry(...),isLayoutDisabled(...)filterLayoutsByClassName(...),filterToConfiguredLayouts(...),filterDisabledLayouts(...)
- Layout discovery:
discoverLayouts(),discoverModuleLayouts(),discoverAdditionalLayouts(),scanTemplateDirectory(...)
- Icon resolution:
getConfiguredLayoutIcon(...),getLayoutIconClass(...),getDiscoveredLayoutIcon(...),getLayoutIconSourcePath()buildLayoutOption(...),getLayoutOptionLabel(...)
- Template fallback and warnings:
resolveTemplateWithFallback(...),getAvailableTemplateClasses(...),isTemplateMissing(),getTemplateMissingNoticeField()
- URL helpers:
getCurrentCMSRecord(),getLinkParentPage(),buildBlockLinkFromParent(...),appendQueryParams(...),appendHash(...)