際際滷

際際滷Share a Scribd company logo
HARNESSING THE POWER OF
BLUEFOOT FOR DEVELOPERS
John Hughes - Fisheye
@JohnHughes1984
ABOUT ME
Technical Director at Fisheye
Working with Magento  5 years
Passionate about:
- Ensuring developers have tools / guidance
to work e鍖ciently and follow best practice
- Providing best in class solutions for
merchants
- Being part of #RealMagento community
IMAGINE 2017
MOST INNOVATIVE
WEBSITE
AWARD WINNERS
@JohnHughes1984
OVERVIEW
What is BlueFoot?
Developer overview of Page Builder Blocks
Creating a module to add BlueFoot Page Builder Blocks
Ideas for new content types and further customisation
What the future holds for BlueFoot
@JohnHughes1984
SO WHAT IS BLUEFOOT?
@JohnHughes1984
LETS HAVE A SHOW OF HANDS 
Who knows what BlueFoot is?
Whos installed it or used it in a project?
Whos extended it?
Harnessing the power of blue foot for developers
CMS & Page Builder for Magento
- Built by Gene Commerce
- Acquired by Magento in December 2015
Drag & drop multiple content types in 鍖exible row / column layouts
Can be used anywhere in admin where WYSIWYG area is present
Harnessing the power of blue foot for developers
PAGE BUILDER BLOCKS
PAGE BUILDER BLOCK TYPES
MENU
STAGE
ROWS
COLUMNS
PAGE BUILDER
BLOCK ATTRIBUTES
EDIT PANEL
TABS
@JohnHughes1984
OK GREAT, BUT IM
A DEVELOPER #$
@JohnHughes1984
ENTITY ATTRIBUTE VALUE
EAV
@JohnHughes1984
ENTITIES
@JohnHughes1984
BLUEFOOT ENTITIES
Every Page Builder Block
instance within a stage is
stored as an Entity
≒gene_bluefoot_entity table
@JohnHughes1984
BLUEFOOT ENTITY TYPE
 Not to be confused with standard
entity types
 BlueFoot Entity Type = 
Page Builder Block
- e.g. Image, Video, 際際滷r
 gene_bluefoot_entity_type table
@JohnHughes1984
BLUEFOOT ENTITY TYPE GROUP
 BlueFoot Entity Types are assigned
to a BlueFoot Entity Type Group
- Menu group headings
- e.g. General, Media, Commerce
- gene_bluefoot_entity_type_group
table
@JohnHughes1984
ATTRIBUTES
@JohnHughes1984
ATTRIBUTE SETS
All attributes can be added to an attribute set just like any other
EAV type
Each BlueFoot Entity Type (Page Builder Block) is linked to a
unique attribute set of the same name
- e.g. the Driver Page Builder Block has an accompanying
attribute set also named Driver to store its attributes
@JohnHughes1984
ATTRIBUTE GROUPS
 Each Page Builder Blocks
attribute set can be further split
into groups
 These groups map to tabs within
Page Builder Block edit panel
- e.g. Images, Link, Seo, Advanced
@JohnHughes1984
VALUES
@JohnHughes1984
PAGE BUILDER BLOCKS 起
@JohnHughes1984
PAGE BUILDER BLOCK
When it comes to rendering each Page Builder Block is assigned a block
class and template 鍖le
≒Page Builder Blocks can also have child items
- e.g. individual banners within a slider / carousel or items within an
accordion
- These child items are also Page Builder Blocks (BlueFoot Entity Types)
but are generally hidden from the menu
@JohnHughes1984
ADDING NEW CONTENT
BlueFoot allows creation / management of attributes sets (Page
Builder Blocks) within the admin panel
Block classes, templates & other settings can also be managed
This is great but for reusable solutions we need to build a
module
@JohnHughes1984
LETS BUILD A NEW PAGE
BUILDER BLOCK &'
@JohnHughes1984
LIST BUILDER
Lets create a list builder, made up of:
 A List Page Builder Block - for <ul>
elements
 A child List Items block - for <li>
elements
 A new Fisheye group to display our
block under in BlueFoot menu
@JohnHughes1984
LIST PAGE BUILDER BLOCK
 Options
- List Title - text 鍖eld
- List Style - select - e.g. none, circle, disc etc.
 Items
- List Items - child_item - for List Item blocks
 Advanced
- CSS Classes - default attribute for CSS
@JohnHughes1984
LIST ITEM PAGE BUILDER BLOCK
 Options
- List Text - text 鍖eld
- List Icon - text 鍖eld - Font Awesome
 Link
- List Link URL - text 鍖eld
- Link Target - boolean
 Advanced
- CSS Classes - default attribute for CSS
@JohnHughes1984
MODULE COMPONENTS
 General module con鍖guration 鍖les
 BlueFoot speci鍖c con鍖guration 鍖les
 Install script and data source(s)
 View 鍖les - block classes and templates
 Static assets - CSS, JS, images etc.
@JohnHughes1984
GENERAL MODULE CONFIGURATION
As with any other module well need the basics:
composer.json - declare dependency on gene/bluefoot package
etc/module.xml - add Gene_BlueFoot to sequence node ensure correct load
order
registration.php - registers module
@JohnHughes1984
BLUEFOOT SPECIFIC CONFIGURATION
BlueFoot has its own XML/XSD con鍖guration 鍖les:
Renderers - block classes for use by Page Builder Blocks
Templates - template 鍖les for for use by Page Builder Blocks
Plugins - JS widgets e.g. colour picker, product search, maps
Structural elements - e.g. rows and columns
@JohnHughes1984
etc/bluefoot/pagebuilder.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:gene:bluefoot:etc/bluefoot/pagebuilder.xsd">
<content_blocks>
<renderers>
<renderer name="fisheye_list_renderer"
class="FisheyeBlueFootListBlockListBlock"/>
<renderer name="fisheye_list_item_renderer"
class="FisheyeBlueFootListBlockListItem"/>
</renderers>
<templates>
<template name="fisheye_list"
file="Fisheye_BlueFootList::list.phtml"/>
<template name="fisheye_list_item"
file="Fisheye_BlueFootList::list/item.phtml"/>
</templates>
</content_blocks>
</config>
@JohnHughes1984
INSTALL SCRIPT
In essence the same as any other installer script
To create new entity type group we need to inject
GeneBlueFootApiContentBlockGroupRepositoryInterface and
GeneBlueFootApiDataContentBlockGroupInterface
Injecting GeneBlueFootModelInstallerFile we can import data
from JSON 鍖le rather than MagentoEavSetupEavSetup methods
@JohnHughes1984
Setup/InstallData.php
class InstallData implements InstallDataInterface
{
/**  */
public function install(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
) {
$setup->startSetup();
$this->addContentBlockGroup();
$this->installData($setup);
$setup->endSetup();
}
@JohnHughes1984
Setup/InstallData.php
/**  */
protected function addContentBlockGroup()
{
/** @var ContentBlockGroupInterface $group */
$group = $this->contentBlockGroupInterfaceFactory-
>create();
$group->setCode('fisheye')
->setName('Fisheye')
->setIcon('<i class="fa fa-chevron-down"></i>')
->setSortOrder('50');
$this->contentBlockGroupRepository->save($group);
}
@JohnHughes1984
Setup/InstallData.php
/**  */
protected function installData(ModuleDataSetupInterface $setup)
{
$file = $this->moduleReader->getModuleDir(false,
'Fisheye_BlueFootList') . DIRECTORY_SEPARATOR . 'Setup' .
DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'install-
blocks-attributes.json';

if ($this->ioFile->fileExists($file)) {
$this->fileInstaller->install($file, $setup);
}
}
@JohnHughes1984
DATA SOURCE - JSON
JSON data provides the source to create:
- Page Builder Blocks
 Linked attributes
- Custom attributes
Reference default BlueFoot JSON 鍖le for data structure
@JohnHughes1984
Setup/data/install-blocks-attributes.json
"content_blocks": [
{
"identifier": "fisheye_list",
"name": "List",
"content_type": "block",
"description": List builder",
"renderer": "fisheye_list_renderer",
"item_view_template": "fisheye_list",
"singular_name": "List",
"include_in_sitemap": "0",
"icon_class": "fa fa-list-ul",
"show_in_page_builder": "1",
"sort_order": "100",
"group": fisheye,

}
]
REFERENCES VALUES
DECLARED IN
PAGEBUILDER.XML
TO SET MENU ICON
(FONT AWESOME)
TO ADD TO NEWLY
CREATED MENU GROUP
FOR ADDING NEW PAGE BUILDER BLOCKS
@JohnHughes1984
Setup/data/install-blocks-attributes.json
"content_blocks": [
{
"identifier": "fisheye_list_item",
"name": List Item",
"content_type": "block",
"description": List builder item",
"renderer": fisheye_list_item_renderer",
"item_view_template": fisheye_list_item",
"singular_name": List Item",
"include_in_sitemap": "0",
"icon_class": "fa fa-circle",
"show_in_page_builder": "0",

}
]
LIST SUB BLOCK NOT
DISPLAYED IN MENU
@JohnHughes1984
Setup/data/install-blocks-attributes.json
"content_blocks": [
{
,
"attribute_data": {
"attributes": [
"list_title",
"list_style",
"list_items",
"css_classes"
],
"groups": [
{
"attribute_group_name": "Options",
"sort_order": "10",
"default_id": "0",
"attributes": [
{
"attribute_code": "list_title",
"sort_order": "10"
},
{
"attribute_code": "list_style",
"sort_order": "20"
}
]
},

DECLARE ATTRIBUTES
DECLARE ATTRIBUTE GROUPS
ADD ATTRIBUTES
TO GROUPS
@JohnHughes1984
Setup/data/install-blocks-attributes.json
"attributes": [
{
"attribute_code": "list_style",
"backend_model": null,
"backend_type": "varchar",
"frontend_input": "select",
"frontend_label": ["List Style"],
"source_model": "FisheyeBlueFootListModelEntityAttributeSourceListStyle",
"is_required": "1",
"is_user_defined": "1",
"note": null,
"is_visible": "1",
"widget": null,
"data_model": null,
"entity_allowed_block_type": false

},

]
CUSTOM SOURCE MODEL
NEVER SET TO 0 AS WILL
ADD ATTRIBUTE TO ALL
ATTRIBUTES SETS!!!
FOR ADDING NEW ATTRIBUTES
@JohnHughes1984
Setup/data/install-blocks-attributes.json
"attributes": [
{
"attribute_code": "list_items",
"backend_model": "MagentoEavModelEntityAttributeBackend
ArrayBackend",
"backend_type": "text",
"frontend_input": "child_entity",
"frontend_label": ["List Items"],
"source_model": "GeneBlueFootModelAttributeSourceEntity
Child",
"entity_allowed_block_type": fisheye_list_item,

},

]
BACKEND & SOURCE
MODEL REQUIRED FOR
CHILD BLOCK ATTRIBUTES
ENSURES ATTRIBUTE IS
ONLY USED FOR THE
SPECIFIED BLOCK TYPE
@JohnHughes1984
VIEW FILES
Block classes / template 鍖les need to be placed as declared in
etc/bluefoot/pagebuilder.xml earlier
Blocks extend GeneBlueFootBlockEntityPageBuilderBlockAbstractBlock
Admin templates use mustache.js templates
- {{attribute_code}} handles are replaced via JS to update preview
@JohnHughes1984
Block/ListBlock.php
class ListBlock extends AbstractBlock
{
/**  */
public function getListTitle()
{
return $this->stripTags($this->getEntity()->getData('list_title'));
}

/**  */
public function getListStyle()
{
return $this->getEntity()->getData('list_style');
}
}
@JohnHughes1984
Block/ListItem.php
class ListItem extends AbstractBlock
{
/**  */
public function getItemIcon()
{
return $this->stripTags($this->getEntity()->getData('list_item_icon'));
}

/**  */
public function getItemLinkUrl()
{
return $this->escapeXssInUrl($this->getEntity()-
>getData('list_item_url'));
}
@JohnHughes1984
view/frontend/templates/list.phtml
<?php
/** @var FisheyeBlueFootListBlockListBlock $block */
?>

<?php if ($block->hasChildEntities('list_items')): ?>

<?php $_items = $block->getChildEntities('list_items'); ?>

<div class="bluefoot-list <?php echo $block->getCssAttributes(); ?>" <?php echo $block->getStyleAttributes(); ?
>>

<h3><?php echo $block->getListTitle(); ?></h3>

<ul style="list-style-type: <?php echo $block->getListStyle(); ?>">
<?php foreach ($_items as $_item): ?>
<?php echo $_item->toHtml(); ?>
<?php endforeach; ?>
</ul>

</div>

<?php endif; ?>
@JohnHughes1984
view/frontend/templates/list/item.phtml
<?php
/** @var FisheyeBlueFootListBlockListItem $block */
$linkIcon = $block->getItemIcon();
$linkUrl = $block->getItemLinkUrl();
?>


<li class="bluefoot-list-item <?php echo $block->getCssAttributes(); ?>"<?php echo $block->getStyleAttributes(); ?>>

<?php if ($linkUrl): ?>
<a href="<?php echo $linkUrl; ?>" <?php echo $block->getItemLinkTarget() ? 'target="_blank"' : '' ?>>
<?php endif; ?>

<?php if ($linkIcon): ?>
<i class="<?php echo $linkIcon; ?>"></i>
<?php endif; ?>

<?php echo $block->getItemText(); ?>

<?php if ($linkUrl): ?>
</a>
<?php endif; ?>

</li>
@JohnHughes1984
view/adminhtml/templates/list.phtml
<div class="bluefoot-list gene-bluefoot-pagebuilder-block bluefoot-entity-
align-{{align}}">
<h3>{{list_title}}</h3>
<ul style="list-style-type: {{list_style}}; padding-left: 20px">
{{#child_blocks.list_items}}
{{{html}}}
{{/child_blocks.list_items}}
</ul>

</div>
@JohnHughes1984
view/adminhtml/templates/list/item.phtml
<li class="bluefoot-list-item gene-bluefoot-pagebuilder-block bluefoot-
entity-align-{{align}}>

{{#list_item_icon}}
<i class="{{list_item_icon}}"></i>
{{/list_item_icon}}
{{list_item_text}}

</li>
@JohnHughes1984
LETS BUILD SOME LISTS!!!
Harnessing the power of blue foot for developers
Harnessing the power of blue foot for developers
Harnessing the power of blue foot for developers
Harnessing the power of blue foot for developers
@JohnHughes1984
CHECK IT OUT 
https://github.com/鍖sheyehq/module-bluefoot-list
composer require 鍖sheye/module-bluefoot-list
@JohnHughes1984
DONT STOP THERE
@JohnHughes1984
FURTHER POSSIBILITIES
Menu builder
Form builder
Magento elements (e.g. advanced search, quick order)
Social media feeds (e.g. Twitter / Facebook / Instagram)
Content from other systems (e.g. WordPress posts via WP API)
@JohnHughes1984
FURTHER POSSIBILITIES CONT.
Add new attribute types with rich content via plugins (JS widgets)
- Default widgets include:
 Colour picker, Google maps, video preview and entity search
e.g. products and categories
New structural elements
@JohnHughes1984
FISHEYE USAGE
At Fisheye weve built our entire frontend around BlueFoot
- Page Builder Blocks - banners, trust, social and more
- Plugins (JS widgets) - CMS page search
- Wrapped into our own CMS framework
@JohnHughes1984
Phillip Jackson, speaking during MageTalk Live at Magento Imagine 2017
BLUEFOOT HAS GIVEN US A
LEG UP TO SELL MAGENTO 2 IN
A BIGGER AND BROADER WAY
@JohnHughes1984
Brain Lange, speaking during MageTalk Live at Magento Imagine 2017
BLUEFOOT ACCELERATES
BUILD TIMES
@JohnHughes1984
WHERE NEXT FOR BLUEFOOT?
Fully integrated in Magento v2.3 as Magento Advanced CMS
- Expected late 2017
Majority of functionality will be for Enterprise Edition only
Core version integrated into Magento UI with native drag & drop
Integration of Adobe CC image editing
@JohnHughes1984
THANK YOU FOR LISTENING! 
Want to know more / see a demo? Come say hi  or get in touch:
Twitter: @JohnHughes1984
Email: johnh@鍖sheyehq.com
LinkedIn: linkedin.com/in/johnhughes1984
@JohnHughes1984
Q&A
Will this example / way of extending be relevant once 2.3 released?
- Unsure, better directed at Magento core team
- At very least vendor and namespaces will change and given the plans to refactor natively there
are bound to be further changes required, but con鍖dent most of concepts will remain similar and
hopefully porting extensions shouldnt be too large a task (not exactly large modules)
How do I get BlueFoot?
- Using composer (requires Enterprise Edition access keys) - composer require gene/bluefoot
- Download via partner portal

More Related Content

Harnessing the power of blue foot for developers