0

My project has a core bundle which holds the main templates, and I have optional features implemented as bundles. Different clients get copies of the project with different bundles(=features) activated.

One thing that the feature bundles need to be able to do is add things to the main templates (in the core bundle). Obviously I don't want the templates in the core bundle to "know" about the optional bundles, so I want to have "hooks" in the templates that other bundles can pour content into.

I have one solution, which seems to work. I would appreciate feedback/suggestions.

I have a twig function which gets a "hook" name. I place that function at different locations in my template.

That function raises an event (through the event dispatcher) that collects html snippets from various event listeners (the feature bundles are responsible for those listeners), joins those snippets and returns them.

code:

twig function:

new \Twig_SimpleFunction('template_hook', array( $this, 'templateHookFunction' ), array('is_safe' => array('html'))),

public function templateHookFunction($hookName)
{
    $hookData = $this->eventDispatcher->dispatch(
        TemplateHookEvent::TEMPLATE_HOOK,
        new TemplateHookEvent($hookName)
    )->getData();

    return $this->hookDataRenderer->render($hookData);
}

the event:

<?php


namespace CRM\TwigBundle\Event;


use CRM\TwigBundle\Hook\HookData;
use Symfony\Component\EventDispatcher\Event;

class TemplateHookEvent extends Event
{

    const TEMPLATE_HOOK = 'crm_twig.template_hook';

    private $hookName;

    /** @var  HookData $data */
    private $data;

    function __construct($hookName)
    {
        $this->hookName = $hookName;
        $this->data = new HookData();
    }

    /**
     * @return mixed
     */
    public function getHookName()
    {
        return $this->hookName;
    }

    /**
     * @return HookData
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * @param HookData $data
     */
    public function setData(HookData $data)
    {
        $this->data = $data;
    }

    public function addData($label, $html, $overwrite = true)
    {
        if ($overwrite || !isset($this->data[$label])) {
            $this->data[$label] = $html;
        } else {
            $this->data[$label] .= $html;
        }
    }
}

an example for a listener:

<?php


namespace CRM\ComputersBundle\EventListener;


use CRM\TwigBundle\Event\TemplateHookEvent;

class TemplateHookListener {

    public function onTemplateHook(TemplateHookEvent $event)
    {
        $event->addData('computersBundle', '<li>CAKE</li>');
    }
}

HookData is just a wrapper for an array (for now), each listener can push to it its own snippet.

and the HookDataRenderer just joins(implode) the array, and returns the result.

Artamiel
  • 3,652
  • 2
  • 19
  • 24
Ami Malimovka
  • 437
  • 7
  • 22
  • @Artamiel thanks :-) – Ami Malimovka Jul 23 '15 at 19:03
  • What's wrong with regular blocks? Pretty much any templates (and their blocks) can be overriden via standard methods: http://symfony.com/doc/current/book/templating.html#overriding-bundle-templates or http://symfony.com/doc/current/cookbook/bundles/inheritance.html – Im0rtality Jul 24 '15 at 11:55
  • @Im0rtality overriding the templates won't help here. I need the other bundles to add content to the core bundle, not override it. – Ami Malimovka Jul 24 '15 at 12:45
  • I assume hooks will inject code into predefined locations. If you mark those with empty `block`s, these blocks can be overriden to "add content" – Im0rtality Jul 24 '15 at 12:57
  • won't the bundles override each other content like that? – Ami Malimovka Jul 24 '15 at 13:26
  • They will, but control granularity depends on how you place your blocks. So yes, they can ruin your entire 'content' block, but that doesn't make much use. Give them 'hook_before_login' or something like that. – Im0rtality Jul 25 '15 at 20:04

1 Answers1

0

I don't see the point in your architecture. Why do you want such a hook system ? Why not using, for example, controller embedding in Twig as described here ?

Community
  • 1
  • 1
MeuhMeuh
  • 826
  • 6
  • 26
  • Thanks for the answer, maybe my reasons weren't clear enough from my question. I don't want my core bundle to "know about" the optional bundles, that means that I don't want to have to change anything in the core bundle after I enable or disable those bundles. Further more, soon I'll be giving other people the option to write such bundles, and I don't want them to have access to my code. A – Ami Malimovka Jul 24 '15 at 09:54