Skip to content

Block guide

WARNING

This article is outdated and may contain information that are not in use anymore

Create block

Use make command

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
<?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.

yaml
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.

yaml
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.

php
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.

php
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.

yaml
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.

php
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.

php
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.

php
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.

yaml
# 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.

php
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.

yaml
# 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.

yaml
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.

yaml
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