Manaus Posted July 27, 2016 Share Posted July 27, 2016 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 More sharing options...
Manaus Posted July 27, 2016 Share Posted July 27, 2016 Ok finally I got it, I added this line to the initEngine function within TemplateEngineTwig.module: $this->twig->addExtension(new Twig_Extension_Debug()); And now there it is! Thanks!! 1 Link to comment Share on other sites More sharing options...
Gazley Posted July 27, 2016 Share Posted July 27, 2016 @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. 2 Link to comment Share on other sites More sharing options...
Manaus Posted July 30, 2016 Share Posted July 30, 2016 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 More sharing options...
Gazley Posted July 30, 2016 Share Posted July 30, 2016 @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 More sharing options...
Manaus Posted July 31, 2016 Share Posted July 31, 2016 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 More sharing options...
Gazley Posted July 31, 2016 Share Posted July 31, 2016 Hi @Manaus, Just a SWAG but, do you have Autojoin checked/ticked in your "body" field definition? If not, select it and see if this makes a difference. 1 Link to comment Share on other sites More sharing options...
Manaus Posted July 31, 2016 Share Posted July 31, 2016 @Gazley you're the man Thanks 1 Link to comment Share on other sites More sharing options...
Gazley Posted July 31, 2016 Share Posted July 31, 2016 @Manaus - I assume that worked? Link to comment Share on other sites More sharing options...
Manaus Posted July 31, 2016 Share Posted July 31, 2016 Yes it did! 1 Link to comment Share on other sites More sharing options...
Gazley Posted July 31, 2016 Share Posted July 31, 2016 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! 1 Link to comment Share on other sites More sharing options...
Manaus Posted August 2, 2016 Share Posted August 2, 2016 Hi @Gazley, just discovered, if the field is not autojoined, it is possible to use: {{ page.get("body") }} and it works as well. Doh! 1 Link to comment Share on other sites More sharing options...
Gazley Posted August 2, 2016 Share Posted August 2, 2016 Hi @Manaus - great tip for those occasional fields that are not autoloaded! Link to comment Share on other sites More sharing options...
dotnetic Posted August 17, 2016 Share Posted August 17, 2016 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 More sharing options...
Gazley Posted August 17, 2016 Share Posted August 17, 2016 @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 More sharing options...
dotnetic Posted August 17, 2016 Share Posted August 17, 2016 @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 More sharing options...
Gazley Posted August 17, 2016 Share Posted August 17, 2016 Your class signature isn't correct - you need to also: class TwigFunctions extends WireData implements Module { ... } Also, you will need to add the module so that PW can find it when it loads. 1 Link to comment Share on other sites More sharing options...
dotnetic Posted August 17, 2016 Share Posted August 17, 2016 I modified my module as you wrote and installed it again, but I still get the error Exception: Unknown "wireRelativeTimeStr" function in "logspot_profile.twig" at line 107 Link to comment Share on other sites More sharing options...
Gazley Posted August 17, 2016 Share Posted August 17, 2016 You probably need to add the PW namespace when you reference wireRelativeTimeStr. return PW\wireRelativeTimeStr($date); // or whatever you have ProcessWire aliased as Link to comment Share on other sites More sharing options...
dotnetic Posted August 18, 2016 Share Posted August 18, 2016 I am using PW 2.8 so there is no namespace. Also I have the function testfunction which should just return a string but also doesn´t work. Link to comment Share on other sites More sharing options...
Gazley Posted August 18, 2016 Share Posted August 18, 2016 Are you certain that you have registered your TwigFunctions module in ProcessWire? Have you set a breakpoint in the init method to see that it's being hit? Link to comment Share on other sites More sharing options...
dotnetic Posted September 16, 2016 Share Posted September 16, 2016 @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 More sharing options...
dotnetic Posted September 16, 2016 Share Posted September 16, 2016 Seems like the variable isn´t available. So I used pages.get('/').url instead. Link to comment Share on other sites More sharing options...
eangulo@spiria Posted September 21, 2016 Share Posted September 21, 2016 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 :). Link to comment Share on other sites More sharing options...
Wanze Posted October 14, 2016 Author Share Posted October 14, 2016 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now