Search code examples
wordpresstwigtimber

Timber - Use to render plugin templates


I'm creating a plugin that is directly correlated with a theme I'm developing which is using Timber. My plugin could render some built in templates (when I call a shortcode the plugin reply with the correct template); Those templates are, for now, PHP files. I would use Timber to render those files.

Unfortunately Issue #261 is still open. And I have no idea on how I can obtain the expected behaviour on the current timber codebase.

Expected behaviour:

  • Register my plugin path for views after the theme path.
  • When a view is called, Timber first check on theme directory, than on the plugin one.

How can I obtain this? Right now I have tested with the templates on my theme and I simply call Timber.render(); but I don't have the local path included.

Standard PHP plugin code:

// On plugin load
add_shortcode('render_social_icons', array($this, 'render_social_icons'));

public function render_social_icons($atts, $content)
    {
        $atts = shortcode_atts(array(
            'class' => '',
            'el-class' => '',
            'link-class' => '',
            'icon-class' => '',
            'size' => '',
        ), $atts);

        ob_start();
        ?>

        <ul class="social-icons shortcode <?php echo $atts['class']; ?>">
            <?php
            $socials = my_socials_links();
            foreach ($socials as $social) :?>
                <?php
                $id = $social['id'];
                $title = $social['name'];
                $baseurl = $social['baseurl'];
                $icon = $social['icon'];

                $social_data = get_theme_mod($id);
                if (!empty($social_data)) :?>
                    <li class="<?php echo $id; ?> <?php echo $atts['el-class']; ?>">
                        <a target="_blank" title="<?php echo $title; ?>" href="<?php printf($baseurl, $social_data); ?>"
                           class="<?php echo $atts['link-class']; ?>">
                            <i class="<?php echo $icon; ?> <?php echo $atts['icon-class']; ?> <?php echo $atts['size']; ?>"></i>
                        </a>
                    </li>
                <?php endif; ?>
            <?php endforeach; ?>
        </ul>

        <?php
        return ob_get_clean();
    }

Converted function for Timber (still a plugin file):

// On plugin load
add_shortcode('render_social_icons', array($this, 'render_social_icons'));

public function render_social_icons($atts, $content)
    {

        $atts = shortcode_atts(array(
            'class' => '',
            'el-class' => '',
            'link-class' => '',
            'icon-class' => '',
            'size' => '',
        ), $atts);

        return Timber.compile('shortcodes/social.twig', array(atts, my_socials_links());
    }

The shortcodes/social.twig is inside the current theme folder, I would like to load this twig template file from the plugin fodder.


Solution

  • Timber does not require you to register a twig file in order to use it with Timber::compile. You just need to provide the full path to the file as your first argument. To do that in a plugin, you will need to get the plugin directory path using plugin_dir_path(). To use your example code, you would do something like the following.

    public function render_social_icons($atts, $content) {
      $plugin_path = plugin_dir_path( __FILE__ );
      $atts = shortcode_atts(array(
              'class' => '',
              'el-class' => '',
              'link-class' => '',
              'icon-class' => '',
              'size' => '',
            ), $atts);
    
       return Timber::compile($plugin_dir_path . '/twig/social.twig', $atts);
    }
    

    The cool thing about Timber::compile is that you can pass an array of paths, and Timber will use the first file that it finds. That means you can allow a theme to override the social.twig file location with a file in the registered Timber paths. For example, you could change the last line to:

    return Timber::compile(array('social-shortcode-custom.twig', $plugin_dir_path . '/twig/social.twig'), $atts);
    

    Then Timber would pass the variables to a file called social-shortcode-custom.twig in the registered Timber locations if it exists, and fall back to the file located in the plugin if not.

    I'm not sure if this is affecting things or not, but I don't recognize the syntax you are using for the compile function. I have always seen and used the static method Timber::compile(), but you are using Timber.compile(). Timber is rapidly updating lately, so maybe you've seen something that I missed?