How to create a Twig function from a third-party function?

#1

I would like to make a function that comes from third-party code available in my Twig templates, also in Admin by the way. I have found two tutorials in the docs on creating Twig extensions, and they differ:

I’ve followed the latter because it seemed simpler to me – can someone explain the differences, perhaps?

This is what I’ve got so far in my plugin.php file (only the relevant bits):

    require_once(__DIR__.'/vendor/autoload.php');

    class CloudinaryPlugin extends Plugin
    {
        public static function getSubscribedEvents()
        {
          return [
            'onPluginsInitialized'      => ['onPluginsInitialized', 0]
          ];
        }

        public function onPluginsInitialized()
        { // why doesn't this go into getSubsribedEvents?
            $this->enable([
              'onTwigInitialized' => ['onTwigInitialized', 0]
            ]);
            return;
          }
        }

        public function onTwigInitialized(Event $e)
        {
            $this->grav['twig']->twig()->addFunction(
                // what is "this" in the parameters?
                new \Twig_SimpleFunction('cl_video', [$this, 'cl_video_test'])
            );
        }

        public function cl_video_test()
        {
            return "just testing this";
        }
    }

I actually would like to point that new \Twig_SimpleFunction to a function called cl_video_tag that is provided by an included third-party library and takes two parameters. I can use this function in that same php file without problems, so maybe I could just point to it like that and be done. However, it didn’t work when I tried, so I built this test function and that doesn’t work either. But I don’t see what I’m doing different from the tutorial? Can somebody spot my mistake here? I’m calling it in the twig with {{ cl_video() }}.

If I could just use this function in Twig, that would fix about 95% of my problems right now :smile: so thank you in advance for any ideas or thoughts you might have!

#2

Well, I got it to work with the method declared in my own CloudinaryPlugin class! The mistake had been a lack of use Grav\Common\Twig\Twig; at the head of the php file. So “just testing this” gets returned as expected now.

However, as I had anticipated this doesn’t work with a method declared in another class – if I just substitute cl_video_tag like so:

$this->grav['twig']->twig()->addFunction(
    new \Twig_SimpleFunction('cl_video', [$this, 'cl_video_tag'])
);

I get a Crikey! error saying "… class 'Grav\Plugin\CloudinaryPlugin' does not have a method 'cl_video_tag'". Which is correct, so it’s all good :slight_smile: but how do I tell Grav to go looking for that method in the Cloudinary class? If I find out the correct namespace to use, will adding that do the trick? Or do I have to change $this when creating the new Twig function, and if so, what should it be? I have no idea what that variable holds at this point…

Thank you for your time and thoughts!

#3

Another little piece to the puzzle: I just discovered that this function cl_video_tag is actually NOT a class method, but a standalone function in a separate file in the library. So I imagine this should be even easier? But how do I actually hand it over to Twig? :thinking: