Jump to content

Module: Twig for the TemplateEngineFactory


Wanze
 Share

Recommended Posts

Hi guys,
sorry I don't catch, I added this code to the _init file

wire()->addHook("TemplateEngineTwig::___initTwig", function($event) {
	$twig = new Twig_Environment($loader, array(
	    'debug' => true,
	));
	$twig->addExtension(new Twig_Extension_Debug());
});

By 'adding the extension' do you mean adding this code to a page?
Thanks

Link to comment
Share on other sites

@Manaus

That's great! Here is my hooked method:

    public function hookInitTwig(HookEvent $event)
    {

        $twig = $event->arguments('twig');
        $twig->addGlobal('hsaApp', wire('config')->hsaApp);
        $twig->addGlobal('hsaDist', wire('config')->hsaDist);
        $twig->addExtension(new \Twig_Extension_Debug());

    }

The only problem with what you have done is that you have amended the original module. When you update that module, you will lose your added code. If you add to a hooked method outside of the Twig module, your changes will be preserved.

  • Like 2
Link to comment
Share on other sites

Hi guys,  
I have a .twig template I'd like to use as a children container.

{% for item in page.children %} 
   {{ item.body }} 
{% endfor %}

Problem is that Method Page::body does not exists or is not callable in this context. I think I should pass it explicitly. Anyone has a chunk of code on how to pass subpages to templates from a controller page?

Thanks!

Link to comment
Share on other sites

@Manaus

$page->children()->getArray() should return an array that you could assign to a variable in your template/controller. For that matter, you could also assign $page->children() to a variable that can also be passed in to the Twig template.

Link to comment
Share on other sites

Thanks @Gazley,

problem is that the view can output page.title which is native, but not page.body, unless it's out of a structure. I mean, if I set a variable 'thepage' as a container of one page

$view->set('thepage', $pages->get('/')) // I get all the fields: {{ thepage.body }} works
$view->set('children', $pages->get('/')->children) // body of child is unknown

This valid also with getArray()...

Link to comment
Share on other sites

Very good! :)

When the field isn't autojoined, ProcessWire effectively lazy-loads it and it just occurred to me that this wasn't happening when the collection is iterated over by the Twig code.

When you set a field as autojoined, it eager-loads it; sometimes, you may not ever touch the field when you are rendering data so, it makes sense to not load it with a page if you aren't going to generally output the value. It's a decision that you would make on a field by field basis but in normal terms, I suppose you would always want the body field to be loaded and therefore set its value to autojoin.

Cheers!

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
On 27.7.2016 at 7:54 PM, Gazley said:

@Manaus

That's great! Here is my hooked method:


    public function hookInitTwig(HookEvent $event)
    {

        $twig = $event->arguments('twig');
        $twig->addGlobal('hsaApp', wire('config')->hsaApp);
        $twig->addGlobal('hsaDist', wire('config')->hsaDist);
        $twig->addExtension(new \Twig_Extension_Debug());

    }

The only problem with what you have done is that you have amended the original module. When you update that module, you will lose your added code. If you add to a hooked method outside of the Twig module, your changes will be preserved.

@Gazley I tried adding a modified version of your code to my prepended _init.php. It looks like this:

function hookInitTwig(HookEvent $event)
    {

        $twig = $event->arguments('twig');
        $twigWireRelativeTimeStr = new Twig_SimpleFunction('wireRelativeTimeStr', function ($date) {
            return wireRelativeTimeStr($date);
        });

        $twig->addFunction($twigWireRelativeTimeStr);
        
        $function = new Twig_SimpleFunction('testfunction', function($string) {
           return 'testfunction';
        });
        $twig->addFunction($function);

    }

But when I try to use a function in a twig template like 

{{ wireRelativeTimeStr('1469455438') }}

I still get 

Exception: Unknown "wireRelativeTimeStr" function in "logspot_profile.twig" at line 107

What did I do wrong?

Link to comment
Share on other sites

@jmartsch In one of my module's init() method, I have a line like this:

$this->addHookAfter('TemplateEngineTwig::initTwig', $this, 'hookInitTwig');

When the TemplateEngineTwig::initTwig after-hook is executed, the above declaration ensures that the hookInitTwig function can be found and executed on $this (the executing object instance).

So, I guess my question would be, have you specified the addHookAfter method to wire this call up? 

From what I can see, I don't really see how you can hook the hookInitTwig function when it is just specified in your _init.php file because you can't really specify an instance of _init.php because, it isn't a class. If you want to keep the code in _init.php file, you probably want to use the following addHookAfter signature:

$this->addHookAfter('TemplateEngineTwig::initTwig', function($event) { 

	$twig = $event->arguments('twig');
        $twigWireRelativeTimeStr = new Twig_SimpleFunction('wireRelativeTimeStr', function ($date) {
            return wireRelativeTimeStr($date);
        });

        $twig->addFunction($twigWireRelativeTimeStr);
        
        $function = new Twig_SimpleFunction('testfunction', function($string) {
           return 'testfunction';
        });
        $twig->addFunction($function);

});

I haven't run the above code and you'll have to make certain that there are no issues with namespaces. However, when the above code is executed in the _init.php file, it registers the hook with the anonymous function that will be called irrespective as to whether the _init.php file has long since departed from execution scope.

Hope this helps.

Link to comment
Share on other sites

@Wanze @Gazley I can´t get it running. I even tried to write a module but I don´t know which class to extend.

Gazley could you send me your module as a reference? Here is the code of my module:

<?php
class TwigFunctions{

	public static function getModuleInfo() {
		return array(
			'title' => "TwigFunctions",
			'version' => "0.0.1",
			'summary' => "",
			
			'author' => "Sir Aceman",
			'href' => "",
			
			'permission' => array("page-view"),
			'autoload' => true,
			'singular' => true,
			'permanent' => false,
			
			'requires' => array("PHP>=5.4.0", "ProcessWire>=2.5.28", ""),

		);
	}

	public function init() {
        $this->addHookAfter('TemplateEngineTwig::initTwig', $this, 'hookInitTwig');

    }

    function hookInitTwig(HookEvent $event)
    {

        $twig = $event->arguments('twig');
        $twigWireRelativeTimeStr = new Twig_SimpleFunction('wireRelativeTimeStr', function ($date) {
            return wireRelativeTimeStr($date);
        });

        $twig->addFunction($twigWireRelativeTimeStr);

        $function = new Twig_SimpleFunction('testfunction', function ($string) {
            return 'testfunction';
        });
        $twig->addFunction($function);

    }
}

 

Link to comment
Share on other sites

  • 5 weeks later...

@Wanze Another problem:

When I try to use config.urls.root in a hyperlink in a .twig file

<a href="{{ config.urls.root }}login/">Anmelden</a>

I get an error:

Exception: An exception has been thrown during the rendering of a template ("Method Paths::root does not exist or is not callable in this context") in "main.twig" at line 135.

If I use another config variable like config.urls.templates it works (but with the wrong path, as I need the root).

What is wrong? Is this a bug?

Link to comment
Share on other sites

Hello, I am doing my first steps in Processwire and the first thing I tried is this module. Let me tell you guys that this is a very interesting module. I like it very much. For the moment I just found something very strange, please let me know if you can help me with this.

Sorry for my english :/ 

  • I am using the module Template Engine Factory and Template Engine Twig as main template engine.

My files structure

/templates
      /controllers
          home.php
          basic-page.php
      /views
          home.html
          basic-page.html
          /structure
              main.html
              head.html
              foot.html

    

home.html

{% extends "structure/main.html" %}

{% block content %}
<div id="home-content">
    {{ page.body }}
</div>
{% endblock content %}

/structure/main.html

<!DOCTYPE html>
<html>
    <!-- head -->
    {% include 'structure/head.html' %}
    <body>
        <div id="main">
            <h1>
                {% block title %}
                    {{ page.title }}
                {% endblock title %}
            </h1>
            {% block content %}
                No content
            {% endblock content %}
        </div><!--/#main-->

        <!-- footer -->
        {% include "structure/foot.html" %}
    </body>
</html>

 

My problem:

When I reload the page everything is ok (please see the screenshot home.png), but when I reload the page one more time, after the page is cached I think, I got the following error (please see the screenshot error.png).

content of cached page on line 88 (please see the screenshot cached_page.png and dir_FileCompiler_cached_page.png)

If I change the include Twig function to include my header.html and footer.html for this one embed everything is ok. But I need to use include instead of embed.

Thank you for your patience and I hope someone can help me :).

 

 

 

home.png

error.png

cached_page.png

dir_FileCompiler_cached_page.png

Link to comment
Share on other sites

  • 4 weeks later...

Hi,

Sorry for my late answer, I was on vacation and traveling for the last 2 months :) The problem is the FileCompiler of ProcessWire trying to compile Twig stuff which should not be the case. I'll look into this. Can you disable the FileCompiler for all templates that are rendered with Twig?

Cheers

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...