Browse code

converted documentation to rst

Fabien Potencier authored on 15/12/2010 11:25:16
Showing 12 changed files
1 1
deleted file mode 100644
... ...
@@ -1,94 +0,0 @@
1
-Introduction
2
-============
3
-
4
-This is the documentation for Twig, the flexible, fast, and secure template
5
-engine for PHP.
6
-
7
-If you have any exposure to other text-based template languages, such as
8
-Smarty, Django, or Jinja, you should feel right at home with Twig. It's both
9
-designer and developer friendly by sticking to PHP's principles and adding
10
-functionality useful for templating environments.
11
-
12
-The key-features are...
13
-
14
- * *Fast*: Twig compiles templates down to plain optimized PHP code. The
15
-   overhead compared to regular PHP code was reduced to the very minimum.
16
-
17
- * *Secure*: Twig has a sandbox mode to evaluate untrusted template code. This
18
-   allows Twig to be used as a template language for applications where users
19
-   may modify the template design.
20
-
21
- * *Flexible*: Twig is powered by a flexible lexer and parser. This allows the
22
-   developer to define its own custom tags and filters, and create its own
23
-   DSL.
24
-
25
-Prerequisites
26
-
27
-Twig needs at least **PHP 5.2.4** to run.
28
-
29
-Installation
30
-
31
-You have multiple ways to install Twig. If you are unsure what to do, go with
32
-the tarball.
33
-
34
-### From the tarball release
35
-
36
- 1. Download the most recent tarball from the [download page](http://www.twig-project.org/installation)
37
- 2. Unpack the tarball
38
- 3. Move the files somewhere in your project
39
-
40
-### Installing the development version
41
-
42
- 1. Install Subversion or Git
43
- 2. For Subversion: `svn co http://svn.twig-project.org/trunk/ twig`, for Git:
44
-    `git clone git://github.com/fabpot/Twig.git`
45
-
46
-### Installing the PEAR package
47
-
48
- 1. Install PEAR
49
- 2. pear channel-discover pear.twig-project.org
50
- 3. pear install twig/Twig (or pear install twig/Twig-beta)
51
-
52
-Basic API Usage
53
-
54
-This section gives you a brief introduction to the PHP API for Twig.
55
-
56
-The first step to use Twig is to register its autoloader:
57
-
58
-    [php]
59
-    require_once '/path/to/lib/Twig/Autoloader.php';
60
-    Twig_Autoloader::register();
61
-
62
-Replace the `/path/to/lib/` path with the path you used for Twig installation.
63
-
64
->**NOTE**
65
->Twig follows the PEAR convention names for its classes, which means you can
66
->easily integrate Twig classes loading in your own autoloader.
67
-
68
-    [php]
69
-    $loader = new Twig_Loader_String();
70
-    $twig = new Twig_Environment($loader);
71
-
72
-    $template = $twig->loadTemplate('Hello {{ name }}!');
73
-
74
-    $template->display(array('name' => 'Fabien'));
75
-
76
-Twig uses a loader (`Twig_Loader_String`) to locate templates, and an
77
-environment (`Twig_Environment`) to store the configuration.
78
-
79
-The `loadTemplate()` method uses the loader to locate and load the template
80
-and returns a template object (`Twig_Template`) which is suitable for
81
-rendering with the `display()` method.
82
-
83
-Twig also comes with a filesystem loader:
84
-
85
-    [php]
86
-    $loader = new Twig_Loader_Filesystem('/path/to/templates');
87
-    $twig = new Twig_Environment($loader, array(
88
-      'cache' => '/path/to/compilation_cache',
89
-    ));
90
-
91
-    $template = $twig->loadTemplate('index.html');
92 0
deleted file mode 100644
... ...
@@ -1,464 +0,0 @@
1
-Twig for Developers
2
-===================
3
-
4
-This chapter describes the API to Twig and not the template language. It will
5
-be most useful as reference to those implementing the template interface to
6
-the application and not those who are creating Twig templates.
7
-
8
-Basics
9
-
10
-Twig uses a central object called the **environment** (of class
11
-`Twig_Environment`). Instances of this class are used to store the
12
-configuration and extensions, and are used to load templates from the file
13
-system or other locations.
14
-
15
-Most applications will create one `Twig_Environment` object on application
16
-initialization and use that to load templates. In some cases it's however
17
-useful to have multiple environments side by side, if different configurations
18
-are in use.
19
-
20
-The simplest way to configure Twig to load templates for your application
21
-looks roughly like this:
22
-
23
-    [php]
24
-    require_once '/path/to/lib/Twig/Autoloader.php';
25
-    Twig_Autoloader::register();
26
-
27
-    $loader = new Twig_Loader_Filesystem('/path/to/templates');
28
-    $twig = new Twig_Environment($loader, array(
29
-      'cache' => '/path/to/compilation_cache',
30
-    ));
31
-
32
-This will create a template environment with the default settings and a loader
33
-that looks up the templates in the `/path/to/templates/` folder. Different
34
-loaders are available and you can also write your own if you want to load
35
-templates from a database or other resources.
36
-
37
->**CAUTION**
38
->Before Twig 0.9.3, the `cache` option did not exist, and the cache directory
39
->was passed as a second argument of the loader.
40
-
41
--
42
-
43
->**NOTE**
44
->Notice that the second argument of the environment is an array of options.
45
->The `cache` option is a compilation cache directory, where Twig caches the
46
->compiled templates to avoid the parsing phase for sub-sequent requests. It
47
->is very different from the cache you might want to add for the evaluated
48
->templates. For such a need, you can use any available PHP cache library.
49
-
50
-To load a template from this environment you just have to call the
51
-`loadTemplate()` method which then returns a `Twig_Template` instance:
52
-
53
-    [php]
54
-    $template = $twig->loadTemplate('index.html');
55
-
56
-To render the template with some variables, call the `render()` method:
57
-
58
-    [php]
59
-    echo $template->render(array('the' => 'variables', 'go' => 'here'));
60
-
61
->**NOTE**
62
->The `display()` method is a shortcut to output the template directly.
63
-
64
-Environment Options
65
-
66
-When creating a new `Twig_Environment` instance, you can pass an array of
67
-options as the constructor second argument:
68
-
69
-    [php]
70
-    $twig = new Twig_Environment($loader, array('debug' => true));
71
-
72
-The following options are available:
73
-
74
- * `debug`: When set to `true`, the generated templates have a `__toString()`
75
-   method that you can use to display the generated nodes (default to
76
-   `false`).
77
-
78
- * `charset`: The charset used by the templates (default to `utf-8`).
79
-
80
- * `base_template_class`: The base template class to use for generated
81
-   templates (default to `Twig_Template`).
82
-
83
- * `cache`: An absolute path where to store the compiled templates, or false
84
-   to disable caching (which is the default).
85
-
86
- * `auto_reload`: When developing with Twig, it's useful to recompile the
87
-   template whenever the source code changes. If you don't provide a value for
88
-   the `auto_reload` option, it will be determined automatically based on the
89
-   `debug` value.
90
-
91
- * `strict_variables` (new in Twig 0.9.7): If set to `false`, Twig will
92
-   silently ignore invalid variables (variables and or attributes/methods that
93
-   do not exist) and replace them with a `null` value. When set to `true`,
94
-   Twig throws an exception instead (default to `false`).
95
-
96
- * `autoescape` (new in Twig 0.9.10): If set to `true`, auto-escaping will be
97
-   enabled by default for all templates (default to `true`).
98
-
99
- * `optimizations` (new in Twig 0.9.10): A flag that indicates which
100
-   optimizations to apply (default to `-1` -- all optimizations are enabled;
101
-   set it to `0` to disable).
102
-
103
->**CAUTION**
104
->Before Twig 0.9.3, the `cache` and `auto_reload` options did not exist. They
105
->were passed as a second and third arguments of the filesystem loader
106
->respectively.
107
-
108
-Loaders
109
-
110
->**CAUTION**
111
->This section describes the loaders as implemented in Twig version 0.9.4 and
112
->above.
113
-
114
-Loaders are responsible for loading templates from a resource such as the file
115
-system.
116
-
117
-### Compilation Cache
118
-
119
-All template loaders can cache the compiled templates on the filesystem for
120
-future reuse. It speeds up Twig a lot as templates are only compiled once;
121
-and the performance boost is even larger if you use a PHP accelerator such as
122
-APC. See the `cache` and `auto_reload` options of `Twig_Environment` above for
123
-more information.
124
-
125
-### Built-in Loaders
126
-
127
-Here is a list of the built-in loaders Twig provides:
128
-
129
- * `Twig_Loader_Filesystem`: Loads templates from the file system. This loader
130
-   can find templates in folders on the file system and is the preferred way
131
-   to load them.
132
-
133
-        [php]
134
-        $loader = new Twig_Loader_Filesystem($templateDir);
135
-
136
-   It can also look for templates in an array of directories:
137
-
138
-        [php]
139
-        $loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2));
140
-
141
-   With such a configuration, Twig will first look for templates in
142
-   `$templateDir1` and if they do not exist, it will fallback to look for them
143
-   in the `$templateDir2`.
144
-
145
- * `Twig_Loader_String`: Loads templates from a string. It's a dummy loader as
146
-   you pass it the source code directly.
147
-
148
-        [php]
149
-        $loader = new Twig_Loader_String();
150
-
151
- * `Twig_Loader_Array`: Loads a template from a PHP array. It's passed an
152
-   array of strings bound to template names. This loader is useful for unit
153
-   testing.
154
-
155
-        [php]
156
-        $loader = new Twig_Loader_Array($templates);
157
-
158
->**TIP**
159
->When using the `Array` or `String` loaders with a cache mechanism, you should
160
->know that a new cache key is generated each time a template content "changes"
161
->(the cache key being the source code of the template). If you don't want to
162
->see your cache grows out of control, you need to take care of clearing the old
163
->cache file by yourself.
164
-
165
-### Create your own Loader
166
-
167
-All loaders implement the `Twig_LoaderInterface`:
168
-
169
-    [php]
170
-    interface Twig_LoaderInterface
171
-    {
172
-      /**
173
-       * Gets the source code of a template, given its name.
174
-       *
175
-       * @param  string $name string The name of the template to load
176
-       *
177
-       * @return string The template source code
178
-       */
179
-      public function getSource($name);
180
-
181
-      /**
182
-       * Gets the cache key to use for the cache for a given template name.
183
-       *
184
-       * @param  string $name string The name of the template to load
185
-       *
186
-       * @return string The cache key
187
-       */
188
-      public function getCacheKey($name);
189
-
190
-      /**
191
-       * Returns true if the template is still fresh.
192
-       *
193
-       * @param string    $name The template name
194
-       * @param timestamp $time The last modification time of the cached template
195
-       */
196
-      public function isFresh($name, $time);
197
-    }
198
-
199
-As an example, here is how the built-in `Twig_Loader_String` reads:
200
-
201
-    [php]
202
-    class Twig_Loader_String implements Twig_LoaderInterface
203
-    {
204
-      public function getSource($name)
205
-      {
206
-        return $name;
207
-      }
208
-
209
-      public function getCacheKey($name)
210
-      {
211
-        return $name;
212
-      }
213
-
214
-      public function isFresh($name, $time)
215
-      {
216
-        return false;
217
-      }
218
-    }
219
-
220
-The `isFresh()` method must return `true` if the current cached template is
221
-still fresh, given the last modification time, or `false` otherwise.
222
-
223
-Using Extensions
224
-
225
-Twig extensions are packages that adds new features to Twig. Using an
226
-extension is as simple as using the `addExtension()` method:
227
-
228
-    [php]
229
-    $twig->addExtension(new Twig_Extension_Sandbox());
230
-
231
-Twig comes bundled with the following extensions:
232
-
233
- * *Twig_Extension_Core*: Defines all the core features of Twig and is automatically
234
-   registered when you create a new environment.
235
-
236
- * *Twig_Extension_Escaper*: Adds automatic output-escaping and the possibility to
237
-   escape/unescape blocks of code.
238
-
239
- * *Twig_Extension_Sandbox*: Adds a sandbox mode to the default Twig environment, making it
240
-   safe to evaluated untrusted code.
241
-
242
- * *Twig_Extension_Optimizer*: Optimizers the node tree before compilation (as
243
-   of Twig 0.9.10).
244
-
245
-The core, escaper, and optimizer extensions do not need to be added to the
246
-Twig environment, as they are registered by default. You can disable an
247
-already registered extension:
248
-
249
-    [php]
250
-    $twig->removeExtension('escaper');
251
-
252
-Built-in Extensions
253
-
254
-This section describes the features added by the built-in extensions.
255
-
256
->**TIP**
257
->Read the chapter about extending Twig to learn how to create your own
258
->extensions.
259
-
260
-### Core Extension
261
-
262
-The `core` extension defines all the core features of Twig:
263
-
264
-  * Tags:
265
-
266
-     * `for`
267
-     * `if`
268
-     * `extends`
269
-     * `include`
270
-     * `block`
271
-     * `parent`
272
-     * `display`
273
-     * `filter`
274
-     * `macro`
275
-     * `import`
276
-     * `set`
277
-
278
-  * Filters:
279
-
280
-     * `date`
281
-     * `format`
282
-     * `even`
283
-     * `odd`
284
-     * `urlencode`
285
-     * `title`
286
-     * `capitalize`
287
-     * `upper`
288
-     * `lower`
289
-     * `striptags`
290
-     * `join`
291
-     * `reverse`
292
-     * `length`
293
-     * `sort`
294
-     * `in`
295
-     * `range`
296
-     * `cycle`
297
-     * `default`
298
-     * `keys`
299
-     * `items`
300
-     * `escape`
301
-     * `e`
302
-
303
-### Escaper Extension
304
-
305
-The `escaper` extension adds automatic output escaping to Twig. It defines a
306
-new tag, `autoescape`, and a new filter, `raw`.
307
-
308
-When creating the escaper extension, you can switch on or off the global
309
-output escaping strategy:
310
-
311
-    [php]
312
-    $escaper = new Twig_Extension_Escaper(true);
313
-    $twig->addExtension($escaper);
314
-
315
-If set to `true`, all variables in templates are escaped, except those using
316
-the `raw` filter:
317
-
318
-    [twig]
319
-    {{ article.to_html|raw }}
320
-
321
-You can also change the escaping mode locally by using the `autoescape` tag:
322
-
323
-    [twig]
324
-    {% autoescape on %}
325
-      {% var %}
326
-      {% var|raw %}     {# var won't be escaped #}
327
-      {% var|escape %}   {# var won't be doubled-escaped #}
328
-    {% endautoescape %}
329
-
330
->**WARNING**
331
->The `autoescape` tag has no effect on included files.
332
-
333
-The escaping rules are implemented as follows (it describes the behavior of
334
-Twig 0.9.9 and above):
335
-
336
- * Literals (integers, booleans, arrays, ...) used in the template directly as
337
-   variables or filter arguments are never automatically escaped:
338
-
339
-        [twig]
340
-        {{ "Twig<br />" }} {# won't be escaped #}
341
-
342
-        {% set text = "Twig<br />" %}
343
-        {{ text }} {# will be escaped #}
344
-
345
- * Expressions which the result is always a literal or a variable marked safe
346
-   are never automatically escaped:
347
-
348
-        [twig]
349
-        {{ foo ? "Twig<br />" : "<br />Twig" }} {# won't be escaped #}
350
-
351
-        {% set text = "Twig<br />" %}
352
-        {{ foo ? text : "<br />Twig" }} {# will be escaped #}
353
-
354
-        {% set text = "Twig<br />" %}
355
-        {{ foo ? text|raw : "<br />Twig" }} {# won't be escaped #}
356
-
357
-        {% set text = "Twig<br />" %}
358
-        {{ foo ? text|escape : "<br />Twig" }} {# the result of the expression won't be escaped #}
359
-
360
- * Escaping is applied before printing, after any other filter is applied:
361
-
362
-        [twig]
363
-        {{ var|upper }} {# is equivalent to {{ var|upper|escape }} #}
364
-
365
- * The `raw` filter should only be used at the end of the filter chain:
366
-
367
-        [twig]
368
-        {{ var|raw|upper }} {# will be escaped #}
369
-
370
-        [twig]
371
-        {{ var|upper|raw }} {# won't be escaped #}
372
-
373
- * Automatic escaping is not applied if the last filter in the chain is marked
374
-   safe for the current context (e.g. `html` or `js`). `escaper` and
375
-   `escaper('html')` are marked safe for html, `escaper('js')` is marked safe
376
-   for javascript, `raw` is marked safe for everything.
377
-
378
-        [twig]
379
-        {% autoescape js on %}
380
-        {{ var|escape('html') }} {# will be escaped for html and javascript #}
381
-        {{ var }} {# will be escaped for javascript #}
382
-        {{ var|escape('js') }} {# won't be double-escaped #}
383
-        {% endautoescape %}
384
-
385
-### Sandbox Extension
386
-
387
-The `sandbox` extension can be used to evaluate untrusted code. Access to
388
-unsafe attributes and methods is prohibited. The sandbox security is managed
389
-by a policy instance. By default, Twig comes with one policy class:
390
-`Twig_Sandbox_SecurityPolicy`. This class allows you to white-list some tags,
391
-filters, properties, and methods:
392
-
393
-    [php]
394
-    $tags = array('if');
395
-    $filters = array('upper');
396
-    $methods = array(
397
-      'Article' => array('getTitle', 'getBody'),
398
-    );
399
-    $properties = array(
400
-      'Article' => array('title', 'body),
401
-    );
402
-    $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties);
403
-
404
-With the previous configuration, the security policy will only allow usage of
405
-the `if` tag, and the `upper` filter. Moreover, the templates will only be
406
-able to call the `getTitle()` and `getBody()` methods on `Article` objects,
407
-and the `title` and `body` public properties. Everything else won't be allowed
408
-and will generate a `Twig_Sandbox_SecurityError` exception.
409
-
410
-The policy object is the first argument of the sandbox constructor:
411
-
412
-    [php]
413
-    $sandbox = new Twig_Extension_Sandbox($policy);
414
-    $twig->addExtension($sandbox);
415
-
416
-By default, the sandbox mode is disabled and should be enabled when including
417
-untrusted template code by using the `sandbox` tag:
418
-
419
-    [twig]
420
-    {% sandbox %}
421
-      {% include 'user.html' %}
422
-    {% endsandbox %}
423
-
424
-You can sandbox all templates by passing `true` as the second argument of the
425
-extension constructor:
426
-
427
-    [php]
428
-    $sandbox = new Twig_Extension_Sandbox($policy, true);
429
-
430
-### Optimizer Extension (as of Twig 0.9.10)
431
-
432
-The `optimizer` extension optimizes the node tree before compilation:
433
-
434
-    [php]
435
-    $twig->addExtension(new Twig_Extension_Optimizer());
436
-
437
-By default, all optimizations are turned on. You can select the ones you want
438
-to enable by passing them to the constructor:
439
-
440
-    [php]
441
-    $optimizer = new Twig_Extension_Optimizer(Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR);
442
-
443
-    $twig->addExtension($optimizer);
444
-
445
-Exceptions
446
-
447
-Twig can throw exceptions:
448
-
449
- * `Twig_Error`: The base exception for all template errors.
450
-
451
- * `Twig_SyntaxError`: Thrown to tell the user that there is a problem with
452
-   the template syntax.
453
-
454
- * `Twig_RuntimeError`: Thrown when an error occurs at runtime (when a filter
455
-   does not exist for instance).
456
-
457
- * `Twig_Sandbox_SecurityError`: Thrown when an unallowed tag, filter, or
458
-   method is called in a sandboxed template.
459 0
deleted file mode 100644
... ...
@@ -1,556 +0,0 @@
1
-Extending Twig
2
-==============
3
-
4
-Twig supports extensions that can add extra tags, filters, or even extend the
5
-parser itself with node visitor classes. The main motivation for writing
6
-an extension is to move often used code into a reusable class like adding
7
-support for internationalization.
8
-
9
-Most of the time, it is useful to create a single extension for your project,
10
-to host all the specific tags and filters you want to add to Twig.
11
-
12
->**NOTE**
13
->Before writing your own extensions, have a look at the Twig official extension
14
->repository: http://github.com/fabpot/Twig-extensions.
15
-
16
-Extending without an Extension (new in Twig 0.9.7)
17
-
18
-If you just need to register a small amount of tags and/or filters, you can
19
-register them without creating an extension:
20
-
21
-    [php]
22
-    $twig = new Twig_Environment($loader);
23
-    $twig->addTokenParser(new CustomTokenParser());
24
-    $twig->addFilter('upper', new Twig_Filter_Function('strtoupper'));
25
-
26
-Anatomy of an Extension
27
-
28
-An extension is a class that implements the following interface:
29
-
30
-    [php]
31
-    interface Twig_ExtensionInterface
32
-    {
33
-      /**
34
-       * Initializes the runtime environment.
35
-       *
36
-       * This is where you can load some file that contains filter functions for instance.
37
-       */
38
-      public function initRuntime();
39
-
40
-      /**
41
-       * Returns the token parser instances to add to the existing list.
42
-       *
43
-       * @return array An array of Twig_TokenParser instances
44
-       */
45
-      public function getTokenParsers();
46
-
47
-      /**
48
-       * Returns the node visitor instances to add to the existing list.
49
-       *
50
-       * @return array An array of Twig_NodeVisitorInterface instances
51
-       */
52
-      public function getNodeVisitors();
53
-
54
-      /**
55
-       * Returns a list of filters to add to the existing list.
56
-       *
57
-       * @return array An array of filters
58
-       */
59
-      public function getFilters();
60
-
61
-      /**
62
-       * Returns a list of tests to add to the existing list.
63
-       *
64
-       * @return array An array of tests
65
-       */
66
-      public function getTests();
67
-
68
-      /**
69
-       * Returns the name of the extension.
70
-       *
71
-       * @return string The extension name
72
-       */
73
-      public function getName();
74
-    }
75
-
76
-To keep your extension class clean and lean, it can inherit from the built-in
77
-`Twig_Extension` class instead of implementing the whole interface. That
78
-way, you just need to implement the `getName()` method as the
79
-`Twig_Extension` provides empty implementations for all other methods.
80
-
81
-The `getName()` method must return a unique identifier for your extension.
82
-
83
-Now, with this information in mind, let's create the most basic extension
84
-possible:
85
-
86
-    [php]
87
-    class Project_Twig_Extension extends Twig_Extension
88
-    {
89
-      public function getName()
90
-      {
91
-        return 'project';
92
-      }
93
-    }
94
-
95
->**NOTE**
96
->Of course, this extension does nothing for now. We will add tags and filters
97
->in the coming sections.
98
-
99
-Twig does not care where you save your extension on the filesystem, as all
100
-extensions must be registered explicitly to be available in your templates.
101
-
102
-You can register an extension by using the `addExtension()` method on your
103
-main `Environment` object:
104
-
105
-    [php]
106
-    $twig = new Twig_Environment($loader);
107
-    $twig->addExtension(new Project_Twig_Extension());
108
-
109
-Of course, you need to first load the extension file by either using
110
-`require_once()` or by using an autoloader (see
111
-[`spl_autoload_register()`](http://www.php.net/spl_autoload_register)).
112
-
113
->**TIP**
114
->The bundled extensions are great examples of how extensions work.
115
-
116
-Defining new Filters
117
-
118
->**CAUTION**
119
->This section describes the creation of new filters for Twig 0.9.5 and above.
120
-
121
-The most common element you will want to add to Twig is filters. A filter is
122
-just a regular PHP function or a method that takes the left side of the filter
123
-(before the pipe `|`) as first argument and the extra arguments passed to the
124
-filter (within parentheses `()`) as extra arguments.
125
-
126
-For instance, let's say you have the following code in a template:
127
-
128
-    [twig]
129
-    {{ 'TWIG'|lower }}
130
-
131
-When compiling this template to PHP, Twig will first look for the PHP function
132
-associated with the `lower` filter. The `lower` filter is a built-in Twig
133
-filter, and it is simply mapped to the PHP `strtolower()` function. After
134
-compilation, the generated PHP code is roughly equivalent to:
135
-
136
-    [php]
137
-    <?php echo strtolower('TWIG') ?>
138
-
139
-As you can see, the `'TWIG'` string is passed as a first argument to the
140
-PHP function.
141
-
142
-A filter can also take extra arguments like in the following example:
143
-
144
-    [twig]
145
-    {{ now|date('d/m/Y') }}
146
-
147
-In this case, the extra arguments are passed to the function after the main
148
-argument, and the compiled code is equivalent to:
149
-
150
-    [php]
151
-    <?php echo twig_date_format_filter($now, 'd/m/Y') ?>
152
-
153
-### Function Filters
154
-
155
-Let's see how to create a new filter.
156
-
157
-In this section, we will create a `rot13` filter, which should return the
158
-[rot13](http://www.php.net/manual/en/function.str-rot13.php) transformation of
159
-a string. Here is an example of its usage and the expected output:
160
-
161
-    [twig]
162
-    {{ "Twig"|rot13 }}
163
-
164
-    {# should displays Gjvt #}
165
-
166
-Adding a filter is as simple as calling the `addFilter` method of the
167
-`Twig_Environment` instance (new in Twig 0.9.7):
168
-
169
-    [php]
170
-    $twig = new Twig_Environment($loader);
171
-    $twig->addFilter('upper', new Twig_Filter_Function('strtoupper'));
172
-
173
-To add a filter to an extension, you need to override the `getFilters()`
174
-method. This method must return an array of filters to add to the Twig
175
-environment:
176
-
177
-    [php]
178
-    class Project_Twig_Extension extends Twig_Extension
179
-    {
180
-      public function getFilters()
181
-      {
182
-        return array(
183
-          'rot13' => new Twig_Filter_Function('str_rot13'),
184
-        );
185
-      }
186
-
187
-      public function getName()
188
-      {
189
-        return 'project';
190
-      }
191
-    }
192
-
193
-As you can see in the above code, the `getFilters()` method returns an array
194
-where keys are the name of the filters (`rot13`) and the values the definition
195
-of the filter (`new Twig_Filter_Function('str_rot13')`).
196
-
197
-The definition of a filter is always an object. For this first example, we
198
-have defined a filter as an object of the `Twig_Filter_Function` class.
199
-
200
-The `Twig_Filter_Function` class is to be used when you need to define a
201
-filter implemented as a function. The first argument passed to the
202
-`Twig_Filter_Function` constructor is the name of the function to call, here
203
-`str_rot13`, a native PHP function.
204
-
205
-Let's say I now want to be able to add a prefix before the converted string:
206
-
207
-    [twig]
208
-    {{ "Twig"|rot13('prefix_') }}
209
-
210
-    {# should displays prefix_Gjvt #}
211
-
212
-As the PHP `str_rot13()` function does not support this requirement, let's
213
-create a new PHP function:
214
-
215
-    [php]
216
-    function project_compute_rot13($string, $prefix = '')
217
-    {
218
-      return $prefix.str_rot13($string);
219
-    }
220
-
221
-As you can see, the `prefix` argument of the filter is passed as an extra
222
-argument to the `project_compute_rot13()` function.
223
-
224
->**NOTE**
225
->This function can declared anywhere by it is a good idea to define it in the
226
->same file as the extension class.
227
-
228
-The new extension code looks very similar to the previous one:
229
-
230
-    [php]
231
-    class Project_Twig_Extension extends Twig_Extension
232
-    {
233
-      public function getFilters()
234
-      {
235
-        return array(
236
-          'rot13' => new Twig_Filter_Function('project_compute_rot13'),
237
-        );
238
-      }
239
-
240
-      public function getName()
241
-      {
242
-        return 'project';
243
-      }
244
-    }
245
-
246
-### Class Method Filters
247
-
248
-Instead of creating a function to define a filter as we have done before, you
249
-can also create a static method in a class for better encapsulation.
250
-
251
-The `Twig_Filter_Function` class can also be used to register such static
252
-methods as filters:
253
-
254
-    [php]
255
-    class Project_Twig_Extension extends Twig_Extension
256
-    {
257
-      public function getFilters()
258
-      {
259
-        return array(
260
-          'rot13' => new Twig_Filter_Function('Project_Twig_Extension::rot13Filter'),
261
-        );
262
-      }
263
-
264
-      static public function rot13Filter($string)
265
-      {
266
-        return str_rot13($string);
267
-      }
268
-
269
-      public function getName()
270
-      {
271
-        return 'project';
272
-      }
273
-    }
274
-
275
-### Object Method Filters
276
-
277
-Defining static methods is one step towards better encapsulation, but defining
278
-filters as methods of your extension class is probably the best solution.
279
-
280
-This is possible by using `Twig_Filter_Method` instead of
281
-`Twig_Filter_Function` when defining a filter:
282
-
283
-    [php]
284
-    class Project_Twig_Extension extends Twig_Extension
285
-    {
286
-      public function getFilters()
287
-      {
288
-        return array(
289
-          'rot13' => new Twig_Filter_Method($this, 'rot13Filter'),
290
-        );
291
-      }
292
-
293
-      public function rot13Filter($string)
294
-      {
295
-        return str_rot13($string);
296
-      }
297
-
298
-      public function getName()
299
-      {
300
-        return 'project';
301
-      }
302
-    }
303
-
304
-The first argument of the `Twig_Filter_Method` constructor is always `$this`,
305
-the current extension object. The second one is the name of the method to
306
-call.
307
-
308
-Using methods for filters is a great way to package your filter without
309
-polluting the global namespace. This also gives the developer more flexibility
310
-at the cost of a small overhead.
311
-
312
-### Environment aware Filters
313
-
314
-The `Twig_Filter` classes take options as their last argument. For instance, if
315
-you want access to the current environment instance in your filter, set the
316
-`needs_environment` option to `true`:
317
-
318
-    [php]
319
-    $filter = new Twig_Filter_Function('str_rot13', array('needs_environment' => true));
320
-
321
-Twig will then pass the current environment as the first argument to the
322
-filter call:
323
-
324
-    [php]
325
-    function twig_compute_rot13(Twig_Environment $env, $string)
326
-    {
327
-      // get the current charset for instance
328
-      $charset = $env->getCharset();
329
-
330
-      return str_rot13($string);
331
-    }
332
-
333
-### Automatic Escaping
334
-
335
-If automatic escaping is enabled, the output of the filter may be escaped before
336
-printing. If your filter acts as an escaper (or explicitly outputs html or
337
-javascript code), you will want the raw output to be printed. In such a case,
338
-set the `is_safe` option:
339
-
340
-    [php]
341
-    $filter = new Twig_Filter_Function('nl2br', array('is_safe' => array('html')));
342
-
343
-Some advanced filters may have to work on already escaped or safe values. In
344
-such a case, set the `pre_escape` option:
345
-
346
-    [php]
347
-    $filter = new Twig_Filter_Function('somefilter', array('pre_escape' => 'html', 'is_safe' => array('html')));
348
-
349
-Overriding default Filters
350
-
351
->**CAUTION**
352
->This section describes how to override default filters for Twig 0.9.5 and
353
->above.
354
-
355
-If some default core filters do not suit your needs, you can easily override
356
-them by creating your own core extension. Of course, you don't need to copy
357
-and paste the whole core extension code of Twig. Instead, you can just extends
358
-it and override the filter(s) you want by overriding the `getFilters()`
359
-method:
360
-
361
-    [php]
362
-    class MyCoreExtension extends Twig_Extension_Core
363
-    {
364
-      public function getFilters()
365
-      {
366
-        return array_merge(
367
-          parent::getFilters(),
368
-          array(
369
-            'date' => Twig_Filter_Method($this, 'dateFilter')
370
-          )
371
-        );
372
-      }
373
-
374
-      public function dateFilter($timestamp, $format = 'F j, Y H:i')
375
-      {
376
-        return '...'.twig_date_format_filter($timestamp, $format);
377
-      }
378
-    }
379
-
380
-Here, we override the `date` filter with a custom one. Using this new core
381
-extension is as simple as registering the `MyCoreExtension` extension by
382
-calling the `addExtension()` method on the environment instance:
383
-
384
-    [php]
385
-    $twig = new Twig_Environment($loader);
386
-    $twig->addExtension(new MyCoreExtension());
387
-
388
-But I can already hear some people wondering how it can work as the Core
389
-extension is loaded by default. That's true, but the trick is that both
390
-extensions share the same unique identifier (`core` - defined in the
391
-`getName()` method). By registering an extension with the same name as an
392
-existing one, you have actually overridden the default one, even if it is
393
-already registered:
394
-
395
-    [php]
396
-    $twig->addExtension(new Twig_Extension_Core());
397
-    $twig->addExtension(new MyCoreExtension());
398
-
399
-Defining new Tags
400
-
401
-One of the most exciting feature of a template engine like Twig is the
402
-possibility to define new language constructs.
403
-
404
-Let's create a simple `set` tag that allows the definition of simple variables
405
-from within a template. The tag can be used like follows:
406
-
407
-    [twig]
408
-    {% set name = "value" %}
409
-
410
-    {{ name }}
411
-
412
-    {# should output value #}
413
-
414
->**NOTE**
415
->The `set` tag is part of the Core extension and as such is always available.
416
->The built-in version is slightly more powerful and supports multiple
417
->assignments by default (cf. the template designers chapter for more
418
->information).
419
-
420
-Three steps are needed to define a new tag:
421
-
422
-  * Defining a Token Parser class (responsible for parsing the template code)
423
-
424
-  * Defining a Node class (responsible for converting the parsed code to PHP)
425
-
426
-  * Registering the tag in an extension
427
-
428
-### Registering a new tag
429
-
430
-Adding a tag in an extension can be done by overriding the `getTokenParsers()`
431
-method. This method must return an array of tags to add to the Twig
432
-environment:
433
-
434
-    [php]
435
-    class Project_Twig_Extension extends Twig_Extension
436
-    {
437
-      public function getTokenParsers()
438
-      {
439
-        return array(new Project_Set_TokenParser());
440
-      }
441
-
442
-      // ...
443
-    }
444
-
445
-In the above code, we have added a single new tag, defined by the
446
-`Project_Set_TokenParser` class. The `Project_Set_TokenParser` class is
447
-responsible for parsing the tag and compiling it to PHP.
448
-
449
-### Defining a Token Parser
450
-
451
-Now, let's see the actual code of this class:
452
-
453
-    [php]
454
-    class Project_Set_TokenParser extends Twig_TokenParser
455
-    {
456
-      public function parse(Twig_Token $token)
457
-      {
458
-        $lineno = $token->getLine();
459
-        $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
460
-        $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, '=');
461
-        $value = $this->parser->getExpressionParser()->parseExpression();
462
-
463
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
464
-
465
-        return new Project_Set_Node($name, $value, $lineno, $this->getTag());
466
-      }
467
-
468
-      public function getTag()
469
-      {
470
-        return 'set';
471
-      }
472
-    }
473
-
474
-The `getTag()` method must return the tag we want to parse, here `set`.
475
-
476
-The `parse()` method is invoked whenever the parser encounters a `set` tag. It
477
-should return a `Twig_Node` instance that represents the node (the
478
-`Project_Set_Node` calls creating is explained in the next section).
479
-
480
-The parsing process is simplified thanks to a bunch of methods you can call
481
-from the token stream (`$this->parser->getStream()`):
482
-
483
- * `test()`: Tests the type and optionally the value of the next token and
484
-   returns it.
485
-
486
- * `expect()`: Expects a token and returns it (like `test()`) or throw a
487
-   syntax error if not found (the second argument is the expected value of the
488
-   token).
489
-
490
- * `look()`: Looks a the next token. This is how you can have a look at the
491
-   next token without consuming it (after you are done with `look()`, you must
492
-   use `rewind()`).
493
-
494
-Parsing expressions is done by calling the `parseExpression()` like we did for
495
-the `set` tag.
496
-
497
->**TIP**
498
->Reading the existing `TokenParser` classes is the best way to learn all the
499
->nitty-gritty details of the parsing process.
500
-
501
-### Defining a Node
502
-
503
-The `Project_Set_Node` class itself is rather simple:
504
-
505
-    [php]
506
-    class Project_Set_Node extends Twig_Node
507
-    {
508
-      public function __construct($name, Twig_Node_Expression $value, $lineno)
509
-      {
510
-        parent::__construct(array('value' => $value), array('name' => $name), $lineno);
511
-      }
512
-
513
-      public function compile($compiler)
514
-      {
515
-        $compiler
516
-          ->addDebugInfo($this)
517
-          ->write('$context[\''.$this->getAttribute('name').'\'] = ')
518
-          ->subcompile($this->getNode('value'))
519
-          ->raw(";\n")
520
-        ;
521
-      }
522
-    }
523
-
524
-The compiler implements a fluid interface and provides methods that helps the
525
-developer generate beautiful and readable PHP code:
526
-
527
- * `subcompile()`: Compiles a node.
528
-
529
- * `raw()`: Writes the given string as is.
530
-
531
- * `write()`: Writes the given string by adding indentation at the beginning
532
-   of each line.
533
-
534
- * `string()`: Writes a quoted string.
535
-
536
- * `repr()`: Writes a PHP representation of a given value (see `Twig_Node_For`
537
-   for a usage example).
538
-
539
- * `addDebugInfo()`: Adds the line of the original template file related to
540
-   the current node as a comment.
541
-
542
- * `indent()`: Indents the generated code (see `Twig_Node_Block` for a usage
543
-   example).
544
-
545
- * `outdent()`: Outdents the generated code (see `Twig_Node_Block` for a usage
546
-   example).
547
-
548
-Creating a Node Visitor
549
-
550
-To be written...
551 0
deleted file mode 100644
... ...
@@ -1,196 +0,0 @@
1
-Hacking Twig
2
-============
3
-
4
-Twig is very extensible and you can easily hack it. Keep in mind that you
5
-should probably try to create an extension before hacking the core, as most
6
-features and enhancements can be done with extensions. This chapter is also
7
-useful for people who want to understand how Twig works under the hood.
8
-
9
-How Twig works?
10
-
11
-The rendering of a Twig template can be summarized into four key steps:
12
-
13
- * **Load** the template: If the template is already compiled, load it and go
14
-   to the *evaluation* step, otherwise:
15
-
16
-   * First, the **lexer** tokenizes the template source code into small pieces
17
-     for easier processing;
18
-
19
-   * Then, the **parser** converts the token stream into a meaningful tree
20
-     of nodes (the Abstract Syntax Tree);
21
-
22
-   * Eventually, the *compiler* transforms the AST into PHP code;
23
-
24
- * **Evaluate** the template: It basically means calling the `display()`
25
-   method of the compiled template and passing it the context.
26
-
27
-The Lexer
28
-
29
-The Twig lexer goal is to tokenize a source code into a token stream (each
30
-token is of class `Token`, and the stream is an instance of
31
-`Twig_TokenStream`). The default lexer recognizes nine different token types:
32
-
33
-  * `Twig_Token::TEXT_TYPE`
34
-  * `Twig_Token::BLOCK_START_TYPE`
35
-  * `Twig_Token::VAR_START_TYPE`
36
-  * `Twig_Token::BLOCK_END_TYPE`
37
-  * `Twig_Token::VAR_END_TYPE`
38
-  * `Twig_Token::NAME_TYPE`
39
-  * `Twig_Token::NUMBER_TYPE`
40
-  * `Twig_Token::STRING_TYPE`
41
-  * `Twig_Token::OPERATOR_TYPE`
42
-  * `Twig_Token::EOF_TYPE`
43
-
44
-You can manually convert a source code into a token stream by calling the
45
-`tokenize()` of an environment:
46
-
47
-    [php]
48
-    $stream = $twig->tokenize($source, $identifier);
49
-
50
-As the stream has a `__toString()` method, you can have a textual
51
-representation of it by echoing the object:
52
-
53
-    [php]
54
-    echo $stream."\n";
55
-
56
-Here is the output for the `Hello {{ name }}` template:
57
-
58
-    [txt]
59
-    TEXT_TYPE(Hello )
60
-    VAR_START_TYPE()
61
-    NAME_TYPE(name)
62
-    VAR_END_TYPE()
63
-    EOF_TYPE()
64
-
65
-You can change the default lexer use by Twig (`Twig_Lexer`) by calling the
66
-`setLexer()` method:
67
-
68
-    [php]
69
-    $twig->setLexer($lexer);
70
-
71
-Lexer classes must implement the `Twig_LexerInterface`:
72
-
73
-    [php]
74
-    interface Twig_LexerInterface
75
-    {
76
-      /**
77
-       * Tokenizes a source code.
78
-       *
79
-       * @param  string $code     The source code
80
-       * @param  string $filename A unique identifier for the source code
81
-       *
82
-       * @return Twig_TokenStream A token stream instance
83
-       */
84
-      public function tokenize($code, $filename = 'n/a');
85
-    }
86
-
87
-The Parser
88
-
89
-The parser converts the token stream into an AST (Abstract Syntax Tree), or a
90
-node tree (of class `Twig_Node_Module`). The core extension defines the basic
91
-nodes like: `for`, `if`, ... and the expression nodes.
92
-
93
-You can manually convert a token stream into a node tree by calling the
94
-`parse()` method of an environment:
95
-
96
-    [php]
97
-    $nodes = $twig->parse($stream);
98
-
99
-Echoing the node object gives you a nice representation of the tree:
100
-
101
-    [php]
102
-    echo $nodes."\n";
103
-
104
-Here is the output for the `Hello {{ name }}` template:
105
-
106
-    [txt]
107
-    Twig_Node_Module(
108
-      Twig_Node_Text(Hello )
109
-      Twig_Node_Print(
110
-        Twig_Node_Expression_Name(name)
111
-      )
112
-    )
113
-
114
-The default parser (`Twig_TokenParser`) can be also changed by calling the
115
-`setParser()` method:
116
-
117
-    [php]
118
-    $twig->setParser($parser);
119
-
120
-All Twig parsers must implement the `Twig_ParserInterface`:
121
-
122
-    [php]
123
-    interface Twig_ParserInterface
124
-    {
125
-      /**
126
-       * Converts a token stream to a node tree.
127
-       *
128
-       * @param  Twig_TokenStream $stream A token stream instance
129
-       *
130
-       * @return Twig_Node_Module A node tree
131
-       */
132
-      public function parser(Twig_TokenStream $code);
133
-    }
134
-
135
-The Compiler
136
-
137
-The last step is done by the compiler. It takes a node tree as an input and
138
-generates PHP code usable for runtime execution of the templates. The default
139
-compiler generates PHP classes to ease the implementation of the template
140
-inheritance feature.
141
-
142
-You can call the compiler by hand with the `compile()` method of an
143
-environment:
144
-
145
-    [php]
146
-    $php = $twig->compile($nodes);
147
-
148
-The `compile()` method returns the PHP source code representing the node.
149
-
150
-The generated template for a `Hello {{ name }}` template reads as follows:
151
-
152
-    [php]
153
-    /* Hello {{ name }} */
154
-    class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Twig_Template
155
-    {
156
-      public function display($context)
157
-      {
158
-        $this->env->initRuntime();
159
-
160
-        // line 1
161
-        echo "Hello ";
162
-        echo (isset($context['name']) ? $context['name'] : null);
163
-      }
164
-    }
165
-
166
-As for the lexer and the parser, the default compiler (`Twig_Compiler`) can be
167
-changed by calling the `setCompiler()` method:
168
-
169
-    [php]
170
-    $twig->setCompiler($compiler);
171
-
172
-All Twig compilers must implement the `Twig_CompilerInterface`:
173
-
174
-    [php]
175
-    interface Twig_CompilerInterface
176
-    {
177
-      /**
178
-       * Compiles a node.
179
-       *
180
-       * @param  Twig_Node $node The node to compile
181
-       *
182
-       * @return Twig_Compiler The current compiler instance
183
-       */
184
-      public function compile(Twig_Node $node);
185
-
186
-      /**
187
-       * Gets the current PHP code after compilation.
188
-       *
189
-       * @return string The PHP code
190
-       */
191
-      public function getSource();
192
-    }
193 0
deleted file mode 100644
... ...
@@ -1,208 +0,0 @@
1
-Recipes
2
-=======
3
-
4
-Making a Layout conditional
5
-
6
-Working with Ajax means that the same content is sometimes displayed as is,
7
-and sometimes decorated with a layout. As Twig layout template names can be
8
-any valid expression, you can pass a variable that evaluates to `true` when
9
-the request is made via Ajax and choose the layout accordingly:
10
-
11
-    [twig]
12
-    {% extends request.ajax ? "base_ajax.html" : "base.html" %}
13
-
14
-    {% block content %}
15
-      This is the content to be displayed.
16
-    {% endblock %}
17
-
18
-Making an Include dynamic
19
-
20
-When including a template, its name does not need to be a string. For
21
-instance, the name can depend on the value of a variable:
22
-
23
-    [twig]
24
-    {% include var ~ '_foo.html' %}
25
-
26
-If `var` evaluates to `index`, the `index_foo.html` template will be
27
-rendered.
28
-
29
-As a matter of fact, the template name can be any valid expression, such as
30
-the following:
31
-
32
-    [twig]
33
-    {% include var|default('index') ~ '_foo.html' %}
34
-
35
-Customizing the Syntax
36
-
37
-Twig allows some syntax customization for the block delimiters. It's not
38
-recommended to use this feature as templates will be tied with your custom
39
-syntax. But for specific projects, it can make sense to change the defaults.
40
-
41
-To change the block delimiters, you need to create your own lexer object:
42
-
43
-    [php]
44
-    $twig = new Twig_Environment();
45
-
46
-    $lexer = new Twig_Lexer($twig, array(
47
-      'tag_comment'  => array('{#', '#}'),
48
-      'tag_block'    => array('{%', '%}'),
49
-      'tag_variable' => array('{{', '}}'),
50
-    ));
51
-    $twig->setLexer($lexer);
52
-
53
-Here are some configuration example that simulates some other template engines
54
-syntax:
55
-
56
-    [php]
57
-    // Ruby erb syntax
58
-    $lexer = new Twig_Lexer($twig, array(
59
-      'tag_comment'  => array('<%#', '%>'),
60
-      'tag_block'    => array('<%', '%>'),
61
-      'tag_variable' => array('<%=', '%>'),
62
-    ));
63
-
64
-    // SGML Comment Syntax
65
-    $lexer = new Twig_Lexer($twig, array(
66
-      'tag_comment'  => array('<!--#', '-->'),
67
-      'tag_block'    => array('<!--', '-->'),
68
-      'tag_variable' => array('${', '}'),
69
-    ));
70
-
71
-    // Smarty like
72
-    $lexer = new Twig_Lexer($twig, array(
73
-      'tag_comment'  => array('{*', '*}'),
74
-      'tag_block'    => array('{', '}'),
75
-      'tag_variable' => array('{$', '}'),
76
-    ));
77
-
78
-Using dynamic Object Properties
79
-
80
-When Twig encounters a variable like `article.title`, it tries to find a
81
-`title` public property in the `article` object.
82
-
83
-It also works if the property does not exist but is rather defined dynamically
84
-thanks to the magic `__get()` method; you just need to also implement the
85
-`__isset()` magic method like shown in the following snippet of code:
86
-
87
-    [php]
88
-    class Article
89
-    {
90
-      public function __get($name)
91
-      {
92
-        if ('title' == $name)
93
-        {
94
-          return 'The title';
95
-        }
96
-
97
-        // throw some kind of error
98
-      }
99
-
100
-      public function __isset($name)
101
-      {
102
-        if ('title' == $name)
103
-        {
104
-          return true;
105
-        }
106
-
107
-        return false;
108
-      }
109
-    }
110
-
111