Jump to content


  • Posts

  • Joined

  • Last visited

Posts posted by peterfoeng

  1. 12 hours ago, tpr said:

    This is how I use multiple layouts in a project.


    {include content}


    {layout '@default.latte'}
    {block content}
            <div class="main">
                {include main}
            <div class="sidebar-left">
                {include sidebar_left}


    {layout 'layouts/@sidebar-left.latte'}
    {block sidebar_left}
    {block main}

    Maybe there's a better setup for this, please share if you find one :)

    You're the man!!! benggg....problem solved

    • Like 1
  2. 10 minutes ago, Mike Rockett said:

    @peterfoeng - I'm not sure about Latte (tpr might be able to answer this better), but surely you can have one layout extend another? So you would have a base layout and a sidebar layout where the sidebar layout extends the base layout, which would import the content of the sidebar layout if it's provided. Blade provides a nice way of doing this by using a combination of @section() and @parent.


    My previous setup is not using this module and seems to be working ok (I am pretty sure I am just missing something here)

    This is my previous setup:
    I have `@base.latte` file which contains the default markup then on my `Contact Page` (where I want this page have to have a sidebar) I have the following markup:

    `Contact.latte` file:

    {extends '@layout.sidebar.latte'}
    {block side_navigation}
      {include $config->paths->templates . 'views/components/_globals/side-navigation/contact.latte'}
    {block content}
    ....My content



    {extends '@base.latte'}
    {block body}
      {var $fixed = in_array($page->template, array("Contact", "Size-Guide", "Product-Information"))}
      <main class="component component--main-content" id="content">
        <div class="component__wrapper">
          <div class="main-content">
            <div class="main-content__wrapper">
              <div class="main-content__col main-content__col--sidebar {if $fixed}main-content__col--sidebar-fixed{/if}">
                {block side_navigation}{/block}
              <div class="main-content__col main-content__col--body">
                {include content}

    This works with my previous setup. Hopefully @tpr can help a bit with his knowledge of this templating engine :)


  3. Hi @tpr,

    Have a question here (more like a Latte question rather than module question): I have my default base layout called @layout.latte which is a base template for almost all of my pages but I also want to have another layout template that does have a sidebar. How do I setup this up in such a way I only declare my base HTML file once? Using {extends} or {layout} directive seems to replace the whole template file? or am I missing something here?

  4. Hi Luc,

    I know what the issue is but I dont know how to solve it and it probably has nothing to do with your module anyway. The issue is the module sends the email using the underlying MTA in my linux box in this case sendmail. Sendmail somehow use the box IP address instead of the IP address of the domain assigned in my mailgun account. I dont really understand how to force sendmail to use mailgun ip address and have been trying here and there but no luck whatsoever.

    So, in the end I decided to install exim4 and use smtp settings which works ok. Maybe, I play around with it in the future to resolve this. If anyone here has unix experience with sendmail can point to the direction, really appreciate it. :D

  5. Hi Luc,

    I am not sure if you can help me with this but I'll try anyway...I am using this module to send transaction email for my online store but I am not sure if I got this setup correctly. So my issue is: the email from mailgun is sent straight to spam and after looking into it, there is no mailed-by/sent-by (which I reckon is the issue it went to spam) in the email header. However when I tested it manually using the curl command (as per example here: https://documentation.mailgun.com/quickstart-sending.html#send-via-smtp) on the server (digital ocean) server, it went ok (not being sent to spam).

    I also notice when using the curl command the IP address from which the email was sent is Mailgun's IP Address (refer to the details below) but when using this module the IP address is the IP address of the digital ocean ubuntu box. I am not sure which one it should be, but I reckon it should be the IP address of the box and not the mailgun API IP address?

    I know this is probably not related to your module direcly but if you can help and potentially point me to the right direction, I really appreciate it. Thank you in advanced!

    Mailgun Details

    State: Active
    IP Address:
    SMTP Hostname: smtp.mailgun.org
    API Base URL: https://api.mailgun.net/v3/v2.weareheim.co
  6. Currently I'm building a multilanguage website but what's more important, I managed to convert my "drop-in" helpers into modules. These include TemplateLatteReplace and NetteFormsHelper modules, which will be shared after they look stable enough. 

    The Latte template engine module is almost invisible: handles default template render and wireRenderFile just fine. I may have gone with the TemplateEngine module but I like that it's lightweight and that I understand what's going on inside :)

    NetteFormsHelper makes creating forms a breeze (though it's 100% developer-centric), and I'm working on adding useful features to it.  

    Currently it supports:

    • ajax or non-ajax submission
    • live form validation (js)
    • automatically add js/css assets
    • saving data as page using "json_storage" field (which is a simple textarea holding a json encoded array, but visually looks like a formatted table in the admin)
    • send emails with Latte tempates
    • several form layouts (form renderers)
    • autocomplete: supports suggestions from arrays and urls (ajax)
    • character counter: needs only passing an array of settings, can count up/downwards, its text is customizable/translatable

    Form and field definitions are separated so forms can be easily copied to another project. Just to clarify: these are non-PW fields.

    I also have an AutoSmush module (imagemin through resmush.it) which actually works but needs a major revisit before going public, if ever. Anyway, bulk running on site images eliminates google pagespeed warning, which is great.

    Another helper I'm usng is Tracy debugger, which was made into a module by adrian so one todo item could be removed :)

    These modules makes development much more fun. I should have started them as modules right from the beginning.

    I am building a site using Latte now using your helpers drop-in method, really curious to see how the template framework coming along (it will be great if you early release it so most of us can test it) HAHA...

    Great work!

  7. Hi all,

    I just wanted to find out how Processwire developers manages their templates and components/partials these days. Are you guys using spex/twig/template data providers or just plain processwire setup?

    Below is my setup:

    - Using Spex which can be found here: http://modules.processwire.com/modules/spex/

    - partials/components are stored within these folders /site/templates/partials (Spex design by default)

    - there are options to set different base using using Spex

    - templates are built by outputting these partials/components

    - the rest of the setup is easier to read from Spex readme file rather than me trying to explain in it here.

    - php short tags whenever possible.

    Here are some screenshots:



    So far so good with Spex setup and I quiet like it however, Spex has not been updated for quiet sometime now and not sure if this module is going to support version PW version 3 moving forward.

    In the past, I've used Twig template engine (http://modules.processwire.com/modules/template-engine-twig/) created by wanze but not really compatible with Procache module which is a deal breaker for me but it works really well if you don't need Procache support.

    I understand the same topics have been brought up couple of times in the past (feel free to close this down if required) but I thought I brought up the same discussion again to get some new and cool ideas how to manage templates to make your life easier as Processwire developers.

    Many thanks!

  8. Hi Nico,

    Thanks for this module! Love it much :)

    I think I may have found a conflicting issue when this module is installed along side with ProcessBackup (DB Backup module). There is an error when you try to view the Database Backup detail and I believe it may be caused by the following line:

    $editedPage = wire('pages')->get($this->config->input->get->id);

    The SEO module kicks in when trying to view the database backup page because there is a querystring id in the url.


    The fix is pretty simple:

        public function ready() {
          // backend hooks
          if(@$this->page->process == 'ProcessPageEdit') {
            $editedPage = wire('pages')->get($this->config->input->get->id);
            if(in_array($editedPage->template->name, $this->includeTemplates)) {
              $this->addHookAfter("ProcessPageEdit::buildFormContent", $this, 'hookCustomizeSeoTab');
          // frontend hooks
          if($this->page->template != 'admin' && in_array($this->page->template->name, $this->includeTemplates)) {
            $this->addHookProperty("Page::seo", $this, 'hookFrontendPage');
            $this->addHookProperty("Config::seo", $this, 'hookFrontendConfig');

    Check the ProcessEditPage first before look for the edited page object. But anyway, I thought I let you know :) Thanks much again!

    • Like 3
  9. Hi Ryan,

    I know it's has been a while but is there any potential cause for this issue? I am having the same issue with 2.5.7, I setup a module with lazycron hook couple days ago and it works perfectly but after several days it stops working and I just couldn't identify why. No errors being logged which tells me lazycron is not being triggered at all.

    Here's my module if that helps:

       * ProcessWire 'Hello world' demonstration module
       * Demonstrates the Module interface and how to add hooks.
       * See README file for further links regarding module development.
       * ProcessWire 2.x
       * Copyright (C) 2014 by Ryan Cramer
       * Licensed under GNU/GPL v2, see LICENSE.TXT
       * http://processwire.com
      class Helloworld extends WireData implements Module {
         * getModuleInfo is a module required by all modules to tell ProcessWire about them
         * @return array
        public static function getModuleInfo() {
          return array(
            // The module'ss title, typically a little more descriptive than the class name
              'title' => 'Hello World',
            // version number
              'version' => 2,
            // summary is brief description of what this module is
              'summary' => 'An example module used for demonstration purposes. See the /site/modules/Helloworld.module file for details.',
            // Optional URL to more information about the module
              'href' => 'http://processwire.com',
            // singular=true: indicates that only one instance of the module is allowed.
            // This is usually what you want for modules that attach hooks.
              'singular' => true,
            // autoload=true: indicates the module should be started with ProcessWire.
            // This is necessary for any modules that attach runtime hooks, otherwise those
            // hooks won't get attached unless some other code calls the module on it's own.
            // Note that autoload modules are almost always also 'singular' (seen above).
              'autoload' => true,
            // Optional font-awesome icon name, minus the 'fa-' part
              'icon' => 'smile-o',
         * Initialize the module
         * ProcessWire calls this when the module is loaded. For 'autoload' modules, this will be called
         * when ProcessWire's API is ready. As a result, this is a good place to attach hooks.
        public function init() {
          $this->addHook('LazyCron::every30seconds', $this, 'fetch');
         * Example1 hooks into the pages->save method and displays a notice every time a page is saved
        public function fetch($interval = null) {
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, 'https://api.instagram.com/v1/users/1334465068/media/recent/?client_id=xxx');
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($ch, CURLOPT_TIMEOUT, 20);
          $result = curl_exec($ch);
          $result = json_decode($result);
          $urls = "";
          foreach ($result->data as $post) {
            $urls .= $post->images->standard_resolution->url . ",";
          if (strlen($urls) > 0) {
            $p = wire('pages')->get(1018);
            $p->instagram_urls = trim($urls, ",");

    Any help to know what's the issue was, is much appreciated! :)


  10. Hi Wanze,

    I figured it out, this is a silly mistake of not supplying the correct path LOL!

    //we use the page title as template
    $template = $sanitizer->name($page->title);
    /* render load body */
    $body = $factory->load('custom-templates/' . $template. '.php');
    if ($config->ajax) {
      $view = $factory->load('_Ajax.php', true);
    /* render custom-templates */
    $view->set('Body', $body->render());

    So, I am rendering the body with the global template option and if there is an ajax request, the global template is overridden with ajax.php or empty template using $factory->load() :D

    Silly mistakes!

    • Like 1
  11. Hi Wanze,

    Any direction how to configure this with $config->ajax?

    //we use the page title as template
    $template = $sanitizer->name($page->title);
    /* render load body */
    $body = $factory->load('custom-templates/' . $template. '.php');
    if ($config->ajax) {
    $view = $factory->load('custom-templates/_Ajax.php', true);
    /* render custom-templates */
    $view->set('Body', $body->render());

    I tried the code above but I dont get the desired result. I am setting the global template with my setup. Need a bit of help :) Thanks :D

  12. Welcome to the forums!


    You can set it as the default in your config.php file:

    $config->defaultAdminTheme = 'AdminThemeReno';

    User's can change between themes from their edit profile page.

    Thanks @adrian, I didn't know this. In fact called me lazy for not reading thoroughly the new enhancement in the config.php

  13. Hi guys,

    I am unable to find the solution to this issue (not sure what is the right keyword). I am seeing a lot of sub links under 'Pages' menu links on my live site, while on my local instance I only see 'Find' and 'Tree'. The screenshot explains it best. Is there anyway to remove all the unnecessary  options (not sure how they end up there) - maybe this is module related issue. Cheers


  14. Hi,

    I am wondering if we can add mobile support for this forum on phablet devices?  O0 I am using nokia 1320 which is 6 inch screen and it's not a pleasing experience to view the desktop version of forum on this screen because everything is tiny.

    Also, I am not so sure why "Welcome to Processwire" section (with 3 subsections) is hidden on my phone by default. Thank you.


  • Create New...