Browse code

initial commit

git-svn-id: http://svn.twig-project.org/trunk@4 93ef8e89-cb99-4229-a87c-7fa0fa45744b

fabien authored on 07/10/2009 21:21:11
Showing 140 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+Twig is written and maintained by the Twig Team:
2
+
3
+Lead Developer:
4
+
5
+- Fabien Potencier <fabien.potencier@symfony-project.org>
6
+
7
+Project Founder:
8
+
9
+- Armin Ronacher <armin.ronacher@active-4.com>
0 10
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+Copyright (c) 2009 by the Twig Team, see AUTHORS for more details.
2
+
3
+Some rights reserved.
4
+
5
+Redistribution and use in source and binary forms, with or without
6
+modification, are permitted provided that the following conditions are
7
+met:
8
+
9
+    * Redistributions of source code must retain the above copyright
10
+      notice, this list of conditions and the following disclaimer.
11
+
12
+    * Redistributions in binary form must reproduce the above
13
+      copyright notice, this list of conditions and the following
14
+      disclaimer in the documentation and/or other materials provided
15
+      with the distribution.
16
+
17
+    * The names of the contributors may not be used to endorse or
18
+      promote products derived from this software without specific
19
+      prior written permission.
20
+
21
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 32
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+Twig, the flexible, fast, and secure template language for PHP
2
+==============================================================
3
+
4
+Twig is a template language for PHP, released under the new BSD license (code
5
+and documentation).
6
+
7
+Twig uses a syntax similar to the Django and Jinja template languages which
8
+inspired the Twig runtime environment.
0 9
new file mode 100644
... ...
@@ -0,0 +1,85 @@
1
+Introduction
2
+============
3
+
4
+This is the documentation for Twig, the flexible, fast, and secure template
5
+language 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 templating language for applications where
19
+   users 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
+
28
+Twig needs at least **PHP 5.2.4** to run.
29
+
30
+Installation
31
+------------
32
+
33
+You have multiple ways to install Twig. If you are unsure what to do, go with
34
+the tarball.
35
+
36
+### From the tarball release
37
+
38
+ 1. Download the most recent tarball from the [download page](http://www.twig-project.org/installation)
39
+ 2. Unpack the tarball
40
+ 3. Move the files somewhere in your project
41
+
42
+### Installing the development version
43
+
44
+ 1. Install Subversion
45
+ 2. `svn co http://svn.twig-project.org/trunk/ twig`
46
+
47
+Basic API Usage
48
+---------------
49
+
50
+This section gives you a brief introduction to the PHP API for Twig.
51
+
52
+The first step to use Twig is to register its autoloader:
53
+
54
+    [php]
55
+    require_once '/path/to/lib/Twig/Autoloader.php';
56
+    Twig_Autoloader::register();
57
+
58
+Replace the `/path/to/lib/` path with the path you used for Twig installation.
59
+
60
+>**NOTE**
61
+>Twig follows the PEAR convention names for its classes, which means you can
62
+>easily integrate Twig classes loading in your own autoloader.
63
+
64
+    [php]
65
+    $loader = new Twig_Loader_String();
66
+    $twig = new Twig_Environment($loader);
67
+
68
+    $template = $twig->loadTemplate('Hello {{ name }}!');
69
+
70
+    $template->display(array('name' => 'Fabien'));
71
+
72
+Twig uses a loader (`Twig_Loader_String`) to locate templates, and an
73
+environment (`Twig_Environment`) to store the configuration.
74
+
75
+The `loadTemplate()` method uses the loader to locate and load the template
76
+and returns a template object (`Twig_Template`) which is suitable for
77
+rendering with the `display()` method.
78
+
79
+Twig also comes with a filesystem loader:
80
+
81
+    [php]
82
+    $loader = new Twig_Loader_Filesystem('/path/to/templates');
83
+    $twig = new Twig_Environment($loader);
84
+
85
+    $template = $twig->loadTemplate('index.html');
0 86
new file mode 100644
... ...
@@ -0,0 +1,692 @@
1
+Twig for Template Designers
2
+===========================
3
+
4
+This document describes the syntax and semantics of the template engine and
5
+will be most useful as reference to those creating Twig templates.
6
+
7
+Synopsis
8
+--------
9
+
10
+A template is simply a text file. It can generate any text-based format (HTML,
11
+XML, CSV, LaTeX, etc.). It doesn't have a specific extension, `.html` or
12
+`.xml` are just fine.
13
+
14
+A template contains **variables** or **expressions**, which get replaced with
15
+values when the template is evaluated, and tags, which control the logic of
16
+the template.
17
+
18
+Below is a minimal template that illustrates a few basics. We will cover the
19
+details later in that document:
20
+
21
+    [twig]
22
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
23
+    <html lang="en">
24
+      <head>
25
+        <title>My Webpage</title>
26
+      </head>
27
+      <body>
28
+        <ul id="navigation">
29
+        {% for item in navigation %}
30
+          <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
31
+        {% endfor %}
32
+        </ul>
33
+
34
+        <h1>My Webpage</h1>
35
+        {{ a_variable }}
36
+      </body>
37
+    </html>
38
+
39
+There are two kinds of delimiters: `{% ... %}` and `{{ ... }}`. The first one
40
+is used to execute statements such as for-loops, the latter prints the result
41
+of an expression to the template.
42
+
43
+Variables
44
+---------
45
+
46
+The application passes variables to the templates you can mess around in the
47
+template. Variables may have attributes or elements on them you can access
48
+too. How a variable looks like, heavily depends on the application providing
49
+those.
50
+
51
+You can use a dot (`.`) to access attributes of a variable, alternative the
52
+so-called "subscript" syntax (`[]`) can be used. The following lines do the
53
+same::
54
+
55
+    [twig]
56
+    {{ foo.bar }}
57
+    {{ foo['bar'] }}
58
+
59
+>**NOTE**
60
+>It's important to know that the curly braces are *not* part of the variable
61
+>but the print statement. If you access variables inside tags don't put the
62
+>braces around.
63
+
64
+If a variable or attribute does not exist you will get back a `null` value.
65
+
66
+>**SIDEBAR**
67
+>Implementation
68
+>
69
+>For convenience sake `foo.bar` does the following things on
70
+>the PHP layer:
71
+>
72
+> * check if `foo` is an array and `bar` a valid element;
73
+> * if not, and if `foo` is an object, check that `bar` is a valid method;
74
+> * if not, and if `foo` is an object, check that `getBar` is a valid method;
75
+> * if not, return a `null` value.
76
+>
77
+>`foo['bar']` on the other hand works mostly the same with the a small
78
+>difference in the order:
79
+>
80
+> * check if `foo` is an array and `bar` a valid element;
81
+> * if not, return a `null` value.
82
+>
83
+>Using the alternative syntax is also useful to dynamically get attributes
84
+>from arrays:
85
+>
86
+>     [twig]
87
+>     foo[bar]
88
+
89
+Filters
90
+-------
91
+
92
+Variables can by modified by **filters**. Filters are separated from the
93
+variable by a pipe symbol (`|`) and may have optional arguments in
94
+parentheses. Multiple filters can be chained. The output of one filter is
95
+applied to the next.
96
+
97
+`{{ name|striptags|title }}` for example will remove all HTML tags from the
98
+`name` and title-cases it. Filters that accept arguments have parentheses
99
+around the arguments, like a function call. This example will join a list by
100
+commas: `{{ list|join(', ') }}`.
101
+
102
+The builtin filters section below describes all the builtin filters.
103
+
104
+Comments
105
+--------
106
+
107
+To comment-out part of a line in a template, use the comment syntax `{# ... #}`.
108
+This is useful to comment out parts of the template for debugging or to
109
+add information for other template designers or yourself:
110
+
111
+    [twig]
112
+    {# note: disabled template because we no longer use this
113
+      {% for user in users %}
114
+          ...
115
+      {% endfor %}
116
+    #}
117
+
118
+Whitespace Control
119
+------------------
120
+
121
+In the default configuration whitespace is not further modified by the
122
+template engine, so each whitespace (spaces, tabs, newlines etc.) is returned
123
+unchanged. If the application configures Twig to `trim_blocks` the first
124
+newline after a template tag is removed automatically (like in PHP).
125
+
126
+Escaping
127
+--------
128
+
129
+It is sometimes desirable or even necessary to have Twig ignore parts it would
130
+otherwise handle as variables or blocks. For example if the default syntax is
131
+used and you want to use `{{` as raw string in the template and not start a
132
+variable you have to use a trick.
133
+
134
+The easiest way is to output the variable delimiter (`{{`) by using a variable
135
+expression:
136
+
137
+    [twig]
138
+    {{ '{{' }}
139
+
140
+For bigger sections it makes sense to mark a block `raw`. For example to put
141
+Twig syntax as example into a template you can use this snippet:
142
+
143
+    [twig]
144
+    {% raw %}
145
+      <ul>
146
+      {% for item in seq %}
147
+        <li>{{ item }}</li>
148
+      {% endfor %}
149
+      </ul>
150
+    {% endraw %}
151
+
152
+Template Inheritance
153
+--------------------
154
+
155
+The most powerful part of Twig is template inheritance. Template inheritance
156
+allows you to build a base "skeleton" template that contains all the common
157
+elements of your site and defines **blocks** that child templates can
158
+override.
159
+
160
+Sounds complicated but is very basic. It's easiest to understand it by
161
+starting with an example.
162
+
163
+### Base Template
164
+
165
+This template, which we'll call `base.html`, defines a simple HTML skeleton
166
+document that you might use for a simple two-column page. It's the job of
167
+"child" templates to fill the empty blocks with content:
168
+
169
+    [twig]
170
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
171
+    <html lang="en">
172
+    <html xmlns="http://www.w3.org/1999/xhtml">
173
+    <head>
174
+      {% block head %}
175
+        <link rel="stylesheet" href="style.css" />
176
+        <title>{% block title %}{% endblock %} - My Webpage</title>
177
+      {% endblock %}
178
+    </head>
179
+    <body>
180
+      <div id="content">{% block content %}{% endblock %}</div>
181
+      <div id="footer">
182
+        {% block footer %}
183
+          &copy; Copyright 2009 by <a href="http://domain.invalid/">you</a>.
184
+        {% endblock %}
185
+      </div>
186
+    </body>
187
+
188
+In this example, the `{% block %}` tags define four blocks that child
189
+templates can fill in. All the `block` tag does is to tell the template engine
190
+that a child template may override those portions of the template.
191
+
192
+### Child Template
193
+
194
+A child template might look like this:
195
+
196
+    [twig]
197
+    {% extends "base.html" %}
198
+
199
+    {% block title %}Index{% endblock %}
200
+    {% block head %}
201
+      {% parent %}
202
+      <style type="text/css">
203
+        .important { color: #336699; }
204
+      </style>
205
+    {% endblock %}
206
+    {% block content %}
207
+      <h1>Index</h1>
208
+      <p class="important">
209
+        Welcome on my awesome homepage.
210
+      </p>
211
+    {% endblock %}
212
+
213
+The `{% extends %}` tag is the key here. It tells the template engine that
214
+this template "extends" another template. When the template system evaluates
215
+this template, first it locates the parent. The extends tag should be the
216
+first tag in the template.
217
+
218
+The filename of the template depends on the template loader. For example the
219
+`Twig_Loader_Filesystem` allows you to access other templates by giving the
220
+filename. You can access templates in subdirectories with a slash:
221
+
222
+    [twig]
223
+    {% extends "layout/default.html" %}
224
+
225
+But this behavior can depend on the application embedding Twig. Note that
226
+since the child template doesn't define the `footer` block, the value from the
227
+parent template is used instead.
228
+
229
+You can't define multiple `{% block %}` tags with the same name in the same
230
+template. This limitation exists because a block tag works in "both"
231
+directions. That is, a block tag doesn't just provide a hole to fill - it also
232
+defines the content that fills the hole in the *parent*. If there were two
233
+similarly-named `{% block %}` tags in a template, that template's parent
234
+wouldn't know which one of the blocks' content to use.
235
+
236
+If you want to print a block multiple times you can however use the `display`
237
+tag:
238
+
239
+    [twig]
240
+    <title>{% block title %}{% endblock %}</title>
241
+    <h1>{% display title %}</h1>
242
+    {% block body %}{% endblock %}
243
+
244
+Like PHP, Twig does not support multiple inheritance. So you can only have one
245
+extends tag called per rendering.
246
+
247
+### Parent Blocks
248
+
249
+It's possible to render the contents of the parent block by using the `parent`
250
+tag. This gives back the results of the parent block:
251
+
252
+    [twig]
253
+    {% block sidebar %}
254
+      <h3>Table Of Contents</h3>
255
+      ...
256
+      {% parent %}
257
+    {% endblock %}
258
+
259
+### Named Block End-Tags
260
+
261
+Twig allows you to put the name of the block after the end tag for better
262
+readability:
263
+
264
+    [twig]
265
+    {% block sidebar %}
266
+      {% block inner_sidebar %}
267
+          ...
268
+      {% endblock inner_sidebar %}
269
+    {% endblock sidebar %}
270
+
271
+However the name after the `endblock` word must match the block name.
272
+
273
+### Block Nesting and Scope
274
+
275
+Blocks can be nested for more complex layouts. Per default, blocks have access
276
+to variables from outer scopes:
277
+
278
+    [twig]
279
+    {% for item in seq %}
280
+      <li>{% block loop_item %}{{ item }}{% endblock %}</li>
281
+    {% endfor %}
282
+
283
+Import Context Behavior
284
+-----------------------
285
+
286
+Per default included templates are passed the current context.
287
+
288
+The context that is passed to the included template includes variables defined
289
+in the template:
290
+
291
+    [twig]
292
+    {% for box in boxes %}
293
+      {% include "render_box.html" %}
294
+    {% endfor %}
295
+
296
+The included template `render_box.html` is able to access `box`.
297
+
298
+HTML Escaping
299
+-------------
300
+
301
+When generating HTML from templates, there's always a risk that a variable
302
+will include characters that affect the resulting HTML. There are two
303
+approaches: manually escaping each variable or automatically escaping
304
+everything by default.
305
+
306
+Twig supports both, but what is used depends on the application configuration.
307
+The default configuration is no automatic escaping for various reasons:
308
+
309
+ * Escaping everything except of safe values will also mean that Twig is
310
+   escaping variables known to not include HTML such as numbers which is a
311
+   huge performance hit.
312
+
313
+ * The information about the safety of a variable is very fragile. It could
314
+   happen that by coercing safe and unsafe values the return value is double
315
+   escaped HTML.
316
+
317
+>**NOTE**
318
+>Escaping is only supported if the *escaper* extension has been enabled.
319
+
320
+### Working with Manual Escaping
321
+
322
+If manual escaping is enabled it's **your** responsibility to escape variables
323
+if needed. What to escape? If you have a variable that *may* include any of
324
+the following chars (`>`, `<`, `&`, or `"`) you **have to** escape it unless
325
+the variable contains well-formed and trusted HTML. Escaping works by piping
326
+the variable through the `|e` filter: `{{ user.username|e }}`.
327
+
328
+### Working with Automatic Escaping
329
+
330
+Automatic escaping is enabled when the `escaper` extension has been enabled.
331
+
332
+Whether automatic escaping is enabled or not, you can mark a section of a
333
+template to be escaped or not by using the `autoescape` tag:
334
+
335
+    [twig]
336
+    {% autoescape on %}
337
+      Everything will be automatically escaped in this block
338
+    {% endautoescape %}
339
+
340
+    {% autoescape off %}
341
+      Everything will be outputed as is in this block
342
+    {% endautoescape %}
343
+
344
+When automatic escaping is enabled everything is escaped by default except for
345
+values explicitly marked as safe. Those can be marked in the template by using
346
+the `|safe` filter.
347
+
348
+Functions returning template data (like `parent`) return safe markup always.
349
+
350
+>**NOTE**
351
+>Twig is smart enough to not escape an already escaped value by the `escape`
352
+>filter.
353
+
354
+List of Control Structures
355
+--------------------------
356
+
357
+A control structure refers to all those things that control the flow of a
358
+program - conditionals (i.e. `if`/`elseif`/`else`), `for`-loops, as well as
359
+things like blocks. Control structures appear inside `{% ... %}` blocks.
360
+
361
+### For
362
+
363
+Loop over each item in a sequence. For example, to display a list of users
364
+provided in a variable called `users`:
365
+
366
+    [twig]
367
+    <h1>Members</h1>
368
+    <ul>
369
+      {% for user in users %}
370
+        <li>{{ user.username|e }}</li>
371
+      {% endfor %}
372
+    </ul>
373
+
374
+Inside of a for loop block you can access some special variables:
375
+
376
+| Variable              | Description
377
+| --------------------- | -------------------------------------------------------------
378
+| `loop.index`          | The current iteration of the loop. (1 indexed)
379
+| `loop.index0`         | The current iteration of the loop. (0 indexed)
380
+| `loop.revindex`       | The number of iterations from the end of the loop (1 indexed)
381
+| `loop.revindex0`      | The number of iterations from the end of the loop (0 indexed)
382
+| `loop.first`          | True if first iteration
383
+| `loop.last`           | True if last iteration
384
+| `loop.length`         | The number of items in the sequence
385
+
386
+Unlike in PHP it's not possible to `break` or `continue` in a loop.
387
+
388
+If no iteration took place because the sequence was empty, you can render a
389
+replacement block by using `else`:
390
+
391
+    [twig]
392
+    <ul>
393
+      {% for user in users %}
394
+        <li>{{ user.username|e }}</li>
395
+      {% else %}
396
+        <li><em>no users found</em></li>
397
+      {% endif %}
398
+    </ul>
399
+
400
+### If
401
+
402
+The `if` statement in Twig is comparable with the if statements of PHP. In the
403
+simplest form you can use it to test if a variable is defined, not empty or
404
+not false:
405
+
406
+    [twig]
407
+    {% if users %}
408
+      <ul>
409
+        {% for user in users %}
410
+          <li>{{ user.username|e }}</li>
411
+        {% endfor %}
412
+      </ul>
413
+    {% endif %}
414
+
415
+For multiple branches `elseif` and `else` can be used like in PHP. You can use
416
+more complex `expressions` there too:
417
+
418
+    {% if kenny.sick %}
419
+      Kenny is sick.
420
+    {% elseif kenny.dead %}
421
+      You killed Kenny!  You bastard!!!
422
+    {% else %}
423
+      Kenny looks okay --- so far
424
+    {% endif %}
425
+
426
+### Filters
427
+
428
+Filter sections allow you to apply regular Twig filters on a block of template
429
+data. Just wrap the code in the special `filter` section:
430
+
431
+    [twig]
432
+    {% filter upper %}
433
+      This text becomes uppercase
434
+    {% endfilter %}
435
+
436
+### Extends
437
+
438
+The `extends` tag can be used to extend a template from another one. You can
439
+have multiple of them in a file but only one of them may be executed at the
440
+time. There is no support for multiple inheritance. See the section about
441
+Template inheritance above.
442
+
443
+### Block
444
+
445
+Blocks are used for inheritance and act as placeholders and replacements at
446
+the same time. They are documented in detail as part of the section about
447
+Template inheritance above.
448
+
449
+### Include
450
+
451
+The `include` statement is useful to include a template and return the
452
+rendered contents of that file into the current namespace:
453
+
454
+    [twig]
455
+    {% include 'header.html' %}
456
+      Body
457
+    {% include 'footer.html' %}
458
+
459
+Included templates have access to the variables of the active context.
460
+
461
+An included file can be evaluated in the sandbox environment by appending
462
+`sandboxed` at the end if the `escaper` extension has been enabled:
463
+
464
+    [twig]
465
+    {% include 'user.html' sandboxed %}
466
+
467
+Expressions
468
+-----------
469
+
470
+Twig allows basic expressions everywhere. These work very similar to regular
471
+PHP and even if you're not working with PHP you should feel comfortable with
472
+it.
473
+
474
+### Literals
475
+
476
+The simplest form of expressions are literals. Literals are representations
477
+for PHP types such as strings and numbers. The following literals exist:
478
+
479
+ * `"Hello World"`: Everything between two double or single quotes is a
480
+   string. They are useful whenever you need a string in the template (for
481
+   example as arguments to function calls, filters or just to extend or
482
+   include a template).
483
+
484
+ * `42` / `42.23`: Integers and floating point numbers are created by just
485
+   writing the number down. If a dot is present the number is a float,
486
+   otherwise an integer.
487
+
488
+### Math
489
+
490
+Twig allows you to calculate with values. This is rarely useful in templates
491
+but exists for completeness' sake. The following operators are supported:
492
+
493
+ * `+`: Adds two objects together. Usually the objects are numbers but if both
494
+   are strings or lists you can concatenate them this way. This however is not
495
+   the preferred way to concatenate strings! For string concatenation have a
496
+   look at the `~` operator. `{{ 1 + 1 }}` is `2`.
497
+
498
+ * `-`: Substract the second number from the first one. `{{ 3 - 2 }}` is `1`.
499
+
500
+ * `/`: Divide two numbers. The return value will be a floating point number.
501
+   `{{ 1 / 2 }}` is `{{ 0.5 }}`.
502
+
503
+ * `//`: Divide two numbers and return the truncated integer result. `{{ 20 //
504
+   7 }}` is `2`.
505
+
506
+ * `%`: Calculate the remainder of an integer division. `{{ 11 % 7 }}` is `4`.
507
+
508
+ * `*`: Multiply the left operand with the right one. `{{ 2 * 2 }}` would
509
+   return `4`. This can also be used to repeat a string multiple times. `{{
510
+   '=' * 80 }}` would print a bar of 80 equal signs.
511
+
512
+ * `**`: Raise the left operand to the power of the right operand. `{{ 2**3
513
+   }}` would return `8`.
514
+
515
+### Logic
516
+
517
+For `if` statements, `for` filtering or `if` expressions it can be useful to
518
+combine multiple expressions:
519
+
520
+ * `and`: Return true if the left and the right operand is true.
521
+
522
+ * `or`: Return true if the left or the right operand is true.
523
+
524
+ * `not`: Negate a statement.
525
+
526
+ * `(expr)`: Group an expression.
527
+
528
+### Comparisons
529
+
530
+The following comparison operators are supported in any expression: `==`,
531
+`!=`, `<`, `>`, `>=`, and `<=`.
532
+
533
+>**TIP**
534
+>Besides PHP classic comparison operators, Twig also supports a shortcut
535
+>notation when you want to test a value in a range:
536
+>
537
+>     [twig]
538
+>     {% if 1 < foo < 4 %}foo is between 1 and 4{% endif %}
539
+
540
+### Other Operators
541
+
542
+The following operators are very useful but don't fit into any of the other
543
+two categories:
544
+
545
+ * `|`: Applies a filter.
546
+
547
+ * `~`: Converts all operands into strings and concatenates them. `{{ "Hello "
548
+   ~ name ~ "!" }}` would return (assuming `name` is `'John'`) `Hello John!`.
549
+
550
+ * `.`, `[]`: Get an attribute of an object.
551
+
552
+ * `?:`: Twig supports the PHP ternary operator:
553
+
554
+        [twig]
555
+        {{ foo ? 'yes' : 'no' }}
556
+
557
+List of Builtin Filters
558
+-----------------------
559
+
560
+### `date`
561
+
562
+The `date` filter is able to format a date to a given format:
563
+
564
+    [twig]
565
+    {{ post.published_at|date("m/d/Y") }}
566
+
567
+### `format`
568
+
569
+The `format` filter formats a given string by replacing the placeholders:
570
+
571
+
572
+    [twig]
573
+    {# string is a format string like: I like %s and %s. #}
574
+    {{ string|format(foo, "bar") }}
575
+    {# returns I like foo and bar. (if the foo parameter equals to the foo string) #}
576
+
577
+### `even`
578
+
579
+The `even` filter returns `true` if the given number is even, `false`
580
+otherwise:
581
+
582
+    [twig]
583
+    {{ var|even ? 'even' : 'odd' }}
584
+
585
+### `odd`
586
+
587
+The `odd` filter returns `true` if the given number is odd, `false`
588
+otherwise:
589
+
590
+    [twig]
591
+    {{ var|odd ? 'odd' : 'even' }}
592
+
593
+### `encoding`
594
+
595
+The `encoding` filter URL encode a given string.
596
+
597
+### `title`
598
+
599
+The `title` filter returns a titlecased version of the value. I.e. words will
600
+start with uppercase letters, all remaining characters are lowercase.
601
+
602
+### `capitalize`
603
+
604
+The `capitalize` filter capitalizes a value. The first character will be
605
+uppercase, all others lowercase.
606
+
607
+### `upper`
608
+
609
+The `upper` filter converts a value to uppercase.
610
+
611
+### `lower`
612
+
613
+The `lower` filter converts a value to lowercase.
614
+
615
+### `striptags`
616
+
617
+The `striptags` filter strips SGML/XML tags and replace adjacent whitespace by
618
+one space.
619
+
620
+### `join`
621
+
622
+The `join` filter returns a string which is the concatenation of the strings
623
+in the sequence. The separator between elements is an empty string per
624
+default, you can define it with the optional parameter:
625
+
626
+    [twig]
627
+    {{ [1, 2, 3]|join('|') }}
628
+    {# returns 1|2|3 #}
629
+
630
+    {{ [1, 2, 3]|join }}
631
+    {# returns 123 #}
632
+
633
+### `reverse`
634
+
635
+The `reverse` filter reverses an array or an object if it implements the
636
+`Iterator` interface.
637
+
638
+### `length`
639
+
640
+The `length` filters returns the number of items of a sequence or mapping, or
641
+the length of a string.
642
+
643
+### `sort`
644
+
645
+The `sort` filter sorts an array.
646
+
647
+### `default`
648
+
649
+The `default` filter returns the passed default value if the value is
650
+undefined, otherwise the value of the variable:
651
+
652
+    [twig]
653
+    {{ my_variable|default('my_variable is not defined') }}
654
+
655
+### `keys`
656
+
657
+The `keys` filter returns the keys of an array. It is useful when you want to
658
+iterate over the keys of an array:
659
+
660
+    [twig]
661
+    {% for key in array|keys %}
662
+        ...
663
+    {% endfor %}
664
+
665
+### `items`
666
+
667
+The `items` filter is mainly useful when using the `for` tag to iterate over
668
+both the keys and the values of an array:
669
+
670
+    [twig]
671
+    {% for key, value in array|items %}
672
+        ...
673
+    {% endfor %}
674
+
675
+### `escape`, `e`
676
+
677
+The `escape` filter converts the characters `&`, `<`, `>`, `'`, and `"` in
678
+strings to HTML-safe sequences. Use this if you need to display text that
679
+might contain such characters in HTML.
680
+
681
+>**NOTE**
682
+>Internally, `escape` uses the PHP `htmlspecialchars` function.
683
+
684
+### `safe`
685
+
686
+The `safe` filter marks the value as safe which means that in an environment
687
+with automatic escaping enabled this variable will not be escaped.
688
+
689
+    [twig]
690
+    {% autoescape on }
691
+      {{ var|safe }} {# var won't be escaped #}
692
+    {% autoescape off %}
0 693
new file mode 100644
... ...
@@ -0,0 +1,284 @@
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
+
11
+Twig uses a central object called the **environment** (of class
12
+`Twig_Environment`). Instances of this class are used to store the
13
+configuration and extensions, and are used to load templates from the file
14
+system or other locations.
15
+
16
+Most applications will create one `Twig_Environment` object on application
17
+initialization and use that to load templates. In some cases it's however
18
+useful to have multiple environments side by side, if different configurations
19
+are in use.
20
+
21
+The simplest way to configure Twig to load templates for your application
22
+looks roughly like this:
23
+
24
+    [php]
25
+    require_once '/path/to/lib/Twig/Autoloader.php';
26
+    Twig_Autoloader::register();
27
+
28
+    $loader = new Twig_Loader_Filesystem('/path/to/templates');
29
+    $twig = new Twig_Environment($loader);
30
+
31
+This will create a template environment with the default settings and a loader
32
+that looks up the templates in the `/path/to/templates/` folder. Different
33
+loaders are available and you can also write your own if you want to load
34
+templates from a database or other resources.
35
+
36
+To load a template from this environment you just have to call the
37
+`loadTemplate()` method which then returns a `Twig_Template` instance:
38
+
39
+    [php]
40
+    $template = $twig->loadTemplate('index.html');
41
+
42
+To render the template with some variables, call the `render()` method:
43
+
44
+    [php]
45
+    echo $template->render(array('the' => 'variables', 'go' => 'here'));
46
+
47
+>**NOTE**
48
+>The `display()` method is a shortcut to output the template directly.
49
+
50
+Environment Options
51
+-------------------
52
+
53
+When creating a new `Twig_Environment` instance, you can pass an array of
54
+options as the constructor second argument:
55
+
56
+    [php]
57
+    $twig = new Twig_Environment($loader, array('debug' => true));
58
+
59
+The following options are available:
60
+
61
+ * `debug`: When set to `true`, the generated templates have a `__toString()`
62
+   method that you can use to display the generated nodes (default to
63
+   `false`).
64
+
65
+ * `trim_blocks`: Mimicks the behavior of PHP by removing the newline that
66
+   follows instructions if present (default to `false`).
67
+
68
+ * `charset`: The charset used by the templates (default to `utf-8`).
69
+
70
+ * `base_template_class`: The base template class to use for generated
71
+   templates (default to `Twig_Template`).
72
+
73
+Loaders
74
+-------
75
+
76
+Loaders are responsible for loading templates from a resource such as the file
77
+system. The environment will keep the compiled templates in memory.
78
+
79
+### Built-in Loaders
80
+
81
+Here a list of the built-in loaders Twig provides:
82
+
83
+ * `Twig_Loader_Filesystem`: Loads templates from the file system. This loader
84
+   can find templates in folders on the file system and is the preferred way
85
+   to load them.
86
+
87
+ * `Twig_Loader_String`: Loads templates from a string. It's a dummy loader as
88
+   you pass it the source code directly.
89
+
90
+ * `Twig_Loader_Array`: Loads a template from a PHP array. It's passed an
91
+   array of strings bound to template names. This loader is useful for unit
92
+   testing.
93
+
94
+### Create your own Loader
95
+
96
+All loaders implement the `Twig_LoaderInterface`:
97
+
98
+    [php]
99
+    interface Twig_LoaderInterface
100
+    {
101
+      /**
102
+       * Loads a template by name.
103
+       *
104
+       * @param  string $name The template name
105
+       *
106
+       * @return string The class name of the compiled template
107
+       */
108
+      public function load($name);
109
+    }
110
+
111
+But if you want to create your own loader, you'd better inherit from the
112
+`Twig_Loader` class, which already provides a lot of useful features. In this
113
+case, you just need to implement the `getSource()` method. As an example, here
114
+is how the built-in `Twig_Loader_String` reads:
115
+
116
+    [php]
117
+    class Twig_Loader_String extends Twig_Loader
118
+    {
119
+      /**
120
+       * Gets the source code of a template, given its name.
121
+       *
122
+       * @param  string $name string The name of the template to load
123
+       *
124
+       * @return array An array consisting of the source code as the first element,
125
+       *               and the last modification time as the second one
126
+       *               or false if it's not relevant
127
+       */
128
+      public function getSource($name)
129
+      {
130
+        return array($name, false);
131
+      }
132
+    }
133
+
134
+Using Extensions
135
+----------------
136
+
137
+Twig extensions are packages that adds new features to Twig. Using an
138
+extension is as simple as using the `addExtension()` method:
139
+
140
+    [php]
141
+    $twig->addExtension('Escaper');
142
+
143
+Twig comes bundled with three extensions:
144
+
145
+ * *Core*: Defines all the core features of Twig and is automatically
146
+   registered when you create a new environment.
147
+
148
+ * *Escaper*: Adds automatic output-escaping and the possibility to
149
+   escape/unescape blocks of code.
150
+
151
+ * *Sandbox*: Adds a sandbox mode to the default Twig environment, making it
152
+   safe to evaluated untrusted code.
153
+
154
+Built-in Extensions
155
+-------------------
156
+
157
+This section describes the features added by the built-in extensions.
158
+
159
+>**TIP**
160
+>Read the chapter about extending Twig to learn how to create your own
161
+>extensions.
162
+
163
+### Core Extension
164
+
165
+The `core` extension defines all the core features of Twig:
166
+
167
+  * Tags:
168
+
169
+     * `for`
170
+     * `if`
171
+     * `extends`
172
+     * `include`
173
+     * `block`
174
+     * `parent`
175
+     * `display`
176
+     * `filter`
177
+
178
+  * Filters:
179
+
180
+     * `date`
181
+     * `format`
182
+     * `even`
183
+     * `odd`
184
+     * `urlencode`
185
+     * `title`
186
+     * `capitalize`
187
+     * `upper`
188
+     * `lower`
189
+     * `striptags`
190
+     * `join`
191
+     * `reverse`
192
+     * `length`
193
+     * `sort`
194
+     * `default`
195
+     * `keys`
196
+     * `items`
197
+     * `escape`
198
+     * `e`
199
+
200
+The core extension does not need to be added to the Twig environment, as it is
201
+registered by default.
202
+
203
+### Escaper Extension
204
+
205
+The `escaper` extension adds automatic output escaping to Twig. It defines a
206
+new tag, `autoescape`, and a new filter, `safe`.
207
+
208
+When creating the escaper extension, you can switch on or off the global
209
+output escaping strategy:
210
+
211
+    [php]
212
+    $escaper = new Twig_Extension_Escaper(true);
213
+    $twig->addExtension($escaper);
214
+
215
+If set to `true`, all variables in templates are escaped, except those using
216
+the `safe` filter:
217
+
218
+    [twig]
219
+    {{ article.to_html|safe }}
220
+
221
+You can also change the escaping mode locally by using the `autoescape` tag:
222
+
223
+    [twig]
224
+    {% autoescape on %}
225
+      {% var %}
226
+      {% var|safe %}     {# var won't be escaped #}
227
+      {% var|escape %}   {# var won't be doubled-escaped #}
228
+    {% endautoescape %}
229
+
230
+### Sandbox Extension
231
+
232
+The `sandbox` extension can be used to evaluate untrusted code. Access to
233
+unsafe attributes and methods is prohibited. The sandbox security is managed
234
+by a policy instance. By default, Twig comes with one policy class:
235
+`Twig_Sandbox_SecurityPolicy`. This class allows you to white-list some tags,
236
+filters, and methods:
237
+
238
+    [php]
239
+    $tags = array('if');
240
+    $filters = array('upper');
241
+    $methods = array(
242
+      'Article' => array('getTitle', 'getBody'),
243
+    );
244
+    $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods);
245
+
246
+With the previous configuration, the security policy will only allow usage of
247
+the `if` tag, and the `upper` filter. Moreover, the templates will only be
248
+able to call the `getTitle()` and `getBody()` methods on `Article` objects.
249
+Everything else won't be allowed and will generate a
250
+`Twig_Sandbox_SecurityError` exception.
251
+
252
+The policy object is the first argument of the sandbox constructor:
253
+
254
+    [php]
255
+    $sandbox = new Twig_Extension_Sandbox($policy);
256
+    $twig->addExtension($sandbox);
257
+
258
+By default, the sandbox mode is disabled and should be enabled when including
259
+untrusted templates:
260
+
261
+    [php]
262
+    {% include "user.html" sandboxed %}
263
+
264
+You can sandbox all templates by passing `true` as the second argument of the
265
+extension constructor:
266
+
267
+    [php]
268
+    $sandbox = new Twig_Extension_Sandbox($policy, true);
269
+
270
+Exceptions
271
+----------
272
+
273
+Twig can throw exceptions:
274
+
275
+ * `Twig_Error`: The base exception for all template errors.
276
+
277
+ * `Twig_SyntaxError`: Thrown to tell the user that there is a problem with
278
+   the template syntax.
279
+
280
+ * `Twig_RuntimeError`: Thrown when an error occurs at runtime (when a filter
281
+   does not exist for instance).
282
+
283
+ * `Twig_Sandbox_SecurityError`: Thrown when an unallowed tag, filter, or
284
+   method is called in a sandboxed template.
0 285
new file mode 100644
... ...
@@ -0,0 +1,290 @@
1
+Extending Twig
2
+==============
3
+
4
+Twig supports extensions that can add extra tags, filters, or even extend the
5
+parser itself with node transformer 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
+Anatomy of an Extension
13
+-----------------------
14
+
15
+An extension is a class that implements the `Twig_ExtensionInterface`:
16
+
17
+    [php]
18
+    interface Twig_ExtensionInterface
19
+    {
20
+      /**
21
+       * Initializes the runtime environment.
22
+       *
23
+       * This is where you can load some file that contains filter functions for instance.
24
+       */
25
+      public function initRuntime();
26
+
27
+      /**
28
+       * Returns the token parser instances to add to the existing list.
29
+       *
30
+       * @return array An array of Twig_TokenParser instances
31
+       */
32
+      public function getTokenParsers();
33
+
34
+      /**
35
+       * Returns the node transformer instances to add to the existing list.
36
+       *
37
+       * @return array An array of Twig_NodeTransformer instances
38
+       */
39
+      public function getNodeTransformers();
40
+
41
+      /**
42
+       * Returns a list of filters to add to the existing list.
43
+       *
44
+       * @return array An array of filters
45
+       */
46
+      public function getFilters();
47
+
48
+      /**
49
+       * Returns the name of the extension.
50
+       *
51
+       * @return string The extension name
52
+       */
53
+      public function getName();
54
+    }
55
+
56
+Instead of you implementing the whole interface, your extension class can
57
+inherit from the `Twig_Extension` class, which provides empty implementations
58
+of all the above methods to keep your extension clean.
59
+
60
+>**TIP**
61
+>The bundled extensions are great examples of how extensions work.
62
+
63
+Defining new Filters
64
+--------------------
65
+
66
+The most common element you will want to add to Twig is filters. A filter is
67
+just a regular PHP callable that takes the left side of the filter as first
68
+argument and the arguments passed to the filter as extra arguments.
69
+
70
+Let's create a filter, named `rot13`, which returns the
71
+[rot13](http://www.php.net/manual/en/function.str-rot13.php) transformation of
72
+a string:
73
+
74
+    [twig]
75
+    {{ "Twig"|rot13 }}
76
+
77
+    {# should displays Gjvt #}
78
+
79
+Here is the simplest extension class you can create to add this filter:
80
+
81
+    [php]
82
+    class Project_Twig_Extension extends Twig_Extension
83
+    {
84
+      public function getFilters()
85
+      {
86
+        return array(
87
+          'rot13' => array('str_rot13', false),
88
+        );
89
+      }
90
+
91
+      public function getName()
92
+      {
93
+        return 'project';
94
+      }
95
+    }
96
+
97
+Registering the new extension is like registering core extensions:
98
+
99
+    [php]
100
+    $twig->addExtension(new Project_Twig_Extension());
101
+
102
+You can of course use any valid PHP callable, like a method call:
103
+
104
+    [php]
105
+    class Project_Twig_Extension extends Twig_Extension
106
+    {
107
+      public function getFilters()
108
+      {
109
+        return array(
110
+          'rot13' => array(array($this, 'computeRot13'), false),
111
+        );
112
+      }
113
+
114
+      public function computeRot13($string)
115
+      {
116
+        return str_rot13($string);
117
+      }
118
+
119
+      // ...
120
+    }
121
+
122
+Filters can also be passed the current environment. You might have noticed
123
+that a filter is defined by a callable and a Boolean. If you change the
124
+Boolean to `true`, Twig will pass the current environment as the first
125
+argument to the filter call:
126
+
127
+    [php]
128
+    class Project_Twig_Extension extends Twig_Extension
129
+    {
130
+      public function getFilters()
131
+      {
132
+        return array(
133
+          'rot13' => array(array($this, 'computeRot13'), true),
134
+        );
135
+      }
136
+
137
+      public function computeRot13(Twig_Environment $env, $string)
138
+      {
139
+        // get the current charset for instance
140
+        $charset = $env->getCharset();
141
+
142
+        return str_rot13($string);
143
+      }
144
+
145
+      // ...
146
+    }
147
+
148
+Defining new Tags
149
+-----------------
150
+
151
+One of the most exiting feature of a template engine like Twig is the
152
+possibility to define new language constructs.
153
+
154
+Let's create a simple `set` tag that allows the definition of simple variables
155
+from within a template. The tag can be used like follows:
156
+
157
+    [twig]
158
+    {% set name "value" %}
159
+
160
+    {{ name }}
161
+
162
+    {# should output value #}
163
+
164
+First, we need to create a `Twig_TokenParser` class which will be able to
165
+parse this new language construct:
166
+
167
+    [php]
168
+    class Project_Twig_Set_TokenParser extends Twig_TokenParser
169
+    {
170
+      // ...
171
+    }
172
+
173
+Of course, we need to register this token parser in our extension class:
174
+
175
+    [php]
176
+    class Project_Twig_Extension extends Twig_Extension
177
+    {
178
+      public function getTokenParsers()
179
+      {
180
+        return array(new Project_Twig_Set_TokenParser());
181
+      }
182
+
183
+      // ...
184
+    }
185
+
186
+Now, let's see the actual code of the token parser class:
187
+
188
+    [php]
189
+    class Project_Twig_Set_TokenParser extends Twig_TokenParser
190
+    {
191
+      public function parse(Twig_Token $token)
192
+      {
193
+        $lineno = $token->getLine();
194
+        $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
195
+        $value = $this->parser->getExpressionParser()->parseExpression();
196
+
197
+        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
198
+
199
+        return new Project_Twig_Set_Node($name, $value, $lineno, $this->getTag());
200
+      }
201
+
202
+      public function getTag()
203
+      {
204
+        return 'set';
205
+      }
206
+    }
207
+
208
+The `getTag()` method must return the tag we want to parse, here `set`. The
209
+`parse()` method is invoked whenever the parser encounters a `set` tag. It
210
+should return a `Twig_Node` instance that represents the node. The parsing
211
+process is simplified thanks to a bunch of methods you can call from the token
212
+stream (`$this->parser->getStream()`):
213
+
214
+ * `test()`: Tests the type and optionally the value of the next token and
215
+   returns it.
216
+
217
+ * `expect()`: Expects a token and returns it (like `test()`) or throw a
218
+   syntax error if not found.
219
+
220
+ * `look()`: Looks a the next token. This is how you can have a look at the
221
+   next token without consume it.
222
+
223
+Parsing expressions is done by calling the `parseExpression()` like we did for
224
+the `set` tag.
225
+
226
+>**TIP**
227
+>Reading the existing `TokenParser` classes is the best way to learn all the
228
+>nitty-gritty details of the parsing process.
229
+
230
+The `Project_Twig_Set_Node` class itself is rather simple:
231
+
232
+    [php]
233
+    class Project_Twig_Set_Node extends Twig_Node
234
+    {
235
+      protected $name;
236
+      protected $value;
237
+
238
+      public function __construct($name, Twig_Node_Expression $value, $lineno)
239
+      {
240
+        parent::__construct($lineno);
241
+
242
+        $this->name = $name;
243
+        $this->value = $value;
244
+      }
245
+
246
+      public function compile($compiler)
247
+      {
248
+        $compiler
249
+          ->addDebugInfo($this)
250
+          ->write('$context[\''.$this->name.'\'] = ')
251
+          ->subcompile($this->value)
252
+          ->raw(";\n")
253
+        ;
254
+      }
255
+    }
256
+
257
+The compiler implements a fluid interface and provides methods that helps the
258
+developer generate beautiful and readable PHP code: