Template system
The new template system in Goteo uses FOIL which is a powerful php-native template system.
However, there's still a lot of the legacy views in use. They will coexist until we can fully get rid of the old system.
This document compares the old and new template system and highlights the main differences:
Old class system:
\Goteo\Core\View::get('template.html.php', array( 'obj' => ... ));
New Foil base templates:
\Goteo\Application\View::render('template', [ 'obj' => ... ]);
Or, inside a Controller which extends \Goteo\Core\Controller just do:
$this->viewResponse('template', ['obj' => ...]);
Main differences
Before:
Variables were located inside the array  $vars[] (or event for even older behaviour inside the $this ArrayObject instance);
File template.html.php
<?php
// Object
$obj = $this['obj'];
$obj->doSomething();
echo htmlspecialchars($this['obj']->doMore()); // Strings needed to be manually escaped
// Scalar
echo htmlspecialchars($this['variable']); // escaped
echo $this['variable']; // non-escaped
?>After:
Variables are instantiated by default as properties of the object $this (that's Foil's behaviour).
NOTE: For compatibility reasons an automatic array $this->vars is created with all variables copied inside. New views (or completely refactored) must not use this array.
File template.php
<?php
// Object
$obj->doSomething();
echo $this->e($this->raw('obj')->doMore()); // Escaped with $this->e() function
// Scalar
echo $this->variable; // HTML escaped by default (strings & arrays)
echo $this->raw('variable'); // Non escaped
// Compatibility with old views needing and array
echo $this->vars['variable']; // HTML escaped if it's a string or a simple array
?>New features
FOIL supports inheritance, custom functions & a great variables manipulation capabilities between templates.
Basic operation:
It starts with a basic layout used as the base by the other templates. Please refer to the official documentation of Foil to know more about this.
File layout.php
<html>
<head>
    <title><?= $this->title ?></title>
</head>
<body>
<?php $this->section('content') ?>
<?php $this->stop() ?>
</body>
</html>Let's override some vars in a final template extending layout.php, in this case the title variable and the section content:
profile.php
<?php $this->layout('template', ['title' => 'User Profile']) ?>
<?php $this->section('content') ?>
    <h1>User Profile</h1>
    <p>Hello, <?=$this->name?></p>
<?php $this->stop() ?>More info:
https://foilphp.github.io/Foil/docs/TEMPLATES/INHERITANCE.html https://foilphp.github.io/Foil/docs/DATA/PASS-DATA.html
Template inheritance:
The new Goteo views can have themes, currently there are 2, default & responsive (which will be the future theme). Located under the folder Resources/templates/. There's another sub-folder legacy which contains the old view system (which will disappear someday).
Plugins can override any view by recreating the same structure and placing a new view with the same name:
Resources/templates                  <- Main template folder
Resources/templates/legacy           <- Default deprecated theme (old system)
Resources/templates/default          <- Default non-responsive theme (migrated)
Resources/templates/responsive       <- New responsive theme (brand new)
extend/{plugin}/Resources/templates  <- Main view plugin template overrider
                                        Any view here will be processed before the default oneExample:
Having this default view and the plugin substitute:
Resources/templates/devault/discover/index.php
extend/my-plugin/Resources/templates/devault/discover/index.phpWhen a controller calls the view, the second one will be used if the plugin is activated. If the plugin is not activated, then the first one will be used:
Controller
<?php
// src/Goteo/Controller/DiscoverController.php
namespace Goteo\Controller;
class DiscoverController extends \Goteo\Core\Controller {
    public function index () {
        // This will render the discover/index.php file 
        // from my-plugin if activated
        return $this->viewResponse('discover/index',
            [ 'test' => 'automatic html escaped text' ]
        );
    }
}
?>Default view:
<?php 
// Resources/templates/default/discover/index.php
$this->layout("layout", ['bodyClass' => 'discover']);
?>
<?php $this->section('content') ?>
Show me the test var: <?=$this->test?>
<?php $this->replace() ?>Plugin view:
<?php 
// extend/my-plugin/Resources/templates/default/discover/index.php
$this->layout("layout", ['bodyClass' => 'discover']);
?>
<?php $this->section('content') ?>
I am the plugin view,
Show me the test var: <?=$this->test?>
<?php $this->replace() ?>Plugin views can also extend from a default view instead of the default layout:
<?php 
// extend/my-plugin/Resources/templates/default/discover/index.php
$this->layout("default:discover/index");
?>
<?php $this->section('content') ?>
I am the plugin view
<?php $this->replace() ?>Views can have partials, same principle applies to it.
Better check the Foil's documentation for more information.
Resources/templates/default/partials/  <- Partials views better placed
                                          in a specific folderPartial include example (Resources/templates/default/layout.php):
<html>
<head>
<?=$this->insert("partials/header/metas")?>
</head>
<body>
<?php $this->section('content') ?>
<?php $this->stop() ?>
</body>
</html>The partial Resources/templates/defaul/partials/header/metas.php will inherit all variables from layout.php
Template extensions:
Views can make use of many built-in functions in order to avoid calling Classes or main functions directly. This classes provides additional functionality to views in Goteo:
src/Goteo/Util/Foil/GoteoCore.php
src/Goteo/Util/Foil/LangUtils.php
src/Goteo/Util/Foil/Pages.php
src/Goteo/Util/Foil/TextUtils.phpSome useful functions
- $this->text('id-text')=> Get the copy of the- id-textin the current language
- $this->get_session('foo')=> Gets the session var "foo"
- $this->get_cookie('foo')=> Gets the cookie var "foo"
- $this->is_logged()=> Return "true" if user is logged in
- ...
Custom functions can be called like this:
<a href="#"><?= $this->text('view-project') ?></a>Guidelines
Ideally, templates must be kept as simple as possible, we will try to follow these guidelines for the new views using Foil (extracted from the Plates templates system):
- Always use HTML with inline PHP. Never use blocks of PHP.
- Always escape potentially dangerous variables prior to outputting using the built-in escape functions. More on escaping here.
- Always use the short echo syntax (<?=) when outputting variables. For all other inline PHP code, use full the<?phptag. Do not use short tags.
- Always use the alternative syntax for control structures, which are designed to make templates more legible.
- Never use PHP curly brackets.
- Only ever have one statement in each PHP tag.
- Avoid using semicolons. They are not needed when there is only one statement per PHP tag.
- Never use the useoperator. Templates should not be interacting with classes in this way. Use custom extensions for that.
- Never use the for,whileorswitchcontrol structures. Instead useifandforeach. Additionally you can take a look at the built-in loop and array Foil structures
- Avoid variable assignment.
