Block guide
WARNING
This article is outdated and may contain information that are not in use anymore
Create block
Create model
tbc.
Create factory
tbc.
Create form
tbc.
Create template
tbc.
Add configuration
tbc.
Create type
First you have to define a class that implements the BlockInterface
. On that interface you have to provide a getType
. This is the type name we use later display this block. If you want to have some additional helper methods we recommend to extend from AbstractType
that provide some helpers like renderTemplate
.
<?php
namespace AppBundle\Block;
use Enhavo\Bundle\BlockBundle\Block\AbstractBlockType;
class SliderBlock extends AbstractBlockType
{
public function render($parameters)
{
$this->renderTemplate('AppBundle:Block:google_analytics.html.twig');
}
public function getType()
{
return 'google_analytics';
}
}
Now you have to add the created class to the dependency injection container.
app.block.google_analytics:
class: AppBundle\Block\GoogleAnalyticsBlock
calls:
- [setContainer, ['@service_container']]
tags:
- { name: enhavo.block }
Add block to block
If you want to use a nested blocks you just need to add a property to your parent block using the Enhavo\Bundle\BlockBundle\Model\NodeInterface
.
First update your meta file of your block.
manyToOne:
content:
cascade: ['persist', 'refresh', 'remove']
targetEntity: Enhavo\Bundle\BlockBundle\Model\NodeInterface
And add a getter and setter function to the parent block class. Set the property and type of the node correctly. For nested blocks you set the type to list type and add a transition to the parent node. Property should be the member name of the parent block. This steps are important to browse correctly through the node three later.
use Enhavo\Bundle\BlockBundle\Entity\AbstractBlock;
class MyBlock extends AbstractBlock
{
/**
* @param NodeInterface|null
*/
private $content;
public function getContent(): ?NodeInterface
{
return $this->content;
}
public function setContent(?NodeInterface $content)
{
$this->content = $content;
if ($content) {
$content->setType(NodeInterface::TYPE_ROOT);
$content->setProperty('content');
}
}
}
And add a migration file and execute it to update your database schema.
To show the block form, you need add the Enhavo\Bundle\BlockBundle\Form\Type\BlockNodeType
to your form builder.
use Enhavo\Bundle\BlockBundle\Form\Type\BlockNodeType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class MyBlockType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('content', BlockNodeType::class);
}
}
Add block to entity
If you want to use a block grid inside a entity you have to add the the Enhavo\Bundle\BlockBundle\Model\NodeInterface
to target entity.
First update your meta file of your entity.
manyToOne:
content:
cascade: ['persist', 'refresh', 'remove']
targetEntity: Enhavo\Bundle\BlockBundle\Model\NodeInterface
And add a getter and setter function to the entity class. Set the property and type of the Node correctly. In this case the type is root, because it is the entry point of the block node tree. Property should be the member name where the Node is stored. This is important to browse through the node three later.
use Enhavo\Bundle\BlockBundle\Model\NodeInterface
class MyEntity
{
/**
* @param NodeInterface|null
*/
private $content;
public function getContent(): ?NodeInterface
{
return $this->content;
}
public function setContent(?NodeInterface $content)
{
if($content) {
$content->setType(NodeInterface::TYPE_ROOT);
$content->setProperty('content');
}
$this->content = $content;
return $this;
}
}
And add a migration file and execute it to update your database schema.
To show the block form, you need add the Enhavo\Bundle\BlockBundle\Form\Type\BlockNodeType
to your form builder.
use Enhavo\Bundle\BlockBundle\Form\Type\BlockNodeType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class MyEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('content', BlockNodeType::class);
}
}
Extend block
Sometimes a block don't have all the properties you need. So you want to extend a enhavo block. This is of course possible. You just need to create a entity block class with the doctrine meta data and create a listener that will register the extension meta data to doctrine. At the end you need to configure the current block configuration to use your extended class.
Create custom block
Create your custom Block class. If you use yaml or xml for your doctrine meta data you need to create a separate meta file. If you use annotations just add doctrine annotations to your entity class.
namespace App\Entity\Block;
class TextBlock extends Enhavo\Bundle\BlockBundle\Model\TextBlock
{
// add your custom properties and functions
}
Add extend listener
Add a doctrine extend listener as a service to the dependency injection container. You have to define the class you want to extend from and the class which extends. This step is needed because you can't add the meta data for extension to the enhavo TextBlock because you can't change the vendor files. This Listener will hook into doctrine and set all configuration to make a single table inheritance.
# config/services.yaml
app.block.text.extend_listener:
class: Enhavo\Bundle\AppBundle\EventListener\DoctrineExtendListener
arguments:
- Enhavo\Bundle\BlockBundle\Model\Block\TextBlock
- App\Entity\Block\TextBlock
- true
tags:
- { name: doctrine.event_subscriber, connection: default }
Extend the current form
You have to create a form for your custom block. Use the getParent
to extend the default form. Otherwise you have to redefine all properties inside buildForm
.
namespace App\Form\Type\Block;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use App\Entity\Block\TextBlock;
class TextBlockType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ... add your property types
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => TextBlock::class
]);
}
public function getParent()
{
return \Enhavo\Bundle\BlockBundle\Form\Type\TextBlockType::class;
}
}
Change block configuration
Change the block configuration and use your custom classes.
# config/packages/enhavo.yaml
enhavo_block:
blocks:
text:
type: text
model: App\Entity\Block\TextBlock
form: App\Form\Type\Block\TextBlockType
repository: App\Entity\Block\TextBlock
Custom templates
To customize the template for a block is very easy. You can just override the template path in the configuration or if the origin template file is located in the vendor code, you can add a file under the same path in your templates
directory. E.g. for the gallery template, save a file under theme/block/gallery.html.twig
.
enhavo_block:
blocks:
gallery:
type: gallery
template: 'theme/block/gallery/custom.html.twig'
How if you want to define more templates? You can also add more templates separated by keys. Only the key will store into the node, so if you change the template path later, there is no migration needed.
If you define templates in that way, the user will have a dropdown field in his block form. The choices are the labels you defined.
enhavo_block:
blocks:
template:
type: template
template:
chart:
template: 'theme/block/template/chart.html.twig'
label: Chart
download:
template: 'theme/block/template/download.html.twig'
label: Download