Jump to content
Wanze

Module: TemplateEngineFactory

Recommended Posts

Updated the module to version 1.1.0 which adds the following features:

  • Multiple data can be passed to the template engine via setArray() (alias: setMultiple())
  • The module now provides a second API variable $factory returning the singleton instance of the TemplateEngineFactory, which can be used to load partial views and chunks
  • Chunks: Reusable code snippets that consist of a PHP file containing the logic and a template (view) to render the output (see https://github.com/wanze/TemplateEngineFactory#chunks)

Thanks @justb3a for the contributions! Twig and Smarty modules were updated as well, shipping with the newest version of Twig/Smarty.

I tested the module on the latest ProcessWire 2.7 and 3.x and everything worked fine. Let me know if you find any issues!

Cheers

  • Like 4

Share this post


Link to post
Share on other sites

Hi,

I don't know whether anyone is actively monitoring the thread for the TemplateEngineTwig.module but I have posted the following message there. Many thanks! :)

 

Share this post


Link to post
Share on other sites

Hi

I am newbie on Processwire an I am using your module with smarty renderer. It works good but I have a difficulty.

My Processwire page tree :

  1. Home (template = home.tpl)
    1. page 1 (template = basic_page.tpl)
    2. special page (template = special.tpl)

I used an extended template 'template.tpl' in special.tpl and a global controller _init.php width the nav definition.

How to do that : if I go to http://mywebsite.com/ (then get home.tpl rendering), I would like to have the render result from "special page" with "special.tpl".

Sorry for my poor english language ;-)

Thx in advance

Besen

 

Share this post


Link to post
Share on other sites

Hi Besen,

So if you visit the homepage of your website, you basically want to display the same as when you visit your special page? Why not use your special page as homepage (thus moving controller logic from site/templates/special.php to site/templates/home.php) and also the smarty template?

Otherwise you could try the following:

  1. Rename home.tpl to home.tpl.temp - The factory won't attach hooks to delegate the rendering to smarty, as no template is found
  2. In your site/templates/home.php controller add the following: echo $pages->get('/special-page/')->render();

I'm not sure if it works though...

Cheers

Share this post


Link to post
Share on other sites

Yeah it won't work sorry... so in this case my solution would be to use the same controller/template for your home page and special page. Still not sure if I understood you correctly though.

Share this post


Link to post
Share on other sites

Ok ! Then I found a simple and evident solution : I associated my template "special-page" on root 'Home' in Processwire back-office. It worked fine !

Thanks for your help and your pretty goode module :-)

  • Like 1

Share this post


Link to post
Share on other sites

I keep getting a cache error. I can delete cache then page loads then won't load again as new cache is created. Any ideas as to why this is happening?

Parse Error: syntax error, unexpected ',' (line 44 of /home4/subtlem2/public_html/vocalcoach.rede-commerce.com/site/assets/cache/TemplateEngineTwig_compile/66/664c8e217f20e0ab2fed758d06f848fe2e2306d2a4af4cd131d4155af1b015e0.php)

This error message was shown because: site is in debug mode. ($config->debug = true; => /site/config.php). Error has been logged.

Share this post


Link to post
Share on other sites

@SubMon I assume you are using ProcessWire 3.x? Check out this comment: 

 

You need to disable the FileCompiler for your twig templates. There's currently no way for the module to tell the compiler to ignore these files, so at the moment this seems like the only solution. However, there is a pull request open to support this and I hope it's getting integrated soon.

Cheers

  • Like 1

Share this post


Link to post
Share on other sites

Hello

When I'm using this code in a controller, the prepend file (_init.php) is not running.

<?php
// ======= basic-page.php =======
// SET ACTIVE NAV (used by _init.php prepend file
$view->set('menuActive', $page->name);

// DETECT IF PORTFOLIO
if ($page->children->get('template=portfolio')) {
  $view = $factory->load('portfolio', true); // Load the main markup
}
 ?>

How can I set the prepend file running ?

Thanks in advance

Share this post


Link to post
Share on other sites

@Besen

The _init.php file isn't processed when loading views. Basically this file is only loaded by ProcessWire when you load a ProcessWire template file (controller). So in the current situation, _init.php was called before your basic-page.php controller was loaded.

I'm not sure what you're trying to do, could you elaborate a bit? Do you want to render a portfolio in your current basic-page template?

Share this post


Link to post
Share on other sites

@Wanze

Then I would like to use basic_page view template normally, but sometimes, if the page to display has got portfolio children I have to display these on a summary portfolio view.

Share this post


Link to post
Share on other sites

In this case you can make use of partial templates or chunks.

Eg:

$view->set('menuActive', $page->name);
$portfolio = $page->children->get('template=portfolio');
$portfolio_partial = $factory->load('partials/portfolio');
$portfolio->set('title', $portfolio->title);
$portfolio->set('body', $portfolio->body);
$view->set('portfolio', $portfolio->render());

 

Hope this helps!

Cheers

Share this post


Link to post
Share on other sites

I'm reposting this from Github - I have the same problem:

https://github.com/wanze/TemplateEngineFactory/issues/6

Quote

I'm setting my template file based on a condition and use $view->setFilename.

E.g.
my-tempalte/json.tpl
my-template/html.tpl

if($format == 'json') {
$view->setFilename('my-tempalte/json.tpl');
} else {
$view->setFilename('my-tempalte/html.tpl');
}

Because of this reason I don't need an .tpl file for each Processwire template.
E.g. If I have in Processwire a tempalte called "home", I have to add an emtpy views/home.tpl file to make smarty work for me. If not i would get an empty white page - also if I do $view->setFilename('my-tempalte/json.tpl');

I don't want to blow up my views folder with so much empty files.

Is there a way to avoid this when using $view->setFilename?

 

Share this post


Link to post
Share on other sites

Hello, I'd like to know how to set the layout block logic for the ProcessWire side (the default one) of the templates. That is, twig uses {% block content %}, Jade uses block content, PW... ?

Also, is there documentation of the module for using PW as the main language? I checked the forums but found none...

Thank you very much

Share this post


Link to post
Share on other sites
3 hours ago, Manaus said:

Hello, I'd like to know how to set the layout block logic for the ProcessWire side (the default one) of the templates. That is, twig uses {% block content %}, Jade uses block content, PW... ?

Also, is there documentation of the module for using PW as the main language? I checked the forums but found none...

Thank you very much

This block thingy are features of the template engines (twig, smarty, jade...). ProcessWire does not offer this, you may look at regions, though I've never used them. This module does not implement any new features, it just serves to connect different template engines to ProcessWire and to use them via a common interface.

If you use ProcessWire as template engine, you get all the features of ProcessWire templates: http://processwire.com/api/templates/

Cheers

  • Like 1

Share this post


Link to post
Share on other sites

I used a simple TemplateFile extension to build a similar module which works fine with ajax (load current page / page part without global layout).

The module is small and simple: 
https://bitbucket.org/pwFoo/templatefilehelper/src/060a9f5129e6eca65c75885572aa0c23ed83e591/TemplateFileHelper.module?at=master&fileviewer=file-view-default

But maybe it would be better to move to your TemplateEngineFactory because it's well written and much more flexible. I think it would be better to have one base instead of different modules with the same goal. ;)

  1. TemplateEngineFactory supports global template / layout. So it outputs the current page inside of a global layout template. 
    Is it possible to skip that for ajax usage? Just output the current page part if it was a ajax call?
  2. Add cache feature to Processwire engine should be easy with WireCache? Or wouldn't it be a good option?
  3. At the moment it isn't needed. What's about multi lang and caching)?
  4. scripts / styles in global or current page context? For example to handle just current page scripts and styles if requested by a ajax call.

Share this post


Link to post
Share on other sites

Some tests done, but I don't know if TemplateEngineFactory fits my needs (current page inside of the global layout, ajax friendly usage, layout / current page scripts and styles).

Share this post


Link to post
Share on other sites

Hi Wanze,

first of all a big thank you for this great module which I stumbled upon a few days ago.

I also have some questions regarding the flexibility of TemplateEngineFactory. Let me explain what I was trying to achieve (using Smarty, but I think this would apply to other template engines as well):

In a page of mine, there is a specific template whose output should be processed by a text filter before sending to the client browser. Also the processed output should be cached a specific amount of time (just output of pages based on this specific template).

What I tried:

  1. attach the text filter via a new module and a hook to Page::render(). With this approach I have to be careful to just apply the filter to the one specific type of pages and also (as the filter is CPU-intensive and the hook is executed at every page view) it does not work well with caching.
  2. attach the text filter via a hook to TemplateEngineSmarty::initSmarty(). Here I also have to be careful to not apply the filter to the wrong pages, caching with Smarty works but only with one global cache timeout config value. This is not acceptable for me because this would also affect pages based on other templates.

I then digged a bit in the source code of the module and had the following idea:

Why not provide a so-called 'direct' mode, globally enabled/disabled via module configuration. This direct mode does not attach the hook to Page::render() and lets the user choose when to output the markup via a method like $view->renderAndPrint(). Wouldn't ths also give back the possibility to control caching time per template via the template caching configuration? Also filters could be added right in the template source file before calling $view->renderAndPrint().

I am not sure If I thought this through entirely and not missed something and would appreciate any feedback on my suggestion.

Thank you in advance,

Menz

 

Share this post


Link to post
Share on other sites

Hi @Menz

Sorry for my late response, I was traveling a longer time while you were posting this. I would be interested if you could solve it using the module? There is another approach which let's you control the caching:

1. Do not create a corresponding smarty template so that the module does not attach the render hook. This means that the controller aka regular ProcessWire template will work just normal. Let's call this template filter_response.php.

2. The filter_response.php can still use the factory to create the markup via Smarty but at the same time control the caching via WireCache.

Something like this (inside site/templates/filter_response.php)

if ($cached = $cache->getFor('my_namespace', $page->id) {
  echo $cached;
} else {
  $tpl = $factory->load('filetered_response_template');
  $tpl->page = $page;
  $output = $tpl->render();
  $output = filter_output($output);
  $cache->setFor('my_namespace', $page->id, $output);
  echo $output;
}

Cheers

  • Like 1

Share this post


Link to post
Share on other sites

Loving this module so far but I am having trouble using markup regions.

I have successfully got it to output markup using the ProcessWire template engine but can't figure out how to use markup regions. I have enabled

$config->useMarkupRegions = true;

and have the following files

includes/_main.php

<!DOCTYPE html>
<html>
  <head>
    <title><?=$page->title?></title>
  </head>
  <body>
    <div id='content'>
      <h1 id='headline'><?=$page->title?></h1>
      <div id='bodycopy'>
        <?=$page->body?>
      </div>
    </div>
    <aside id='sidebar'>
      <p>Welcome!</p>
    </aside>
    <footer id='footer'>
      <p>Copyright 2017</p>
    </footer>
  </body>
</html>

views/home.php

<aside id='sidebar'>
  <p>Hello from home</p>
</aside>

<?php include('../includes/_main.php')?>

as per the tutorial linked above. (I am not using any MVC features because I was trying to debug it)

I'm not a huge fan of Twig but I am a fan of MVC so if anybody could help me out it would be greatly appreciated.

Share this post


Link to post
Share on other sites

I have two templates:

  1. basic-page
    1. title
    2. body
  2. calendar-posting
    1. title
    2. event_description

I'm trying to build a search page that can search for text in any of those fields.  Right now my selector looks like "title|body|event_description*=support, limit=3".  It correctly returns a Page Array when I perform a search.

I can output the page's title just fine, but the problem happens when I try to output the event_description field.  I get the following error:

User Error

Exception: An exception has been thrown during the rendering of a template ("Method Page::event_description does not exist or is not callable in this context") in "search.twig" at line 50. (in /Users/glenn/websites/mysite/wwwroot/site/assets/cache/FileCompiler/site/modules/TemplateEngineTwig/TemplateEngineTwig.module line 110)

Note: I am using the TemplateEngineTwig and TemplateEngineFactory modules.

In my search.twig

{% for post in paginated_items  %}
              <article class="card post">
                <div class="card-section">
                  <h3>
                    <a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a>
                  </h3>
                  <div class="meta">
                    <p>{% if post.editable() %}
                      <a href="{{ config.urls('admin') }}page/edit/?id={{ post.id }}">Edit</a>
                    {% endif %}
                    </p>
                  </div>

                  {% if post.event_description %}
                    <div class="post-content">{{ post.event_description|striptags('<style>')|truncate(440, false, "...") }}
                      <a class="read-more" href="{{ post.url }}" title="{{ post.title }}">{{ 'Read More' }}</a>
                    </div>
                  {% endif %}
                  
                </div><!-- card-section -->
              </article>
{% endfor %}

 

Anyone have any ideas as to what could be the cause?

If the returned PageArray from my find returns two items, I should be able to access and output any of those page's fields right?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Robin S
      After forgetting the class name of the wonderful AdminPageFieldEditLinks module for what feels like the 100th time I decided I needed to give my failing memory a helping hand...
      Autocomplete Module Class Name
      Provides class name autocomplete suggestions for the "Add Module From Directory" field at Modules > New.
      Requires ProcessWire >= v3.0.16.
      Screencast

      Installation
      Install the Autocomplete Module Class Name module.
      Configuration
      Choose the type of autocomplete options list: "Module class names from directory" or "Custom list of module class names". The latter could be useful if you regularly install some modules and would prefer a shorter list of autocomplete suggestions. The list of class names in the modules directory is generated when the Autocomplete Module Class Name module is installed. It doesn't update automatically (because the retrieval of the class names is quite slow), but you can use the button underneath when you want to retrieve an updated list of class names from the directory. The "fuzzy search" option uses custom filter and item functions for Awesomplete so that the characters you type just have to exist in the module class name and occur after preceding matches but do not need to be contiguous. Uncheck this option if you prefer the standard Awesomplete matching. Custom settings for Awesomplete can be entered in the "Awesomplete options" field if needed. See the Awesomplete documentation for more information.  
      https://github.com/Toutouwai/AutocompleteModuleClassName
      https://modules.processwire.com/modules/autocomplete-module-class-name/
    • By teppo
      MarkupMenu is a markup module for generating menu trees. When provided a root page as a starting point, it generates a navigation tree (by default as a HTML "<ul>" element wrapped by a "<nav>" element) from that point onwards. If you've also provided it with current (active) page, the menu will be rendered accordingly, with current item highlighted and items rendered up to that item and its children (unless you disable the "collapsed" option, in which case the full page tree will be rendered instead).
      Modules directory: https://modules.processwire.com/modules/markup-menu/ GitHub repository: https://github.com/teppokoivula/MarkupMenu Usage
      As a markup module, MarkupMenu is intended for front-end use, but you can of course use it in a module as well. Typically you'll only need the render() method, which takes an array of options as its only argument:
      echo $modules->get('MarkupMenu')->render([ 'root_page' => $pages->get(1), 'current_page' => $page, ]); Note: if you omit root_page, site root page is used by default. If you omit current_page, the menu will be rendered, but current (active) page won't be highlighted etc.
      A slightly more complex example, based on what I'm using on one of my own sites to render a (single-level) top menu:
      echo $modules->get('MarkupMenu')->render([ 'current_page' => $page, 'templates' => [ 'nav' => '<nav class="{classes} menu--{menu_class_modifier}" aria-label="{aria_label}">%s</nav>', 'item_current' => '<a class="menu__item menu__item--current" href="{item.url}" tabindex="0" aria-label="Current page: {item.title}">{item.title}</a>', ], 'placeholders' => [ 'menu_class_modifier' => 'top', 'aria_label' => 'Main navigation', ], 'include' => [ 'root_page' => true, ], 'exclude' => [ 'level_greater_than' => 1, ], ]); Note: some things you see above may not be entirely sensible, such as the use of {menu_class_modifier} and {aria_label} placeholders. On the actual site the "nav" template is defined in site config, so I can define just these parts on a case-by-case basis while actual nav markup is maintained in one place.
      Please check out the README file for available render options. I'd very much prefer not to keep this list up to date in multiple places. Basically there are settings for defining "templates" for different parts of the menu (list, item, etc.), include array for defining rules for including in the menu and exclude array for the opposite effect, classes and placeholders arrays for overriding default classes and injecting custom placeholders, etc. 🙂
      MarkupMenu vs. MarkupSimpleNavigation
      TL;DR: this is another take on the same concept. There are many similarities, but also some differences – especially when it comes to the supported options and syntax. If you're currently using MarkupSimpleNavigation then there's probably no reason to switch over.
      I'd be surprised if anyone didn't draw lines between this module and Soma's awesome MarkupSimpleNavigation. Simply put, I've been using MSN (...) for a number of years, and it's been great – but there have been some smallish issues with it, particularly with the markup generation part, and it's also doing some things in a way that just doesn't work for me – the xtemplates thing being one of these. In many ways it's less about features, and more about style.
      In MarkupMenu I've tried to correct these little hiccups, modernise the default markup, and allow for more flexibility with placeholder variables and additional / different options. MarkupMenu was built for ProcessWire 3.0.112+ and PHP 7.1+, it's installable with Composer, and I have a few additional ideas (such as conditional placeholders) on my todo list.
      One smallish and rather specific difference is that MarkupMenu supports overriding default options via $config->MarkupMenu. I find myself redefining the default markup for every site, which until now meant that each site has a wrapper function for MarkupSimpleNavigation (to avoid code / config repetition), and this way I've been able to omit that 🙂
      Requirements
      ProcessWire >= 3.0.112 PHP >= 7.1.0 If you're working on an earlier version of ProcessWire or PHP, use MarkupSimpleNavigation instead.
    • By Robin S
      Repeater Images
      Adds options to modify Repeater fields to make them convenient for "page-per-image" usage. Using a page-per-image approach allows for additional fields to be associated with each image, to record things such as photographer, date, license, links, etc.
      When Repeater Images is enabled for a Repeater field the module changes the appearance of the Repeater inputfield to be similar (but not identical) to an Images field. The collapsed view shows a thumbnail for each Repeater item, and items can be expanded for field editing.
      Screencast

      Installation
      Install the Repeater Images module.
      Setup
      Create an image field to use in the Repeater field. Recommended settings for the image field are "Maximum files allowed" set to 1 and "Formatted value" set to "Single item (null if empty)". Create a Repeater field. Add the image field to the Repeater. If you want additional fields in the Repeater create and add these also. Repeater Images configuration
      Tick the "Activate Repeater Images for this Repeater field" checkbox. In the "Image field within Repeater" dropdown select the single image field. You must save the Repeater field settings to see any newly added Image fields in the dropdown. Adjust the image thumbnail height if you want (unlike the core Images field there is no slider to change thumbnail height within Page Edit). Note: the depth option for Repeater fields is not compatible with the Repeater Images module.
      Image uploads feature
      There is a checkbox to activate image uploads. This feature allows users to quickly and easily add images to the Repeater Images field by uploading them to an adjacent "upload" field.
      To use this feature you must add the image field selected in the Repeater Images config to the template of the page containing the Repeater Images field - immediately above or below the Repeater Images field would be a good position.
      It's recommended to set the label for this field in template context to "Upload images" or similar, and set the visibility of the field to "Closed" so that it takes up less room when it's not being used. Note that when you drag images to a closed Images field it will automatically open. You don't need to worry about the "Maximum files allowed" setting because the Repeater Images module overrides this for the upload field.
      New Repeater items will be created from the images uploaded to the upload field when the page is saved. The user can add descriptions and tags to the images while they are still in the upload field and these will be retained in the Repeater items. Images are automatically deleted from the upload field when the page is saved.
      Tips
      The "Use accordion mode?" option in the Repeater field settings is useful for keeping the inputfield compact, with only one image item open for editing at a time. The "Repeater item labels" setting determines what is shown in the thumbnail overlay on hover. Example for an image field named "image": {image.basename} ({image.width}x{image.height})  
      https://github.com/Toutouwai/RepeaterImages
      https://modules.processwire.com/modules/repeater-images/
    • By EyeDentify
      Hello There Guys.

      I am in the process of getting into making my first modules for PW and i had a question for you PHP and PW gurus in here.

      I was wondering how i could use an external library, lets say TwitterOAuth in my PW module.
      Link to library
      https://twitteroauth.com/

      Would the code below be correct or how would i go about this:
      <?PHP namespace ProcessWire; /* load the TwitterOAuth library from my Module folder */ require "twitteroauth/autoload.php"; use Abraham\TwitterOAuth\TwitterOAuth; class EyeTwitter extends WireData,TwitterOAuth implements Module { /* vars */ protected $twConnection; /* extend parent TwitterOAuth contructor $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token, $access_token_secret); */ public function myTwitterConnection ($consumer_key, $consumer_secret, $access_token, $access_token_secret) { /* save the connection for use later */ $this->twConnection = TwitterOAuth::__construct($consumer_key, $consumer_secret, $access_token, $access_token_secret); } } ?> Am i on the right trail here or i am barking up the wrong tree?
      I don´t need a complete solution, i just wonder if i am including the external library the right way.
      If not, then give me a few hint´s and i will figure it out.

      Thanks a bunch.

      /EyeDentify
    • By dimitrios
      Hello,
      this module can publish content of a Processwire page on a Facebook page, triggered by saving the Processwire page.
      To set it up, configure the module with a Facebook app ID, secret and a Page ID. Following is additional configuration on Facebook for developers:
      Minimum Required Facebook App configuration:
      on Settings -> Basics, provide the App Domains, provide the Site URL, on Settings -> Advanced, set the API version (has been tested up to v3.3), add Product: Facebook Login, on Facebook Login -> Settings, set Client OAuth Login: Yes, set Web OAuth Login: Yes, set Enforce HTTPS: Yes, add "http://www.example.com/processwire/page/" to field Valid OAuth Redirect URIs. This module is configurable as follows:
      Templates: posts can take place only for pages with the defined templates. On/Off switch: specify a checkbox field that will not allow the post if checked. Specify a message and/or an image for the post.
      Usage
      edit the desired PW page and save; it will post right after the initial Facebook log in and permission granting. After that, an access token is kept.
       
      Download
      PW module directory: http://modules.processwire.com/modules/auto-fb-post/ Github: https://github.com/kastrind/AutoFbPost   Note: Facebook SDK for PHP is utilized.


×
×
  • Create New...