aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/symfony/twig-bridge
diff options
context:
space:
mode:
authorNicolas LÅ“uillet <nicolas.loeuillet@gmail.com>2013-08-03 19:26:54 +0200
committerNicolas LÅ“uillet <nicolas.loeuillet@gmail.com>2013-08-03 19:26:54 +0200
commit4f5b44bd3bd490309eb2ba7b44df4769816ba729 (patch)
tree6cefe170dfe0a5a361cb1e2d1fc4d580a3316d02 /vendor/symfony/twig-bridge
parent2b840e0cfb63a453bea67a98541f3df9c273c5f5 (diff)
downloadwallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.tar.gz
wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.tar.zst
wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.zip
twig implementation
Diffstat (limited to 'vendor/symfony/twig-bridge')
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/.gitignore4
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/CHANGELOG.md29
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/CodeExtension.php232
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/FormExtension.php136
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php88
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/RoutingExtension.php100
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/SecurityExtension.php63
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/TranslationExtension.php118
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/YamlExtension.php67
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRenderer.php41
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngine.php183
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php27
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererInterface.php27
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/LICENSE19
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormEnctypeNode.php31
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormThemeNode.php40
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/RenderBlockNode.php42
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php106
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php33
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransNode.php119
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php135
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php106
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php137
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/README.md15
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig390
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig52
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php69
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php30
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php35
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php209
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php131
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php68
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php60
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php151
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig3
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig16
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig3
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig6
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig8
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig8
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php85
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php282
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php25
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php83
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php61
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php77
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TestCase.php22
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php108
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php81
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php61
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php89
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php48
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php89
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Translation/TwigExtractor.php86
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TwigEngine.php126
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/composer.json50
-rw-r--r--vendor/symfony/twig-bridge/Symfony/Bridge/Twig/phpunit.xml.dist30
57 files changed, 4540 insertions, 0 deletions
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/.gitignore b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/.gitignore
new file mode 100644
index 00000000..44de97a3
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/.gitignore
@@ -0,0 +1,4 @@
1vendor/
2composer.lock
3phpunit.xml
4
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/CHANGELOG.md b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/CHANGELOG.md
new file mode 100644
index 00000000..ad22216e
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/CHANGELOG.md
@@ -0,0 +1,29 @@
1CHANGELOG
2=========
3
42.3.0
5-----
6
7 * added helpers form(), form_start() and form_end()
8 * deprecated form_enctype() in favor of form_start()
9
102.2.0
11-----
12
13 * added a `controller` function to help generating controller references
14 * added a `render_esi` and a `render_hinclude` function
15 * [BC BREAK] restricted the `render` tag to only accept URIs or ControllerReference instances (the signature changed)
16 * added a `render` function to render a request
17 * The `app` global variable is now injected even when using the twig service directly.
18 * Added an optional parameter to the `path` and `url` function which allows to generate
19 relative paths (e.g. "../parent-file") and scheme-relative URLs (e.g. "//example.com/dir/file").
20
212.1.0
22-----
23
24 * added global variables access in a form theme
25 * added TwigEngine
26 * added TwigExtractor
27 * added a csrf_token function
28 * added a way to specify a default domain for a Twig template (via the
29 'trans_default_domain' tag)
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/CodeExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/CodeExtension.php
new file mode 100644
index 00000000..a6202b24
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/CodeExtension.php
@@ -0,0 +1,232 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14if (!defined('ENT_SUBSTITUTE')) {
15 define('ENT_SUBSTITUTE', 8);
16}
17
18/**
19 * Twig extension relate to PHP code and used by the profiler and the default exception templates.
20 *
21 * @author Fabien Potencier <fabien@symfony.com>
22 */
23class CodeExtension extends \Twig_Extension
24{
25 private $fileLinkFormat;
26 private $rootDir;
27 private $charset;
28
29 /**
30 * Constructor.
31 *
32 * @param string $fileLinkFormat The format for links to source files
33 * @param string $rootDir The project root directory
34 * @param string $charset The charset
35 */
36 public function __construct($fileLinkFormat, $rootDir, $charset)
37 {
38 $this->fileLinkFormat = empty($fileLinkFormat) ? ini_get('xdebug.file_link_format') : $fileLinkFormat;
39 $this->rootDir = str_replace('\\', '/', $rootDir).'/';
40 $this->charset = $charset;
41 }
42
43 /**
44 * {@inheritdoc}
45 */
46 public function getFilters()
47 {
48 return array(
49 'abbr_class' => new \Twig_Filter_Method($this, 'abbrClass', array('is_safe' => array('html'))),
50 'abbr_method' => new \Twig_Filter_Method($this, 'abbrMethod', array('is_safe' => array('html'))),
51 'format_args' => new \Twig_Filter_Method($this, 'formatArgs', array('is_safe' => array('html'))),
52 'format_args_as_text' => new \Twig_Filter_Method($this, 'formatArgsAsText'),
53 'file_excerpt' => new \Twig_Filter_Method($this, 'fileExcerpt', array('is_safe' => array('html'))),
54 'format_file' => new \Twig_Filter_Method($this, 'formatFile', array('is_safe' => array('html'))),
55 'format_file_from_text' => new \Twig_Filter_Method($this, 'formatFileFromText', array('is_safe' => array('html'))),
56 'file_link' => new \Twig_Filter_Method($this, 'getFileLink', array('is_safe' => array('html'))),
57 );
58 }
59
60 public function abbrClass($class)
61 {
62 $parts = explode('\\', $class);
63 $short = array_pop($parts);
64
65 return sprintf("<abbr title=\"%s\">%s</abbr>", $class, $short);
66 }
67
68 public function abbrMethod($method)
69 {
70 if (false !== strpos($method, '::')) {
71 list($class, $method) = explode('::', $method, 2);
72 $result = sprintf("%s::%s()", $this->abbrClass($class), $method);
73 } elseif ('Closure' === $method) {
74 $result = sprintf("<abbr title=\"%s\">%s</abbr>", $method, $method);
75 } else {
76 $result = sprintf("<abbr title=\"%s\">%s</abbr>()", $method, $method);
77 }
78
79 return $result;
80 }
81
82 /**
83 * Formats an array as a string.
84 *
85 * @param array $args The argument array
86 *
87 * @return string
88 */
89 public function formatArgs($args)
90 {
91 $result = array();
92 foreach ($args as $key => $item) {
93 if ('object' === $item[0]) {
94 $parts = explode('\\', $item[1]);
95 $short = array_pop($parts);
96 $formattedValue = sprintf("<em>object</em>(<abbr title=\"%s\">%s</abbr>)", $item[1], $short);
97 } elseif ('array' === $item[0]) {
98 $formattedValue = sprintf("<em>array</em>(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
99 } elseif ('string' === $item[0]) {
100 $formattedValue = sprintf("'%s'", htmlspecialchars($item[1], ENT_QUOTES, $this->charset));
101 } elseif ('null' === $item[0]) {
102 $formattedValue = '<em>null</em>';
103 } elseif ('boolean' === $item[0]) {
104 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
105 } elseif ('resource' === $item[0]) {
106 $formattedValue = '<em>resource</em>';
107 } else {
108 $formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES, $this->charset), true));
109 }
110
111 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
112 }
113
114 return implode(', ', $result);
115 }
116
117 /**
118 * Formats an array as a string.
119 *
120 * @param array $args The argument array
121 *
122 * @return string
123 */
124 public function formatArgsAsText($args)
125 {
126 return strip_tags($this->formatArgs($args));
127 }
128
129 /**
130 * Returns an excerpt of a code file around the given line number.
131 *
132 * @param string $file A file path
133 * @param int $line The selected line number
134 *
135 * @return string An HTML string
136 */
137 public function fileExcerpt($file, $line)
138 {
139 if (is_readable($file)) {
140 $code = highlight_file($file, true);
141 // remove main code/span tags
142 $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
143 $content = preg_split('#<br />#', $code);
144
145 $lines = array();
146 for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) {
147 $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
148 }
149
150 return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
151 }
152 }
153
154 /**
155 * Formats a file path.
156 *
157 * @param string $file An absolute file path
158 * @param integer $line The line number
159 * @param string $text Use this text for the link rather than the file path
160 *
161 * @return string
162 */
163 public function formatFile($file, $line, $text = null)
164 {
165 if (null === $text) {
166 $file = trim($file);
167 $text = $file;
168 if (0 === strpos($text, $this->rootDir)) {
169 $text = str_replace($this->rootDir, '', str_replace('\\', '/', $text));
170 $text = sprintf('<abbr title="%s">kernel.root_dir</abbr>/%s', $this->rootDir, $text);
171 }
172 }
173
174 $text = "$text at line $line";
175
176 if (false !== $link = $this->getFileLink($file, $line)) {
177 return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), $text);
178 }
179
180 return $text;
181 }
182
183 /**
184 * Returns the link for a given file/line pair.
185 *
186 * @param string $file An absolute file path
187 * @param integer $line The line number
188 *
189 * @return string A link of false
190 */
191 public function getFileLink($file, $line)
192 {
193 if ($this->fileLinkFormat && is_file($file)) {
194 return strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
195 }
196
197 return false;
198 }
199
200 public function formatFileFromText($text)
201 {
202 $that = $this;
203
204 return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) use ($that) {
205 return 'in '.$that->formatFile($match[2], $match[3]);
206 }, $text);
207 }
208
209 public function getName()
210 {
211 return 'code';
212 }
213
214 protected static function fixCodeMarkup($line)
215 {
216 // </span> ending tag from previous line
217 $opening = strpos($line, '<span');
218 $closing = strpos($line, '</span>');
219 if (false !== $closing && (false === $opening || $closing < $opening)) {
220 $line = substr_replace($line, '', $closing, 7);
221 }
222
223 // missing </span> tag at the end of line
224 $opening = strpos($line, '<span');
225 $closing = strpos($line, '</span>');
226 if (false !== $opening && (false === $closing || $closing > $opening)) {
227 $line .= '</span>';
228 }
229
230 return $line;
231 }
232}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/FormExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/FormExtension.php
new file mode 100644
index 00000000..fbfa5243
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/FormExtension.php
@@ -0,0 +1,136 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
15use Symfony\Bridge\Twig\Form\TwigRendererInterface;
16use Symfony\Component\Form\Extension\Core\View\ChoiceView;
17
18/**
19 * FormExtension extends Twig with form capabilities.
20 *
21 * @author Fabien Potencier <fabien@symfony.com>
22 * @author Bernhard Schussek <bschussek@gmail.com>
23 */
24class FormExtension extends \Twig_Extension
25{
26 /**
27 * This property is public so that it can be accessed directly from compiled
28 * templates without having to call a getter, which slightly decreases performance.
29 *
30 * @var TwigRendererInterface
31 */
32 public $renderer;
33
34 public function __construct(TwigRendererInterface $renderer)
35 {
36 $this->renderer = $renderer;
37 }
38
39 /**
40 * {@inheritdoc}
41 */
42 public function initRuntime(\Twig_Environment $environment)
43 {
44 $this->renderer->setEnvironment($environment);
45 }
46
47 /**
48 * {@inheritdoc}
49 */
50 public function getTokenParsers()
51 {
52 return array(
53 // {% form_theme form "SomeBundle::widgets.twig" %}
54 new FormThemeTokenParser(),
55 );
56 }
57
58 /**
59 * {@inheritdoc}
60 */
61 public function getFunctions()
62 {
63 return array(
64 'form_enctype' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\FormEnctypeNode', array('is_safe' => array('html'))),
65 'form_widget' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
66 'form_errors' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
67 'form_label' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
68 'form_row' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
69 'form_rest' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
70 'form' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
71 'form_start' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
72 'form_end' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
73 'csrf_token' => new \Twig_Function_Method($this, 'renderer->renderCsrfToken'),
74 );
75 }
76
77 /**
78 * {@inheritdoc}
79 */
80 public function getFilters()
81 {
82 return array(
83 'humanize' => new \Twig_Filter_Method($this, 'renderer->humanize'),
84 );
85 }
86
87 /**
88 * {@inheritdoc}
89 */
90 public function getTests()
91 {
92 return array(
93 'selectedchoice' => new \Twig_Test_Method($this, 'isSelectedChoice'),
94 );
95 }
96
97 /**
98 * Returns whether a choice is selected for a given form value.
99 *
100 * Unfortunately Twig does not support an efficient way to execute the
101 * "is_selected" closure passed to the template by ChoiceType. It is faster
102 * to implement the logic here (around 65ms for a specific form).
103 *
104 * Directly implementing the logic here is also faster than doing so in
105 * ChoiceView (around 30ms).
106 *
107 * The worst option tested so far is to implement the logic in ChoiceView
108 * and access the ChoiceView method directly in the template. Doing so is
109 * around 220ms slower than doing the method call here in the filter. Twig
110 * seems to be much more efficient at executing filters than at executing
111 * methods of an object.
112 *
113 * @param ChoiceView $choice The choice to check.
114 * @param string|array $selectedValue The selected value to compare.
115 *
116 * @return Boolean Whether the choice is selected.
117 *
118 * @see ChoiceView::isSelected()
119 */
120 public function isSelectedChoice(ChoiceView $choice, $selectedValue)
121 {
122 if (is_array($selectedValue)) {
123 return false !== array_search($choice->value, $selectedValue, true);
124 }
125
126 return $choice->value === $selectedValue;
127 }
128
129 /**
130 * {@inheritdoc}
131 */
132 public function getName()
133 {
134 return 'form';
135 }
136}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php
new file mode 100644
index 00000000..a8377234
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php
@@ -0,0 +1,88 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
15use Symfony\Component\HttpKernel\Controller\ControllerReference;
16
17/**
18 * Provides integration with the HttpKernel component.
19 *
20 * @author Fabien Potencier <fabien@symfony.com>
21 */
22class HttpKernelExtension extends \Twig_Extension
23{
24 private $handler;
25
26 /**
27 * Constructor.
28 *
29 * @param FragmentHandler $handler A FragmentHandler instance
30 */
31 public function __construct(FragmentHandler $handler)
32 {
33 $this->handler = $handler;
34 }
35
36 public function getFunctions()
37 {
38 return array(
39 'render' => new \Twig_Function_Method($this, 'renderFragment', array('is_safe' => array('html'))),
40 'render_*' => new \Twig_Function_Method($this, 'renderFragmentStrategy', array('is_safe' => array('html'))),
41 'controller' => new \Twig_Function_Method($this, 'controller'),
42 );
43 }
44
45 /**
46 * Renders a fragment.
47 *
48 * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance
49 * @param array $options An array of options
50 *
51 * @return string The fragment content
52 *
53 * @see Symfony\Component\HttpKernel\Fragment\FragmentHandler::render()
54 */
55 public function renderFragment($uri, $options = array())
56 {
57 $strategy = isset($options['strategy']) ? $options['strategy'] : 'inline';
58 unset($options['strategy']);
59
60 return $this->handler->render($uri, $strategy, $options);
61 }
62
63 /**
64 * Renders a fragment.
65 *
66 * @param string $strategy A strategy name
67 * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance
68 * @param array $options An array of options
69 *
70 * @return string The fragment content
71 *
72 * @see Symfony\Component\HttpKernel\Fragment\FragmentHandler::render()
73 */
74 public function renderFragmentStrategy($strategy, $uri, $options = array())
75 {
76 return $this->handler->render($uri, $strategy, $options);
77 }
78
79 public function controller($controller, $attributes = array(), $query = array())
80 {
81 return new ControllerReference($controller, $attributes, $query);
82 }
83
84 public function getName()
85 {
86 return 'http_kernel';
87 }
88}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/RoutingExtension.php
new file mode 100644
index 00000000..8274abf3
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/RoutingExtension.php
@@ -0,0 +1,100 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
15
16/**
17 * Provides integration of the Routing component with Twig.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class RoutingExtension extends \Twig_Extension
22{
23 private $generator;
24
25 public function __construct(UrlGeneratorInterface $generator)
26 {
27 $this->generator = $generator;
28 }
29
30 /**
31 * Returns a list of functions to add to the existing list.
32 *
33 * @return array An array of functions
34 */
35 public function getFunctions()
36 {
37 return array(
38 'url' => new \Twig_Function_Method($this, 'getUrl', array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))),
39 'path' => new \Twig_Function_Method($this, 'getPath', array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))),
40 );
41 }
42
43 public function getPath($name, $parameters = array(), $relative = false)
44 {
45 return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
46 }
47
48 public function getUrl($name, $parameters = array(), $schemeRelative = false)
49 {
50 return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
51 }
52
53 /**
54 * Determines at compile time whether the generated URL will be safe and thus
55 * saving the unneeded automatic escaping for performance reasons.
56 *
57 * The URL generation process percent encodes non-alphanumeric characters. So there is no risk
58 * that malicious/invalid characters are part of the URL. The only character within an URL that
59 * must be escaped in html is the ampersand ("&") which separates query params. So we cannot mark
60 * the URL generation as always safe, but only when we are sure there won't be multiple query
61 * params. This is the case when there are none or only one constant parameter given.
62 * E.g. we know beforehand this will be safe:
63 * - path('route')
64 * - path('route', {'param': 'value'})
65 * But the following may not:
66 * - path('route', var)
67 * - path('route', {'param': ['val1', 'val2'] }) // a sub-array
68 * - path('route', {'param1': 'value1', 'param2': 'value2'})
69 * If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know.
70 *
71 * @param \Twig_Node $argsNode The arguments of the path/url function
72 *
73 * @return array An array with the contexts the URL is safe
74 */
75 public function isUrlGenerationSafe(\Twig_Node $argsNode)
76 {
77 // support named arguments
78 $paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : (
79 $argsNode->hasNode(1) ? $argsNode->getNode(1) : null
80 );
81
82 if (null === $paramsNode || $paramsNode instanceof \Twig_Node_Expression_Array && count($paramsNode) <= 2 &&
83 (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof \Twig_Node_Expression_Constant)
84 ) {
85 return array('html');
86 }
87
88 return array();
89 }
90
91 /**
92 * Returns the name of the extension.
93 *
94 * @return string The extension name
95 */
96 public function getName()
97 {
98 return 'routing';
99 }
100}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/SecurityExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/SecurityExtension.php
new file mode 100644
index 00000000..c9f4466c
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/SecurityExtension.php
@@ -0,0 +1,63 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14use Symfony\Component\Security\Acl\Voter\FieldVote;
15use Symfony\Component\Security\Core\SecurityContextInterface;
16
17/**
18 * SecurityExtension exposes security context features.
19 *
20 * @author Fabien Potencier <fabien@symfony.com>
21 */
22class SecurityExtension extends \Twig_Extension
23{
24 private $context;
25
26 public function __construct(SecurityContextInterface $context = null)
27 {
28 $this->context = $context;
29 }
30
31 public function isGranted($role, $object = null, $field = null)
32 {
33 if (null === $this->context) {
34 return false;
35 }
36
37 if (null !== $field) {
38 $object = new FieldVote($object, $field);
39 }
40
41 return $this->context->isGranted($role, $object);
42 }
43
44 /**
45 * {@inheritdoc}
46 */
47 public function getFunctions()
48 {
49 return array(
50 'is_granted' => new \Twig_Function_Method($this, 'isGranted'),
51 );
52 }
53
54 /**
55 * Returns the name of the extension.
56 *
57 * @return string The extension name
58 */
59 public function getName()
60 {
61 return 'security';
62 }
63}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/TranslationExtension.php
new file mode 100644
index 00000000..2ab3832d
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/TranslationExtension.php
@@ -0,0 +1,118 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
15use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser;
16use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
17use Symfony\Component\Translation\TranslatorInterface;
18use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
19use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
20
21/**
22 * Provides integration of the Translation component with Twig.
23 *
24 * @author Fabien Potencier <fabien@symfony.com>
25 */
26class TranslationExtension extends \Twig_Extension
27{
28 private $translator;
29 private $translationNodeVisitor;
30
31 public function __construct(TranslatorInterface $translator, \Twig_NodeVisitorInterface $translationNodeVisitor = null)
32 {
33 if (!$translationNodeVisitor) {
34 $translationNodeVisitor = new TranslationNodeVisitor();
35 }
36
37 $this->translator = $translator;
38 $this->translationNodeVisitor = $translationNodeVisitor;
39 }
40
41 public function getTranslator()
42 {
43 return $this->translator;
44 }
45
46 /**
47 * {@inheritdoc}
48 */
49 public function getFilters()
50 {
51 return array(
52 'trans' => new \Twig_Filter_Method($this, 'trans'),
53 'transchoice' => new \Twig_Filter_Method($this, 'transchoice'),
54 );
55 }
56
57 /**
58 * Returns the token parser instance to add to the existing list.
59 *
60 * @return array An array of Twig_TokenParser instances
61 */
62 public function getTokenParsers()
63 {
64 return array(
65 // {% trans %}Symfony is great!{% endtrans %}
66 new TransTokenParser(),
67
68 // {% transchoice count %}
69 // {0} There is no apples|{1} There is one apple|]1,Inf] There is {{ count }} apples
70 // {% endtranschoice %}
71 new TransChoiceTokenParser(),
72
73 // {% trans_default_domain "foobar" %}
74 new TransDefaultDomainTokenParser(),
75 );
76 }
77
78 /**
79 * {@inheritdoc}
80 */
81 public function getNodeVisitors()
82 {
83 return array($this->translationNodeVisitor, new TranslationDefaultDomainNodeVisitor());
84 }
85
86 public function getTranslationNodeVisitor()
87 {
88 return $this->translationNodeVisitor;
89 }
90
91 public function trans($message, array $arguments = array(), $domain = null, $locale = null)
92 {
93 if (null === $domain) {
94 $domain = 'messages';
95 }
96
97 return $this->translator->trans($message, $arguments, $domain, $locale);
98 }
99
100 public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null)
101 {
102 if (null === $domain) {
103 $domain = 'messages';
104 }
105
106 return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
107 }
108
109 /**
110 * Returns the name of the extension.
111 *
112 * @return string The extension name
113 */
114 public function getName()
115 {
116 return 'translator';
117 }
118}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/YamlExtension.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/YamlExtension.php
new file mode 100644
index 00000000..f88829ee
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Extension/YamlExtension.php
@@ -0,0 +1,67 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Extension;
13
14use Symfony\Component\Yaml\Dumper as YamlDumper;
15
16/**
17 * Provides integration of the Yaml component with Twig.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class YamlExtension extends \Twig_Extension
22{
23 /**
24 * {@inheritdoc}
25 */
26 public function getFilters()
27 {
28 return array(
29 'yaml_encode' => new \Twig_Filter_Method($this, 'encode'),
30 'yaml_dump' => new \Twig_Filter_Method($this, 'dump'),
31 );
32 }
33
34 public function encode($input, $inline = 0, $dumpObjects = false)
35 {
36 static $dumper;
37
38 if (null === $dumper) {
39 $dumper = new YamlDumper();
40 }
41
42 return $dumper->dump($input, $inline, false, $dumpObjects);
43 }
44
45 public function dump($value, $inline = 0, $dumpObjects = false)
46 {
47 if (is_resource($value)) {
48 return '%Resource%';
49 }
50
51 if (is_array($value) || is_object($value)) {
52 return '%'.gettype($value).'% '.$this->encode($value, $inline, $dumpObjects);
53 }
54
55 return $this->encode($value, $inline, $dumpObjects);
56 }
57
58 /**
59 * Returns the name of the extension.
60 *
61 * @return string The extension name
62 */
63 public function getName()
64 {
65 return 'yaml';
66 }
67}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRenderer.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRenderer.php
new file mode 100644
index 00000000..72798d10
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRenderer.php
@@ -0,0 +1,41 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Form;
13
14use Symfony\Component\Form\FormRenderer;
15use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
16
17/**
18 * @author Bernhard Schussek <bschussek@gmail.com>
19 */
20class TwigRenderer extends FormRenderer implements TwigRendererInterface
21{
22 /**
23 * @var TwigRendererEngineInterface
24 */
25 private $engine;
26
27 public function __construct(TwigRendererEngineInterface $engine, CsrfProviderInterface $csrfProvider = null)
28 {
29 parent::__construct($engine, $csrfProvider);
30
31 $this->engine = $engine;
32 }
33
34 /**
35 * {@inheritdoc}
36 */
37 public function setEnvironment(\Twig_Environment $environment)
38 {
39 $this->engine->setEnvironment($environment);
40 }
41}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngine.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngine.php
new file mode 100644
index 00000000..05beb315
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngine.php
@@ -0,0 +1,183 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Form;
13
14use Symfony\Component\Form\AbstractRendererEngine;
15use Symfony\Component\Form\FormView;
16
17/**
18 * @author Bernhard Schussek <bschussek@gmail.com>
19 */
20class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererEngineInterface
21{
22 /**
23 * @var \Twig_Environment
24 */
25 private $environment;
26
27 /**
28 * @var \Twig_Template
29 */
30 private $template;
31
32 /**
33 * {@inheritdoc}
34 */
35 public function setEnvironment(\Twig_Environment $environment)
36 {
37 $this->environment = $environment;
38 }
39
40 /**
41 * {@inheritdoc}
42 */
43 public function renderBlock(FormView $view, $resource, $blockName, array $variables = array())
44 {
45 $cacheKey = $view->vars[self::CACHE_KEY_VAR];
46
47 $context = $this->environment->mergeGlobals($variables);
48
49 ob_start();
50
51 // By contract,This method can only be called after getting the resource
52 // (which is passed to the method). Getting a resource for the first time
53 // (with an empty cache) is guaranteed to invoke loadResourcesFromTheme(),
54 // where the property $template is initialized.
55
56 // We do not call renderBlock here to avoid too many nested level calls
57 // (XDebug limits the level to 100 by default)
58 $this->template->displayBlock($blockName, $context, $this->resources[$cacheKey]);
59
60 return ob_get_clean();
61 }
62
63 /**
64 * Loads the cache with the resource for a given block name.
65 *
66 * This implementation eagerly loads all blocks of the themes assigned to the given view
67 * and all of its ancestors views. This is necessary, because Twig receives the
68 * list of blocks later. At that point, all blocks must already be loaded, for the
69 * case that the function "block()" is used in the Twig template.
70 *
71 * @see getResourceForBlock()
72 *
73 * @param string $cacheKey The cache key of the form view.
74 * @param FormView $view The form view for finding the applying themes.
75 * @param string $blockName The name of the block to load.
76 *
77 * @return Boolean True if the resource could be loaded, false otherwise.
78 */
79 protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName)
80 {
81 // The caller guarantees that $this->resources[$cacheKey][$block] is
82 // not set, but it doesn't have to check whether $this->resources[$cacheKey]
83 // is set. If $this->resources[$cacheKey] is set, all themes for this
84 // $cacheKey are already loaded (due to the eager population, see doc comment).
85 if (isset($this->resources[$cacheKey])) {
86 // As said in the previous, the caller guarantees that
87 // $this->resources[$cacheKey][$block] is not set. Since the themes are
88 // already loaded, it can only be a non-existing block.
89 $this->resources[$cacheKey][$blockName] = false;
90
91 return false;
92 }
93
94 // Recursively try to find the block in the themes assigned to $view,
95 // then of its parent view, then of the parent view of the parent and so on.
96 // When the root view is reached in this recursion, also the default
97 // themes are taken into account.
98
99 // Check each theme whether it contains the searched block
100 if (isset($this->themes[$cacheKey])) {
101 for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) {
102 $this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]);
103 // CONTINUE LOADING (see doc comment)
104 }
105 }
106
107 // Check the default themes once we reach the root view without success
108 if (!$view->parent) {
109 for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) {
110 $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]);
111 // CONTINUE LOADING (see doc comment)
112 }
113 }
114
115 // Proceed with the themes of the parent view
116 if ($view->parent) {
117 $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR];
118
119 if (!isset($this->resources[$parentCacheKey])) {
120 $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName);
121 }
122
123 // EAGER CACHE POPULATION (see doc comment)
124 foreach ($this->resources[$parentCacheKey] as $nestedBlockName => $resource) {
125 if (!isset($this->resources[$cacheKey][$nestedBlockName])) {
126 $this->resources[$cacheKey][$nestedBlockName] = $resource;
127 }
128 }
129 }
130
131 // Even though we loaded the themes, it can happen that none of them
132 // contains the searched block
133 if (!isset($this->resources[$cacheKey][$blockName])) {
134 // Cache that we didn't find anything to speed up further accesses
135 $this->resources[$cacheKey][$blockName] = false;
136 }
137
138 return false !== $this->resources[$cacheKey][$blockName];
139 }
140
141 /**
142 * Loads the resources for all blocks in a theme.
143 *
144 * @param string $cacheKey The cache key for storing the resource.
145 * @param mixed $theme The theme to load the block from. This parameter
146 * is passed by reference, because it might be necessary
147 * to initialize the theme first. Any changes made to
148 * this variable will be kept and be available upon
149 * further calls to this method using the same theme.
150 */
151 protected function loadResourcesFromTheme($cacheKey, &$theme)
152 {
153 if (!$theme instanceof \Twig_Template) {
154 /* @var \Twig_Template $theme */
155 $theme = $this->environment->loadTemplate($theme);
156 }
157
158 if (null === $this->template) {
159 // Store the first \Twig_Template instance that we find so that
160 // we can call displayBlock() later on. It doesn't matter *which*
161 // template we use for that, since we pass the used blocks manually
162 // anyway.
163 $this->template = $theme;
164 }
165
166 // Use a separate variable for the inheritance traversal, because
167 // theme is a reference and we don't want to change it.
168 $currentTheme = $theme;
169
170 // The do loop takes care of template inheritance.
171 // Add blocks from all templates in the inheritance tree, but avoid
172 // overriding blocks already set.
173 do {
174 foreach ($currentTheme->getBlocks() as $block => $blockData) {
175 if (!isset($this->resources[$cacheKey][$block])) {
176 // The resource given back is the key to the bucket that
177 // contains this block.
178 $this->resources[$cacheKey][$block] = $blockData;
179 }
180 }
181 } while (false !== $currentTheme = $currentTheme->getParent(array()));
182 }
183}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php
new file mode 100644
index 00000000..ef764a24
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php
@@ -0,0 +1,27 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Form;
13
14use Symfony\Component\Form\FormRendererEngineInterface;
15
16/**
17 * @author Bernhard Schussek <bschussek@gmail.com>
18 */
19interface TwigRendererEngineInterface extends FormRendererEngineInterface
20{
21 /**
22 * Sets Twig's environment.
23 *
24 * @param \Twig_Environment $environment
25 */
26 public function setEnvironment(\Twig_Environment $environment);
27}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererInterface.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererInterface.php
new file mode 100644
index 00000000..4682f520
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Form/TwigRendererInterface.php
@@ -0,0 +1,27 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Form;
13
14use Symfony\Component\Form\FormRendererInterface;
15
16/**
17 * @author Bernhard Schussek <bschussek@gmail.com>
18 */
19interface TwigRendererInterface extends FormRendererInterface
20{
21 /**
22 * Sets Twig's environment.
23 *
24 * @param \Twig_Environment $environment
25 */
26 public function setEnvironment(\Twig_Environment $environment);
27}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/LICENSE b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/LICENSE
new file mode 100644
index 00000000..88a57f8d
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/LICENSE
@@ -0,0 +1,19 @@
1Copyright (c) 2004-2013 Fabien Potencier
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is furnished
8to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19THE SOFTWARE.
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormEnctypeNode.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormEnctypeNode.php
new file mode 100644
index 00000000..93bce1b9
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormEnctypeNode.php
@@ -0,0 +1,31 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Node;
13
14/**
15 * @author Bernhard Schussek <bschussek@gmail.com>
16 *
17 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
18 * the helper "form_start()" instead.
19 */
20class FormEnctypeNode extends SearchAndRenderBlockNode
21{
22 public function compile(\Twig_Compiler $compiler)
23 {
24 parent::compile($compiler);
25
26 $compiler->raw(";\n");
27
28 // Uncomment this as soon as the deprecation note should be shown
29 // $compiler->write('trigger_error(\'The helper form_enctype(form) is deprecated since version 2.3 and will be removed in 3.0. Use form_start(form) instead.\', E_USER_DEPRECATED)');
30 }
31}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormThemeNode.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormThemeNode.php
new file mode 100644
index 00000000..329ab86f
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/FormThemeNode.php
@@ -0,0 +1,40 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Node;
13
14/**
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class FormThemeNode extends \Twig_Node
18{
19 public function __construct(\Twig_NodeInterface $form, \Twig_NodeInterface $resources, $lineno, $tag = null)
20 {
21 parent::__construct(array('form' => $form, 'resources' => $resources), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param \Twig_Compiler $compiler A Twig_Compiler instance
28 */
29 public function compile(\Twig_Compiler $compiler)
30 {
31 $compiler
32 ->addDebugInfo($this)
33 ->write('$this->env->getExtension(\'form\')->renderer->setTheme(')
34 ->subcompile($this->getNode('form'))
35 ->raw(', ')
36 ->subcompile($this->getNode('resources'))
37 ->raw(");\n");
38 ;
39 }
40}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/RenderBlockNode.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/RenderBlockNode.php
new file mode 100644
index 00000000..822a2727
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/RenderBlockNode.php
@@ -0,0 +1,42 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Node;
13
14/**
15 * Compiles a call to {@link FormRendererInterface::renderBlock()}.
16 *
17 * The function name is used as block name. For example, if the function name
18 * is "foo", the block "foo" will be rendered.
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class RenderBlockNode extends \Twig_Node_Expression_Function
23{
24 public function compile(\Twig_Compiler $compiler)
25 {
26 $compiler->addDebugInfo($this);
27 $arguments = iterator_to_array($this->getNode('arguments'));
28 $compiler->write('$this->env->getExtension(\'form\')->renderer->renderBlock(');
29
30 if (isset($arguments[0])) {
31 $compiler->subcompile($arguments[0]);
32 $compiler->raw(', \'' . $this->getAttribute('name') . '\'');
33
34 if (isset($arguments[1])) {
35 $compiler->raw(', ');
36 $compiler->subcompile($arguments[1]);
37 }
38 }
39
40 $compiler->raw(')');
41 }
42}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php
new file mode 100644
index 00000000..630e2638
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php
@@ -0,0 +1,106 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Node;
13
14/**
15 * @author Bernhard Schussek <bschussek@gmail.com>
16 */
17class SearchAndRenderBlockNode extends \Twig_Node_Expression_Function
18{
19 public function compile(\Twig_Compiler $compiler)
20 {
21 $compiler->addDebugInfo($this);
22 $compiler->raw('$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(');
23
24 preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches);
25
26 $label = null;
27 $arguments = iterator_to_array($this->getNode('arguments'));
28 $blockNameSuffix = $matches[1];
29
30 if (isset($arguments[0])) {
31 $compiler->subcompile($arguments[0]);
32 $compiler->raw(', \''.$blockNameSuffix.'\'');
33
34 if (isset($arguments[1])) {
35 if ('label' === $blockNameSuffix) {
36 // The "label" function expects the label in the second and
37 // the variables in the third argument
38 $label = $arguments[1];
39 $variables = isset($arguments[2]) ? $arguments[2] : null;
40 $lineno = $label->getLine();
41
42 if ($label instanceof \Twig_Node_Expression_Constant) {
43 // If the label argument is given as a constant, we can either
44 // strip it away if it is empty, or integrate it into the array
45 // of variables at compile time.
46 $labelIsExpression = false;
47
48 // Only insert the label into the array if it is not empty
49 if (!twig_test_empty($label->getAttribute('value'))) {
50 $originalVariables = $variables;
51 $variables = new \Twig_Node_Expression_Array(array(), $lineno);
52 $labelKey = new \Twig_Node_Expression_Constant('label', $lineno);
53
54 if (null !== $originalVariables) {
55 foreach ($originalVariables->getKeyValuePairs() as $pair) {
56 // Don't copy the original label attribute over if it exists
57 if ((string) $labelKey !== (string) $pair['key']) {
58 $variables->addElement($pair['value'], $pair['key']);
59 }
60 }
61 }
62
63 // Insert the label argument into the array
64 $variables->addElement($label, $labelKey);
65 }
66 } else {
67 // The label argument is not a constant, but some kind of
68 // expression. This expression needs to be evaluated at runtime.
69 // Depending on the result (whether it is null or not), the
70 // label in the arguments should take precedence over the label
71 // in the attributes or not.
72 $labelIsExpression = true;
73 }
74 } else {
75 // All other functions than "label" expect the variables
76 // in the second argument
77 $label = null;
78 $variables = $arguments[1];
79 $labelIsExpression = false;
80 }
81
82 if (null !== $variables || $labelIsExpression) {
83 $compiler->raw(', ');
84
85 if (null !== $variables) {
86 $compiler->subcompile($variables);
87 }
88
89 if ($labelIsExpression) {
90 if (null !== $variables) {
91 $compiler->raw(' + ');
92 }
93
94 // Check at runtime whether the label is empty.
95 // If not, add it to the array at runtime.
96 $compiler->raw('(twig_test_empty($_label_ = ');
97 $compiler->subcompile($label);
98 $compiler->raw(') ? array() : array("label" => $_label_))');
99 }
100 }
101 }
102 }
103
104 $compiler->raw(")");
105 }
106}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php
new file mode 100644
index 00000000..adee71ff
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php
@@ -0,0 +1,33 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Node;
13
14/**
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class TransDefaultDomainNode extends \Twig_Node
18{
19 public function __construct(\Twig_Node_Expression $expr, $lineno = 0, $tag = null)
20 {
21 parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param \Twig_Compiler $compiler A Twig_Compiler instance
28 */
29 public function compile(\Twig_Compiler $compiler)
30 {
31 // noop as this node is just a marker for TranslationDefaultDomainNodeVisitor
32 }
33}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransNode.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransNode.php
new file mode 100644
index 00000000..a68c101a
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Node/TransNode.php
@@ -0,0 +1,119 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Node;
13
14/**
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class TransNode extends \Twig_Node
18{
19 public function __construct(\Twig_NodeInterface $body, \Twig_NodeInterface $domain = null, \Twig_Node_Expression $count = null, \Twig_Node_Expression $vars = null, \Twig_Node_Expression $locale = null, $lineno = 0, $tag = null)
20 {
21 parent::__construct(array('count' => $count, 'body' => $body, 'domain' => $domain, 'vars' => $vars, 'locale' => $locale), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param \Twig_Compiler $compiler A Twig_Compiler instance
28 */
29 public function compile(\Twig_Compiler $compiler)
30 {
31 $compiler->addDebugInfo($this);
32
33 $vars = $this->getNode('vars');
34 $defaults = new \Twig_Node_Expression_Array(array(), -1);
35 if ($vars instanceof \Twig_Node_Expression_Array) {
36 $defaults = $this->getNode('vars');
37 $vars = null;
38 }
39 list($msg, $defaults) = $this->compileString($this->getNode('body'), $defaults);
40
41 $method = null === $this->getNode('count') ? 'trans' : 'transChoice';
42
43 $compiler
44 ->write('echo $this->env->getExtension(\'translator\')->getTranslator()->'.$method.'(')
45 ->subcompile($msg)
46 ;
47
48 $compiler->raw(', ');
49
50 if (null !== $this->getNode('count')) {
51 $compiler
52 ->subcompile($this->getNode('count'))
53 ->raw(', ')
54 ;
55 }
56
57 if (null !== $vars) {
58 $compiler
59 ->raw('array_merge(')
60 ->subcompile($defaults)
61 ->raw(', ')
62 ->subcompile($this->getNode('vars'))
63 ->raw(')')
64 ;
65 } else {
66 $compiler->subcompile($defaults);
67 }
68
69 $compiler->raw(', ');
70
71 if (null === $this->getNode('domain')) {
72 $compiler->repr('messages');
73 } else {
74 $compiler->subcompile($this->getNode('domain'));
75 }
76
77 if (null !== $this->getNode('locale')) {
78 $compiler
79 ->raw(', ')
80 ->subcompile($this->getNode('locale'))
81 ;
82 }
83 $compiler->raw(");\n");
84 }
85
86 protected function compileString(\Twig_NodeInterface $body, \Twig_Node_Expression_Array $vars)
87 {
88 if ($body instanceof \Twig_Node_Expression_Constant) {
89 $msg = $body->getAttribute('value');
90 } elseif ($body instanceof \Twig_Node_Text) {
91 $msg = $body->getAttribute('data');
92 } else {
93 return array($body, $vars);
94 }
95
96 preg_match_all('/(?<!%)%([^%]+)%/', $msg, $matches);
97
98 if (version_compare(\Twig_Environment::VERSION, '1.5', '>=')) {
99 foreach ($matches[1] as $var) {
100 $key = new \Twig_Node_Expression_Constant('%'.$var.'%', $body->getLine());
101 if (!$vars->hasElement($key)) {
102 $vars->addElement(new \Twig_Node_Expression_Name($var, $body->getLine()), $key);
103 }
104 }
105 } else {
106 $current = array();
107 foreach ($vars as $name => $var) {
108 $current[$name] = true;
109 }
110 foreach ($matches[1] as $var) {
111 if (!isset($current['%'.$var.'%'])) {
112 $vars->setNode('%'.$var.'%', new \Twig_Node_Expression_Name($var, $body->getLine()));
113 }
114 }
115 }
116
117 return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars);
118 }
119}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php
new file mode 100644
index 00000000..ce27b6a6
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php
@@ -0,0 +1,135 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\NodeVisitor;
13
14/**
15 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
16 */
17class Scope
18{
19 /**
20 * @var Scope|null
21 */
22 private $parent;
23
24 /**
25 * @var Scope[]
26 */
27 private $children;
28
29 /**
30 * @var array
31 */
32 private $data;
33
34 /**
35 * @var boolean
36 */
37 private $left;
38
39 /**
40 * @param Scope $parent
41 */
42 public function __construct(Scope $parent = null)
43 {
44 $this->parent = $parent;
45 $this->left = false;
46 $this->data = array();
47 }
48
49 /**
50 * Opens a new child scope.
51 *
52 * @return Scope
53 */
54 public function enter()
55 {
56 $child = new self($this);
57 $this->children[] = $child;
58
59 return $child;
60 }
61
62 /**
63 * Closes current scope and returns parent one.
64 *
65 * @return Scope|null
66 */
67 public function leave()
68 {
69 $this->left = true;
70
71 return $this->parent;
72 }
73
74 /**
75 * Stores data into current scope.
76 *
77 * @param string $key
78 * @param mixed $value
79 *
80 * @throws \LogicException
81 *
82 * @return Scope Current scope
83 */
84 public function set($key, $value)
85 {
86 if ($this->left) {
87 throw new \LogicException('Left scope is not mutable.');
88 }
89
90 $this->data[$key] = $value;
91
92 return $this;
93 }
94
95 /**
96 * Tests if a data is visible from current scope.
97 *
98 * @param string $key
99 *
100 * @return boolean
101 */
102 public function has($key)
103 {
104 if (array_key_exists($key, $this->data)) {
105 return true;
106 }
107
108 if (null === $this->parent) {
109 return false;
110 }
111
112 return $this->parent->has($key);
113 }
114
115 /**
116 * Returns data visible from current scope.
117 *
118 * @param string $key
119 * @param mixed $default
120 *
121 * @return mixed
122 */
123 public function get($key, $default = null)
124 {
125 if (array_key_exists($key, $this->data)) {
126 return $this->data[$key];
127 }
128
129 if (null === $this->parent) {
130 return $default;
131 }
132
133 return $this->parent->get($key, $default);
134 }
135}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php
new file mode 100644
index 00000000..8e7e7f48
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php
@@ -0,0 +1,106 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\NodeVisitor;
13
14use Symfony\Bridge\Twig\Node\TransNode;
15use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
16
17/**
18 * TranslationDefaultDomainNodeVisitor.
19 *
20 * @author Fabien Potencier <fabien@symfony.com>
21 */
22class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface
23{
24 /**
25 * @var Scope
26 */
27 private $scope;
28
29 /**
30 * Constructor.
31 */
32 public function __construct()
33 {
34 $this->scope = new Scope();
35 }
36
37 /**
38 * {@inheritdoc}
39 */
40 public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env)
41 {
42 if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) {
43 $this->scope = $this->scope->enter();
44 }
45
46 if ($node instanceof TransDefaultDomainNode) {
47 if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) {
48 $this->scope->set('domain', $node->getNode('expr'));
49
50 return $node;
51 } else {
52 $var = $env->getParser()->getVarName();
53 $name = new \Twig_Node_Expression_AssignName($var, $node->getLine());
54 $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getLine()));
55
56 return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getLine());
57 }
58 }
59
60 if (!$this->scope->has('domain')) {
61 return $node;
62 }
63
64 if ($node instanceof \Twig_Node_Expression_Filter && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) {
65 $ind = 'trans' === $node->getNode('filter')->getAttribute('value') ? 1 : 2;
66 $arguments = $node->getNode('arguments');
67 if (!$arguments->hasNode($ind)) {
68 if (!$arguments->hasNode($ind - 1)) {
69 $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getLine()));
70 }
71
72 $arguments->setNode($ind, $this->scope->get('domain'));
73 }
74 } elseif ($node instanceof TransNode) {
75 if (null === $node->getNode('domain')) {
76 $node->setNode('domain', $this->scope->get('domain'));
77 }
78 }
79
80 return $node;
81 }
82
83 /**
84 * {@inheritdoc}
85 */
86 public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env)
87 {
88 if ($node instanceof TransDefaultDomainNode) {
89 return false;
90 }
91
92 if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) {
93 $this->scope = $this->scope->leave();
94 }
95
96 return $node;
97 }
98
99 /**
100 * {@inheritdoc}
101 */
102 public function getPriority()
103 {
104 return -10;
105 }
106}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php
new file mode 100644
index 00000000..592c2506
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php
@@ -0,0 +1,137 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\NodeVisitor;
13
14use Symfony\Bridge\Twig\Node\TransNode;
15
16/**
17 * TranslationNodeVisitor extracts translation messages.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class TranslationNodeVisitor implements \Twig_NodeVisitorInterface
22{
23 const UNDEFINED_DOMAIN = '_undefined';
24
25 private $enabled = false;
26 private $messages = array();
27
28 public function enable()
29 {
30 $this->enabled = true;
31 $this->messages = array();
32 }
33
34 public function disable()
35 {
36 $this->enabled = false;
37 $this->messages = array();
38 }
39
40 public function getMessages()
41 {
42 return $this->messages;
43 }
44
45 /**
46 * {@inheritdoc}
47 */
48 public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env)
49 {
50 if (!$this->enabled) {
51 return $node;
52 }
53
54 if (
55 $node instanceof \Twig_Node_Expression_Filter &&
56 'trans' === $node->getNode('filter')->getAttribute('value') &&
57 $node->getNode('node') instanceof \Twig_Node_Expression_Constant
58 ) {
59 // extract constant nodes with a trans filter
60 $this->messages[] = array(
61 $node->getNode('node')->getAttribute('value'),
62 $this->getReadDomainFromArguments($node->getNode('arguments'), 1),
63 );
64 } elseif (
65 $node instanceof \Twig_Node_Expression_Filter &&
66 'transchoice' === $node->getNode('filter')->getAttribute('value') &&
67 $node->getNode('node') instanceof \Twig_Node_Expression_Constant
68 ) {
69 // extract constant nodes with a trans filter
70 $this->messages[] = array(
71 $node->getNode('node')->getAttribute('value'),
72 $this->getReadDomainFromArguments($node->getNode('arguments'), 2),
73 );
74 } elseif ($node instanceof TransNode) {
75 // extract trans nodes
76 $this->messages[] = array(
77 $node->getNode('body')->getAttribute('data'),
78 $this->getReadDomainFromNode($node->getNode('domain')),
79 );
80 }
81
82 return $node;
83 }
84
85 /**
86 * {@inheritdoc}
87 */
88 public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env)
89 {
90 return $node;
91 }
92
93 /**
94 * {@inheritdoc}
95 */
96 public function getPriority()
97 {
98 return 0;
99 }
100
101 /**
102 * @param \Twig_Node $arguments
103 * @param int $index
104 *
105 * @return string|null
106 */
107 private function getReadDomainFromArguments(\Twig_Node $arguments, $index)
108 {
109 if ($arguments->hasNode('domain')) {
110 $argument = $arguments->getNode('domain');
111 } elseif ($arguments->hasNode($index)) {
112 $argument = $arguments->getNode($index);
113 } else {
114 return null;
115 }
116
117 return $this->getReadDomainFromNode($argument);
118 }
119
120 /**
121 * @param \Twig_Node $node
122 *
123 * @return string|null
124 */
125 private function getReadDomainFromNode(\Twig_Node $node = null)
126 {
127 if (null === $node) {
128 return null;
129 }
130
131 if ($node instanceof \Twig_Node_Expression_Constant) {
132 return $node->getAttribute('value');
133 }
134
135 return self::UNDEFINED_DOMAIN;
136 }
137}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/README.md b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/README.md
new file mode 100644
index 00000000..e5663236
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/README.md
@@ -0,0 +1,15 @@
1Twig Bridge
2===========
3
4Provides integration for [Twig](http://twig.sensiolabs.org/) with various
5Symfony2 components.
6
7Resources
8---------
9
10If you want to run the unit tests, install dev dependencies before
11running PHPUnit:
12
13 $ cd path/to/Symfony/Bridge/Twig/
14 $ composer.phar install --dev
15 $ phpunit
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
new file mode 100644
index 00000000..453c29c6
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
@@ -0,0 +1,390 @@
1{# Widgets #}
2
3{% block form_widget %}
4{% spaceless %}
5 {% if compound %}
6 {{ block('form_widget_compound') }}
7 {% else %}
8 {{ block('form_widget_simple') }}
9 {% endif %}
10{% endspaceless %}
11{% endblock form_widget %}
12
13{% block form_widget_simple %}
14{% spaceless %}
15 {% set type = type|default('text') %}
16 <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
17{% endspaceless %}
18{% endblock form_widget_simple %}
19
20{% block form_widget_compound %}
21{% spaceless %}
22 <div {{ block('widget_container_attributes') }}>
23 {% if form.parent is empty %}
24 {{ form_errors(form) }}
25 {% endif %}
26 {{ block('form_rows') }}
27 {{ form_rest(form) }}
28 </div>
29{% endspaceless %}
30{% endblock form_widget_compound %}
31
32{% block collection_widget %}
33{% spaceless %}
34 {% if prototype is defined %}
35 {% set attr = attr|merge({'data-prototype': form_row(prototype) }) %}
36 {% endif %}
37 {{ block('form_widget') }}
38{% endspaceless %}
39{% endblock collection_widget %}
40
41{% block textarea_widget %}
42{% spaceless %}
43 <textarea {{ block('widget_attributes') }}>{{ value }}</textarea>
44{% endspaceless %}
45{% endblock textarea_widget %}
46
47{% block choice_widget %}
48{% spaceless %}
49 {% if expanded %}
50 {{ block('choice_widget_expanded') }}
51 {% else %}
52 {{ block('choice_widget_collapsed') }}
53 {% endif %}
54{% endspaceless %}
55{% endblock choice_widget %}
56
57{% block choice_widget_expanded %}
58{% spaceless %}
59 <div {{ block('widget_container_attributes') }}>
60 {% for child in form %}
61 {{ form_widget(child) }}
62 {{ form_label(child) }}
63 {% endfor %}
64 </div>
65{% endspaceless %}
66{% endblock choice_widget_expanded %}
67
68{% block choice_widget_collapsed %}
69{% spaceless %}
70 <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
71 {% if empty_value is not none %}
72 <option {% if required %} disabled="disabled"{% if value is empty %} selected="selected"{% endif %}{% else %} value=""{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
73 {% endif %}
74 {% if preferred_choices|length > 0 %}
75 {% set options = preferred_choices %}
76 {{ block('choice_widget_options') }}
77 {% if choices|length > 0 and separator is not none %}
78 <option disabled="disabled">{{ separator }}</option>
79 {% endif %}
80 {% endif %}
81 {% set options = choices %}
82 {{ block('choice_widget_options') }}
83 </select>
84{% endspaceless %}
85{% endblock choice_widget_collapsed %}
86
87{% block choice_widget_options %}
88{% spaceless %}
89 {% for group_label, choice in options %}
90 {% if choice is iterable %}
91 <optgroup label="{{ group_label|trans({}, translation_domain) }}">
92 {% set options = choice %}
93 {{ block('choice_widget_options') }}
94 </optgroup>
95 {% else %}
96 <option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.label|trans({}, translation_domain) }}</option>
97 {% endif %}
98 {% endfor %}
99{% endspaceless %}
100{% endblock choice_widget_options %}
101
102{% block checkbox_widget %}
103{% spaceless %}
104 <input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
105{% endspaceless %}
106{% endblock checkbox_widget %}
107
108{% block radio_widget %}
109{% spaceless %}
110 <input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
111{% endspaceless %}
112{% endblock radio_widget %}
113
114{% block datetime_widget %}
115{% spaceless %}
116 {% if widget == 'single_text' %}
117 {{ block('form_widget_simple') }}
118 {% else %}
119 <div {{ block('widget_container_attributes') }}>
120 {{ form_errors(form.date) }}
121 {{ form_errors(form.time) }}
122 {{ form_widget(form.date) }}
123 {{ form_widget(form.time) }}
124 </div>
125 {% endif %}
126{% endspaceless %}
127{% endblock datetime_widget %}
128
129{% block date_widget %}
130{% spaceless %}
131 {% if widget == 'single_text' %}
132 {{ block('form_widget_simple') }}
133 {% else %}
134 <div {{ block('widget_container_attributes') }}>
135 {{ date_pattern|replace({
136 '{{ year }}': form_widget(form.year),
137 '{{ month }}': form_widget(form.month),
138 '{{ day }}': form_widget(form.day),
139 })|raw }}
140 </div>
141 {% endif %}
142{% endspaceless %}
143{% endblock date_widget %}
144
145{% block time_widget %}
146{% spaceless %}
147 {% if widget == 'single_text' %}
148 {{ block('form_widget_simple') }}
149 {% else %}
150 {% set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} %}
151 <div {{ block('widget_container_attributes') }}>
152 {{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
153 </div>
154 {% endif %}
155{% endspaceless %}
156{% endblock time_widget %}
157
158{% block number_widget %}
159{% spaceless %}
160 {# type="number" doesn't work with floats #}
161 {% set type = type|default('text') %}
162 {{ block('form_widget_simple') }}
163{% endspaceless %}
164{% endblock number_widget %}
165
166{% block integer_widget %}
167{% spaceless %}
168 {% set type = type|default('number') %}
169 {{ block('form_widget_simple') }}
170{% endspaceless %}
171{% endblock integer_widget %}
172
173{% block money_widget %}
174{% spaceless %}
175 {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }}
176{% endspaceless %}
177{% endblock money_widget %}
178
179{% block url_widget %}
180{% spaceless %}
181 {% set type = type|default('url') %}
182 {{ block('form_widget_simple') }}
183{% endspaceless %}
184{% endblock url_widget %}
185
186{% block search_widget %}
187{% spaceless %}
188 {% set type = type|default('search') %}
189 {{ block('form_widget_simple') }}
190{% endspaceless %}
191{% endblock search_widget %}
192
193{% block percent_widget %}
194{% spaceless %}
195 {% set type = type|default('text') %}
196 {{ block('form_widget_simple') }} %
197{% endspaceless %}
198{% endblock percent_widget %}
199
200{% block password_widget %}
201{% spaceless %}
202 {% set type = type|default('password') %}
203 {{ block('form_widget_simple') }}
204{% endspaceless %}
205{% endblock password_widget %}
206
207{% block hidden_widget %}
208{% spaceless %}
209 {% set type = type|default('hidden') %}
210 {{ block('form_widget_simple') }}
211{% endspaceless %}
212{% endblock hidden_widget %}
213
214{% block email_widget %}
215{% spaceless %}
216 {% set type = type|default('email') %}
217 {{ block('form_widget_simple') }}
218{% endspaceless %}
219{% endblock email_widget %}
220
221{% block button_widget %}
222{% spaceless %}
223 {% if label is empty %}
224 {% set label = name|humanize %}
225 {% endif %}
226 <button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain) }}</button>
227{% endspaceless %}
228{% endblock button_widget %}
229
230{% block submit_widget %}
231{% spaceless %}
232 {% set type = type|default('submit') %}
233 {{ block('button_widget') }}
234{% endspaceless %}
235{% endblock submit_widget %}
236
237{% block reset_widget %}
238{% spaceless %}
239 {% set type = type|default('reset') %}
240 {{ block('button_widget') }}
241{% endspaceless %}
242{% endblock reset_widget %}
243
244{# Labels #}
245
246{% block form_label %}
247{% spaceless %}
248 {% if label is not sameas(false) %}
249 {% if not compound %}
250 {% set label_attr = label_attr|merge({'for': id}) %}
251 {% endif %}
252 {% if required %}
253 {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
254 {% endif %}
255 {% if label is empty %}
256 {% set label = name|humanize %}
257 {% endif %}
258 <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}</label>
259 {% endif %}
260{% endspaceless %}
261{% endblock form_label %}
262
263{% block button_label %}{% endblock %}
264
265{# Rows #}
266
267{% block repeated_row %}
268{% spaceless %}
269 {#
270 No need to render the errors here, as all errors are mapped
271 to the first child (see RepeatedTypeValidatorExtension).
272 #}
273 {{ block('form_rows') }}
274{% endspaceless %}
275{% endblock repeated_row %}
276
277{% block form_row %}
278{% spaceless %}
279 <div>
280 {{ form_label(form) }}
281 {{ form_errors(form) }}
282 {{ form_widget(form) }}
283 </div>
284{% endspaceless %}
285{% endblock form_row %}
286
287{% block button_row %}
288{% spaceless %}
289 <div>
290 {{ form_widget(form) }}
291 </div>
292{% endspaceless %}
293{% endblock button_row %}
294
295{% block hidden_row %}
296 {{ form_widget(form) }}
297{% endblock hidden_row %}
298
299{# Misc #}
300
301{% block form %}
302{% spaceless %}
303 {{ form_start(form) }}
304 {{ form_widget(form) }}
305 {{ form_end(form) }}
306{% endspaceless %}
307{% endblock form %}
308
309{% block form_start %}
310{% spaceless %}
311 {% set method = method|upper %}
312 {% if method in ["GET", "POST"] %}
313 {% set form_method = method %}
314 {% else %}
315 {% set form_method = "POST" %}
316 {% endif %}
317 <form method="{{ form_method|lower }}" action="{{ action }}"{% for attrname, attrvalue in attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}{% if multipart %} enctype="multipart/form-data"{% endif %}>
318 {% if form_method != method %}
319 <input type="hidden" name="_method" value="{{ method }}" />
320 {% endif %}
321{% endspaceless %}
322{% endblock form_start %}
323
324{% block form_end %}
325{% spaceless %}
326 {% if not render_rest is defined or render_rest %}
327 {{ form_rest(form) }}
328 {% endif %}
329 </form>
330{% endspaceless %}
331{% endblock form_end %}
332
333{% block form_enctype %}
334{% spaceless %}
335 {% if multipart %}enctype="multipart/form-data"{% endif %}
336{% endspaceless %}
337{% endblock form_enctype %}
338
339{% block form_errors %}
340{% spaceless %}
341 {% if errors|length > 0 %}
342 <ul>
343 {% for error in errors %}
344 <li>{{ error.message }}</li>
345 {% endfor %}
346 </ul>
347 {% endif %}
348{% endspaceless %}
349{% endblock form_errors %}
350
351{% block form_rest %}
352{% spaceless %}
353 {% for child in form %}
354 {% if not child.rendered %}
355 {{ form_row(child) }}
356 {% endif %}
357 {% endfor %}
358{% endspaceless %}
359{% endblock form_rest %}
360
361{# Support #}
362
363{% block form_rows %}
364{% spaceless %}
365 {% for child in form %}
366 {{ form_row(child) }}
367 {% endfor %}
368{% endspaceless %}
369{% endblock form_rows %}
370
371{% block widget_attributes %}
372{% spaceless %}
373 id="{{ id }}" name="{{ full_name }}"{% if read_only %} readonly="readonly"{% endif %}{% if disabled %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %}
374 {% for attrname, attrvalue in attr %}{% if attrname in ['placeholder', 'title'] %}{{ attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {% else %}{{ attrname }}="{{ attrvalue }}" {% endif %}{% endfor %}
375{% endspaceless %}
376{% endblock widget_attributes %}
377
378{% block widget_container_attributes %}
379{% spaceless %}
380 {% if id is not empty %}id="{{ id }}" {% endif %}
381 {% for attrname, attrvalue in attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
382{% endspaceless %}
383{% endblock widget_container_attributes %}
384
385{% block button_attributes %}
386{% spaceless %}
387 id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif %}
388 {% for attrname, attrvalue in attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
389{% endspaceless %}
390{% endblock button_attributes %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig
new file mode 100644
index 00000000..aed4f8d7
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig
@@ -0,0 +1,52 @@
1{% use "form_div_layout.html.twig" %}
2
3{% block form_row %}
4{% spaceless %}
5 <tr>
6 <td>
7 {{ form_label(form) }}
8 </td>
9 <td>
10 {{ form_errors(form) }}
11 {{ form_widget(form) }}
12 </td>
13 </tr>
14{% endspaceless %}
15{% endblock form_row %}
16
17{% block button_row %}
18{% spaceless %}
19 <tr>
20 <td></td>
21 <td>
22 {{ form_widget(form) }}
23 </td>
24 </tr>
25{% endspaceless %}
26{% endblock button_row %}
27
28{% block hidden_row %}
29{% spaceless %}
30 <tr style="display: none">
31 <td colspan="2">
32 {{ form_widget(form) }}
33 </td>
34 </tr>
35{% endspaceless %}
36{% endblock hidden_row %}
37
38{% block form_widget_compound %}
39{% spaceless %}
40 <table {{ block('widget_container_attributes') }}>
41 {% if form.parent is empty and errors|length > 0 %}
42 <tr>
43 <td colspan="2">
44 {{ form_errors(form) }}
45 </td>
46 </tr>
47 {% endif %}
48 {{ block('form_rows') }}
49 {{ form_rest(form) }}
50 </table>
51{% endspaceless %}
52{% endblock form_widget_compound %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
new file mode 100644
index 00000000..d9356514
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
@@ -0,0 +1,69 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension;
13
14use Symfony\Bridge\Twig\Extension\CodeExtension;
15
16class CodeExtensionTest extends \PHPUnit_Framework_TestCase
17{
18 protected $helper;
19
20 public function testFormatFile()
21 {
22 $expected = sprintf('<a href="txmt://open?url=file://%s&amp;line=25" title="Click to open this file" class="file_link">%s at line 25</a>', __FILE__, __FILE__);
23 $this->assertEquals($expected, $this->getExtension()->formatFile(__FILE__, 25));
24 }
25
26 /**
27 * @dataProvider getClassNameProvider
28 */
29 public function testGettingClassAbbreviation($class, $abbr)
30 {
31 $this->assertEquals($this->getExtension()->abbrClass($class), $abbr);
32 }
33
34 /**
35 * @dataProvider getMethodNameProvider
36 */
37 public function testGettingMethodAbbreviation($method, $abbr)
38 {
39 $this->assertEquals($this->getExtension()->abbrMethod($method), $abbr);
40 }
41
42 public function getClassNameProvider()
43 {
44 return array(
45 array('F\Q\N\Foo', '<abbr title="F\Q\N\Foo">Foo</abbr>'),
46 array('Bare', '<abbr title="Bare">Bare</abbr>'),
47 );
48 }
49
50 public function getMethodNameProvider()
51 {
52 return array(
53 array('F\Q\N\Foo::Method', '<abbr title="F\Q\N\Foo">Foo</abbr>::Method()'),
54 array('Bare::Method', '<abbr title="Bare">Bare</abbr>::Method()'),
55 array('Closure', '<abbr title="Closure">Closure</abbr>'),
56 array('Method', '<abbr title="Method">Method</abbr>()')
57 );
58 }
59
60 public function testGetName()
61 {
62 $this->assertEquals('code', $this->getExtension()->getName());
63 }
64
65 protected function getExtension()
66 {
67 return new CodeExtension('txmt://open?url=file://%f&line=%l', '/root', 'UTF-8');
68 }
69}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php
new file mode 100644
index 00000000..36c61cd6
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php
@@ -0,0 +1,30 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures;
13
14// Preventing autoloader throwing E_FATAL when Twig is now available
15if (!class_exists('Twig_Environment')) {
16 class StubFilesystemLoader
17 {
18 }
19} else {
20 class StubFilesystemLoader extends \Twig_Loader_Filesystem
21 {
22 protected function findTemplate($name)
23 {
24 // strip away bundle name
25 $parts = explode(':', $name);
26
27 return parent::findTemplate(end($parts));
28 }
29 }
30}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php
new file mode 100644
index 00000000..b7d011b5
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php
@@ -0,0 +1,35 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures;
13
14use Symfony\Component\Translation\TranslatorInterface;
15
16class StubTranslator implements TranslatorInterface
17{
18 public function trans($id, array $parameters = array(), $domain = null, $locale = null)
19 {
20 return '[trans]'.$id.'[/trans]';
21 }
22
23 public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
24 {
25 return '[trans]'.$id.'[/trans]';
26 }
27
28 public function setLocale($locale)
29 {
30 }
31
32 public function getLocale()
33 {
34 }
35}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
new file mode 100644
index 00000000..c5c134bc
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
@@ -0,0 +1,209 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension;
13
14use Symfony\Bridge\Twig\Extension\FormExtension;
15use Symfony\Bridge\Twig\Form\TwigRenderer;
16use Symfony\Bridge\Twig\Form\TwigRendererEngine;
17use Symfony\Bridge\Twig\Extension\TranslationExtension;
18use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator;
19use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
20use Symfony\Component\Form\FormView;
21use Symfony\Component\Form\Extension\Core\View\ChoiceView;
22use Symfony\Component\Form\Tests\AbstractDivLayoutTest;
23
24class FormExtensionDivLayoutTest extends AbstractDivLayoutTest
25{
26 /**
27 * @var FormExtension
28 */
29 protected $extension;
30
31 protected function setUp()
32 {
33 if (!class_exists('Symfony\Component\Locale\Locale')) {
34 $this->markTestSkipped('The "Locale" component is not available');
35 }
36
37 if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
38 $this->markTestSkipped('The "EventDispatcher" component is not available');
39 }
40
41 if (!class_exists('Symfony\Component\Form\Form')) {
42 $this->markTestSkipped('The "Form" component is not available');
43 }
44
45 if (!class_exists('Twig_Environment')) {
46 $this->markTestSkipped('Twig is not available.');
47 }
48
49 parent::setUp();
50
51 $rendererEngine = new TwigRendererEngine(array(
52 'form_div_layout.html.twig',
53 'custom_widgets.html.twig',
54 ));
55 $renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'));
56
57 $this->extension = new FormExtension($renderer);
58
59 $loader = new StubFilesystemLoader(array(
60 __DIR__.'/../../Resources/views/Form',
61 __DIR__,
62 ));
63
64 $environment = new \Twig_Environment($loader, array('strict_variables' => true));
65 $environment->addExtension(new TranslationExtension(new StubTranslator()));
66 $environment->addGlobal('global', '');
67 $environment->addExtension($this->extension);
68
69 $this->extension->initRuntime($environment);
70 }
71
72 protected function tearDown()
73 {
74 parent::tearDown();
75
76 $this->extension = null;
77 }
78
79 public function testThemeBlockInheritanceUsingUse()
80 {
81 $view = $this->factory
82 ->createNamed('name', 'email')
83 ->createView()
84 ;
85
86 $this->setTheme($view, array('theme_use.html.twig'));
87
88 $this->assertMatchesXpath(
89 $this->renderWidget($view),
90 '/input[@type="email"][@rel="theme"]'
91 );
92 }
93
94 public function testThemeBlockInheritanceUsingExtend()
95 {
96 $view = $this->factory
97 ->createNamed('name', 'email')
98 ->createView()
99 ;
100
101 $this->setTheme($view, array('theme_extends.html.twig'));
102
103 $this->assertMatchesXpath(
104 $this->renderWidget($view),
105 '/input[@type="email"][@rel="theme"]'
106 );
107 }
108
109 public function isSelectedChoiceProvider()
110 {
111 // The commented cases should not be necessary anymore, because the
112 // choice lists should assure that both values passed here are always
113 // strings
114 return array(
115// array(true, 0, 0),
116 array(true, '0', '0'),
117 array(true, '1', '1'),
118// array(true, false, 0),
119// array(true, true, 1),
120 array(true, '', ''),
121// array(true, null, ''),
122 array(true, '1.23', '1.23'),
123 array(true, 'foo', 'foo'),
124 array(true, 'foo10', 'foo10'),
125 array(true, 'foo', array(1, 'foo', 'foo10')),
126
127 array(false, 10, array(1, 'foo', 'foo10')),
128 array(false, 0, array(1, 'foo', 'foo10')),
129 );
130 }
131
132 /**
133 * @dataProvider isSelectedChoiceProvider
134 */
135 public function testIsChoiceSelected($expected, $choice, $value)
136 {
137 $choice = new ChoiceView($choice, $choice, $choice.' label');
138
139 $this->assertSame($expected, $this->extension->isSelectedChoice($choice, $value));
140 }
141
142 protected function renderForm(FormView $view, array $vars = array())
143 {
144 return (string) $this->extension->renderer->renderBlock($view, 'form', $vars);
145 }
146
147 protected function renderEnctype(FormView $view)
148 {
149 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'enctype');
150 }
151
152 protected function renderLabel(FormView $view, $label = null, array $vars = array())
153 {
154 if ($label !== null) {
155 $vars += array('label' => $label);
156 }
157
158 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'label', $vars);
159 }
160
161 protected function renderErrors(FormView $view)
162 {
163 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'errors');
164 }
165
166 protected function renderWidget(FormView $view, array $vars = array())
167 {
168 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'widget', $vars);
169 }
170
171 protected function renderRow(FormView $view, array $vars = array())
172 {
173 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'row', $vars);
174 }
175
176 protected function renderRest(FormView $view, array $vars = array())
177 {
178 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'rest', $vars);
179 }
180
181 protected function renderStart(FormView $view, array $vars = array())
182 {
183 return (string) $this->extension->renderer->renderBlock($view, 'form_start', $vars);
184 }
185
186 protected function renderEnd(FormView $view, array $vars = array())
187 {
188 return (string) $this->extension->renderer->renderBlock($view, 'form_end', $vars);
189 }
190
191 protected function setTheme(FormView $view, array $themes)
192 {
193 $this->extension->renderer->setTheme($view, $themes);
194 }
195
196 public static function themeBlockInheritanceProvider()
197 {
198 return array(
199 array(array('theme.html.twig'))
200 );
201 }
202
203 public static function themeInheritanceProvider()
204 {
205 return array(
206 array(array('parent_label.html.twig'), array('child_label.html.twig'))
207 );
208 }
209}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
new file mode 100644
index 00000000..99a78217
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
@@ -0,0 +1,131 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension;
13
14use Symfony\Component\Form\FormView;
15use Symfony\Bridge\Twig\Form\TwigRenderer;
16use Symfony\Bridge\Twig\Form\TwigRendererEngine;
17use Symfony\Bridge\Twig\Extension\FormExtension;
18use Symfony\Bridge\Twig\Extension\TranslationExtension;
19use Symfony\Component\Form\Tests\AbstractTableLayoutTest;
20use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator;
21use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
22
23class FormExtensionTableLayoutTest extends AbstractTableLayoutTest
24{
25 /**
26 * @var FormExtension
27 */
28 protected $extension;
29
30 protected function setUp()
31 {
32 if (!class_exists('Symfony\Component\Locale\Locale')) {
33 $this->markTestSkipped('The "Locale" component is not available');
34 }
35
36 if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
37 $this->markTestSkipped('The "EventDispatcher" component is not available');
38 }
39
40 if (!class_exists('Symfony\Component\Form\Form')) {
41 $this->markTestSkipped('The "Form" component is not available');
42 }
43
44 if (!class_exists('Twig_Environment')) {
45 $this->markTestSkipped('Twig is not available.');
46 }
47
48 parent::setUp();
49
50 $rendererEngine = new TwigRendererEngine(array(
51 'form_table_layout.html.twig',
52 'custom_widgets.html.twig',
53 ));
54 $renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'));
55
56 $this->extension = new FormExtension($renderer);
57
58 $loader = new StubFilesystemLoader(array(
59 __DIR__.'/../../Resources/views/Form',
60 __DIR__,
61 ));
62
63 $environment = new \Twig_Environment($loader, array('strict_variables' => true));
64 $environment->addExtension(new TranslationExtension(new StubTranslator()));
65 $environment->addGlobal('global', '');
66 $environment->addExtension($this->extension);
67
68 $this->extension->initRuntime($environment);
69 }
70
71 protected function tearDown()
72 {
73 parent::tearDown();
74
75 $this->extension = null;
76 }
77
78 protected function renderForm(FormView $view, array $vars = array())
79 {
80 return (string) $this->extension->renderer->renderBlock($view, 'form', $vars);
81 }
82
83 protected function renderEnctype(FormView $view)
84 {
85 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'enctype');
86 }
87
88 protected function renderLabel(FormView $view, $label = null, array $vars = array())
89 {
90 if ($label !== null) {
91 $vars += array('label' => $label);
92 }
93
94 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'label', $vars);
95 }
96
97 protected function renderErrors(FormView $view)
98 {
99 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'errors');
100 }
101
102 protected function renderWidget(FormView $view, array $vars = array())
103 {
104 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'widget', $vars);
105 }
106
107 protected function renderRow(FormView $view, array $vars = array())
108 {
109 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'row', $vars);
110 }
111
112 protected function renderRest(FormView $view, array $vars = array())
113 {
114 return (string) $this->extension->renderer->searchAndRenderBlock($view, 'rest', $vars);
115 }
116
117 protected function renderStart(FormView $view, array $vars = array())
118 {
119 return (string) $this->extension->renderer->renderBlock($view, 'form_start', $vars);
120 }
121
122 protected function renderEnd(FormView $view, array $vars = array())
123 {
124 return (string) $this->extension->renderer->renderBlock($view, 'form_end', $vars);
125 }
126
127 protected function setTheme(FormView $view, array $themes)
128 {
129 $this->extension->renderer->setTheme($view, $themes);
130 }
131}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
new file mode 100644
index 00000000..077927cd
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
@@ -0,0 +1,68 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension;
13
14use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
15use Symfony\Bridge\Twig\Tests\TestCase;
16use Symfony\Component\HttpFoundation\Request;
17use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
18
19class HttpKernelExtensionTest extends TestCase
20{
21 protected function setUp()
22 {
23 parent::setUp();
24
25 if (!class_exists('Symfony\Component\HttpKernel\HttpKernel')) {
26 $this->markTestSkipped('The "HttpKernel" component is not available');
27 }
28
29 if (!class_exists('Twig_Environment')) {
30 $this->markTestSkipped('Twig is not available.');
31 }
32 }
33
34 /**
35 * @expectedException \Twig_Error_Runtime
36 */
37 public function testFragmentWithError()
38 {
39 $kernel = $this->getFragmentHandler($this->throwException(new \Exception('foo')));
40
41 $loader = new \Twig_Loader_Array(array('index' => '{{ fragment("foo") }}'));
42 $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
43 $twig->addExtension(new HttpKernelExtension($kernel));
44
45 $this->renderTemplate($kernel);
46 }
47
48 protected function getFragmentHandler($return)
49 {
50 $strategy = $this->getMock('Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface');
51 $strategy->expects($this->once())->method('getName')->will($this->returnValue('inline'));
52 $strategy->expects($this->once())->method('render')->will($return);
53
54 $renderer = new FragmentHandler(array($strategy));
55 $renderer->setRequest(Request::create('/'));
56
57 return $renderer;
58 }
59
60 protected function renderTemplate(FragmentHandler $renderer, $template = '{{ render("foo") }}')
61 {
62 $loader = new \Twig_Loader_Array(array('index' => $template));
63 $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
64 $twig->addExtension(new HttpKernelExtension($renderer));
65
66 return $twig->render('index');
67 }
68}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php
new file mode 100644
index 00000000..3c5d762c
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php
@@ -0,0 +1,60 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension;
13
14use Symfony\Bridge\Twig\Extension\RoutingExtension;
15use Symfony\Bridge\Twig\Tests\TestCase;
16
17class RoutingExtensionTest extends TestCase
18{
19 protected function setUp()
20 {
21 parent::setUp();
22
23 if (!class_exists('Symfony\Component\Routing\Route')) {
24 $this->markTestSkipped('The "Routing" component is not available');
25 }
26 }
27
28 /**
29 * @dataProvider getEscapingTemplates
30 */
31 public function testEscaping($template, $mustBeEscaped)
32 {
33 $twig = new \Twig_Environment(null, array('debug' => true, 'cache' => false, 'autoescape' => true, 'optimizations' => 0));
34 $twig->addExtension(new RoutingExtension($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')));
35
36 $nodes = $twig->parse($twig->tokenize($template));
37
38 $this->assertSame($mustBeEscaped, $nodes->getNode('body')->getNode(0)->getNode('expr') instanceof \Twig_Node_Expression_Filter);
39 }
40
41 public function getEscapingTemplates()
42 {
43 return array(
44 array('{{ path("foo") }}', false),
45 array('{{ path("foo", {}) }}', false),
46 array('{{ path("foo", { foo: "foo" }) }}', false),
47 array('{{ path("foo", foo) }}', true),
48 array('{{ path("foo", { foo: foo }) }}', true),
49 array('{{ path("foo", { foo: ["foo", "bar"] }) }}', true),
50 array('{{ path("foo", { foo: "foo", bar: "bar" }) }}', true),
51
52 array('{{ path(name = "foo", parameters = {}) }}', false),
53 array('{{ path(name = "foo", parameters = { foo: "foo" }) }}', false),
54 array('{{ path(name = "foo", parameters = foo) }}', true),
55 array('{{ path(name = "foo", parameters = { foo: ["foo", "bar"] }) }}', true),
56 array('{{ path(name = "foo", parameters = { foo: foo }) }}', true),
57 array('{{ path(name = "foo", parameters = { foo: "foo", bar: "bar" }) }}', true),
58 );
59 }
60}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
new file mode 100644
index 00000000..2b9c5533
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
@@ -0,0 +1,151 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Extension;
13
14use Symfony\Bridge\Twig\Extension\TranslationExtension;
15use Symfony\Component\Translation\Translator;
16use Symfony\Component\Translation\MessageSelector;
17use Symfony\Component\Translation\Loader\ArrayLoader;
18use Symfony\Bridge\Twig\Tests\TestCase;
19
20class TranslationExtensionTest extends TestCase
21{
22 protected function setUp()
23 {
24 parent::setUp();
25
26 if (!class_exists('Symfony\Component\Translation\Translator')) {
27 $this->markTestSkipped('The "Translation" component is not available');
28 }
29
30 if (!class_exists('Twig_Environment')) {
31 $this->markTestSkipped('Twig is not available.');
32 }
33 }
34
35 public function testEscaping()
36 {
37 $output = $this->getTemplate('{% trans %}Percent: %value%%% (%msg%){% endtrans %}')->render(array('value' => 12, 'msg' => 'approx.'));
38
39 $this->assertEquals('Percent: 12% (approx.)', $output);
40 }
41
42 /**
43 * @dataProvider getTransTests
44 */
45 public function testTrans($template, $expected, array $variables = array())
46 {
47 if ($expected != $this->getTemplate($template)->render($variables)) {
48 print $template."\n";
49 $loader = new \Twig_Loader_Array(array('index' => $template));
50 $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
51 $twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector())));
52
53 echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSource('index'), 'index')))."\n\n";
54 $this->assertEquals($expected, $this->getTemplate($template)->render($variables));
55 }
56
57 $this->assertEquals($expected, $this->getTemplate($template)->render($variables));
58 }
59
60 public function getTransTests()
61 {
62 return array(
63 // trans tag
64 array('{% trans %}Hello{% endtrans %}', 'Hello'),
65 array('{% trans %}%name%{% endtrans %}', 'Symfony2', array('name' => 'Symfony2')),
66
67 array('{% trans from elsewhere %}Hello{% endtrans %}', 'Hello'),
68
69 array('{% trans %}Hello %name%{% endtrans %}', 'Hello Symfony2', array('name' => 'Symfony2')),
70 array('{% trans with { \'%name%\': \'Symfony2\' } %}Hello %name%{% endtrans %}', 'Hello Symfony2'),
71 array('{% set vars = { \'%name%\': \'Symfony2\' } %}{% trans with vars %}Hello %name%{% endtrans %}', 'Hello Symfony2'),
72
73 array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),
74
75 // transchoice
76 array('{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
77 'There is no apples', array('count' => 0)),
78 array('{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
79 'There is 5 apples', array('count' => 5)),
80 array('{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}',
81 'There is 5 apples (Symfony2)', array('count' => 5, 'name' => 'Symfony2')),
82 array('{% transchoice count with { \'%name%\': \'Symfony2\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}',
83 'There is 5 apples (Symfony2)', array('count' => 5)),
84 array('{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
85 'There is no apples', array('count' => 0)),
86
87 // trans filter
88 array('{{ "Hello"|trans }}', 'Hello'),
89 array('{{ name|trans }}', 'Symfony2', array('name' => 'Symfony2')),
90 array('{{ hello|trans({ \'%name%\': \'Symfony2\' }) }}', 'Hello Symfony2', array('hello' => 'Hello %name%')),
91 array('{% set vars = { \'%name%\': \'Symfony2\' } %}{{ hello|trans(vars) }}', 'Hello Symfony2', array('hello' => 'Hello %name%')),
92 array('{{ "Hello"|trans({}, "messages", "fr") }}', 'Hello'),
93
94 // transchoice filter
95 array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count) }}', 'There is 5 apples', array('count' => 5)),
96 array('{{ text|transchoice(5, {\'%name%\': \'Symfony2\'}) }}', 'There is 5 apples (Symfony2)', array('text' => '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%)')),
97 array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count, {}, "messages", "fr") }}', 'There is 5 apples', array('count' => 5)),
98 );
99 }
100
101 public function testDefaultTranslationDomain()
102 {
103 $templates = array(
104 'index' => '
105 {%- extends "base" %}
106
107 {%- trans_default_domain "foo" %}
108
109 {%- block content %}
110 {%- trans %}foo{% endtrans %}
111 {%- trans from "custom" %}foo{% endtrans %}
112 {{- "foo"|trans }}
113 {{- "foo"|trans({}, "custom") }}
114 {{- "foo"|transchoice(1) }}
115 {{- "foo"|transchoice(1, {}, "custom") }}
116 {% endblock %}
117 ',
118
119 'base' => '
120 {%- block content "" %}
121 ',
122 );
123
124 $translator = new Translator('en', new MessageSelector());
125 $translator->addLoader('array', new ArrayLoader());
126 $translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
127 $translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
128 $translator->addResource('array', array('foo' => 'foo (foo)'), 'en', 'foo');
129
130 $template = $this->getTemplate($templates, $translator);
131
132 $this->assertEquals('foo (foo)foo (custom)foo (foo)foo (custom)foo (foo)foo (custom)', trim($template->render(array())));
133 }
134
135 protected function getTemplate($template, $translator = null)
136 {
137 if (null === $translator) {
138 $translator = new Translator('en', new MessageSelector());
139 }
140
141 if (is_array($template)) {
142 $loader = new \Twig_Loader_Array($template);
143 } else {
144 $loader = new \Twig_Loader_Array(array('index' => $template));
145 }
146 $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
147 $twig->addExtension(new TranslationExtension($translator));
148
149 return $twig->loadTemplate('index');
150 }
151}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig
new file mode 100644
index 00000000..8c7c2489
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig
@@ -0,0 +1,3 @@
1{% block form_label %}
2 <label>{{ global }}child</label>
3{% endblock form_label %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig
new file mode 100644
index 00000000..12fd7c66
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig
@@ -0,0 +1,16 @@
1{% block _text_id_widget %}
2{% spaceless %}
3 <div id="container">
4 {{ form_widget(form) }}
5 </div>
6{% endspaceless %}
7{% endblock _text_id_widget %}
8
9{% block _name_entry_label %}
10{% spaceless %}
11 {% if label is empty %}
12 {% set label = name|humanize %}
13 {% endif %}
14 <label>Custom label: {{ label|trans({}, translation_domain) }}</label>
15{% endspaceless %}
16{% endblock _name_entry_label %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig
new file mode 100644
index 00000000..e96278b8
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig
@@ -0,0 +1,3 @@
1{% block form_label %}
2 <label>parent</label>
3{% endblock form_label %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig
new file mode 100644
index 00000000..da1c1b64
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig
@@ -0,0 +1,6 @@
1{% block form_widget_simple %}
2{% spaceless %}
3 {% set type = type|default('text') %}
4 <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
5{% endspaceless %}
6{% endblock form_widget_simple %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig
new file mode 100644
index 00000000..8c719867
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig
@@ -0,0 +1,8 @@
1{% extends 'form_div_layout.html.twig' %}
2
3{% block form_widget_simple %}
4{% spaceless %}
5 {% set type = type|default('text') %}
6 <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
7{% endspaceless %}
8{% endblock form_widget_simple %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig
new file mode 100644
index 00000000..d485b8d0
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig
@@ -0,0 +1,8 @@
1{% use 'form_div_layout.html.twig' %}
2
3{% block form_widget_simple %}
4{% spaceless %}
5 {% set type = type|default('text') %}
6 <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
7{% endspaceless %}
8{% endblock form_widget_simple %}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php
new file mode 100644
index 00000000..90afef12
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php
@@ -0,0 +1,85 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Node;
13
14use Symfony\Bridge\Twig\Tests\TestCase;
15use Symfony\Bridge\Twig\Node\FormThemeNode;
16
17class FormThemeTest extends TestCase
18{
19 protected function setUp()
20 {
21 parent::setUp();
22
23 if (version_compare(\Twig_Environment::VERSION, '1.5.0', '<')) {
24 $this->markTestSkipped('Requires Twig version to be at least 1.5.0.');
25 }
26 }
27
28 public function testConstructor()
29 {
30 $form = new \Twig_Node_Expression_Name('form', 0);
31 $resources = new \Twig_Node(array(
32 new \Twig_Node_Expression_Constant('tpl1', 0),
33 new \Twig_Node_Expression_Constant('tpl2', 0)
34 ));
35
36 $node = new FormThemeNode($form, $resources, 0);
37
38 $this->assertEquals($form, $node->getNode('form'));
39 $this->assertEquals($resources, $node->getNode('resources'));
40 }
41
42 public function testCompile()
43 {
44 $form = new \Twig_Node_Expression_Name('form', 0);
45 $resources = new \Twig_Node_Expression_Array(array(
46 new \Twig_Node_Expression_Constant(0, 0),
47 new \Twig_Node_Expression_Constant('tpl1', 0),
48 new \Twig_Node_Expression_Constant(1, 0),
49 new \Twig_Node_Expression_Constant('tpl2', 0)
50 ), 0);
51
52 $node = new FormThemeNode($form, $resources, 0);
53
54 $compiler = new \Twig_Compiler(new \Twig_Environment());
55
56 $this->assertEquals(
57 sprintf(
58 '$this->env->getExtension(\'form\')->renderer->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));',
59 $this->getVariableGetter('form')
60 ),
61 trim($compiler->compile($node)->getSource())
62 );
63
64 $resources = new \Twig_Node_Expression_Constant('tpl1', 0);
65
66 $node = new FormThemeNode($form, $resources, 0);
67
68 $this->assertEquals(
69 sprintf(
70 '$this->env->getExtension(\'form\')->renderer->setTheme(%s, "tpl1");',
71 $this->getVariableGetter('form')
72 ),
73 trim($compiler->compile($node)->getSource())
74 );
75 }
76
77 protected function getVariableGetter($name)
78 {
79 if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
80 return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
81 }
82
83 return sprintf('$this->getContext($context, "%s")', $name);
84 }
85}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php
new file mode 100644
index 00000000..c1f247ca
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php
@@ -0,0 +1,282 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Node;
13
14use Symfony\Bridge\Twig\Tests\TestCase;
15use Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode;
16
17class SearchAndRenderBlockNodeTest extends TestCase
18{
19 protected function setUp()
20 {
21 parent::setUp();
22
23 if (version_compare(\Twig_Environment::VERSION, '1.5.0', '<')) {
24 $this->markTestSkipped('Requires Twig version to be at least 1.5.0.');
25 }
26 }
27
28 public function testCompileWidget()
29 {
30 $arguments = new \Twig_Node(array(
31 new \Twig_Node_Expression_Name('form', 0),
32 ));
33
34 $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0);
35
36 $compiler = new \Twig_Compiler(new \Twig_Environment());
37
38 $this->assertEquals(
39 sprintf(
40 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'widget\')',
41 $this->getVariableGetter('form')
42 ),
43 trim($compiler->compile($node)->getSource())
44 );
45 }
46
47 public function testCompileWidgetWithVariables()
48 {
49 $arguments = new \Twig_Node(array(
50 new \Twig_Node_Expression_Name('form', 0),
51 new \Twig_Node_Expression_Array(array(
52 new \Twig_Node_Expression_Constant('foo', 0),
53 new \Twig_Node_Expression_Constant('bar', 0),
54 ), 0),
55 ));
56
57 $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0);
58
59 $compiler = new \Twig_Compiler(new \Twig_Environment());
60
61 $this->assertEquals(
62 sprintf(
63 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))',
64 $this->getVariableGetter('form')
65 ),
66 trim($compiler->compile($node)->getSource())
67 );
68 }
69
70 public function testCompileLabelWithLabel()
71 {
72 $arguments = new \Twig_Node(array(
73 new \Twig_Node_Expression_Name('form', 0),
74 new \Twig_Node_Expression_Constant('my label', 0),
75 ));
76
77 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
78
79 $compiler = new \Twig_Compiler(new \Twig_Environment());
80
81 $this->assertEquals(
82 sprintf(
83 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))',
84 $this->getVariableGetter('form')
85 ),
86 trim($compiler->compile($node)->getSource())
87 );
88 }
89
90 public function testCompileLabelWithNullLabel()
91 {
92 $arguments = new \Twig_Node(array(
93 new \Twig_Node_Expression_Name('form', 0),
94 new \Twig_Node_Expression_Constant(null, 0),
95 ));
96
97 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
98
99 $compiler = new \Twig_Compiler(new \Twig_Environment());
100
101 // "label" => null must not be included in the output!
102 // Otherwise the default label is overwritten with null.
103 $this->assertEquals(
104 sprintf(
105 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')',
106 $this->getVariableGetter('form')
107 ),
108 trim($compiler->compile($node)->getSource())
109 );
110 }
111
112 public function testCompileLabelWithEmptyStringLabel()
113 {
114 $arguments = new \Twig_Node(array(
115 new \Twig_Node_Expression_Name('form', 0),
116 new \Twig_Node_Expression_Constant('', 0),
117 ));
118
119 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
120
121 $compiler = new \Twig_Compiler(new \Twig_Environment());
122
123 // "label" => null must not be included in the output!
124 // Otherwise the default label is overwritten with null.
125 $this->assertEquals(
126 sprintf(
127 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')',
128 $this->getVariableGetter('form')
129 ),
130 trim($compiler->compile($node)->getSource())
131 );
132 }
133
134 public function testCompileLabelWithDefaultLabel()
135 {
136 $arguments = new \Twig_Node(array(
137 new \Twig_Node_Expression_Name('form', 0),
138 ));
139
140 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
141
142 $compiler = new \Twig_Compiler(new \Twig_Environment());
143
144 $this->assertEquals(
145 sprintf(
146 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')',
147 $this->getVariableGetter('form')
148 ),
149 trim($compiler->compile($node)->getSource())
150 );
151 }
152
153 public function testCompileLabelWithAttributes()
154 {
155 $arguments = new \Twig_Node(array(
156 new \Twig_Node_Expression_Name('form', 0),
157 new \Twig_Node_Expression_Constant(null, 0),
158 new \Twig_Node_Expression_Array(array(
159 new \Twig_Node_Expression_Constant('foo', 0),
160 new \Twig_Node_Expression_Constant('bar', 0),
161 ), 0),
162 ));
163
164 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
165
166 $compiler = new \Twig_Compiler(new \Twig_Environment());
167
168 // "label" => null must not be included in the output!
169 // Otherwise the default label is overwritten with null.
170 // https://github.com/symfony/symfony/issues/5029
171 $this->assertEquals(
172 sprintf(
173 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))',
174 $this->getVariableGetter('form')
175 ),
176 trim($compiler->compile($node)->getSource())
177 );
178 }
179
180 public function testCompileLabelWithLabelAndAttributes()
181 {
182 $arguments = new \Twig_Node(array(
183 new \Twig_Node_Expression_Name('form', 0),
184 new \Twig_Node_Expression_Constant('value in argument', 0),
185 new \Twig_Node_Expression_Array(array(
186 new \Twig_Node_Expression_Constant('foo', 0),
187 new \Twig_Node_Expression_Constant('bar', 0),
188 new \Twig_Node_Expression_Constant('label', 0),
189 new \Twig_Node_Expression_Constant('value in attributes', 0),
190 ), 0),
191 ));
192
193 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
194
195 $compiler = new \Twig_Compiler(new \Twig_Environment());
196
197 $this->assertEquals(
198 sprintf(
199 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))',
200 $this->getVariableGetter('form')
201 ),
202 trim($compiler->compile($node)->getSource())
203 );
204 }
205
206 public function testCompileLabelWithLabelThatEvaluatesToNull()
207 {
208 $arguments = new \Twig_Node(array(
209 new \Twig_Node_Expression_Name('form', 0),
210 new \Twig_Node_Expression_Conditional(
211 // if
212 new \Twig_Node_Expression_Constant(true, 0),
213 // then
214 new \Twig_Node_Expression_Constant(null, 0),
215 // else
216 new \Twig_Node_Expression_Constant(null, 0),
217 0
218 ),
219 ));
220
221 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
222
223 $compiler = new \Twig_Compiler(new \Twig_Environment());
224
225 // "label" => null must not be included in the output!
226 // Otherwise the default label is overwritten with null.
227 // https://github.com/symfony/symfony/issues/5029
228 $this->assertEquals(
229 sprintf(
230 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))',
231 $this->getVariableGetter('form')
232 ),
233 trim($compiler->compile($node)->getSource())
234 );
235 }
236
237 public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes()
238 {
239 $arguments = new \Twig_Node(array(
240 new \Twig_Node_Expression_Name('form', 0),
241 new \Twig_Node_Expression_Conditional(
242 // if
243 new \Twig_Node_Expression_Constant(true, 0),
244 // then
245 new \Twig_Node_Expression_Constant(null, 0),
246 // else
247 new \Twig_Node_Expression_Constant(null, 0),
248 0
249 ),
250 new \Twig_Node_Expression_Array(array(
251 new \Twig_Node_Expression_Constant('foo', 0),
252 new \Twig_Node_Expression_Constant('bar', 0),
253 new \Twig_Node_Expression_Constant('label', 0),
254 new \Twig_Node_Expression_Constant('value in attributes', 0),
255 ), 0),
256 ));
257
258 $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
259
260 $compiler = new \Twig_Compiler(new \Twig_Environment());
261
262 // "label" => null must not be included in the output!
263 // Otherwise the default label is overwritten with null.
264 // https://github.com/symfony/symfony/issues/5029
265 $this->assertEquals(
266 sprintf(
267 '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))',
268 $this->getVariableGetter('form')
269 ),
270 trim($compiler->compile($node)->getSource())
271 );
272 }
273
274 protected function getVariableGetter($name)
275 {
276 if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
277 return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
278 }
279
280 return sprintf('$this->getContext($context, "%s")', $name);
281 }
282}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php
new file mode 100644
index 00000000..bcae5919
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php
@@ -0,0 +1,25 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
13
14use Symfony\Bridge\Twig\NodeVisitor\Scope;
15use Symfony\Bridge\Twig\Tests\TestCase;
16
17class ScopeTest extends TestCase
18{
19 public function testScopeInitiation()
20 {
21 $scope = new Scope();
22 $scope->enter();
23 $this->assertNull($scope->get('test'));
24 }
25}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php
new file mode 100644
index 00000000..24a6215e
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php
@@ -0,0 +1,83 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
13
14use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
15use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
16use Symfony\Bridge\Twig\Tests\TestCase;
17
18class TranslationDefaultDomainNodeVisitorTest extends TestCase
19{
20 private static $message = 'message';
21 private static $domain = 'domain';
22
23 /** @dataProvider getDefaultDomainAssignmentTestData */
24 public function testDefaultDomainAssignment(\Twig_Node $node)
25 {
26 $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
27 $visitor = new TranslationDefaultDomainNodeVisitor();
28
29 // visit trans_default_domain tag
30 $defaultDomain = TwigNodeProvider::getTransDefaultDomainTag(self::$domain);
31 $visitor->enterNode($defaultDomain, $env);
32 $visitor->leaveNode($defaultDomain, $env);
33
34 // visit tested node
35 $enteredNode = $visitor->enterNode($node, $env);
36 $leavedNode = $visitor->leaveNode($node, $env);
37 $this->assertSame($node, $enteredNode);
38 $this->assertSame($node, $leavedNode);
39
40 // extracting tested node messages
41 $visitor = new TranslationNodeVisitor();
42 $visitor->enable();
43 $visitor->enterNode($node, $env);
44 $visitor->leaveNode($node, $env);
45
46 $this->assertEquals(array(array(self::$message, self::$domain)), $visitor->getMessages());
47 }
48
49 /** @dataProvider getDefaultDomainAssignmentTestData */
50 public function testNewModuleWithoutDefaultDomainTag(\Twig_Node $node)
51 {
52 $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
53 $visitor = new TranslationDefaultDomainNodeVisitor();
54
55 // visit trans_default_domain tag
56 $newModule = TwigNodeProvider::getModule('test');
57 $visitor->enterNode($newModule, $env);
58 $visitor->leaveNode($newModule, $env);
59
60 // visit tested node
61 $enteredNode = $visitor->enterNode($node, $env);
62 $leavedNode = $visitor->leaveNode($node, $env);
63 $this->assertSame($node, $enteredNode);
64 $this->assertSame($node, $leavedNode);
65
66 // extracting tested node messages
67 $visitor = new TranslationNodeVisitor();
68 $visitor->enable();
69 $visitor->enterNode($node, $env);
70 $visitor->leaveNode($node, $env);
71
72 $this->assertEquals(array(array(self::$message, null)), $visitor->getMessages());
73 }
74
75 public function getDefaultDomainAssignmentTestData()
76 {
77 return array(
78 array(TwigNodeProvider::getTransFilter(self::$message)),
79 array(TwigNodeProvider::getTransChoiceFilter(self::$message)),
80 array(TwigNodeProvider::getTransTag(self::$message)),
81 );
82 }
83}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php
new file mode 100644
index 00000000..4e3ee6fd
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php
@@ -0,0 +1,61 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
13
14use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
15use Symfony\Bridge\Twig\Tests\TestCase;
16
17class TranslationNodeVisitorTest extends TestCase
18{
19 /** @dataProvider getMessagesExtractionTestData */
20 public function testMessagesExtraction(\Twig_Node $node, array $expectedMessages)
21 {
22 $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
23 $visitor = new TranslationNodeVisitor();
24 $visitor->enable();
25 $visitor->enterNode($node, $env);
26 $visitor->leaveNode($node, $env);
27 $this->assertEquals($expectedMessages, $visitor->getMessages());
28 }
29
30 public function testMessageExtractionWithInvalidDomainNode()
31 {
32 $message = 'new key';
33
34 $node = new \Twig_Node_Expression_Filter(
35 new \Twig_Node_Expression_Constant($message, 0),
36 new \Twig_Node_Expression_Constant('trans', 0),
37 new \Twig_Node(array(
38 new \Twig_Node_Expression_Array(array(), 0),
39 new \Twig_Node_Expression_Name('variable', 0),
40 )),
41 0
42 );
43
44 $this->testMessagesExtraction($node, array(array($message, TranslationNodeVisitor::UNDEFINED_DOMAIN)));
45 }
46
47 public function getMessagesExtractionTestData()
48 {
49 $message = 'new key';
50 $domain = 'domain';
51
52 return array(
53 array(TwigNodeProvider::getTransFilter($message), array(array($message, null))),
54 array(TwigNodeProvider::getTransChoiceFilter($message), array(array($message, null))),
55 array(TwigNodeProvider::getTransTag($message), array(array($message, null))),
56 array(TwigNodeProvider::getTransFilter($message, $domain), array(array($message, $domain))),
57 array(TwigNodeProvider::getTransChoiceFilter($message, $domain), array(array($message, $domain))),
58 array(TwigNodeProvider::getTransTag($message, $domain), array(array($message, $domain))),
59 );
60 }
61}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php
new file mode 100644
index 00000000..277e7774
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php
@@ -0,0 +1,77 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
13
14use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
15use Symfony\Bridge\Twig\Node\TransNode;
16
17class TwigNodeProvider
18{
19 public static function getModule($content)
20 {
21 return new \Twig_Node_Module(
22 new \Twig_Node_Expression_Constant($content, 0),
23 null,
24 new \Twig_Node_Expression_Array(array(), 0),
25 new \Twig_Node_Expression_Array(array(), 0),
26 new \Twig_Node_Expression_Array(array(), 0),
27 null,
28 null
29 );
30 }
31
32 public static function getTransFilter($message, $domain = null)
33 {
34 $arguments = $domain ? array(
35 new \Twig_Node_Expression_Array(array(), 0),
36 new \Twig_Node_Expression_Constant($domain, 0),
37 ) : array();
38
39 return new \Twig_Node_Expression_Filter(
40 new \Twig_Node_Expression_Constant($message, 0),
41 new \Twig_Node_Expression_Constant('trans', 0),
42 new \Twig_Node($arguments),
43 0
44 );
45 }
46
47 public static function getTransChoiceFilter($message, $domain = null)
48 {
49 $arguments = $domain ? array(
50 new \Twig_Node_Expression_Constant(0, 0),
51 new \Twig_Node_Expression_Array(array(), 0),
52 new \Twig_Node_Expression_Constant($domain, 0),
53 ) : array();
54
55 return new \Twig_Node_Expression_Filter(
56 new \Twig_Node_Expression_Constant($message, 0),
57 new \Twig_Node_Expression_Constant('transchoice', 0),
58 new \Twig_Node($arguments),
59 0
60 );
61 }
62
63 public static function getTransTag($message, $domain = null)
64 {
65 return new TransNode(
66 new \Twig_Node_Body(array(), array('data' => $message)),
67 $domain ? new \Twig_Node_Expression_Constant($domain, 0) : null
68 );
69 }
70
71 public static function getTransDefaultDomainTag($domain)
72 {
73 return new TransDefaultDomainNode(
74 new \Twig_Node_Expression_Constant($domain, 0)
75 );
76 }
77}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TestCase.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TestCase.php
new file mode 100644
index 00000000..ecfb7daf
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TestCase.php
@@ -0,0 +1,22 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests;
13
14abstract class TestCase extends \PHPUnit_Framework_TestCase
15{
16 protected function setUp()
17 {
18 if (!class_exists('Twig_Environment')) {
19 $this->markTestSkipped('Twig is not available.');
20 }
21 }
22}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php
new file mode 100644
index 00000000..077cd76a
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php
@@ -0,0 +1,108 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Node;
13
14use Symfony\Bridge\Twig\Tests\TestCase;
15use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
16use Symfony\Bridge\Twig\Node\FormThemeNode;
17
18class FormThemeTokenParserTest extends TestCase
19{
20 protected function setUp()
21 {
22 parent::setUp();
23
24 if (version_compare(\Twig_Environment::VERSION, '1.5.0', '<')) {
25 $this->markTestSkipped('Requires Twig version to be at least 1.5.0.');
26 }
27 }
28
29 /**
30 * @dataProvider getTestsForFormTheme
31 */
32 public function testCompile($source, $expected)
33 {
34 $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
35 $env->addTokenParser(new FormThemeTokenParser());
36 $stream = $env->tokenize($source);
37 $parser = new \Twig_Parser($env);
38
39 $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0));
40 }
41
42 public function getTestsForFormTheme()
43 {
44 return array(
45 array(
46 '{% form_theme form "tpl1" %}',
47 new FormThemeNode(
48 new \Twig_Node_Expression_Name('form', 1),
49 new \Twig_Node_Expression_Array(array(
50 new \Twig_Node_Expression_Constant(0, 1),
51 new \Twig_Node_Expression_Constant('tpl1', 1),
52 ), 1),
53 1,
54 'form_theme'
55 )
56 ),
57 array(
58 '{% form_theme form "tpl1" "tpl2" %}',
59 new FormThemeNode(
60 new \Twig_Node_Expression_Name('form', 1),
61 new \Twig_Node_Expression_Array(array(
62 new \Twig_Node_Expression_Constant(0, 1),
63 new \Twig_Node_Expression_Constant('tpl1', 1),
64 new \Twig_Node_Expression_Constant(1, 1),
65 new \Twig_Node_Expression_Constant('tpl2', 1)
66 ), 1),
67 1,
68 'form_theme'
69 )
70 ),
71 array(
72 '{% form_theme form with "tpl1" %}',
73 new FormThemeNode(
74 new \Twig_Node_Expression_Name('form', 1),
75 new \Twig_Node_Expression_Constant('tpl1', 1),
76 1,
77 'form_theme'
78 )
79 ),
80 array(
81 '{% form_theme form with ["tpl1"] %}',
82 new FormThemeNode(
83 new \Twig_Node_Expression_Name('form', 1),
84 new \Twig_Node_Expression_Array(array(
85 new \Twig_Node_Expression_Constant(0, 1),
86 new \Twig_Node_Expression_Constant('tpl1', 1),
87 ), 1),
88 1,
89 'form_theme'
90 )
91 ),
92 array(
93 '{% form_theme form with ["tpl1", "tpl2"] %}',
94 new FormThemeNode(
95 new \Twig_Node_Expression_Name('form', 1),
96 new \Twig_Node_Expression_Array(array(
97 new \Twig_Node_Expression_Constant(0, 1),
98 new \Twig_Node_Expression_Constant('tpl1', 1),
99 new \Twig_Node_Expression_Constant(1, 1),
100 new \Twig_Node_Expression_Constant('tpl2', 1)
101 ), 1),
102 1,
103 'form_theme'
104 )
105 ),
106 );
107 }
108}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php
new file mode 100644
index 00000000..a2c5cd3d
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php
@@ -0,0 +1,81 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Tests\Translation;
13
14use Symfony\Bridge\Twig\Extension\TranslationExtension;
15use Symfony\Bridge\Twig\Translation\TwigExtractor;
16use Symfony\Component\Translation\MessageCatalogue;
17use Symfony\Bridge\Twig\Tests\TestCase;
18
19class TwigExtractorTest extends TestCase
20{
21 protected function setUp()
22 {
23 if (!class_exists('Symfony\Component\Translation\Translator')) {
24 $this->markTestSkipped('The "Translation" component is not available');
25 }
26 }
27
28 /**
29 * @dataProvider getExtractData
30 */
31 public function testExtract($template, $messages)
32 {
33 $loader = new \Twig_Loader_Array(array());
34 $twig = new \Twig_Environment($loader, array(
35 'strict_variables' => true,
36 'debug' => true,
37 'cache' => false,
38 'autoescape' => false,
39 ));
40 $twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface')));
41
42 $extractor = new TwigExtractor($twig);
43 $extractor->setPrefix('prefix');
44 $catalogue = new MessageCatalogue('en');
45
46 $m = new \ReflectionMethod($extractor, 'extractTemplate');
47 $m->setAccessible(true);
48 $m->invoke($extractor, $template, $catalogue);
49
50 foreach ($messages as $key => $domain) {
51 $this->assertTrue($catalogue->has($key, $domain));
52 $this->assertEquals('prefix'.$key, $catalogue->get($key, $domain));
53 }
54 }
55
56 public function getExtractData()
57 {
58 return array(
59 array('{{ "new key" | trans() }}', array('new key' => 'messages')),
60 array('{{ "new key" | trans() | upper }}', array('new key' => 'messages')),
61 array('{{ "new key" | trans({}, "domain") }}', array('new key' => 'domain')),
62 array('{{ "new key" | transchoice(1) }}', array('new key' => 'messages')),
63 array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')),
64 array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')),
65 array('{% trans %}new key{% endtrans %}', array('new key' => 'messages')),
66 array('{% trans %} new key {% endtrans %}', array('new key' => 'messages')),
67 array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')),
68 array('{% set foo = "new key" | trans %}', array('new key' => 'messages')),
69 array('{{ 1 ? "new key" | trans : "another key" | trans }}', array('new key' => 'messages', 'another key' => 'messages')),
70
71 // make sure 'trans_default_domain' tag is supported
72 array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')),
73 array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')),
74 array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')),
75
76 // make sure this works with twig's named arguments
77 array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')),
78 array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')),
79 );
80 }
81}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php
new file mode 100644
index 00000000..244d676e
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php
@@ -0,0 +1,61 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\TokenParser;
13
14use Symfony\Bridge\Twig\Node\FormThemeNode;
15
16/**
17 * Token Parser for the 'form_theme' tag.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class FormThemeTokenParser extends \Twig_TokenParser
22{
23 /**
24 * Parses a token and returns a node.
25 *
26 * @param \Twig_Token $token A Twig_Token instance
27 *
28 * @return \Twig_NodeInterface A Twig_NodeInterface instance
29 */
30 public function parse(\Twig_Token $token)
31 {
32 $lineno = $token->getLine();
33 $stream = $this->parser->getStream();
34
35 $form = $this->parser->getExpressionParser()->parseExpression();
36
37 if ($this->parser->getStream()->test(\Twig_Token::NAME_TYPE, 'with')) {
38 $this->parser->getStream()->next();
39 $resources = $this->parser->getExpressionParser()->parseExpression();
40 } else {
41 $resources = new \Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
42 do {
43 $resources->addElement($this->parser->getExpressionParser()->parseExpression());
44 } while (!$stream->test(\Twig_Token::BLOCK_END_TYPE));
45 }
46
47 $stream->expect(\Twig_Token::BLOCK_END_TYPE);
48
49 return new FormThemeNode($form, $resources, $lineno, $this->getTag());
50 }
51
52 /**
53 * Gets the tag name associated with this token parser.
54 *
55 * @return string The tag name
56 */
57 public function getTag()
58 {
59 return 'form_theme';
60 }
61}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php
new file mode 100644
index 00000000..be8ac5cf
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php
@@ -0,0 +1,89 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\TokenParser;
13
14use Symfony\Bridge\Twig\Node\TransNode;
15
16/**
17 * Token Parser for the 'transchoice' tag.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class TransChoiceTokenParser extends TransTokenParser
22{
23 /**
24 * Parses a token and returns a node.
25 *
26 * @param \Twig_Token $token A Twig_Token instance
27 *
28 * @return \Twig_NodeInterface A Twig_NodeInterface instance
29 *
30 * @throws \Twig_Error_Syntax
31 */
32 public function parse(\Twig_Token $token)
33 {
34 $lineno = $token->getLine();
35 $stream = $this->parser->getStream();
36
37 $vars = new \Twig_Node_Expression_Array(array(), $lineno);
38
39 $count = $this->parser->getExpressionParser()->parseExpression();
40
41 $domain = null;
42 $locale = null;
43
44 if ($stream->test('with')) {
45 // {% transchoice count with vars %}
46 $stream->next();
47 $vars = $this->parser->getExpressionParser()->parseExpression();
48 }
49
50 if ($stream->test('from')) {
51 // {% transchoice count from "messages" %}
52 $stream->next();
53 $domain = $this->parser->getExpressionParser()->parseExpression();
54 }
55
56 if ($stream->test('into')) {
57 // {% transchoice count into "fr" %}
58 $stream->next();
59 $locale = $this->parser->getExpressionParser()->parseExpression();
60 }
61
62 $stream->expect(\Twig_Token::BLOCK_END_TYPE);
63
64 $body = $this->parser->subparse(array($this, 'decideTransChoiceFork'), true);
65
66 if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) {
67 throw new \Twig_Error_Syntax('A message must be a simple text.');
68 }
69
70 $stream->expect(\Twig_Token::BLOCK_END_TYPE);
71
72 return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag());
73 }
74
75 public function decideTransChoiceFork($token)
76 {
77 return $token->test(array('endtranschoice'));
78 }
79
80 /**
81 * Gets the tag name associated with this token parser.
82 *
83 * @return string The tag name
84 */
85 public function getTag()
86 {
87 return 'transchoice';
88 }
89}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php
new file mode 100644
index 00000000..0a0ed55b
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php
@@ -0,0 +1,48 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\TokenParser;
13
14use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
15
16/**
17 * Token Parser for the 'trans_default_domain' tag.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class TransDefaultDomainTokenParser extends \Twig_TokenParser
22{
23 /**
24 * Parses a token and returns a node.
25 *
26 * @param \Twig_Token $token A Twig_Token instance
27 *
28 * @return \Twig_NodeInterface A Twig_NodeInterface instance
29 */
30 public function parse(\Twig_Token $token)
31 {
32 $expr = $this->parser->getExpressionParser()->parseExpression();
33
34 $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
35
36 return new TransDefaultDomainNode($expr, $token->getLine(), $this->getTag());
37 }
38
39 /**
40 * Gets the tag name associated with this token parser.
41 *
42 * @return string The tag name
43 */
44 public function getTag()
45 {
46 return 'trans_default_domain';
47 }
48}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php
new file mode 100644
index 00000000..a11681c2
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php
@@ -0,0 +1,89 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\TokenParser;
13
14use Symfony\Bridge\Twig\Node\TransNode;
15
16/**
17 * Token Parser for the 'trans' tag.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class TransTokenParser extends \Twig_TokenParser
22{
23 /**
24 * Parses a token and returns a node.
25 *
26 * @param \Twig_Token $token A Twig_Token instance
27 *
28 * @return \Twig_NodeInterface A Twig_NodeInterface instance
29 *
30 * @throws \Twig_Error_Syntax
31 */
32 public function parse(\Twig_Token $token)
33 {
34 $lineno = $token->getLine();
35 $stream = $this->parser->getStream();
36
37 $vars = new \Twig_Node_Expression_Array(array(), $lineno);
38 $domain = null;
39 $locale = null;
40 if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
41 if ($stream->test('with')) {
42 // {% trans with vars %}
43 $stream->next();
44 $vars = $this->parser->getExpressionParser()->parseExpression();
45 }
46
47 if ($stream->test('from')) {
48 // {% trans from "messages" %}
49 $stream->next();
50 $domain = $this->parser->getExpressionParser()->parseExpression();
51 }
52
53 if ($stream->test('into')) {
54 // {% trans into "fr" %}
55 $stream->next();
56 $locale = $this->parser->getExpressionParser()->parseExpression();
57 } elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
58 throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "with" or "from" keyword.');
59 }
60 }
61
62 // {% trans %}message{% endtrans %}
63 $stream->expect(\Twig_Token::BLOCK_END_TYPE);
64 $body = $this->parser->subparse(array($this, 'decideTransFork'), true);
65
66 if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) {
67 throw new \Twig_Error_Syntax('A message inside a trans tag must be a simple text');
68 }
69
70 $stream->expect(\Twig_Token::BLOCK_END_TYPE);
71
72 return new TransNode($body, $domain, null, $vars, $locale, $lineno, $this->getTag());
73 }
74
75 public function decideTransFork($token)
76 {
77 return $token->test(array('endtrans'));
78 }
79
80 /**
81 * Gets the tag name associated with this token parser.
82 *
83 * @return string The tag name
84 */
85 public function getTag()
86 {
87 return 'trans';
88 }
89}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Translation/TwigExtractor.php
new file mode 100644
index 00000000..b93193f2
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Translation/TwigExtractor.php
@@ -0,0 +1,86 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig\Translation;
13
14use Symfony\Component\Finder\Finder;
15use Symfony\Component\Translation\Extractor\ExtractorInterface;
16use Symfony\Component\Translation\MessageCatalogue;
17
18/**
19 * TwigExtractor extracts translation messages from a twig template.
20 *
21 * @author Michel Salib <michelsalib@hotmail.com>
22 * @author Fabien Potencier <fabien@symfony.com>
23 */
24class TwigExtractor implements ExtractorInterface
25{
26 /**
27 * Default domain for found messages.
28 *
29 * @var string
30 */
31 private $defaultDomain = 'messages';
32
33 /**
34 * Prefix for found message.
35 *
36 * @var string
37 */
38 private $prefix = '';
39
40 /**
41 * The twig environment.
42 *
43 * @var \Twig_Environment
44 */
45 private $twig;
46
47 public function __construct(\Twig_Environment $twig)
48 {
49 $this->twig = $twig;
50 }
51
52 /**
53 * {@inheritDoc}
54 */
55 public function extract($directory, MessageCatalogue $catalogue)
56 {
57 // load any existing translation files
58 $finder = new Finder();
59 $files = $finder->files()->name('*.twig')->in($directory);
60 foreach ($files as $file) {
61 $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
62 }
63 }
64
65 /**
66 * {@inheritDoc}
67 */
68 public function setPrefix($prefix)
69 {
70 $this->prefix = $prefix;
71 }
72
73 protected function extractTemplate($template, MessageCatalogue $catalogue)
74 {
75 $visitor = $this->twig->getExtension('translator')->getTranslationNodeVisitor();
76 $visitor->enable();
77
78 $this->twig->parse($this->twig->tokenize($template));
79
80 foreach ($visitor->getMessages() as $message) {
81 $catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ? $message[1] : $this->defaultDomain);
82 }
83
84 $visitor->disable();
85 }
86}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TwigEngine.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TwigEngine.php
new file mode 100644
index 00000000..955d4e0b
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/TwigEngine.php
@@ -0,0 +1,126 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bridge\Twig;
13
14use Symfony\Component\Templating\EngineInterface;
15use Symfony\Component\Templating\StreamingEngineInterface;
16use Symfony\Component\Templating\TemplateNameParserInterface;
17
18/**
19 * This engine knows how to render Twig templates.
20 *
21 * @author Fabien Potencier <fabien@symfony.com>
22 */
23class TwigEngine implements EngineInterface, StreamingEngineInterface
24{
25 protected $environment;
26 protected $parser;
27
28 /**
29 * Constructor.
30 *
31 * @param \Twig_Environment $environment A \Twig_Environment instance
32 * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance
33 */
34 public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser)
35 {
36 $this->environment = $environment;
37 $this->parser = $parser;
38 }
39
40 /**
41 * Renders a template.
42 *
43 * @param mixed $name A template name
44 * @param array $parameters An array of parameters to pass to the template
45 *
46 * @return string The evaluated template as a string
47 *
48 * @throws \InvalidArgumentException if the template does not exist
49 * @throws \RuntimeException if the template cannot be rendered
50 */
51 public function render($name, array $parameters = array())
52 {
53 return $this->load($name)->render($parameters);
54 }
55
56 /**
57 * Streams a template.
58 *
59 * @param mixed $name A template name or a TemplateReferenceInterface instance
60 * @param array $parameters An array of parameters to pass to the template
61 *
62 * @throws \RuntimeException if the template cannot be rendered
63 */
64 public function stream($name, array $parameters = array())
65 {
66 $this->load($name)->display($parameters);
67 }
68
69 /**
70 * Returns true if the template exists.
71 *
72 * @param mixed $name A template name
73 *
74 * @return Boolean true if the template exists, false otherwise
75 */
76 public function exists($name)
77 {
78 try {
79 $this->load($name);
80 } catch (\InvalidArgumentException $e) {
81 return false;
82 }
83
84 return true;
85 }
86
87 /**
88 * Returns true if this class is able to render the given template.
89 *
90 * @param string $name A template name
91 *
92 * @return Boolean True if this class supports the given resource, false otherwise
93 */
94 public function supports($name)
95 {
96 if ($name instanceof \Twig_Template) {
97 return true;
98 }
99
100 $template = $this->parser->parse($name);
101
102 return 'twig' === $template->get('engine');
103 }
104
105 /**
106 * Loads the given template.
107 *
108 * @param mixed $name A template name or an instance of Twig_Template
109 *
110 * @return \Twig_TemplateInterface A \Twig_TemplateInterface instance
111 *
112 * @throws \InvalidArgumentException if the template does not exist
113 */
114 protected function load($name)
115 {
116 if ($name instanceof \Twig_Template) {
117 return $name;
118 }
119
120 try {
121 return $this->environment->loadTemplate($name);
122 } catch (\Twig_Error_Loader $e) {
123 throw new \InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
124 }
125 }
126}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/composer.json b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/composer.json
new file mode 100644
index 00000000..9cd57ae6
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/composer.json
@@ -0,0 +1,50 @@
1{
2 "name": "symfony/twig-bridge",
3 "type": "symfony-bridge",
4 "description": "Symfony Twig Bridge",
5 "keywords": [],
6 "homepage": "http://symfony.com",
7 "license": "MIT",
8 "authors": [
9 {
10 "name": "Fabien Potencier",
11 "email": "fabien@symfony.com"
12 },
13 {
14 "name": "Symfony Community",
15 "homepage": "http://symfony.com/contributors"
16 }
17 ],
18 "require": {
19 "php": ">=5.3.3",
20 "twig/twig": "~1.11"
21 },
22 "require-dev": {
23 "symfony/form": "2.2.*",
24 "symfony/http-kernel": "~2.2",
25 "symfony/routing": "~2.2",
26 "symfony/templating": "~2.1",
27 "symfony/translation": "~2.2",
28 "symfony/yaml": "~2.0",
29 "symfony/security": "~2.0"
30 },
31 "suggest": {
32 "symfony/form": "",
33 "symfony/http-kernel": "",
34 "symfony/routing": "",
35 "symfony/templating": "",
36 "symfony/translation": "",
37 "symfony/yaml": "",
38 "symfony/security": ""
39 },
40 "autoload": {
41 "psr-0": { "Symfony\\Bridge\\Twig\\": "" }
42 },
43 "target-dir": "Symfony/Bridge/Twig",
44 "minimum-stability": "dev",
45 "extra": {
46 "branch-alias": {
47 "dev-master": "2.3-dev"
48 }
49 }
50}
diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/phpunit.xml.dist b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/phpunit.xml.dist
new file mode 100644
index 00000000..cc9e0e86
--- /dev/null
+++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/phpunit.xml.dist
@@ -0,0 +1,30 @@
1<?xml version="1.0" encoding="UTF-8"?>
2
3<phpunit backupGlobals="false"
4 backupStaticAttributes="false"
5 colors="true"
6 convertErrorsToExceptions="true"
7 convertNoticesToExceptions="true"
8 convertWarningsToExceptions="true"
9 processIsolation="false"
10 stopOnFailure="false"
11 syntaxCheck="false"
12 bootstrap="vendor/autoload.php"
13>
14 <testsuites>
15 <testsuite name="Symfony Twig Bridge Test Suite">
16 <directory>./Tests/</directory>
17 </testsuite>
18 </testsuites>
19
20 <filter>
21 <whitelist>
22 <directory>./</directory>
23 <exclude>
24 <directory>./Resources</directory>
25 <directory>./Tests</directory>
26 <directory>./vendor</directory>
27 </exclude>
28 </whitelist>
29 </filter>
30</phpunit>