Version Description
- Corrected error with sidebar retrieval
- language_attributes are now avaiable as part of Timber::get_context(); payload.
- Upgraded to Twig 1.13.1
Download this release
Release Info
Developer | jarednova |
Plugin | Timber |
Version | 0.10.3 |
Comparing to | |
See all releases |
Code changes from version 0.10.2 to 0.10.3
- Twig/.editorconfig +0 -18
- Twig/.gitignore +0 -2
- Twig/.travis.yml +0 -14
- Twig/CHANGELOG +30 -3
- Twig/composer.json +0 -31
- Twig/doc/advanced.rst +0 -776
- Twig/doc/advanced_legacy.rst +0 -887
- Twig/doc/api.rst +0 -585
- Twig/doc/coding_standards.rst +0 -101
- Twig/doc/deprecated.rst +0 -98
- Twig/doc/filters/abs.rst +0 -18
- Twig/doc/filters/capitalize.rst +0 -11
- Twig/doc/filters/convert_encoding.rst +0 -28
- Twig/doc/filters/date.rst +0 -88
- Twig/doc/filters/date_modify.rst +0 -23
- Twig/doc/filters/default.rst +0 -33
- Twig/doc/filters/escape.rst +0 -93
- Twig/doc/filters/format.rst +0 -16
- Twig/doc/filters/index.rst +0 -33
- Twig/doc/filters/join.rst +0 -23
- Twig/doc/filters/json_encode.rst +0 -19
- Twig/doc/filters/keys.rst +0 -11
- Twig/doc/filters/length.rst +0 -12
- Twig/doc/filters/lower.rst +0 -10
- Twig/doc/filters/merge.rst +0 -41
- Twig/doc/filters/nl2br.rst +0 -22
- Twig/doc/filters/number_format.rst +0 -45
- Twig/doc/filters/raw.rst +0 -12
- Twig/doc/filters/replace.rst +0 -19
- Twig/doc/filters/reverse.rst +0 -23
- Twig/doc/filters/slice.rst +0 -70
- Twig/doc/filters/sort.rst +0 -17
- Twig/doc/filters/split.rst +0 -53
- Twig/doc/filters/striptags.rst +0 -15
- Twig/doc/filters/title.rst +0 -11
- Twig/doc/filters/trim.rst +0 -29
- Twig/doc/filters/upper.rst +0 -10
- Twig/doc/filters/url_encode.rst +0 -14
- Twig/doc/functions/attribute.rst +0 -18
- Twig/doc/functions/block.rst +0 -15
- Twig/doc/functions/constant.rst +0 -18
- Twig/doc/functions/cycle.rst +0 -25
- Twig/doc/functions/date.rst +0 -52
- Twig/doc/functions/dump.rst +0 -69
- Twig/doc/functions/include.rst +0 -80
- Twig/doc/functions/index.rst +0 -17
- Twig/doc/functions/parent.rst +0 -20
- Twig/doc/functions/random.rst +0 -29
- Twig/doc/functions/range.rst +0 -45
- Twig/doc/functions/template_from_string.rst +0 -32
- Twig/doc/index.rst +0 -18
- Twig/doc/internals.rst +0 -140
- Twig/doc/intro.rst +0 -164
- Twig/doc/recipes.rst +0 -474
- Twig/doc/tags/autoescape.rst +0 -71
- Twig/doc/tags/block.rst +0 -11
- Twig/doc/tags/do.rst +0 -12
- Twig/doc/tags/embed.rst +0 -178
- Twig/doc/tags/extends.rst +0 -268
- Twig/doc/tags/filter.rst +0 -21
- Twig/doc/tags/flush.rst +0 -17
- Twig/doc/tags/for.rst +0 -157
- Twig/doc/tags/from.rst +0 -8
- Twig/doc/tags/if.rst +0 -43
- Twig/doc/tags/import.rst +0 -57
- Twig/doc/tags/include.rst +0 -86
- Twig/doc/tags/index.rst +0 -24
- Twig/doc/tags/macro.rst +0 -83
- Twig/doc/tags/sandbox.rst +0 -30
- Twig/doc/tags/set.rst +0 -32
- Twig/doc/tags/spaceless.rst +0 -37
- Twig/doc/tags/use.rst +0 -123
- Twig/doc/tags/verbatim.rst +0 -24
- Twig/doc/templates.rst +0 -837
- Twig/doc/tests/constant.rst +0 -11
- Twig/doc/tests/defined.rst +0 -30
- Twig/doc/tests/divisibleby.rst +0 -10
- Twig/doc/tests/empty.rst +0 -11
- Twig/doc/tests/even.rst +0 -10
- Twig/doc/tests/index.rst +0 -15
- Twig/doc/tests/iterable.rst +0 -19
- Twig/doc/tests/null.rst +0 -12
- Twig/doc/tests/odd.rst +0 -10
- Twig/doc/tests/sameas.rst +0 -11
- Twig/ext/twig/.gitignore +0 -30
- Twig/ext/twig/LICENSE +0 -22
- Twig/ext/twig/config.m4 +0 -8
- Twig/ext/twig/config.w32 +0 -8
- Twig/ext/twig/php_twig.h +0 -31
- Twig/ext/twig/twig.c +0 -1051
- Twig/lib/Twig/Autoloader.php +9 -5
- Twig/lib/Twig/Compiler.php +1 -2
- Twig/lib/Twig/CompilerInterface.php +1 -2
- Twig/lib/Twig/Environment.php +45 -30
- Twig/lib/Twig/Error.php +9 -3
- Twig/lib/Twig/Error/Loader.php +1 -2
- Twig/lib/Twig/Error/Runtime.php +1 -2
- Twig/lib/Twig/Error/Syntax.php +1 -2
- Twig/lib/Twig/ExistsLoaderInterface.php +1 -2
- Twig/lib/Twig/ExpressionParser.php +2 -3
- Twig/lib/Twig/Extension/Core.php +137 -58
- Twig/lib/Twig/Extension/Debug.php +1 -0
- Twig/lib/Twig/Extension/Staging.php +1 -2
- Twig/lib/Twig/Extension/StringLoader.php +1 -1
- Twig/lib/Twig/ExtensionInterface.php +1 -2
- Twig/lib/Twig/Filter.php +1 -4
- Twig/lib/Twig/Filter/Function.php +1 -2
- Twig/lib/Twig/Filter/Method.php +1 -2
- Twig/lib/Twig/Filter/Node.php +1 -2
- Twig/lib/Twig/FilterCallableInterface.php +1 -2
- Twig/lib/Twig/FilterInterface.php +1 -2
- Twig/lib/Twig/Function.php +1 -2
- Twig/lib/Twig/Function/Function.php +1 -2
- Twig/lib/Twig/Function/Method.php +1 -2
- Twig/lib/Twig/Function/Node.php +1 -2
- Twig/lib/Twig/FunctionCallableInterface.php +1 -2
- Twig/lib/Twig/FunctionInterface.php +1 -2
- Twig/lib/Twig/Lexer.php +5 -3
- Twig/lib/Twig/LexerInterface.php +1 -2
- Twig/lib/Twig/Loader/Array.php +1 -2
- Twig/lib/Twig/Loader/Chain.php +7 -4
- Twig/lib/Twig/Loader/Filesystem.php +6 -4
- Twig/lib/Twig/Loader/String.php +1 -2
- Twig/lib/Twig/LoaderInterface.php +1 -2
- Twig/lib/Twig/Markup.php +1 -2
- Twig/lib/Twig/Node.php +1 -2
- Twig/lib/Twig/Node/AutoEscape.php +1 -2
- Twig/lib/Twig/Node/Block.php +1 -2
- Twig/lib/Twig/Node/BlockReference.php +1 -2
- Twig/lib/Twig/Node/Body.php +1 -2
- Twig/lib/Twig/Node/Do.php +1 -2
- Twig/lib/Twig/Node/Embed.php +1 -2
- Twig/lib/Twig/Node/Expression.php +1 -2
- Twig/lib/Twig/Node/Expression/BlockReference.php +1 -2
- Twig/lib/Twig/Node/Expression/Call.php +7 -0
- Twig/lib/Twig/Node/Expression/ExtensionReference.php +1 -2
- Twig/lib/Twig/Node/Expression/Filter/Default.php +1 -2
- Twig/lib/Twig/Node/Expression/Parent.php +1 -2
- Twig/lib/Twig/Node/Expression/Test/Constant.php +12 -2
- Twig/lib/Twig/Node/Expression/Test/Defined.php +2 -3
- Twig/lib/Twig/Node/Expression/Test/Divisibleby.php +1 -2
- Twig/lib/Twig/Node/Expression/Test/Even.php +1 -2
- Twig/lib/Twig/Node/Expression/Test/Null.php +1 -2
- Twig/lib/Twig/Node/Expression/Test/Odd.php +1 -2
- Twig/lib/Twig/Node/Expression/Test/Sameas.php +1 -2
- Twig/lib/Twig/Node/Flush.php +1 -2
- Twig/lib/Twig/Node/For.php +2 -3
- Twig/lib/Twig/Node/ForLoop.php +1 -2
- Twig/lib/Twig/Node/If.php +1 -2
- Twig/lib/Twig/Node/Import.php +1 -2
- Twig/lib/Twig/Node/Include.php +1 -2
- Twig/lib/Twig/Node/Macro.php +1 -2
- Twig/lib/Twig/Node/Module.php +1 -2
- Twig/lib/Twig/Node/Print.php +1 -2
- Twig/lib/Twig/Node/Sandbox.php +1 -2
- Twig/lib/Twig/Node/SandboxedModule.php +1 -2
- Twig/lib/Twig/Node/SandboxedPrint.php +1 -2
- Twig/lib/Twig/Node/Set.php +1 -2
- Twig/lib/Twig/Node/Spaceless.php +1 -2
- Twig/lib/Twig/Node/Text.php +1 -2
- Twig/lib/Twig/NodeInterface.php +1 -2
- Twig/lib/Twig/NodeOutputInterface.php +1 -2
- Twig/lib/Twig/NodeTraverser.php +1 -2
- Twig/lib/Twig/NodeVisitor/Escaper.php +1 -2
- Twig/lib/Twig/NodeVisitor/Optimizer.php +1 -2
- Twig/lib/Twig/NodeVisitor/SafeAnalysis.php +0 -2
- Twig/lib/Twig/NodeVisitor/Sandbox.php +1 -2
- Twig/lib/Twig/NodeVisitorInterface.php +2 -3
- Twig/lib/Twig/Parser.php +1 -2
- Twig/lib/Twig/ParserInterface.php +1 -2
- Twig/lib/Twig/Sandbox/SecurityError.php +1 -2
- Twig/lib/Twig/Sandbox/SecurityPolicy.php +1 -2
- Twig/lib/Twig/Sandbox/SecurityPolicyInterface.php +1 -2
- Twig/lib/Twig/SimpleFilter.php +1 -4
- Twig/lib/Twig/SimpleFunction.php +1 -2
- Twig/lib/Twig/SimpleTest.php +1 -2
- Twig/lib/Twig/Template.php +16 -15
- Twig/lib/Twig/TemplateInterface.php +1 -2
- Twig/lib/Twig/Test.php +1 -2
- Twig/lib/Twig/Test/Function.php +1 -2
- Twig/lib/Twig/Test/IntegrationTestCase.php +2 -3
- Twig/lib/Twig/Test/Method.php +1 -2
- Twig/lib/Twig/Test/Node.php +1 -2
- Twig/lib/Twig/TestCallableInterface.php +1 -2
- Twig/lib/Twig/TestInterface.php +1 -2
- Twig/lib/Twig/Token.php +1 -2
- Twig/lib/Twig/TokenParser.php +1 -2
- Twig/lib/Twig/TokenParser/Do.php +1 -1
- Twig/lib/Twig/TokenParser/Extends.php +0 -2
- Twig/lib/Twig/TokenParser/Macro.php +0 -2
- Twig/lib/Twig/TokenParser/Set.php +1 -1
- Twig/lib/Twig/TokenParser/Use.php +0 -2
- Twig/lib/Twig/TokenParserBroker.php +1 -4
- Twig/lib/Twig/TokenParserBrokerInterface.php +1 -2
- Twig/lib/Twig/TokenParserInterface.php +1 -2
- Twig/lib/Twig/TokenStream.php +1 -2
- Twig/phpunit.xml.dist +0 -25
- Twig/test/Twig/Tests/AutoloaderTest.php +0 -21
- Twig/test/Twig/Tests/CompilerTest.php +0 -33
- Twig/test/Twig/Tests/EnvironmentTest.php +0 -272
- Twig/test/Twig/Tests/ErrorTest.php +0 -159
- Twig/test/Twig/Tests/ExpressionParserTest.php +0 -332
- Twig/test/Twig/Tests/Extension/CoreTest.php +0 -115
- Twig/test/Twig/Tests/Extension/SandboxTest.php +0 -212
- Twig/test/Twig/Tests/FileCachingTest.php +0 -70
- Twig/test/Twig/Tests/Fixtures/errors/base.html +0 -1
- Twig/test/Twig/Tests/Fixtures/errors/index.html +0 -7
- Twig/test/Twig/Tests/Fixtures/exceptions/unclosed_tag.test +0 -20
- Twig/test/Twig/Tests/Fixtures/expressions/array.test +0 -61
- Twig/test/Twig/Tests/Fixtures/expressions/array_call.test +0 -14
- Twig/test/Twig/Tests/Fixtures/expressions/binary.test +0 -46
- Twig/test/Twig/Tests/Fixtures/expressions/bitwise.test +0 -14
- Twig/test/Twig/Tests/Fixtures/expressions/comparison.test +0 -14
- Twig/test/Twig/Tests/Fixtures/expressions/dotdot.test +0 -20
- Twig/test/Twig/Tests/Fixtures/expressions/grouping.test +0 -8
- Twig/test/Twig/Tests/Fixtures/expressions/literals.test +0 -22
- Twig/test/Twig/Tests/Fixtures/expressions/magic_call.test +0 -27
- Twig/test/Twig/Tests/Fixtures/expressions/method_call.test +0 -28
- Twig/test/Twig/Tests/Fixtures/expressions/postfix.test +0 -22
- Twig/test/Twig/Tests/Fixtures/expressions/strings.test +0 -10
- Twig/test/Twig/Tests/Fixtures/expressions/ternary_operator.test +0 -18
- Twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_noelse.test +0 -10
- Twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_nothen.test +0 -10
- Twig/test/Twig/Tests/Fixtures/expressions/unary.test +0 -12
- Twig/test/Twig/Tests/Fixtures/expressions/unary_precedence.test +0 -14
- Twig/test/Twig/Tests/Fixtures/filters/abs.test +0 -30
- Twig/test/Twig/Tests/Fixtures/filters/convert_encoding.test +0 -10
- Twig/test/Twig/Tests/Fixtures/filters/date.test +0 -61
- Twig/test/Twig/Tests/Fixtures/filters/date_default_format.test +0 -14
- Twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test +0 -16
- Twig/test/Twig/Tests/Fixtures/filters/date_interval.test +0 -19
- Twig/test/Twig/Tests/Fixtures/filters/date_modify.test +0 -14
- Twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test +0 -15
- Twig/test/Twig/Tests/Fixtures/filters/default.test +0 -150
- Twig/test/Twig/Tests/Fixtures/filters/dynamic_filter.test +0 -10
- Twig/test/Twig/Tests/Fixtures/filters/escape.test +0 -8
- Twig/test/Twig/Tests/Fixtures/filters/escape_non_supported_charset.test +0 -8
- Twig/test/Twig/Tests/Fixtures/filters/force_escape.test +0 -18
- Twig/test/Twig/Tests/Fixtures/filters/format.test +0 -8
- Twig/test/Twig/Tests/Fixtures/filters/join.test +0 -12
- Twig/test/Twig/Tests/Fixtures/filters/json_encode.test +0 -12
- Twig/test/Twig/Tests/Fixtures/filters/length.test +0 -14
- Twig/test/Twig/Tests/Fixtures/filters/length_utf8.test +0 -12
- Twig/test/Twig/Tests/Fixtures/filters/merge.test +0 -16
- Twig/test/Twig/Tests/Fixtures/filters/nl2br.test +0 -14
- Twig/test/Twig/Tests/Fixtures/filters/number_format.test +0 -18
- Twig/test/Twig/Tests/Fixtures/filters/number_format_default.test +0 -21
- Twig/test/Twig/Tests/Fixtures/filters/replace.test +0 -8
- Twig/test/Twig/Tests/Fixtures/filters/reverse.test +0 -18
- Twig/test/Twig/Tests/Fixtures/filters/slice.test +0 -42
- Twig/test/Twig/Tests/Fixtures/filters/sort.test +0 -10
- Twig/test/Twig/Tests/Fixtures/filters/special_chars.test +0 -8
- Twig/test/Twig/Tests/Fixtures/filters/split.test +0 -18
- Twig/test/Twig/Tests/Fixtures/filters/trim.test +0 -12
- Twig/test/Twig/Tests/Fixtures/functions/attribute.test +0 -12
- Twig/test/Twig/Tests/Fixtures/functions/block.test +0 -12
- Twig/test/Twig/Tests/Fixtures/functions/constant.test +0 -10
- Twig/test/Twig/Tests/Fixtures/functions/cycle.test +0 -16
- Twig/test/Twig/Tests/Fixtures/functions/date.test +0 -25
- Twig/test/Twig/Tests/Fixtures/functions/date_namedargs.test +0 -11
- Twig/test/Twig/Tests/Fixtures/functions/dump.test +0 -16
- Twig/test/Twig/Tests/Fixtures/functions/dump_array.test +0 -19
- Twig/test/Twig/Tests/Fixtures/functions/dynamic_function.test +0 -10
- Twig/test/Twig/Tests/Fixtures/functions/include/basic.test +0 -17
- Twig/test/Twig/Tests/Fixtures/functions/include/expression.test +0 -17
- Twig/test/Twig/Tests/Fixtures/functions/include/ignore_missing.test +0 -10
- Twig/test/Twig/Tests/Fixtures/functions/include/missing.test +0 -8
- Twig/test/Twig/Tests/Fixtures/functions/include/missing_nested.test +0 -16
- Twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test +0 -10
- Twig/test/Twig/Tests/Fixtures/functions/include/template_instance.test +0 -10
- Twig/test/Twig/Tests/Fixtures/functions/include/templates_as_array.test +0 -12
- Twig/test/Twig/Tests/Fixtures/functions/include/with_context.test +0 -16
- Twig/test/Twig/Tests/Fixtures/functions/include/with_variables.test +0 -12
- Twig/test/Twig/Tests/Fixtures/functions/range.test +0 -8
- Twig/test/Twig/Tests/Fixtures/functions/special_chars.test +0 -8
- Twig/test/Twig/Tests/Fixtures/functions/template_from_string.test +0 -11
- Twig/test/Twig/Tests/Fixtures/macros/default_values.test +0 -16
- Twig/test/Twig/Tests/Fixtures/macros/nested_calls.test +0 -18
- Twig/test/Twig/Tests/Fixtures/macros/reserved_variables.test +0 -14
- Twig/test/Twig/Tests/Fixtures/macros/simple.test +0 -22
- Twig/test/Twig/Tests/Fixtures/macros/with_filters.test +0 -14
- Twig/test/Twig/Tests/Fixtures/regression/empty_token.test +0 -8
- Twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test +0 -17
- Twig/test/Twig/Tests/Fixtures/regression/strings_like_numbers.test +0 -8
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/basic.test +0 -26
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/blocks.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/double_escaping.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/functions.test +0 -83
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/literal.test +0 -45
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/nested.test +0 -26
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/objects.test +0 -26
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/raw.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.test +0 -17
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/type.test +0 -69
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters.test +0 -131
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters_arguments.test +0 -23
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_pre_escape_filters.test +0 -68
- Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test +0 -50
- Twig/test/Twig/Tests/Fixtures/tags/block/basic.test +0 -11
- Twig/test/Twig/Tests/Fixtures/tags/block/block_unique_name.test +0 -11
- Twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/embed/basic.test +0 -35
- Twig/test/Twig/Tests/Fixtures/tags/embed/multiple.test +0 -50
- Twig/test/Twig/Tests/Fixtures/tags/embed/nested.test +0 -42
- Twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test +0 -57
- Twig/test/Twig/Tests/Fixtures/tags/filter/basic.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/filter/json_encode.test +0 -8
- Twig/test/Twig/Tests/Fixtures/tags/filter/multiple.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/filter/nested.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/filter/with_for_tag.test +0 -13
- Twig/test/Twig/Tests/Fixtures/tags/filter/with_if_tag.test +0 -29
- Twig/test/Twig/Tests/Fixtures/tags/for/condition.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/for/context.test +0 -18
- Twig/test/Twig/Tests/Fixtures/tags/for/else.test +0 -23
- Twig/test/Twig/Tests/Fixtures/tags/for/inner_variables.test +0 -17
- Twig/test/Twig/Tests/Fixtures/tags/for/keys.test +0 -11
- Twig/test/Twig/Tests/Fixtures/tags/for/keys_and_values.test +0 -11
- Twig/test/Twig/Tests/Fixtures/tags/for/loop_context.test +0 -19
- Twig/test/Twig/Tests/Fixtures/tags/for/loop_context_local.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined_cond.test +0 -9
- Twig/test/Twig/Tests/Fixtures/tags/for/nested_else.test +0 -17
- Twig/test/Twig/Tests/Fixtures/tags/for/objects.test +0 -43
- Twig/test/Twig/Tests/Fixtures/tags/for/objects_countable.test +0 -47
- Twig/test/Twig/Tests/Fixtures/tags/for/recursive.test +0 -18
- Twig/test/Twig/Tests/Fixtures/tags/for/values.test +0 -11
- Twig/test/Twig/Tests/Fixtures/tags/from.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/if/basic.test +0 -22
- Twig/test/Twig/Tests/Fixtures/tags/if/expression.test +0 -22
- Twig/test/Twig/Tests/Fixtures/tags/include/basic.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/include/expression.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/include/ignore_missing.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/include/missing.test +0 -8
- Twig/test/Twig/Tests/Fixtures/tags/include/missing_nested.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/include/only.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/include/template_instance.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/include/templates_as_array.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/include/with_variables.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/basic.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/conditional.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/dynamic.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/empty.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks.test +0 -22
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test +0 -15
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_inheritance.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_change.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_in_a_block.test +0 -8
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_isolation.test +0 -20
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_nested.test +0 -28
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends.test +0 -8
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/template_instance.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/inheritance/use.test +0 -44
- Twig/test/Twig/Tests/Fixtures/tags/macro/basic.test +0 -17
- Twig/test/Twig/Tests/Fixtures/tags/macro/endmacro_name.test +0 -16
- Twig/test/Twig/Tests/Fixtures/tags/macro/external.test +0 -17
- Twig/test/Twig/Tests/Fixtures/tags/macro/from.test +0 -18
- Twig/test/Twig/Tests/Fixtures/tags/macro/global.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/macro/self_import.test +0 -17
- Twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/raw/basic.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/raw/mixed_usage_with_raw.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/raw/whitespace_control.test +0 -56
- Twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid1.test +0 -11
- Twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid2.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tags/sandbox/simple.test +0 -22
- Twig/test/Twig/Tests/Fixtures/tags/set/basic.test +0 -20
- Twig/test/Twig/Tests/Fixtures/tags/set/capture-empty.test +0 -9
- Twig/test/Twig/Tests/Fixtures/tags/set/capture.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/set/expression.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/spaceless/simple.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/special_chars.test +0 -8
- Twig/test/Twig/Tests/Fixtures/tags/trim_block.test +0 -74
- Twig/test/Twig/Tests/Fixtures/tags/use/aliases.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/use/basic.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tags/use/deep.test +0 -22
- Twig/test/Twig/Tests/Fixtures/tags/use/deep_empty.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/use/multiple.test +0 -21
- Twig/test/Twig/Tests/Fixtures/tags/use/multiple_aliases.test +0 -23
- Twig/test/Twig/Tests/Fixtures/tags/verbatim/basic.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test +0 -10
- Twig/test/Twig/Tests/Fixtures/tags/verbatim/whitespace_control.test +0 -56
- Twig/test/Twig/Tests/Fixtures/tests/array.test +0 -24
- Twig/test/Twig/Tests/Fixtures/tests/constant.test +0 -12
- Twig/test/Twig/Tests/Fixtures/tests/defined.test +0 -108
- Twig/test/Twig/Tests/Fixtures/tests/empty.test +0 -45
- Twig/test/Twig/Tests/Fixtures/tests/even.test +0 -14
- Twig/test/Twig/Tests/Fixtures/tests/in.test +0 -48
- Twig/test/Twig/Tests/Fixtures/tests/in_with_objects.test +0 -19
- Twig/test/Twig/Tests/Fixtures/tests/iterable.test +0 -19
- Twig/test/Twig/Tests/Fixtures/tests/odd.test +0 -10
- Twig/test/Twig/Tests/IntegrationTest.php +0 -217
- Twig/test/Twig/Tests/LexerTest.php +0 -249
- Twig/test/Twig/Tests/Loader/ArrayTest.php +0 -97
- Twig/test/Twig/Tests/Loader/ChainTest.php +0 -63
- Twig/test/Twig/Tests/Loader/FilesystemTest.php +0 -90
- Twig/test/Twig/Tests/Loader/Fixtures/named/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/named_bis/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/named_final/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/named_ter/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/normal/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/normal_bis/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/normal_final/index.html +0 -1
- Twig/test/Twig/Tests/Loader/Fixtures/normal_ter/index.html +0 -1
- Twig/test/Twig/Tests/NativeExtensionTest.php +0 -29
- Twig/test/Twig/Tests/Node/AutoEscapeTest.php +0 -44
- Twig/test/Twig/Tests/Node/BlockReferenceTest.php +0 -43
- Twig/test/Twig/Tests/Node/BlockTest.php +0 -51
- Twig/test/Twig/Tests/Node/DoTest.php +0 -44
- Twig/test/Twig/Tests/Node/Expression/ArrayTest.php +0 -49
- Twig/test/Twig/Tests/Node/Expression/AssignNameTest.php +0 -41
- Twig/test/Twig/Tests/Node/Expression/Binary/AddTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/AndTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/ConcatTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/DivTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/FloorDivTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/ModTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/MulTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/OrTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/Binary/SubTest.php +0 -47
- Twig/test/Twig/Tests/Node/Expression/ConditionalTest.php +0 -50
- Twig/test/Twig/Tests/Node/Expression/ConstantTest.php +0 -42
- Twig/test/Twig/Tests/Node/Expression/FilterTest.php +0 -133
- Twig/test/Twig/Tests/Node/Expression/FunctionTest.php +0 -99
- Twig/test/Twig/Tests/Node/Expression/GetAttrTest.php +0 -62
- Twig/test/Twig/Tests/Node/Expression/NameTest.php +0 -49
- Twig/test/Twig/Tests/Node/Expression/PHP53/FilterInclude.php +0 -6
- Twig/test/Twig/Tests/Node/Expression/PHP53/FunctionInclude.php +0 -6
- Twig/test/Twig/Tests/Node/Expression/PHP53/TestInclude.php +0 -6
- Twig/test/Twig/Tests/Node/Expression/ParentTest.php +0 -40
- Twig/test/Twig/Tests/Node/Expression/TestTest.php +0 -68
- Twig/test/Twig/Tests/Node/Expression/Unary/NegTest.php +0 -44
- Twig/test/Twig/Tests/Node/Expression/Unary/NotTest.php +0 -44
- Twig/test/Twig/Tests/Node/Expression/Unary/PosTest.php +0 -44
- Twig/test/Twig/Tests/Node/ForTest.php +0 -203
- Twig/test/Twig/Tests/Node/IfTest.php +0 -100
- Twig/test/Twig/Tests/Node/ImportTest.php +0 -52
- Twig/test/Twig/Tests/Node/IncludeTest.php +0 -96
- Twig/test/Twig/Tests/Node/MacroTest.php +0 -73
- Twig/test/Twig/Tests/Node/ModuleTest.php +0 -196
- Twig/test/Twig/Tests/Node/PrintTest.php +0 -41
- Twig/test/Twig/Tests/Node/SandboxTest.php +0 -56
- Twig/test/Twig/Tests/Node/SandboxedModuleTest.php +0 -173
- Twig/test/Twig/Tests/Node/SandboxedPrintTest.php +0 -45
- Twig/test/Twig/Tests/Node/SetTest.php +0 -81
- Twig/test/Twig/Tests/Node/SpacelessTest.php +0 -49
- Twig/test/Twig/Tests/Node/TextTest.php +0 -40
- Twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php +0 -114
- Twig/test/Twig/Tests/ParserTest.php +0 -180
- Twig/test/Twig/Tests/TemplateTest.php +0 -556
- Twig/test/Twig/Tests/TokenStreamTest.php +0 -70
- Twig/test/Twig/Tests/escapingTest.php +0 -320
- Twig/test/bootstrap.php +0 -13
- admin/timber-admin.css +0 -23
- admin/timber-admin.php +0 -33
- admin/timber-admin.twig +0 -19
- admin/timber-menu.png +0 -0
- admin/timber-menu.psd +0 -0
- functions/functions-wp-helper.php +9 -0
- readme.txt +10 -4
- timber-starter-theme/views/html-header.twig +1 -1
- timber.php +9 -7
Twig/.editorconfig
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
; top-most EditorConfig file
|
2 |
-
root = true
|
3 |
-
|
4 |
-
; Unix-style newlines
|
5 |
-
[*]
|
6 |
-
end_of_line = LF
|
7 |
-
|
8 |
-
[*.php]
|
9 |
-
indent_style = space
|
10 |
-
indent_size = 4
|
11 |
-
|
12 |
-
[*.test]
|
13 |
-
indent_style = space
|
14 |
-
indent_size = 4
|
15 |
-
|
16 |
-
[*.rst]
|
17 |
-
indent_style = space
|
18 |
-
indent_size = 4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/.gitignore
DELETED
@@ -1,2 +0,0 @@
|
|
1 |
-
/ext/twig/autom4te.cache/
|
2 |
-
|
|
|
|
Twig/.travis.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
language: php
|
2 |
-
|
3 |
-
php:
|
4 |
-
- 5.2
|
5 |
-
- 5.3
|
6 |
-
- 5.4
|
7 |
-
|
8 |
-
env:
|
9 |
-
- TWIG_EXT=no
|
10 |
-
- TWIG_EXT=yes
|
11 |
-
|
12 |
-
before_script:
|
13 |
-
- if [ "$TWIG_EXT" == "yes" ]; then sh -c "cd ext/twig && phpize && ./configure --enable-twig && make && sudo make install"; fi
|
14 |
-
- if [ "$TWIG_EXT" == "yes" ]; then echo "extension=twig.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/CHANGELOG
CHANGED
@@ -1,6 +1,33 @@
|
|
1 |
-
* 1.
|
2 |
|
3 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
* 1.12.1 (2013-01-15)
|
6 |
|
@@ -379,7 +406,7 @@ Changes:
|
|
379 |
* enhanced error messages when an unexpected token is parsed in an expression
|
380 |
* fixed filename not being added to syntax error messages
|
381 |
* added the autoescape option to enable/disable autoescaping
|
382 |
-
* removed the newline after a comment (
|
383 |
* added a syntax error exception when parent block is used on a template that does not extend another one
|
384 |
* made the Escaper extension enabled by default
|
385 |
* fixed sandbox extension when used with auto output escaping
|
1 |
+
* 1.13.1 (2013-06-06)
|
2 |
|
3 |
+
* added the possibility to ignore the filesystem constructor argument in Twig_Loader_Filesystem
|
4 |
+
* fixed Twig_Loader_Chain::exists() for a loader which implements Twig_ExistsLoaderInterface
|
5 |
+
* adjusted backtrace call to reduce memory usage when an error occurs
|
6 |
+
* added support for object instances as the second argument of the constant test
|
7 |
+
* fixed the include function when used in an assignment
|
8 |
+
|
9 |
+
* 1.13.0 (2013-05-10)
|
10 |
+
|
11 |
+
* fixed getting a numeric-like item on a variable ('09' for instance)
|
12 |
+
* fixed getting a boolean or float key on an array, so it is consistent with PHP's array access:
|
13 |
+
`{{ array[false] }}` behaves the same as `echo $array[false];` (equals `$array[0]`)
|
14 |
+
* made the escape filter 20% faster for happy path (escaping string for html with UTF-8)
|
15 |
+
* changed ☃ to § in tests
|
16 |
+
* enforced usage of named arguments after positional ones
|
17 |
+
|
18 |
+
* 1.12.3 (2013-04-08)
|
19 |
+
|
20 |
+
* fixed a security issue in the filesystem loader where it was possible to include a template one
|
21 |
+
level above the configured path
|
22 |
+
* fixed fatal error that should be an exception when adding a filter/function/test too late
|
23 |
+
* added a batch filter
|
24 |
+
* added support for encoding an array as query string in the url_encode filter
|
25 |
+
|
26 |
+
* 1.12.2 (2013-02-09)
|
27 |
+
|
28 |
+
* fixed the timezone used by the date filter and function when the given date contains a timezone (like 2010-01-28T15:00:00+02:00)
|
29 |
+
* fixed globals when getGlobals is called early on
|
30 |
+
* added the first and last filter
|
31 |
|
32 |
* 1.12.1 (2013-01-15)
|
33 |
|
406 |
* enhanced error messages when an unexpected token is parsed in an expression
|
407 |
* fixed filename not being added to syntax error messages
|
408 |
* added the autoescape option to enable/disable autoescaping
|
409 |
+
* removed the newline after a comment (mimics PHP behavior)
|
410 |
* added a syntax error exception when parent block is used on a template that does not extend another one
|
411 |
* made the Escaper extension enabled by default
|
412 |
* fixed sandbox extension when used with auto output escaping
|
Twig/composer.json
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "twig/twig",
|
3 |
-
"type": "library",
|
4 |
-
"description": "Twig, the flexible, fast, and secure template language for PHP",
|
5 |
-
"keywords": ["templating"],
|
6 |
-
"homepage": "http://twig.sensiolabs.org",
|
7 |
-
"license": "BSD-3",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Fabien Potencier",
|
11 |
-
"email": "fabien@symfony.com"
|
12 |
-
},
|
13 |
-
{
|
14 |
-
"name": "Armin Ronacher",
|
15 |
-
"email": "armin.ronacher@active-4.com"
|
16 |
-
}
|
17 |
-
],
|
18 |
-
"require": {
|
19 |
-
"php": ">=5.2.4"
|
20 |
-
},
|
21 |
-
"autoload": {
|
22 |
-
"psr-0" : {
|
23 |
-
"Twig_" : "lib/"
|
24 |
-
}
|
25 |
-
},
|
26 |
-
"extra": {
|
27 |
-
"branch-alias": {
|
28 |
-
"dev-master": "1.12-dev"
|
29 |
-
}
|
30 |
-
}
|
31 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/advanced.rst
DELETED
@@ -1,776 +0,0 @@
|
|
1 |
-
Extending Twig
|
2 |
-
==============
|
3 |
-
|
4 |
-
.. caution::
|
5 |
-
|
6 |
-
This section describes how to extend Twig as of **Twig 1.12**. If you are
|
7 |
-
using an older version, read the :doc:`legacy<advanced_legacy>` chapter
|
8 |
-
instead.
|
9 |
-
|
10 |
-
Twig can be extended in many ways; you can add extra tags, filters, tests,
|
11 |
-
operators, global variables, and functions. You can even extend the parser
|
12 |
-
itself with node visitors.
|
13 |
-
|
14 |
-
.. note::
|
15 |
-
|
16 |
-
The first section of this chapter describes how to extend Twig easily. If
|
17 |
-
you want to reuse your changes in different projects or if you want to
|
18 |
-
share them with others, you should then create an extension as described
|
19 |
-
in the following section.
|
20 |
-
|
21 |
-
.. caution::
|
22 |
-
|
23 |
-
When extending Twig without creating an extension, Twig won't be able to
|
24 |
-
recompile your templates when the PHP code is updated. To see your changes
|
25 |
-
in real-time, either disable template caching or package your code into an
|
26 |
-
extension (see the next section of this chapter).
|
27 |
-
|
28 |
-
Before extending Twig, you must understand the differences between all the
|
29 |
-
different possible extension points and when to use them.
|
30 |
-
|
31 |
-
First, remember that Twig has two main language constructs:
|
32 |
-
|
33 |
-
* ``{{ }}``: used to print the result of an expression evaluation;
|
34 |
-
|
35 |
-
* ``{% %}``: used to execute statements.
|
36 |
-
|
37 |
-
To understand why Twig exposes so many extension points, let's see how to
|
38 |
-
implement a *Lorem ipsum* generator (it needs to know the number of words to
|
39 |
-
generate).
|
40 |
-
|
41 |
-
You can use a ``lipsum`` *tag*:
|
42 |
-
|
43 |
-
.. code-block:: jinja
|
44 |
-
|
45 |
-
{% lipsum 40 %}
|
46 |
-
|
47 |
-
That works, but using a tag for ``lipsum`` is not a good idea for at least
|
48 |
-
three main reasons:
|
49 |
-
|
50 |
-
* ``lipsum`` is not a language construct;
|
51 |
-
* The tag outputs something;
|
52 |
-
* The tag is not flexible as you cannot use it in an expression:
|
53 |
-
|
54 |
-
.. code-block:: jinja
|
55 |
-
|
56 |
-
{{ 'some text' ~ {% lipsum 40 %} ~ 'some more text' }}
|
57 |
-
|
58 |
-
In fact, you rarely need to create tags; and that's good news because tags are
|
59 |
-
the most complex extension point of Twig.
|
60 |
-
|
61 |
-
Now, let's use a ``lipsum`` *filter*:
|
62 |
-
|
63 |
-
.. code-block:: jinja
|
64 |
-
|
65 |
-
{{ 40|lipsum }}
|
66 |
-
|
67 |
-
Again, it works, but it looks weird. A filter transforms the passed value to
|
68 |
-
something else but here we use the value to indicate the number of words to
|
69 |
-
generate (so, ``40`` is an argument of the filter, not the value we want to
|
70 |
-
transform).
|
71 |
-
|
72 |
-
Next, let's use a ``lipsum`` *function*:
|
73 |
-
|
74 |
-
.. code-block:: jinja
|
75 |
-
|
76 |
-
{{ lipsum(40) }}
|
77 |
-
|
78 |
-
Here we go. For this specific example, the creation of a function is the
|
79 |
-
extension point to use. And you can use it anywhere an expression is accepted:
|
80 |
-
|
81 |
-
.. code-block:: jinja
|
82 |
-
|
83 |
-
{{ 'some text' ~ lipsum(40) ~ 'some more text' }}
|
84 |
-
|
85 |
-
{% set lipsum = lipsum(40) %}
|
86 |
-
|
87 |
-
Last but not the least, you can also use a *global* object with a method able
|
88 |
-
to generate lorem ipsum text:
|
89 |
-
|
90 |
-
.. code-block:: jinja
|
91 |
-
|
92 |
-
{{ text.lipsum(40) }}
|
93 |
-
|
94 |
-
As a rule of thumb, use functions for frequently used features and global
|
95 |
-
objects for everything else.
|
96 |
-
|
97 |
-
Keep in mind the following when you want to extend Twig:
|
98 |
-
|
99 |
-
========== ========================== ========== =========================
|
100 |
-
What? Implementation difficulty? How often? When?
|
101 |
-
========== ========================== ========== =========================
|
102 |
-
*macro* trivial frequent Content generation
|
103 |
-
*global* trivial frequent Helper object
|
104 |
-
*function* trivial frequent Content generation
|
105 |
-
*filter* trivial frequent Value transformation
|
106 |
-
*tag* complex rare DSL language construct
|
107 |
-
*test* trivial rare Boolean decision
|
108 |
-
*operator* trivial rare Values transformation
|
109 |
-
========== ========================== ========== =========================
|
110 |
-
|
111 |
-
Globals
|
112 |
-
-------
|
113 |
-
|
114 |
-
A global variable is like any other template variable, except that it's
|
115 |
-
available in all templates and macros::
|
116 |
-
|
117 |
-
$twig = new Twig_Environment($loader);
|
118 |
-
$twig->addGlobal('text', new Text());
|
119 |
-
|
120 |
-
You can then use the ``text`` variable anywhere in a template:
|
121 |
-
|
122 |
-
.. code-block:: jinja
|
123 |
-
|
124 |
-
{{ text.lipsum(40) }}
|
125 |
-
|
126 |
-
Filters
|
127 |
-
-------
|
128 |
-
|
129 |
-
Creating a filter is as simple as associating a name with a PHP callable::
|
130 |
-
|
131 |
-
// an anonymous function
|
132 |
-
$filter = new Twig_SimpleFilter('rot13', function ($string) {
|
133 |
-
return str_rot13($string);
|
134 |
-
});
|
135 |
-
|
136 |
-
// or a simple PHP function
|
137 |
-
$filter = new Twig_SimpleFilter('rot13', 'str_rot13');
|
138 |
-
|
139 |
-
// or a class method
|
140 |
-
$filter = new Twig_SimpleFilter('rot13', array('SomeClass', 'rot13Filter'));
|
141 |
-
|
142 |
-
The first argument passed to the ``Twig_SimpleFilter`` constructor is the name
|
143 |
-
of the filter you will use in templates and the second one is the PHP callable
|
144 |
-
to associate with it.
|
145 |
-
|
146 |
-
Then, add the filter to your Twig environment::
|
147 |
-
|
148 |
-
$twig = new Twig_Environment($loader);
|
149 |
-
$twig->addFilter($filter);
|
150 |
-
|
151 |
-
And here is how to use it in a template:
|
152 |
-
|
153 |
-
.. code-block:: jinja
|
154 |
-
|
155 |
-
{{ 'Twig'|rot13 }}
|
156 |
-
|
157 |
-
{# will output Gjvt #}
|
158 |
-
|
159 |
-
When called by Twig, the PHP callable receives the left side of the filter
|
160 |
-
(before the pipe ``|``) as the first argument and the extra arguments passed
|
161 |
-
to the filter (within parentheses ``()``) as extra arguments.
|
162 |
-
|
163 |
-
For instance, the following code:
|
164 |
-
|
165 |
-
.. code-block:: jinja
|
166 |
-
|
167 |
-
{{ 'TWIG'|lower }}
|
168 |
-
{{ now|date('d/m/Y') }}
|
169 |
-
|
170 |
-
is compiled to something like the following::
|
171 |
-
|
172 |
-
<?php echo strtolower('TWIG') ?>
|
173 |
-
<?php echo twig_date_format_filter($now, 'd/m/Y') ?>
|
174 |
-
|
175 |
-
The ``Twig_SimpleFilter`` class takes an array of options as its last
|
176 |
-
argument::
|
177 |
-
|
178 |
-
$filter = new Twig_SimpleFilter('rot13', 'str_rot13', $options);
|
179 |
-
|
180 |
-
Environment aware Filters
|
181 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~
|
182 |
-
|
183 |
-
If you want to access the current environment instance in your filter, set the
|
184 |
-
``needs_environment`` option to ``true``; Twig will pass the current
|
185 |
-
environment as the first argument to the filter call::
|
186 |
-
|
187 |
-
$filter = new Twig_SimpleFilter('rot13', function (Twig_Environment $env, $string) {
|
188 |
-
// get the current charset for instance
|
189 |
-
$charset = $env->getCharset();
|
190 |
-
|
191 |
-
return str_rot13($string);
|
192 |
-
}, array('needs_environment' => true));
|
193 |
-
|
194 |
-
Context aware Filters
|
195 |
-
~~~~~~~~~~~~~~~~~~~~~
|
196 |
-
|
197 |
-
If you want to access the current context in your filter, set the
|
198 |
-
``needs_context`` option to ``true``; Twig will pass the current context as
|
199 |
-
the first argument to the filter call (or the second one if
|
200 |
-
``needs_environment`` is also set to ``true``)::
|
201 |
-
|
202 |
-
$filter = new Twig_SimpleFilter('rot13', function ($context, $string) {
|
203 |
-
// ...
|
204 |
-
}, array('needs_context' => true));
|
205 |
-
|
206 |
-
$filter = new Twig_SimpleFilter('rot13', function (Twig_Environment $env, $context, $string) {
|
207 |
-
// ...
|
208 |
-
}, array('needs_context' => true, 'needs_environment' => true));
|
209 |
-
|
210 |
-
Automatic Escaping
|
211 |
-
~~~~~~~~~~~~~~~~~~
|
212 |
-
|
213 |
-
If automatic escaping is enabled, the output of the filter may be escaped
|
214 |
-
before printing. If your filter acts as an escaper (or explicitly outputs html
|
215 |
-
or JavaScript code), you will want the raw output to be printed. In such a
|
216 |
-
case, set the ``is_safe`` option::
|
217 |
-
|
218 |
-
$filter = new Twig_SimpleFilter('nl2br', 'nl2br', array('is_safe' => array('html')));
|
219 |
-
|
220 |
-
Some filters may need to work on input that is already escaped or safe, for
|
221 |
-
example when adding (safe) html tags to originally unsafe output. In such a
|
222 |
-
case, set the ``pre_escape`` option to escape the input data before it is run
|
223 |
-
through your filter::
|
224 |
-
|
225 |
-
$filter = new Twig_SimpleFilter('somefilter', 'somefilter', array('pre_escape' => 'html', 'is_safe' => array('html')));
|
226 |
-
|
227 |
-
Dynamic Filters
|
228 |
-
~~~~~~~~~~~~~~~
|
229 |
-
|
230 |
-
A filter name containing the special ``*`` character is a dynamic filter as
|
231 |
-
the ``*`` can be any string::
|
232 |
-
|
233 |
-
$filter = new Twig_SimpleFilter('*_path', function ($name, $arguments) {
|
234 |
-
// ...
|
235 |
-
});
|
236 |
-
|
237 |
-
The following filters will be matched by the above defined dynamic filter:
|
238 |
-
|
239 |
-
* ``product_path``
|
240 |
-
* ``category_path``
|
241 |
-
|
242 |
-
A dynamic filter can define more than one dynamic parts::
|
243 |
-
|
244 |
-
$filter = new Twig_SimpleFilter('*_path', function ($name, $suffix, $arguments) {
|
245 |
-
// ...
|
246 |
-
});
|
247 |
-
|
248 |
-
The filter will receive all dynamic part values before the normal filters
|
249 |
-
arguments, but after the environment and the context. For instance, a call to
|
250 |
-
``'foo'|a_path_b()`` will result in the following arguments to be passed to
|
251 |
-
the filter: ``('a', 'b', 'foo')``.
|
252 |
-
|
253 |
-
Functions
|
254 |
-
---------
|
255 |
-
|
256 |
-
Functions are defined in the exact same way as filters, but you need to create
|
257 |
-
an instance of ``Twig_SimpleFunction``::
|
258 |
-
|
259 |
-
$twig = new Twig_Environment($loader);
|
260 |
-
$function = new Twig_SimpleFunction('function_name', function () {
|
261 |
-
// ...
|
262 |
-
});
|
263 |
-
$twig->addFunction($function);
|
264 |
-
|
265 |
-
Functions support the same features as filters, except for the ``pre_escape``
|
266 |
-
and ``preserves_safety`` options.
|
267 |
-
|
268 |
-
Tests
|
269 |
-
-----
|
270 |
-
|
271 |
-
Tests are defined in the exact same way as filters and functions, but you need
|
272 |
-
to create an instance of ``Twig_SimpleTest``::
|
273 |
-
|
274 |
-
$twig = new Twig_Environment($loader);
|
275 |
-
$test = new Twig_SimpleTest('test_name', function () {
|
276 |
-
// ...
|
277 |
-
});
|
278 |
-
$twig->addTest($test);
|
279 |
-
|
280 |
-
Tests do not support any options.
|
281 |
-
|
282 |
-
Tags
|
283 |
-
----
|
284 |
-
|
285 |
-
One of the most exciting feature of a template engine like Twig is the
|
286 |
-
possibility to define new language constructs. This is also the most complex
|
287 |
-
feature as you need to understand how Twig's internals work.
|
288 |
-
|
289 |
-
Let's create a simple ``set`` tag that allows the definition of simple
|
290 |
-
variables from within a template. The tag can be used like follows:
|
291 |
-
|
292 |
-
.. code-block:: jinja
|
293 |
-
|
294 |
-
{% set name = "value" %}
|
295 |
-
|
296 |
-
{{ name }}
|
297 |
-
|
298 |
-
{# should output value #}
|
299 |
-
|
300 |
-
.. note::
|
301 |
-
|
302 |
-
The ``set`` tag is part of the Core extension and as such is always
|
303 |
-
available. The built-in version is slightly more powerful and supports
|
304 |
-
multiple assignments by default (cf. the template designers chapter for
|
305 |
-
more information).
|
306 |
-
|
307 |
-
Three steps are needed to define a new tag:
|
308 |
-
|
309 |
-
* Defining a Token Parser class (responsible for parsing the template code);
|
310 |
-
|
311 |
-
* Defining a Node class (responsible for converting the parsed code to PHP);
|
312 |
-
|
313 |
-
* Registering the tag.
|
314 |
-
|
315 |
-
Registering a new tag
|
316 |
-
~~~~~~~~~~~~~~~~~~~~~
|
317 |
-
|
318 |
-
Adding a tag is as simple as calling the ``addTokenParser`` method on the
|
319 |
-
``Twig_Environment`` instance::
|
320 |
-
|
321 |
-
$twig = new Twig_Environment($loader);
|
322 |
-
$twig->addTokenParser(new Project_Set_TokenParser());
|
323 |
-
|
324 |
-
Defining a Token Parser
|
325 |
-
~~~~~~~~~~~~~~~~~~~~~~~
|
326 |
-
|
327 |
-
Now, let's see the actual code of this class::
|
328 |
-
|
329 |
-
class Project_Set_TokenParser extends Twig_TokenParser
|
330 |
-
{
|
331 |
-
public function parse(Twig_Token $token)
|
332 |
-
{
|
333 |
-
$lineno = $token->getLine();
|
334 |
-
$name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
|
335 |
-
$this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, '=');
|
336 |
-
$value = $this->parser->getExpressionParser()->parseExpression();
|
337 |
-
|
338 |
-
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
339 |
-
|
340 |
-
return new Project_Set_Node($name, $value, $lineno, $this->getTag());
|
341 |
-
}
|
342 |
-
|
343 |
-
public function getTag()
|
344 |
-
{
|
345 |
-
return 'set';
|
346 |
-
}
|
347 |
-
}
|
348 |
-
|
349 |
-
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
350 |
-
|
351 |
-
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
352 |
-
tag. It should return a ``Twig_Node`` instance that represents the node (the
|
353 |
-
``Project_Set_Node`` calls creating is explained in the next section).
|
354 |
-
|
355 |
-
The parsing process is simplified thanks to a bunch of methods you can call
|
356 |
-
from the token stream (``$this->parser->getStream()``):
|
357 |
-
|
358 |
-
* ``getCurrent()``: Gets the current token in the stream.
|
359 |
-
|
360 |
-
* ``next()``: Moves to the next token in the stream, *but returns the old one*.
|
361 |
-
|
362 |
-
* ``test($type)``, ``test($value)`` or ``test($type, $value)``: Determines whether
|
363 |
-
the current token is of a particular type or value (or both). The value may be an
|
364 |
-
array of several possible values.
|
365 |
-
|
366 |
-
* ``expect($type[, $value[, $message]])``: If the current token isn't of the given
|
367 |
-
type/value a syntax error is thrown. Otherwise, if the type and value are correct,
|
368 |
-
the token is returned and the stream moves to the next token.
|
369 |
-
|
370 |
-
* ``look()``: Looks a the next token without consuming it.
|
371 |
-
|
372 |
-
Parsing expressions is done by calling the ``parseExpression()`` like we did for
|
373 |
-
the ``set`` tag.
|
374 |
-
|
375 |
-
.. tip::
|
376 |
-
|
377 |
-
Reading the existing ``TokenParser`` classes is the best way to learn all
|
378 |
-
the nitty-gritty details of the parsing process.
|
379 |
-
|
380 |
-
Defining a Node
|
381 |
-
~~~~~~~~~~~~~~~
|
382 |
-
|
383 |
-
The ``Project_Set_Node`` class itself is rather simple::
|
384 |
-
|
385 |
-
class Project_Set_Node extends Twig_Node
|
386 |
-
{
|
387 |
-
public function __construct($name, Twig_Node_Expression $value, $lineno, $tag = null)
|
388 |
-
{
|
389 |
-
parent::__construct(array('value' => $value), array('name' => $name), $lineno, $tag);
|
390 |
-
}
|
391 |
-
|
392 |
-
public function compile(Twig_Compiler $compiler)
|
393 |
-
{
|
394 |
-
$compiler
|
395 |
-
->addDebugInfo($this)
|
396 |
-
->write('$context[\''.$this->getAttribute('name').'\'] = ')
|
397 |
-
->subcompile($this->getNode('value'))
|
398 |
-
->raw(";\n")
|
399 |
-
;
|
400 |
-
}
|
401 |
-
}
|
402 |
-
|
403 |
-
The compiler implements a fluid interface and provides methods that helps the
|
404 |
-
developer generate beautiful and readable PHP code:
|
405 |
-
|
406 |
-
* ``subcompile()``: Compiles a node.
|
407 |
-
|
408 |
-
* ``raw()``: Writes the given string as is.
|
409 |
-
|
410 |
-
* ``write()``: Writes the given string by adding indentation at the beginning
|
411 |
-
of each line.
|
412 |
-
|
413 |
-
* ``string()``: Writes a quoted string.
|
414 |
-
|
415 |
-
* ``repr()``: Writes a PHP representation of a given value (see
|
416 |
-
``Twig_Node_For`` for a usage example).
|
417 |
-
|
418 |
-
* ``addDebugInfo()``: Adds the line of the original template file related to
|
419 |
-
the current node as a comment.
|
420 |
-
|
421 |
-
* ``indent()``: Indents the generated code (see ``Twig_Node_Block`` for a
|
422 |
-
usage example).
|
423 |
-
|
424 |
-
* ``outdent()``: Outdents the generated code (see ``Twig_Node_Block`` for a
|
425 |
-
usage example).
|
426 |
-
|
427 |
-
.. _creating_extensions:
|
428 |
-
|
429 |
-
Creating an Extension
|
430 |
-
---------------------
|
431 |
-
|
432 |
-
The main motivation for writing an extension is to move often used code into a
|
433 |
-
reusable class like adding support for internationalization. An extension can
|
434 |
-
define tags, filters, tests, operators, global variables, functions, and node
|
435 |
-
visitors.
|
436 |
-
|
437 |
-
Creating an extension also makes for a better separation of code that is
|
438 |
-
executed at compilation time and code needed at runtime. As such, it makes
|
439 |
-
your code faster.
|
440 |
-
|
441 |
-
Most of the time, it is useful to create a single extension for your project,
|
442 |
-
to host all the specific tags and filters you want to add to Twig.
|
443 |
-
|
444 |
-
.. tip::
|
445 |
-
|
446 |
-
When packaging your code into an extension, Twig is smart enough to
|
447 |
-
recompile your templates whenever you make a change to it (when
|
448 |
-
``auto_reload`` is enabled).
|
449 |
-
|
450 |
-
.. note::
|
451 |
-
|
452 |
-
Before writing your own extensions, have a look at the Twig official
|
453 |
-
extension repository: http://github.com/fabpot/Twig-extensions.
|
454 |
-
|
455 |
-
An extension is a class that implements the following interface::
|
456 |
-
|
457 |
-
interface Twig_ExtensionInterface
|
458 |
-
{
|
459 |
-
/**
|
460 |
-
* Initializes the runtime environment.
|
461 |
-
*
|
462 |
-
* This is where you can load some file that contains filter functions for instance.
|
463 |
-
*
|
464 |
-
* @param Twig_Environment $environment The current Twig_Environment instance
|
465 |
-
*/
|
466 |
-
function initRuntime(Twig_Environment $environment);
|
467 |
-
|
468 |
-
/**
|
469 |
-
* Returns the token parser instances to add to the existing list.
|
470 |
-
*
|
471 |
-
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
472 |
-
*/
|
473 |
-
function getTokenParsers();
|
474 |
-
|
475 |
-
/**
|
476 |
-
* Returns the node visitor instances to add to the existing list.
|
477 |
-
*
|
478 |
-
* @return array An array of Twig_NodeVisitorInterface instances
|
479 |
-
*/
|
480 |
-
function getNodeVisitors();
|
481 |
-
|
482 |
-
/**
|
483 |
-
* Returns a list of filters to add to the existing list.
|
484 |
-
*
|
485 |
-
* @return array An array of filters
|
486 |
-
*/
|
487 |
-
function getFilters();
|
488 |
-
|
489 |
-
/**
|
490 |
-
* Returns a list of tests to add to the existing list.
|
491 |
-
*
|
492 |
-
* @return array An array of tests
|
493 |
-
*/
|
494 |
-
function getTests();
|
495 |
-
|
496 |
-
/**
|
497 |
-
* Returns a list of functions to add to the existing list.
|
498 |
-
*
|
499 |
-
* @return array An array of functions
|
500 |
-
*/
|
501 |
-
function getFunctions();
|
502 |
-
|
503 |
-
/**
|
504 |
-
* Returns a list of operators to add to the existing list.
|
505 |
-
*
|
506 |
-
* @return array An array of operators
|
507 |
-
*/
|
508 |
-
function getOperators();
|
509 |
-
|
510 |
-
/**
|
511 |
-
* Returns a list of global variables to add to the existing list.
|
512 |
-
*
|
513 |
-
* @return array An array of global variables
|
514 |
-
*/
|
515 |
-
function getGlobals();
|
516 |
-
|
517 |
-
/**
|
518 |
-
* Returns the name of the extension.
|
519 |
-
*
|
520 |
-
* @return string The extension name
|
521 |
-
*/
|
522 |
-
function getName();
|
523 |
-
}
|
524 |
-
|
525 |
-
To keep your extension class clean and lean, it can inherit from the built-in
|
526 |
-
``Twig_Extension`` class instead of implementing the whole interface. That
|
527 |
-
way, you just need to implement the ``getName()`` method as the
|
528 |
-
``Twig_Extension`` provides empty implementations for all other methods.
|
529 |
-
|
530 |
-
The ``getName()`` method must return a unique identifier for your extension.
|
531 |
-
|
532 |
-
Now, with this information in mind, let's create the most basic extension
|
533 |
-
possible::
|
534 |
-
|
535 |
-
class Project_Twig_Extension extends Twig_Extension
|
536 |
-
{
|
537 |
-
public function getName()
|
538 |
-
{
|
539 |
-
return 'project';
|
540 |
-
}
|
541 |
-
}
|
542 |
-
|
543 |
-
.. note::
|
544 |
-
|
545 |
-
Of course, this extension does nothing for now. We will customize it in
|
546 |
-
the next sections.
|
547 |
-
|
548 |
-
Twig does not care where you save your extension on the filesystem, as all
|
549 |
-
extensions must be registered explicitly to be available in your templates.
|
550 |
-
|
551 |
-
You can register an extension by using the ``addExtension()`` method on your
|
552 |
-
main ``Environment`` object::
|
553 |
-
|
554 |
-
$twig = new Twig_Environment($loader);
|
555 |
-
$twig->addExtension(new Project_Twig_Extension());
|
556 |
-
|
557 |
-
Of course, you need to first load the extension file by either using
|
558 |
-
``require_once()`` or by using an autoloader (see `spl_autoload_register()`_).
|
559 |
-
|
560 |
-
.. tip::
|
561 |
-
|
562 |
-
The bundled extensions are great examples of how extensions work.
|
563 |
-
|
564 |
-
Globals
|
565 |
-
~~~~~~~
|
566 |
-
|
567 |
-
Global variables can be registered in an extension via the ``getGlobals()``
|
568 |
-
method::
|
569 |
-
|
570 |
-
class Project_Twig_Extension extends Twig_Extension
|
571 |
-
{
|
572 |
-
public function getGlobals()
|
573 |
-
{
|
574 |
-
return array(
|
575 |
-
'text' => new Text(),
|
576 |
-
);
|
577 |
-
}
|
578 |
-
|
579 |
-
// ...
|
580 |
-
}
|
581 |
-
|
582 |
-
Functions
|
583 |
-
~~~~~~~~~
|
584 |
-
|
585 |
-
Functions can be registered in an extension via the ``getFunctions()``
|
586 |
-
method::
|
587 |
-
|
588 |
-
class Project_Twig_Extension extends Twig_Extension
|
589 |
-
{
|
590 |
-
public function getFunctions()
|
591 |
-
{
|
592 |
-
return array(
|
593 |
-
new Twig_SimpleFunction('lipsum', 'generate_lipsum'),
|
594 |
-
);
|
595 |
-
}
|
596 |
-
|
597 |
-
// ...
|
598 |
-
}
|
599 |
-
|
600 |
-
Filters
|
601 |
-
~~~~~~~
|
602 |
-
|
603 |
-
To add a filter to an extension, you need to override the ``getFilters()``
|
604 |
-
method. This method must return an array of filters to add to the Twig
|
605 |
-
environment::
|
606 |
-
|
607 |
-
class Project_Twig_Extension extends Twig_Extension
|
608 |
-
{
|
609 |
-
public function getFilters()
|
610 |
-
{
|
611 |
-
return array(
|
612 |
-
new Twig_SimpleFilter('rot13', 'str_rot13'),
|
613 |
-
);
|
614 |
-
}
|
615 |
-
|
616 |
-
// ...
|
617 |
-
}
|
618 |
-
|
619 |
-
Tags
|
620 |
-
~~~~
|
621 |
-
|
622 |
-
Adding a tag in an extension can be done by overriding the
|
623 |
-
``getTokenParsers()`` method. This method must return an array of tags to add
|
624 |
-
to the Twig environment::
|
625 |
-
|
626 |
-
class Project_Twig_Extension extends Twig_Extension
|
627 |
-
{
|
628 |
-
public function getTokenParsers()
|
629 |
-
{
|
630 |
-
return array(new Project_Set_TokenParser());
|
631 |
-
}
|
632 |
-
|
633 |
-
// ...
|
634 |
-
}
|
635 |
-
|
636 |
-
In the above code, we have added a single new tag, defined by the
|
637 |
-
``Project_Set_TokenParser`` class. The ``Project_Set_TokenParser`` class is
|
638 |
-
responsible for parsing the tag and compiling it to PHP.
|
639 |
-
|
640 |
-
Operators
|
641 |
-
~~~~~~~~~
|
642 |
-
|
643 |
-
The ``getOperators()`` methods allows to add new operators. Here is how to add
|
644 |
-
``!``, ``||``, and ``&&`` operators::
|
645 |
-
|
646 |
-
class Project_Twig_Extension extends Twig_Extension
|
647 |
-
{
|
648 |
-
public function getOperators()
|
649 |
-
{
|
650 |
-
return array(
|
651 |
-
array(
|
652 |
-
'!' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
|
653 |
-
),
|
654 |
-
array(
|
655 |
-
'||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
656 |
-
'&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
657 |
-
),
|
658 |
-
);
|
659 |
-
}
|
660 |
-
|
661 |
-
// ...
|
662 |
-
}
|
663 |
-
|
664 |
-
Tests
|
665 |
-
~~~~~
|
666 |
-
|
667 |
-
The ``getTests()`` methods allows to add new test functions::
|
668 |
-
|
669 |
-
class Project_Twig_Extension extends Twig_Extension
|
670 |
-
{
|
671 |
-
public function getTests()
|
672 |
-
{
|
673 |
-
return array(
|
674 |
-
new Twig_SimpleTest('even', 'twig_test_even'),
|
675 |
-
);
|
676 |
-
}
|
677 |
-
|
678 |
-
// ...
|
679 |
-
}
|
680 |
-
|
681 |
-
Overloading
|
682 |
-
-----------
|
683 |
-
|
684 |
-
To overload an already defined filter, test, operator, global variable, or
|
685 |
-
function, define it again **as late as possible**::
|
686 |
-
|
687 |
-
$twig = new Twig_Environment($loader);
|
688 |
-
$twig->addFilter(new Twig_SimpleFilter('date', function ($timestamp, $format = 'F j, Y H:i') {
|
689 |
-
// do something different from the built-in date filter
|
690 |
-
}));
|
691 |
-
|
692 |
-
Here, we have overloaded the built-in ``date`` filter with a custom one.
|
693 |
-
|
694 |
-
That also works with an extension::
|
695 |
-
|
696 |
-
class MyCoreExtension extends Twig_Extension
|
697 |
-
{
|
698 |
-
public function getFilters()
|
699 |
-
{
|
700 |
-
return array(
|
701 |
-
new Twig_SimpleFilter('date', array($this, 'dateFilter')),
|
702 |
-
);
|
703 |
-
}
|
704 |
-
|
705 |
-
public function dateFilter($timestamp, $format = 'F j, Y H:i')
|
706 |
-
{
|
707 |
-
// do something different from the built-in date filter
|
708 |
-
}
|
709 |
-
|
710 |
-
public function getName()
|
711 |
-
{
|
712 |
-
return 'project';
|
713 |
-
}
|
714 |
-
}
|
715 |
-
|
716 |
-
$twig = new Twig_Environment($loader);
|
717 |
-
$twig->addExtension(new MyCoreExtension());
|
718 |
-
|
719 |
-
.. caution::
|
720 |
-
|
721 |
-
Note that overloading the built-in Twig elements is not recommended as it
|
722 |
-
might be confusing.
|
723 |
-
|
724 |
-
Testing an Extension
|
725 |
-
--------------------
|
726 |
-
|
727 |
-
Functional Tests
|
728 |
-
~~~~~~~~~~~~~~~~
|
729 |
-
|
730 |
-
You can create functional tests for extensions simply by creating the
|
731 |
-
following file structure in your test directory::
|
732 |
-
|
733 |
-
Fixtures/
|
734 |
-
filters/
|
735 |
-
foo.test
|
736 |
-
bar.test
|
737 |
-
functions/
|
738 |
-
foo.test
|
739 |
-
bar.test
|
740 |
-
tags/
|
741 |
-
foo.test
|
742 |
-
bar.test
|
743 |
-
IntegrationTest.php
|
744 |
-
|
745 |
-
The ``IntegrationTest.php`` file should look like this::
|
746 |
-
|
747 |
-
class Project_Tests_IntegrationTest extends Twig_Test_IntegrationTestCase
|
748 |
-
{
|
749 |
-
public function getExtensions()
|
750 |
-
{
|
751 |
-
return array(
|
752 |
-
new Project_Twig_Extension1(),
|
753 |
-
new Project_Twig_Extension2(),
|
754 |
-
);
|
755 |
-
}
|
756 |
-
|
757 |
-
public function getFixturesDir()
|
758 |
-
{
|
759 |
-
return dirname(__FILE__).'/Fixtures/';
|
760 |
-
}
|
761 |
-
}
|
762 |
-
|
763 |
-
Fixtures examples can be found within the Twig repository
|
764 |
-
`tests/Twig/Fixtures`_ directory.
|
765 |
-
|
766 |
-
Node Tests
|
767 |
-
~~~~~~~~~~
|
768 |
-
|
769 |
-
Testing the node visitors can be complex, so extend your test cases from
|
770 |
-
``Twig_Test_NodeTestCase``. Examples can be found in the Twig repository
|
771 |
-
`tests/Twig/Node`_ directory.
|
772 |
-
|
773 |
-
.. _`spl_autoload_register()`: http://www.php.net/spl_autoload_register
|
774 |
-
.. _`rot13`: http://www.php.net/manual/en/function.str-rot13.php
|
775 |
-
.. _`tests/Twig/Fixtures`: https://github.com/fabpot/Twig/tree/master/test/Twig/Tests/Fixtures
|
776 |
-
.. _`tests/Twig/Node`: https://github.com/fabpot/Twig/tree/master/test/Twig/Tests/Node
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/advanced_legacy.rst
DELETED
@@ -1,887 +0,0 @@
|
|
1 |
-
Extending Twig
|
2 |
-
==============
|
3 |
-
|
4 |
-
.. caution::
|
5 |
-
|
6 |
-
This section describes how to extends Twig for versions **older than
|
7 |
-
1.12**. If you are using a newer version, read the :doc:`newer<advanced>`
|
8 |
-
chapter instead.
|
9 |
-
|
10 |
-
Twig can be extended in many ways; you can add extra tags, filters, tests,
|
11 |
-
operators, global variables, and functions. You can even extend the parser
|
12 |
-
itself with node visitors.
|
13 |
-
|
14 |
-
.. note::
|
15 |
-
|
16 |
-
The first section of this chapter describes how to extend Twig easily. If
|
17 |
-
you want to reuse your changes in different projects or if you want to
|
18 |
-
share them with others, you should then create an extension as described
|
19 |
-
in the following section.
|
20 |
-
|
21 |
-
.. caution::
|
22 |
-
|
23 |
-
When extending Twig by calling methods on the Twig environment instance,
|
24 |
-
Twig won't be able to recompile your templates when the PHP code is
|
25 |
-
updated. To see your changes in real-time, either disable template caching
|
26 |
-
or package your code into an extension (see the next section of this
|
27 |
-
chapter).
|
28 |
-
|
29 |
-
Before extending Twig, you must understand the differences between all the
|
30 |
-
different possible extension points and when to use them.
|
31 |
-
|
32 |
-
First, remember that Twig has two main language constructs:
|
33 |
-
|
34 |
-
* ``{{ }}``: used to print the result of an expression evaluation;
|
35 |
-
|
36 |
-
* ``{% %}``: used to execute statements.
|
37 |
-
|
38 |
-
To understand why Twig exposes so many extension points, let's see how to
|
39 |
-
implement a *Lorem ipsum* generator (it needs to know the number of words to
|
40 |
-
generate).
|
41 |
-
|
42 |
-
You can use a ``lipsum`` *tag*:
|
43 |
-
|
44 |
-
.. code-block:: jinja
|
45 |
-
|
46 |
-
{% lipsum 40 %}
|
47 |
-
|
48 |
-
That works, but using a tag for ``lipsum`` is not a good idea for at least
|
49 |
-
three main reasons:
|
50 |
-
|
51 |
-
* ``lipsum`` is not a language construct;
|
52 |
-
* The tag outputs something;
|
53 |
-
* The tag is not flexible as you cannot use it in an expression:
|
54 |
-
|
55 |
-
.. code-block:: jinja
|
56 |
-
|
57 |
-
{{ 'some text' ~ {% lipsum 40 %} ~ 'some more text' }}
|
58 |
-
|
59 |
-
In fact, you rarely need to create tags; and that's good news because tags are
|
60 |
-
the most complex extension point of Twig.
|
61 |
-
|
62 |
-
Now, let's use a ``lipsum`` *filter*:
|
63 |
-
|
64 |
-
.. code-block:: jinja
|
65 |
-
|
66 |
-
{{ 40|lipsum }}
|
67 |
-
|
68 |
-
Again, it works, but it looks weird. A filter transforms the passed value to
|
69 |
-
something else but here we use the value to indicate the number of words to
|
70 |
-
generate (so, ``40`` is an argument of the filter, not the value we want to
|
71 |
-
transform).
|
72 |
-
|
73 |
-
Next, let's use a ``lipsum`` *function*:
|
74 |
-
|
75 |
-
.. code-block:: jinja
|
76 |
-
|
77 |
-
{{ lipsum(40) }}
|
78 |
-
|
79 |
-
Here we go. For this specific example, the creation of a function is the
|
80 |
-
extension point to use. And you can use it anywhere an expression is accepted:
|
81 |
-
|
82 |
-
.. code-block:: jinja
|
83 |
-
|
84 |
-
{{ 'some text' ~ ipsum(40) ~ 'some more text' }}
|
85 |
-
|
86 |
-
{% set ipsum = ipsum(40) %}
|
87 |
-
|
88 |
-
Last but not the least, you can also use a *global* object with a method able
|
89 |
-
to generate lorem ipsum text:
|
90 |
-
|
91 |
-
.. code-block:: jinja
|
92 |
-
|
93 |
-
{{ text.lipsum(40) }}
|
94 |
-
|
95 |
-
As a rule of thumb, use functions for frequently used features and global
|
96 |
-
objects for everything else.
|
97 |
-
|
98 |
-
Keep in mind the following when you want to extend Twig:
|
99 |
-
|
100 |
-
========== ========================== ========== =========================
|
101 |
-
What? Implementation difficulty? How often? When?
|
102 |
-
========== ========================== ========== =========================
|
103 |
-
*macro* trivial frequent Content generation
|
104 |
-
*global* trivial frequent Helper object
|
105 |
-
*function* trivial frequent Content generation
|
106 |
-
*filter* trivial frequent Value transformation
|
107 |
-
*tag* complex rare DSL language construct
|
108 |
-
*test* trivial rare Boolean decision
|
109 |
-
*operator* trivial rare Values transformation
|
110 |
-
========== ========================== ========== =========================
|
111 |
-
|
112 |
-
Globals
|
113 |
-
-------
|
114 |
-
|
115 |
-
A global variable is like any other template variable, except that it's
|
116 |
-
available in all templates and macros::
|
117 |
-
|
118 |
-
$twig = new Twig_Environment($loader);
|
119 |
-
$twig->addGlobal('text', new Text());
|
120 |
-
|
121 |
-
You can then use the ``text`` variable anywhere in a template:
|
122 |
-
|
123 |
-
.. code-block:: jinja
|
124 |
-
|
125 |
-
{{ text.lipsum(40) }}
|
126 |
-
|
127 |
-
Filters
|
128 |
-
-------
|
129 |
-
|
130 |
-
A filter is a regular PHP function or an object method that takes the left
|
131 |
-
side of the filter (before the pipe ``|``) as first argument and the extra
|
132 |
-
arguments passed to the filter (within parentheses ``()``) as extra arguments.
|
133 |
-
|
134 |
-
Defining a filter is as easy as associating the filter name with a PHP
|
135 |
-
callable. For instance, let's say you have the following code in a template:
|
136 |
-
|
137 |
-
.. code-block:: jinja
|
138 |
-
|
139 |
-
{{ 'TWIG'|lower }}
|
140 |
-
|
141 |
-
When compiling this template to PHP, Twig looks for the PHP callable
|
142 |
-
associated with the ``lower`` filter. The ``lower`` filter is a built-in Twig
|
143 |
-
filter, and it is simply mapped to the PHP ``strtolower()`` function. After
|
144 |
-
compilation, the generated PHP code is roughly equivalent to:
|
145 |
-
|
146 |
-
.. code-block:: html+php
|
147 |
-
|
148 |
-
<?php echo strtolower('TWIG') ?>
|
149 |
-
|
150 |
-
As you can see, the ``'TWIG'`` string is passed as a first argument to the PHP
|
151 |
-
function.
|
152 |
-
|
153 |
-
A filter can also take extra arguments like in the following example:
|
154 |
-
|
155 |
-
.. code-block:: jinja
|
156 |
-
|
157 |
-
{{ now|date('d/m/Y') }}
|
158 |
-
|
159 |
-
In this case, the extra arguments are passed to the function after the main
|
160 |
-
argument, and the compiled code is equivalent to:
|
161 |
-
|
162 |
-
.. code-block:: html+php
|
163 |
-
|
164 |
-
<?php echo twig_date_format_filter($now, 'd/m/Y') ?>
|
165 |
-
|
166 |
-
Let's see how to create a new filter.
|
167 |
-
|
168 |
-
In this section, we will create a ``rot13`` filter, which should return the
|
169 |
-
`rot13`_ transformation of a string. Here is an example of its usage and the
|
170 |
-
expected output:
|
171 |
-
|
172 |
-
.. code-block:: jinja
|
173 |
-
|
174 |
-
{{ "Twig"|rot13 }}
|
175 |
-
|
176 |
-
{# should displays Gjvt #}
|
177 |
-
|
178 |
-
Adding a filter is as simple as calling the ``addFilter()`` method on the
|
179 |
-
``Twig_Environment`` instance::
|
180 |
-
|
181 |
-
$twig = new Twig_Environment($loader);
|
182 |
-
$twig->addFilter('rot13', new Twig_Filter_Function('str_rot13'));
|
183 |
-
|
184 |
-
The second argument of ``addFilter()`` is an instance of ``Twig_Filter``.
|
185 |
-
Here, we use ``Twig_Filter_Function`` as the filter is a PHP function. The
|
186 |
-
first argument passed to the ``Twig_Filter_Function`` constructor is the name
|
187 |
-
of the PHP function to call, here ``str_rot13``, a native PHP function.
|
188 |
-
|
189 |
-
Let's say I now want to be able to add a prefix before the converted string:
|
190 |
-
|
191 |
-
.. code-block:: jinja
|
192 |
-
|
193 |
-
{{ "Twig"|rot13('prefix_') }}
|
194 |
-
|
195 |
-
{# should displays prefix_Gjvt #}
|
196 |
-
|
197 |
-
As the PHP ``str_rot13()`` function does not support this requirement, let's
|
198 |
-
create a new PHP function::
|
199 |
-
|
200 |
-
function project_compute_rot13($string, $prefix = '')
|
201 |
-
{
|
202 |
-
return $prefix.str_rot13($string);
|
203 |
-
}
|
204 |
-
|
205 |
-
As you can see, the ``prefix`` argument of the filter is passed as an extra
|
206 |
-
argument to the ``project_compute_rot13()`` function.
|
207 |
-
|
208 |
-
Adding this filter is as easy as before::
|
209 |
-
|
210 |
-
$twig->addFilter('rot13', new Twig_Filter_Function('project_compute_rot13'));
|
211 |
-
|
212 |
-
For better encapsulation, a filter can also be defined as a static method of a
|
213 |
-
class. The ``Twig_Filter_Function`` class can also be used to register such
|
214 |
-
static methods as filters::
|
215 |
-
|
216 |
-
$twig->addFilter('rot13', new Twig_Filter_Function('SomeClass::rot13Filter'));
|
217 |
-
|
218 |
-
.. tip::
|
219 |
-
|
220 |
-
In an extension, you can also define a filter as a static method of the
|
221 |
-
extension class.
|
222 |
-
|
223 |
-
Environment aware Filters
|
224 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~
|
225 |
-
|
226 |
-
The ``Twig_Filter`` classes take options as their last argument. For instance,
|
227 |
-
if you want access to the current environment instance in your filter, set the
|
228 |
-
``needs_environment`` option to ``true``::
|
229 |
-
|
230 |
-
$filter = new Twig_Filter_Function('str_rot13', array('needs_environment' => true));
|
231 |
-
|
232 |
-
Twig will then pass the current environment as the first argument to the
|
233 |
-
filter call::
|
234 |
-
|
235 |
-
function twig_compute_rot13(Twig_Environment $env, $string)
|
236 |
-
{
|
237 |
-
// get the current charset for instance
|
238 |
-
$charset = $env->getCharset();
|
239 |
-
|
240 |
-
return str_rot13($string);
|
241 |
-
}
|
242 |
-
|
243 |
-
Automatic Escaping
|
244 |
-
~~~~~~~~~~~~~~~~~~
|
245 |
-
|
246 |
-
If automatic escaping is enabled, the output of the filter may be escaped
|
247 |
-
before printing. If your filter acts as an escaper (or explicitly outputs html
|
248 |
-
or javascript code), you will want the raw output to be printed. In such a
|
249 |
-
case, set the ``is_safe`` option::
|
250 |
-
|
251 |
-
$filter = new Twig_Filter_Function('nl2br', array('is_safe' => array('html')));
|
252 |
-
|
253 |
-
Some filters may need to work on input that is already escaped or safe, for
|
254 |
-
example when adding (safe) html tags to originally unsafe output. In such a
|
255 |
-
case, set the ``pre_escape`` option to escape the input data before it is run
|
256 |
-
through your filter::
|
257 |
-
|
258 |
-
$filter = new Twig_Filter_Function('somefilter', array('pre_escape' => 'html', 'is_safe' => array('html')));
|
259 |
-
|
260 |
-
Dynamic Filters
|
261 |
-
~~~~~~~~~~~~~~~
|
262 |
-
|
263 |
-
.. versionadded:: 1.5
|
264 |
-
Dynamic filters support was added in Twig 1.5.
|
265 |
-
|
266 |
-
A filter name containing the special ``*`` character is a dynamic filter as
|
267 |
-
the ``*`` can be any string::
|
268 |
-
|
269 |
-
$twig->addFilter('*_path', new Twig_Filter_Function('twig_path'));
|
270 |
-
|
271 |
-
function twig_path($name, $arguments)
|
272 |
-
{
|
273 |
-
// ...
|
274 |
-
}
|
275 |
-
|
276 |
-
The following filters will be matched by the above defined dynamic filter:
|
277 |
-
|
278 |
-
* ``product_path``
|
279 |
-
* ``category_path``
|
280 |
-
|
281 |
-
A dynamic filter can define more than one dynamic parts::
|
282 |
-
|
283 |
-
$twig->addFilter('*_path_*', new Twig_Filter_Function('twig_path'));
|
284 |
-
|
285 |
-
function twig_path($name, $suffix, $arguments)
|
286 |
-
{
|
287 |
-
// ...
|
288 |
-
}
|
289 |
-
|
290 |
-
The filter will receive all dynamic part values before the normal filters
|
291 |
-
arguments. For instance, a call to ``'foo'|a_path_b()`` will result in the
|
292 |
-
following PHP call: ``twig_path('a', 'b', 'foo')``.
|
293 |
-
|
294 |
-
Functions
|
295 |
-
---------
|
296 |
-
|
297 |
-
A function is a regular PHP function or an object method that can be called from
|
298 |
-
templates.
|
299 |
-
|
300 |
-
.. code-block:: jinja
|
301 |
-
|
302 |
-
{{ constant("DATE_W3C") }}
|
303 |
-
|
304 |
-
When compiling this template to PHP, Twig looks for the PHP callable
|
305 |
-
associated with the ``constant`` function. The ``constant`` function is a built-in Twig
|
306 |
-
function, and it is simply mapped to the PHP ``constant()`` function. After
|
307 |
-
compilation, the generated PHP code is roughly equivalent to:
|
308 |
-
|
309 |
-
.. code-block:: html+php
|
310 |
-
|
311 |
-
<?php echo constant('DATE_W3C') ?>
|
312 |
-
|
313 |
-
Adding a function is similar to adding a filter. This can be done by calling the
|
314 |
-
``addFunction()`` method on the ``Twig_Environment`` instance::
|
315 |
-
|
316 |
-
$twig = new Twig_Environment($loader);
|
317 |
-
$twig->addFunction('functionName', new Twig_Function_Function('someFunction'));
|
318 |
-
|
319 |
-
You can also expose extension methods as functions in your templates::
|
320 |
-
|
321 |
-
// $this is an object that implements Twig_ExtensionInterface.
|
322 |
-
$twig = new Twig_Environment($loader);
|
323 |
-
$twig->addFunction('otherFunction', new Twig_Function_Method($this, 'someMethod'));
|
324 |
-
|
325 |
-
Functions also support ``needs_environment`` and ``is_safe`` parameters.
|
326 |
-
|
327 |
-
Dynamic Functions
|
328 |
-
~~~~~~~~~~~~~~~~~
|
329 |
-
|
330 |
-
.. versionadded:: 1.5
|
331 |
-
Dynamic functions support was added in Twig 1.5.
|
332 |
-
|
333 |
-
A function name containing the special ``*`` character is a dynamic function
|
334 |
-
as the ``*`` can be any string::
|
335 |
-
|
336 |
-
$twig->addFunction('*_path', new Twig_Function_Function('twig_path'));
|
337 |
-
|
338 |
-
function twig_path($name, $arguments)
|
339 |
-
{
|
340 |
-
// ...
|
341 |
-
}
|
342 |
-
|
343 |
-
The following functions will be matched by the above defined dynamic function:
|
344 |
-
|
345 |
-
* ``product_path``
|
346 |
-
* ``category_path``
|
347 |
-
|
348 |
-
A dynamic function can define more than one dynamic parts::
|
349 |
-
|
350 |
-
$twig->addFilter('*_path_*', new Twig_Filter_Function('twig_path'));
|
351 |
-
|
352 |
-
function twig_path($name, $suffix, $arguments)
|
353 |
-
{
|
354 |
-
// ...
|
355 |
-
}
|
356 |
-
|
357 |
-
The function will receive all dynamic part values before the normal functions
|
358 |
-
arguments. For instance, a call to ``a_path_b('foo')`` will result in the
|
359 |
-
following PHP call: ``twig_path('a', 'b', 'foo')``.
|
360 |
-
|
361 |
-
Tags
|
362 |
-
----
|
363 |
-
|
364 |
-
One of the most exciting feature of a template engine like Twig is the
|
365 |
-
possibility to define new language constructs. This is also the most complex
|
366 |
-
feature as you need to understand how Twig's internals work.
|
367 |
-
|
368 |
-
Let's create a simple ``set`` tag that allows the definition of simple
|
369 |
-
variables from within a template. The tag can be used like follows:
|
370 |
-
|
371 |
-
.. code-block:: jinja
|
372 |
-
|
373 |
-
{% set name = "value" %}
|
374 |
-
|
375 |
-
{{ name }}
|
376 |
-
|
377 |
-
{# should output value #}
|
378 |
-
|
379 |
-
.. note::
|
380 |
-
|
381 |
-
The ``set`` tag is part of the Core extension and as such is always
|
382 |
-
available. The built-in version is slightly more powerful and supports
|
383 |
-
multiple assignments by default (cf. the template designers chapter for
|
384 |
-
more information).
|
385 |
-
|
386 |
-
Three steps are needed to define a new tag:
|
387 |
-
|
388 |
-
* Defining a Token Parser class (responsible for parsing the template code);
|
389 |
-
|
390 |
-
* Defining a Node class (responsible for converting the parsed code to PHP);
|
391 |
-
|
392 |
-
* Registering the tag.
|
393 |
-
|
394 |
-
Registering a new tag
|
395 |
-
~~~~~~~~~~~~~~~~~~~~~
|
396 |
-
|
397 |
-
Adding a tag is as simple as calling the ``addTokenParser`` method on the
|
398 |
-
``Twig_Environment`` instance::
|
399 |
-
|
400 |
-
$twig = new Twig_Environment($loader);
|
401 |
-
$twig->addTokenParser(new Project_Set_TokenParser());
|
402 |
-
|
403 |
-
Defining a Token Parser
|
404 |
-
~~~~~~~~~~~~~~~~~~~~~~~
|
405 |
-
|
406 |
-
Now, let's see the actual code of this class::
|
407 |
-
|
408 |
-
class Project_Set_TokenParser extends Twig_TokenParser
|
409 |
-
{
|
410 |
-
public function parse(Twig_Token $token)
|
411 |
-
{
|
412 |
-
$lineno = $token->getLine();
|
413 |
-
$name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
|
414 |
-
$this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, '=');
|
415 |
-
$value = $this->parser->getExpressionParser()->parseExpression();
|
416 |
-
|
417 |
-
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
418 |
-
|
419 |
-
return new Project_Set_Node($name, $value, $lineno, $this->getTag());
|
420 |
-
}
|
421 |
-
|
422 |
-
public function getTag()
|
423 |
-
{
|
424 |
-
return 'set';
|
425 |
-
}
|
426 |
-
}
|
427 |
-
|
428 |
-
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
429 |
-
|
430 |
-
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
431 |
-
tag. It should return a ``Twig_Node`` instance that represents the node (the
|
432 |
-
``Project_Set_Node`` calls creating is explained in the next section).
|
433 |
-
|
434 |
-
The parsing process is simplified thanks to a bunch of methods you can call
|
435 |
-
from the token stream (``$this->parser->getStream()``):
|
436 |
-
|
437 |
-
* ``getCurrent()``: Gets the current token in the stream.
|
438 |
-
|
439 |
-
* ``next()``: Moves to the next token in the stream, *but returns the old one*.
|
440 |
-
|
441 |
-
* ``test($type)``, ``test($value)`` or ``test($type, $value)``: Determines whether
|
442 |
-
the current token is of a particular type or value (or both). The value may be an
|
443 |
-
array of several possible values.
|
444 |
-
|
445 |
-
* ``expect($type[, $value[, $message]])``: If the current token isn't of the given
|
446 |
-
type/value a syntax error is thrown. Otherwise, if the type and value are correct,
|
447 |
-
the token is returned and the stream moves to the next token.
|
448 |
-
|
449 |
-
* ``look()``: Looks a the next token without consuming it.
|
450 |
-
|
451 |
-
Parsing expressions is done by calling the ``parseExpression()`` like we did for
|
452 |
-
the ``set`` tag.
|
453 |
-
|
454 |
-
.. tip::
|
455 |
-
|
456 |
-
Reading the existing ``TokenParser`` classes is the best way to learn all
|
457 |
-
the nitty-gritty details of the parsing process.
|
458 |
-
|
459 |
-
Defining a Node
|
460 |
-
~~~~~~~~~~~~~~~
|
461 |
-
|
462 |
-
The ``Project_Set_Node`` class itself is rather simple::
|
463 |
-
|
464 |
-
class Project_Set_Node extends Twig_Node
|
465 |
-
{
|
466 |
-
public function __construct($name, Twig_Node_Expression $value, $lineno, $tag = null)
|
467 |
-
{
|
468 |
-
parent::__construct(array('value' => $value), array('name' => $name), $lineno, $tag);
|
469 |
-
}
|
470 |
-
|
471 |
-
public function compile(Twig_Compiler $compiler)
|
472 |
-
{
|
473 |
-
$compiler
|
474 |
-
->addDebugInfo($this)
|
475 |
-
->write('$context[\''.$this->getAttribute('name').'\'] = ')
|
476 |
-
->subcompile($this->getNode('value'))
|
477 |
-
->raw(";\n")
|
478 |
-
;
|
479 |
-
}
|
480 |
-
}
|
481 |
-
|
482 |
-
The compiler implements a fluid interface and provides methods that helps the
|
483 |
-
developer generate beautiful and readable PHP code:
|
484 |
-
|
485 |
-
* ``subcompile()``: Compiles a node.
|
486 |
-
|
487 |
-
* ``raw()``: Writes the given string as is.
|
488 |
-
|
489 |
-
* ``write()``: Writes the given string by adding indentation at the beginning
|
490 |
-
of each line.
|
491 |
-
|
492 |
-
* ``string()``: Writes a quoted string.
|
493 |
-
|
494 |
-
* ``repr()``: Writes a PHP representation of a given value (see
|
495 |
-
``Twig_Node_For`` for a usage example).
|
496 |
-
|
497 |
-
* ``addDebugInfo()``: Adds the line of the original template file related to
|
498 |
-
the current node as a comment.
|
499 |
-
|
500 |
-
* ``indent()``: Indents the generated code (see ``Twig_Node_Block`` for a
|
501 |
-
usage example).
|
502 |
-
|
503 |
-
* ``outdent()``: Outdents the generated code (see ``Twig_Node_Block`` for a
|
504 |
-
usage example).
|
505 |
-
|
506 |
-
.. _creating_extensions:
|
507 |
-
|
508 |
-
Creating an Extension
|
509 |
-
---------------------
|
510 |
-
|
511 |
-
The main motivation for writing an extension is to move often used code into a
|
512 |
-
reusable class like adding support for internationalization. An extension can
|
513 |
-
define tags, filters, tests, operators, global variables, functions, and node
|
514 |
-
visitors.
|
515 |
-
|
516 |
-
Creating an extension also makes for a better separation of code that is
|
517 |
-
executed at compilation time and code needed at runtime. As such, it makes
|
518 |
-
your code faster.
|
519 |
-
|
520 |
-
Most of the time, it is useful to create a single extension for your project,
|
521 |
-
to host all the specific tags and filters you want to add to Twig.
|
522 |
-
|
523 |
-
.. tip::
|
524 |
-
|
525 |
-
When packaging your code into an extension, Twig is smart enough to
|
526 |
-
recompile your templates whenever you make a change to it (when the
|
527 |
-
``auto_reload`` is enabled).
|
528 |
-
|
529 |
-
.. note::
|
530 |
-
|
531 |
-
Before writing your own extensions, have a look at the Twig official
|
532 |
-
extension repository: http://github.com/fabpot/Twig-extensions.
|
533 |
-
|
534 |
-
An extension is a class that implements the following interface::
|
535 |
-
|
536 |
-
interface Twig_ExtensionInterface
|
537 |
-
{
|
538 |
-
/**
|
539 |
-
* Initializes the runtime environment.
|
540 |
-
*
|
541 |
-
* This is where you can load some file that contains filter functions for instance.
|
542 |
-
*
|
543 |
-
* @param Twig_Environment $environment The current Twig_Environment instance
|
544 |
-
*/
|
545 |
-
function initRuntime(Twig_Environment $environment);
|
546 |
-
|
547 |
-
/**
|
548 |
-
* Returns the token parser instances to add to the existing list.
|
549 |
-
*
|
550 |
-
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
551 |
-
*/
|
552 |
-
function getTokenParsers();
|
553 |
-
|
554 |
-
/**
|
555 |
-
* Returns the node visitor instances to add to the existing list.
|
556 |
-
*
|
557 |
-
* @return array An array of Twig_NodeVisitorInterface instances
|
558 |
-
*/
|
559 |
-
function getNodeVisitors();
|
560 |
-
|
561 |
-
/**
|
562 |
-
* Returns a list of filters to add to the existing list.
|
563 |
-
*
|
564 |
-
* @return array An array of filters
|
565 |
-
*/
|
566 |
-
function getFilters();
|
567 |
-
|
568 |
-
/**
|
569 |
-
* Returns a list of tests to add to the existing list.
|
570 |
-
*
|
571 |
-
* @return array An array of tests
|
572 |
-
*/
|
573 |
-
function getTests();
|
574 |
-
|
575 |
-
/**
|
576 |
-
* Returns a list of functions to add to the existing list.
|
577 |
-
*
|
578 |
-
* @return array An array of functions
|
579 |
-
*/
|
580 |
-
function getFunctions();
|
581 |
-
|
582 |
-
/**
|
583 |
-
* Returns a list of operators to add to the existing list.
|
584 |
-
*
|
585 |
-
* @return array An array of operators
|
586 |
-
*/
|
587 |
-
function getOperators();
|
588 |
-
|
589 |
-
/**
|
590 |
-
* Returns a list of global variables to add to the existing list.
|
591 |
-
*
|
592 |
-
* @return array An array of global variables
|
593 |
-
*/
|
594 |
-
function getGlobals();
|
595 |
-
|
596 |
-
/**
|
597 |
-
* Returns the name of the extension.
|
598 |
-
*
|
599 |
-
* @return string The extension name
|
600 |
-
*/
|
601 |
-
function getName();
|
602 |
-
}
|
603 |
-
|
604 |
-
To keep your extension class clean and lean, it can inherit from the built-in
|
605 |
-
``Twig_Extension`` class instead of implementing the whole interface. That
|
606 |
-
way, you just need to implement the ``getName()`` method as the
|
607 |
-
``Twig_Extension`` provides empty implementations for all other methods.
|
608 |
-
|
609 |
-
The ``getName()`` method must return a unique identifier for your extension.
|
610 |
-
|
611 |
-
Now, with this information in mind, let's create the most basic extension
|
612 |
-
possible::
|
613 |
-
|
614 |
-
class Project_Twig_Extension extends Twig_Extension
|
615 |
-
{
|
616 |
-
public function getName()
|
617 |
-
{
|
618 |
-
return 'project';
|
619 |
-
}
|
620 |
-
}
|
621 |
-
|
622 |
-
.. note::
|
623 |
-
|
624 |
-
Of course, this extension does nothing for now. We will customize it in
|
625 |
-
the next sections.
|
626 |
-
|
627 |
-
Twig does not care where you save your extension on the filesystem, as all
|
628 |
-
extensions must be registered explicitly to be available in your templates.
|
629 |
-
|
630 |
-
You can register an extension by using the ``addExtension()`` method on your
|
631 |
-
main ``Environment`` object::
|
632 |
-
|
633 |
-
$twig = new Twig_Environment($loader);
|
634 |
-
$twig->addExtension(new Project_Twig_Extension());
|
635 |
-
|
636 |
-
Of course, you need to first load the extension file by either using
|
637 |
-
``require_once()`` or by using an autoloader (see `spl_autoload_register()`_).
|
638 |
-
|
639 |
-
.. tip::
|
640 |
-
|
641 |
-
The bundled extensions are great examples of how extensions work.
|
642 |
-
|
643 |
-
Globals
|
644 |
-
~~~~~~~
|
645 |
-
|
646 |
-
Global variables can be registered in an extension via the ``getGlobals()``
|
647 |
-
method::
|
648 |
-
|
649 |
-
class Project_Twig_Extension extends Twig_Extension
|
650 |
-
{
|
651 |
-
public function getGlobals()
|
652 |
-
{
|
653 |
-
return array(
|
654 |
-
'text' => new Text(),
|
655 |
-
);
|
656 |
-
}
|
657 |
-
|
658 |
-
// ...
|
659 |
-
}
|
660 |
-
|
661 |
-
Functions
|
662 |
-
~~~~~~~~~
|
663 |
-
|
664 |
-
Functions can be registered in an extension via the ``getFunctions()``
|
665 |
-
method::
|
666 |
-
|
667 |
-
class Project_Twig_Extension extends Twig_Extension
|
668 |
-
{
|
669 |
-
public function getFunctions()
|
670 |
-
{
|
671 |
-
return array(
|
672 |
-
'lipsum' => new Twig_Function_Function('generate_lipsum'),
|
673 |
-
);
|
674 |
-
}
|
675 |
-
|
676 |
-
// ...
|
677 |
-
}
|
678 |
-
|
679 |
-
Filters
|
680 |
-
~~~~~~~
|
681 |
-
|
682 |
-
To add a filter to an extension, you need to override the ``getFilters()``
|
683 |
-
method. This method must return an array of filters to add to the Twig
|
684 |
-
environment::
|
685 |
-
|
686 |
-
class Project_Twig_Extension extends Twig_Extension
|
687 |
-
{
|
688 |
-
public function getFilters()
|
689 |
-
{
|
690 |
-
return array(
|
691 |
-
'rot13' => new Twig_Filter_Function('str_rot13'),
|
692 |
-
);
|
693 |
-
}
|
694 |
-
|
695 |
-
// ...
|
696 |
-
}
|
697 |
-
|
698 |
-
As you can see in the above code, the ``getFilters()`` method returns an array
|
699 |
-
where keys are the name of the filters (``rot13``) and the values the
|
700 |
-
definition of the filter (``new Twig_Filter_Function('str_rot13')``).
|
701 |
-
|
702 |
-
As seen in the previous chapter, you can also define filters as static methods
|
703 |
-
on the extension class::
|
704 |
-
|
705 |
-
$twig->addFilter('rot13', new Twig_Filter_Function('Project_Twig_Extension::rot13Filter'));
|
706 |
-
|
707 |
-
You can also use ``Twig_Filter_Method`` instead of ``Twig_Filter_Function``
|
708 |
-
when defining a filter to use a method::
|
709 |
-
|
710 |
-
class Project_Twig_Extension extends Twig_Extension
|
711 |
-
{
|
712 |
-
public function getFilters()
|
713 |
-
{
|
714 |
-
return array(
|
715 |
-
'rot13' => new Twig_Filter_Method($this, 'rot13Filter'),
|
716 |
-
);
|
717 |
-
}
|
718 |
-
|
719 |
-
public function rot13Filter($string)
|
720 |
-
{
|
721 |
-
return str_rot13($string);
|
722 |
-
}
|
723 |
-
|
724 |
-
// ...
|
725 |
-
}
|
726 |
-
|
727 |
-
The first argument of the ``Twig_Filter_Method`` constructor is always
|
728 |
-
``$this``, the current extension object. The second one is the name of the
|
729 |
-
method to call.
|
730 |
-
|
731 |
-
Using methods for filters is a great way to package your filter without
|
732 |
-
polluting the global namespace. This also gives the developer more flexibility
|
733 |
-
at the cost of a small overhead.
|
734 |
-
|
735 |
-
Overriding default Filters
|
736 |
-
..........................
|
737 |
-
|
738 |
-
If some default core filters do not suit your needs, you can easily override
|
739 |
-
them by creating your own extension. Just use the same names as the one you
|
740 |
-
want to override::
|
741 |
-
|
742 |
-
class MyCoreExtension extends Twig_Extension
|
743 |
-
{
|
744 |
-
public function getFilters()
|
745 |
-
{
|
746 |
-
return array(
|
747 |
-
'date' => new Twig_Filter_Method($this, 'dateFilter'),
|
748 |
-
// ...
|
749 |
-
);
|
750 |
-
}
|
751 |
-
|
752 |
-
public function dateFilter($timestamp, $format = 'F j, Y H:i')
|
753 |
-
{
|
754 |
-
return '...'.twig_date_format_filter($timestamp, $format);
|
755 |
-
}
|
756 |
-
|
757 |
-
public function getName()
|
758 |
-
{
|
759 |
-
return 'project';
|
760 |
-
}
|
761 |
-
}
|
762 |
-
|
763 |
-
Here, we override the ``date`` filter with a custom one. Using this extension
|
764 |
-
is as simple as registering the ``MyCoreExtension`` extension by calling the
|
765 |
-
``addExtension()`` method on the environment instance::
|
766 |
-
|
767 |
-
$twig = new Twig_Environment($loader);
|
768 |
-
$twig->addExtension(new MyCoreExtension());
|
769 |
-
|
770 |
-
Tags
|
771 |
-
~~~~
|
772 |
-
|
773 |
-
Adding a tag in an extension can be done by overriding the
|
774 |
-
``getTokenParsers()`` method. This method must return an array of tags to add
|
775 |
-
to the Twig environment::
|
776 |
-
|
777 |
-
class Project_Twig_Extension extends Twig_Extension
|
778 |
-
{
|
779 |
-
public function getTokenParsers()
|
780 |
-
{
|
781 |
-
return array(new Project_Set_TokenParser());
|
782 |
-
}
|
783 |
-
|
784 |
-
// ...
|
785 |
-
}
|
786 |
-
|
787 |
-
In the above code, we have added a single new tag, defined by the
|
788 |
-
``Project_Set_TokenParser`` class. The ``Project_Set_TokenParser`` class is
|
789 |
-
responsible for parsing the tag and compiling it to PHP.
|
790 |
-
|
791 |
-
Operators
|
792 |
-
~~~~~~~~~
|
793 |
-
|
794 |
-
The ``getOperators()`` methods allows to add new operators. Here is how to add
|
795 |
-
``!``, ``||``, and ``&&`` operators::
|
796 |
-
|
797 |
-
class Project_Twig_Extension extends Twig_Extension
|
798 |
-
{
|
799 |
-
public function getOperators()
|
800 |
-
{
|
801 |
-
return array(
|
802 |
-
array(
|
803 |
-
'!' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
|
804 |
-
),
|
805 |
-
array(
|
806 |
-
'||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
807 |
-
'&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
808 |
-
),
|
809 |
-
);
|
810 |
-
}
|
811 |
-
|
812 |
-
// ...
|
813 |
-
}
|
814 |
-
|
815 |
-
Tests
|
816 |
-
~~~~~
|
817 |
-
|
818 |
-
The ``getTests()`` methods allows to add new test functions::
|
819 |
-
|
820 |
-
class Project_Twig_Extension extends Twig_Extension
|
821 |
-
{
|
822 |
-
public function getTests()
|
823 |
-
{
|
824 |
-
return array(
|
825 |
-
'even' => new Twig_Test_Function('twig_test_even'),
|
826 |
-
);
|
827 |
-
}
|
828 |
-
|
829 |
-
// ...
|
830 |
-
}
|
831 |
-
|
832 |
-
Testing an Extension
|
833 |
-
--------------------
|
834 |
-
|
835 |
-
.. versionadded:: 1.10
|
836 |
-
Support for functional tests was added in Twig 1.10.
|
837 |
-
|
838 |
-
Functional Tests
|
839 |
-
~~~~~~~~~~~~~~~~
|
840 |
-
|
841 |
-
You can create functional tests for extensions simply by creating the
|
842 |
-
following file structure in your test directory::
|
843 |
-
|
844 |
-
Fixtures/
|
845 |
-
filters/
|
846 |
-
foo.test
|
847 |
-
bar.test
|
848 |
-
functions/
|
849 |
-
foo.test
|
850 |
-
bar.test
|
851 |
-
tags/
|
852 |
-
foo.test
|
853 |
-
bar.test
|
854 |
-
IntegrationTest.php
|
855 |
-
|
856 |
-
The ``IntegrationTest.php`` file should look like this::
|
857 |
-
|
858 |
-
class Project_Tests_IntegrationTest extends Twig_Test_IntegrationTestCase
|
859 |
-
{
|
860 |
-
public function getExtensions()
|
861 |
-
{
|
862 |
-
return array(
|
863 |
-
new Project_Twig_Extension1(),
|
864 |
-
new Project_Twig_Extension2(),
|
865 |
-
);
|
866 |
-
}
|
867 |
-
|
868 |
-
public function getFixturesDir()
|
869 |
-
{
|
870 |
-
return dirname(__FILE__).'/Fixtures/';
|
871 |
-
}
|
872 |
-
}
|
873 |
-
|
874 |
-
Fixtures examples can be found within the Twig repository
|
875 |
-
`tests/Twig/Fixtures`_ directory.
|
876 |
-
|
877 |
-
Node Tests
|
878 |
-
~~~~~~~~~~
|
879 |
-
|
880 |
-
Testing the node visitors can be complex, so extend your test cases from
|
881 |
-
``Twig_Test_NodeTestCase``. Examples can be found in the Twig repository
|
882 |
-
`tests/Twig/Node`_ directory.
|
883 |
-
|
884 |
-
.. _`spl_autoload_register()`: http://www.php.net/spl_autoload_register
|
885 |
-
.. _`rot13`: http://www.php.net/manual/en/function.str-rot13.php
|
886 |
-
.. _`tests/Twig/Fixtures`: https://github.com/fabpot/Twig/tree/master/test/Twig/Tests/Fixtures
|
887 |
-
.. _`tests/Twig/Node`: https://github.com/fabpot/Twig/tree/master/test/Twig/Tests/Node
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/api.rst
DELETED
@@ -1,585 +0,0 @@
|
|
1 |
-
Twig for Developers
|
2 |
-
===================
|
3 |
-
|
4 |
-
This chapter describes the API to Twig and not the template language. It will
|
5 |
-
be most useful as reference to those implementing the template interface to
|
6 |
-
the application and not those who are creating Twig templates.
|
7 |
-
|
8 |
-
Basics
|
9 |
-
------
|
10 |
-
|
11 |
-
Twig uses a central object called the **environment** (of class
|
12 |
-
``Twig_Environment``). Instances of this class are used to store the
|
13 |
-
configuration and extensions, and are used to load templates from the file
|
14 |
-
system or other locations.
|
15 |
-
|
16 |
-
Most applications will create one ``Twig_Environment`` object on application
|
17 |
-
initialization and use that to load templates. In some cases it's however
|
18 |
-
useful to have multiple environments side by side, if different configurations
|
19 |
-
are in use.
|
20 |
-
|
21 |
-
The simplest way to configure Twig to load templates for your application
|
22 |
-
looks roughly like this::
|
23 |
-
|
24 |
-
require_once '/path/to/lib/Twig/Autoloader.php';
|
25 |
-
Twig_Autoloader::register();
|
26 |
-
|
27 |
-
$loader = new Twig_Loader_Filesystem('/path/to/templates');
|
28 |
-
$twig = new Twig_Environment($loader, array(
|
29 |
-
'cache' => '/path/to/compilation_cache',
|
30 |
-
));
|
31 |
-
|
32 |
-
This will create a template environment with the default settings and a loader
|
33 |
-
that looks up the templates in the ``/path/to/templates/`` folder. Different
|
34 |
-
loaders are available and you can also write your own if you want to load
|
35 |
-
templates from a database or other resources.
|
36 |
-
|
37 |
-
.. note::
|
38 |
-
|
39 |
-
Notice that the second argument of the environment is an array of options.
|
40 |
-
The ``cache`` option is a compilation cache directory, where Twig caches
|
41 |
-
the compiled templates to avoid the parsing phase for sub-sequent
|
42 |
-
requests. It is very different from the cache you might want to add for
|
43 |
-
the evaluated templates. For such a need, you can use any available PHP
|
44 |
-
cache library.
|
45 |
-
|
46 |
-
To load a template from this environment you just have to call the
|
47 |
-
``loadTemplate()`` method which then returns a ``Twig_Template`` instance::
|
48 |
-
|
49 |
-
$template = $twig->loadTemplate('index.html');
|
50 |
-
|
51 |
-
To render the template with some variables, call the ``render()`` method::
|
52 |
-
|
53 |
-
echo $template->render(array('the' => 'variables', 'go' => 'here'));
|
54 |
-
|
55 |
-
.. note::
|
56 |
-
|
57 |
-
The ``display()`` method is a shortcut to output the template directly.
|
58 |
-
|
59 |
-
You can also load and render the template in one fell swoop::
|
60 |
-
|
61 |
-
echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here'));
|
62 |
-
|
63 |
-
.. _environment_options:
|
64 |
-
|
65 |
-
Environment Options
|
66 |
-
-------------------
|
67 |
-
|
68 |
-
When creating a new ``Twig_Environment`` instance, you can pass an array of
|
69 |
-
options as the constructor second argument::
|
70 |
-
|
71 |
-
$twig = new Twig_Environment($loader, array('debug' => true));
|
72 |
-
|
73 |
-
The following options are available:
|
74 |
-
|
75 |
-
* ``debug``: When set to ``true``, the generated templates have a
|
76 |
-
``__toString()`` method that you can use to display the generated nodes
|
77 |
-
(default to ``false``).
|
78 |
-
|
79 |
-
* ``charset``: The charset used by the templates (default to ``utf-8``).
|
80 |
-
|
81 |
-
* ``base_template_class``: The base template class to use for generated
|
82 |
-
templates (default to ``Twig_Template``).
|
83 |
-
|
84 |
-
* ``cache``: An absolute path where to store the compiled templates, or
|
85 |
-
``false`` to disable caching (which is the default).
|
86 |
-
|
87 |
-
* ``auto_reload``: When developing with Twig, it's useful to recompile the
|
88 |
-
template whenever the source code changes. If you don't provide a value for
|
89 |
-
the ``auto_reload`` option, it will be determined automatically based on the
|
90 |
-
``debug`` value.
|
91 |
-
|
92 |
-
* ``strict_variables``: If set to ``false``, Twig will silently ignore invalid
|
93 |
-
variables (variables and or attributes/methods that do not exist) and
|
94 |
-
replace them with a ``null`` value. When set to ``true``, Twig throws an
|
95 |
-
exception instead (default to ``false``).
|
96 |
-
|
97 |
-
* ``autoescape``: If set to ``true``, auto-escaping will be enabled by default
|
98 |
-
for all templates (default to ``true``). As of Twig 1.8, you can set the
|
99 |
-
escaping strategy to use (``html``, ``js``, ``false`` to disable).
|
100 |
-
As of Twig 1.9, you can set the escaping strategy to use (``css``, ``url``,
|
101 |
-
``html_attr``, or a PHP callback that takes the template "filename" and must
|
102 |
-
return the escaping strategy to use -- the callback cannot be a function name
|
103 |
-
to avoid collision with built-in escaping strategies).
|
104 |
-
|
105 |
-
* ``optimizations``: A flag that indicates which optimizations to apply
|
106 |
-
(default to ``-1`` -- all optimizations are enabled; set it to ``0`` to
|
107 |
-
disable).
|
108 |
-
|
109 |
-
Loaders
|
110 |
-
-------
|
111 |
-
|
112 |
-
Loaders are responsible for loading templates from a resource such as the file
|
113 |
-
system.
|
114 |
-
|
115 |
-
Compilation Cache
|
116 |
-
~~~~~~~~~~~~~~~~~
|
117 |
-
|
118 |
-
All template loaders can cache the compiled templates on the filesystem for
|
119 |
-
future reuse. It speeds up Twig a lot as templates are only compiled once; and
|
120 |
-
the performance boost is even larger if you use a PHP accelerator such as APC.
|
121 |
-
See the ``cache`` and ``auto_reload`` options of ``Twig_Environment`` above
|
122 |
-
for more information.
|
123 |
-
|
124 |
-
Built-in Loaders
|
125 |
-
~~~~~~~~~~~~~~~~
|
126 |
-
|
127 |
-
Here is a list of the built-in loaders Twig provides:
|
128 |
-
|
129 |
-
``Twig_Loader_Filesystem``
|
130 |
-
..........................
|
131 |
-
|
132 |
-
.. versionadded:: 1.10
|
133 |
-
The ``prependPath()`` and support for namespaces were added in Twig 1.10.
|
134 |
-
|
135 |
-
``Twig_Loader_Filesystem`` loads templates from the file system. This loader
|
136 |
-
can find templates in folders on the file system and is the preferred way to
|
137 |
-
load them::
|
138 |
-
|
139 |
-
$loader = new Twig_Loader_Filesystem($templateDir);
|
140 |
-
|
141 |
-
It can also look for templates in an array of directories::
|
142 |
-
|
143 |
-
$loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2));
|
144 |
-
|
145 |
-
With such a configuration, Twig will first look for templates in
|
146 |
-
``$templateDir1`` and if they do not exist, it will fallback to look for them
|
147 |
-
in the ``$templateDir2``.
|
148 |
-
|
149 |
-
You can add or prepend paths via the ``addPath()`` and ``prependPath()``
|
150 |
-
methods::
|
151 |
-
|
152 |
-
$loader->addPath($templateDir3);
|
153 |
-
$loader->prependPath($templateDir4);
|
154 |
-
|
155 |
-
The filesystem loader also supports namespaced templates. This allows to group
|
156 |
-
your templates under different namespaces which have their own template paths.
|
157 |
-
|
158 |
-
When using the ``setPaths()``, ``addPath()``, and ``prependPath()`` methods,
|
159 |
-
specify the namespace as the second argument (when not specified, these
|
160 |
-
methods act on the "main" namespace)::
|
161 |
-
|
162 |
-
$loader->addPath($templateDir, 'admin');
|
163 |
-
|
164 |
-
Namespaced templates can be accessed via the special
|
165 |
-
``@namespace_name/template_path`` notation::
|
166 |
-
|
167 |
-
$twig->render('@admin/index.html', array());
|
168 |
-
|
169 |
-
``Twig_Loader_String``
|
170 |
-
......................
|
171 |
-
|
172 |
-
``Twig_Loader_String`` loads templates from strings. It's a dummy loader as
|
173 |
-
the template reference is the template source code::
|
174 |
-
|
175 |
-
$loader = new Twig_Loader_String();
|
176 |
-
$twig = new Twig_Environment($loader);
|
177 |
-
|
178 |
-
echo $twig->render('Hello {{ name }}!', array('name' => 'Fabien'));
|
179 |
-
|
180 |
-
This loader should only be used for unit testing as it has severe limitations:
|
181 |
-
several tags, like ``extends`` or ``include`` do not make sense to use as the
|
182 |
-
reference to the template is the template source code itself.
|
183 |
-
|
184 |
-
``Twig_Loader_Array``
|
185 |
-
.....................
|
186 |
-
|
187 |
-
``Twig_Loader_Array`` loads a template from a PHP array. It's passed an array
|
188 |
-
of strings bound to template names::
|
189 |
-
|
190 |
-
$loader = new Twig_Loader_Array(array(
|
191 |
-
'index.html' => 'Hello {{ name }}!',
|
192 |
-
));
|
193 |
-
$twig = new Twig_Environment($loader);
|
194 |
-
|
195 |
-
echo $twig->render('index.html', array('name' => 'Fabien'));
|
196 |
-
|
197 |
-
This loader is very useful for unit testing. It can also be used for small
|
198 |
-
projects where storing all templates in a single PHP file might make sense.
|
199 |
-
|
200 |
-
.. tip::
|
201 |
-
|
202 |
-
When using the ``Array`` or ``String`` loaders with a cache mechanism, you
|
203 |
-
should know that a new cache key is generated each time a template content
|
204 |
-
"changes" (the cache key being the source code of the template). If you
|
205 |
-
don't want to see your cache grows out of control, you need to take care
|
206 |
-
of clearing the old cache file by yourself.
|
207 |
-
|
208 |
-
``Twig_Loader_Chain``
|
209 |
-
.....................
|
210 |
-
|
211 |
-
``Twig_Loader_Chain`` delegates the loading of templates to other loaders::
|
212 |
-
|
213 |
-
$loader1 = new Twig_Loader_Array(array(
|
214 |
-
'base.html' => '{% block content %}{% endblock %}',
|
215 |
-
));
|
216 |
-
$loader2 = new Twig_Loader_Array(array(
|
217 |
-
'index.html' => '{% extends "base.twig" %}{% block content %}Hello {{ name }}{% endblock %}',
|
218 |
-
'base.html' => 'Will never be loaded',
|
219 |
-
));
|
220 |
-
|
221 |
-
$loader = new Twig_Loader_Chain(array($loader1, $loader2));
|
222 |
-
|
223 |
-
$twig = new Twig_Environment($loader);
|
224 |
-
|
225 |
-
When looking for a template, Twig will try each loader in turn and it will
|
226 |
-
return as soon as the template is found. When rendering the ``index.html``
|
227 |
-
template from the above example, Twig will load it with ``$loader2`` but the
|
228 |
-
``base.html`` template will be loaded from ``$loader1``.
|
229 |
-
|
230 |
-
``Twig_Loader_Chain`` accepts any loader that implements
|
231 |
-
``Twig_LoaderInterface``.
|
232 |
-
|
233 |
-
.. note::
|
234 |
-
|
235 |
-
You can also add loaders via the ``addLoader()`` method.
|
236 |
-
|
237 |
-
Create your own Loader
|
238 |
-
~~~~~~~~~~~~~~~~~~~~~~
|
239 |
-
|
240 |
-
All loaders implement the ``Twig_LoaderInterface``::
|
241 |
-
|
242 |
-
interface Twig_LoaderInterface
|
243 |
-
{
|
244 |
-
/**
|
245 |
-
* Gets the source code of a template, given its name.
|
246 |
-
*
|
247 |
-
* @param string $name string The name of the template to load
|
248 |
-
*
|
249 |
-
* @return string The template source code
|
250 |
-
*/
|
251 |
-
function getSource($name);
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Gets the cache key to use for the cache for a given template name.
|
255 |
-
*
|
256 |
-
* @param string $name string The name of the template to load
|
257 |
-
*
|
258 |
-
* @return string The cache key
|
259 |
-
*/
|
260 |
-
function getCacheKey($name);
|
261 |
-
|
262 |
-
/**
|
263 |
-
* Returns true if the template is still fresh.
|
264 |
-
*
|
265 |
-
* @param string $name The template name
|
266 |
-
* @param timestamp $time The last modification time of the cached template
|
267 |
-
*/
|
268 |
-
function isFresh($name, $time);
|
269 |
-
}
|
270 |
-
|
271 |
-
As an example, here is how the built-in ``Twig_Loader_String`` reads::
|
272 |
-
|
273 |
-
class Twig_Loader_String implements Twig_LoaderInterface
|
274 |
-
{
|
275 |
-
public function getSource($name)
|
276 |
-
{
|
277 |
-
return $name;
|
278 |
-
}
|
279 |
-
|
280 |
-
public function getCacheKey($name)
|
281 |
-
{
|
282 |
-
return $name;
|
283 |
-
}
|
284 |
-
|
285 |
-
public function isFresh($name, $time)
|
286 |
-
{
|
287 |
-
return false;
|
288 |
-
}
|
289 |
-
}
|
290 |
-
|
291 |
-
The ``isFresh()`` method must return ``true`` if the current cached template
|
292 |
-
is still fresh, given the last modification time, or ``false`` otherwise.
|
293 |
-
|
294 |
-
.. tip::
|
295 |
-
|
296 |
-
As of Twig 1.11.0, you can also implement ``Twig_ExistsLoaderInterface``
|
297 |
-
to make your loader faster when used with the chain loader.
|
298 |
-
|
299 |
-
Using Extensions
|
300 |
-
----------------
|
301 |
-
|
302 |
-
Twig extensions are packages that add new features to Twig. Using an
|
303 |
-
extension is as simple as using the ``addExtension()`` method::
|
304 |
-
|
305 |
-
$twig->addExtension(new Twig_Extension_Sandbox());
|
306 |
-
|
307 |
-
Twig comes bundled with the following extensions:
|
308 |
-
|
309 |
-
* *Twig_Extension_Core*: Defines all the core features of Twig.
|
310 |
-
|
311 |
-
* *Twig_Extension_Escaper*: Adds automatic output-escaping and the possibility
|
312 |
-
to escape/unescape blocks of code.
|
313 |
-
|
314 |
-
* *Twig_Extension_Sandbox*: Adds a sandbox mode to the default Twig
|
315 |
-
environment, making it safe to evaluated untrusted code.
|
316 |
-
|
317 |
-
* *Twig_Extension_Optimizer*: Optimizers the node tree before compilation.
|
318 |
-
|
319 |
-
The core, escaper, and optimizer extensions do not need to be added to the
|
320 |
-
Twig environment, as they are registered by default.
|
321 |
-
|
322 |
-
Built-in Extensions
|
323 |
-
-------------------
|
324 |
-
|
325 |
-
This section describes the features added by the built-in extensions.
|
326 |
-
|
327 |
-
.. tip::
|
328 |
-
|
329 |
-
Read the chapter about extending Twig to learn how to create your own
|
330 |
-
extensions.
|
331 |
-
|
332 |
-
Core Extension
|
333 |
-
~~~~~~~~~~~~~~
|
334 |
-
|
335 |
-
The ``core`` extension defines all the core features of Twig:
|
336 |
-
|
337 |
-
* Tags:
|
338 |
-
|
339 |
-
* ``for``
|
340 |
-
* ``if``
|
341 |
-
* ``extends``
|
342 |
-
* ``include``
|
343 |
-
* ``block``
|
344 |
-
* ``filter``
|
345 |
-
* ``macro``
|
346 |
-
* ``import``
|
347 |
-
* ``from``
|
348 |
-
* ``set``
|
349 |
-
* ``spaceless``
|
350 |
-
* ``autoescape``
|
351 |
-
* ``do``
|
352 |
-
* ``embed``
|
353 |
-
* ``flush``
|
354 |
-
* ``verbatim``
|
355 |
-
* ``sandbox``
|
356 |
-
* ``use``
|
357 |
-
|
358 |
-
* Filters:
|
359 |
-
|
360 |
-
* ``date``
|
361 |
-
* ``format``
|
362 |
-
* ``replace``
|
363 |
-
* ``url_encode``
|
364 |
-
* ``json_encode``
|
365 |
-
* ``title``
|
366 |
-
* ``capitalize``
|
367 |
-
* ``upper``
|
368 |
-
* ``lower``
|
369 |
-
* ``striptags``
|
370 |
-
* ``join``
|
371 |
-
* ``reverse``
|
372 |
-
* ``length``
|
373 |
-
* ``sort``
|
374 |
-
* ``merge``
|
375 |
-
* ``default``
|
376 |
-
* ``keys``
|
377 |
-
* ``escape``
|
378 |
-
* ``e``
|
379 |
-
* ``abs``
|
380 |
-
* ``convert_encoding``
|
381 |
-
* ``date_modify``
|
382 |
-
* ``nl2br``
|
383 |
-
* ``number_format``
|
384 |
-
* ``raw``
|
385 |
-
* ``slice``
|
386 |
-
* ``trim``
|
387 |
-
|
388 |
-
* Functions:
|
389 |
-
|
390 |
-
* ``range``
|
391 |
-
* ``constant``
|
392 |
-
* ``cycle``
|
393 |
-
* ``parent``
|
394 |
-
* ``block``
|
395 |
-
* ``attribute``
|
396 |
-
* ``date``
|
397 |
-
* ``dump``
|
398 |
-
* ``random``
|
399 |
-
|
400 |
-
* Tests:
|
401 |
-
|
402 |
-
* ``even``
|
403 |
-
* ``odd``
|
404 |
-
* ``defined``
|
405 |
-
* ``sameas``
|
406 |
-
* ``null``
|
407 |
-
* ``divisibleby``
|
408 |
-
* ``constant``
|
409 |
-
* ``empty``
|
410 |
-
* ``iterable``
|
411 |
-
|
412 |
-
Escaper Extension
|
413 |
-
~~~~~~~~~~~~~~~~~
|
414 |
-
|
415 |
-
The ``escaper`` extension adds automatic output escaping to Twig. It defines a
|
416 |
-
tag, ``autoescape``, and a filter, ``raw``.
|
417 |
-
|
418 |
-
When creating the escaper extension, you can switch on or off the global
|
419 |
-
output escaping strategy::
|
420 |
-
|
421 |
-
$escaper = new Twig_Extension_Escaper(true);
|
422 |
-
$twig->addExtension($escaper);
|
423 |
-
|
424 |
-
If set to ``true``, all variables in templates are escaped (using the ``html``
|
425 |
-
escaping strategy), except those using the ``raw`` filter:
|
426 |
-
|
427 |
-
.. code-block:: jinja
|
428 |
-
|
429 |
-
{{ article.to_html|raw }}
|
430 |
-
|
431 |
-
You can also change the escaping mode locally by using the ``autoescape`` tag
|
432 |
-
(see the :doc:`autoescape<tags/autoescape>` doc for the syntax used before
|
433 |
-
Twig 1.8):
|
434 |
-
|
435 |
-
.. code-block:: jinja
|
436 |
-
|
437 |
-
{% autoescape 'html' %}
|
438 |
-
{{ var }}
|
439 |
-
{{ var|raw }} {# var won't be escaped #}
|
440 |
-
{{ var|escape }} {# var won't be double-escaped #}
|
441 |
-
{% endautoescape %}
|
442 |
-
|
443 |
-
.. warning::
|
444 |
-
|
445 |
-
The ``autoescape`` tag has no effect on included files.
|
446 |
-
|
447 |
-
The escaping rules are implemented as follows:
|
448 |
-
|
449 |
-
* Literals (integers, booleans, arrays, ...) used in the template directly as
|
450 |
-
variables or filter arguments are never automatically escaped:
|
451 |
-
|
452 |
-
.. code-block:: jinja
|
453 |
-
|
454 |
-
{{ "Twig<br />" }} {# won't be escaped #}
|
455 |
-
|
456 |
-
{% set text = "Twig<br />" %}
|
457 |
-
{{ text }} {# will be escaped #}
|
458 |
-
|
459 |
-
* Expressions which the result is always a literal or a variable marked safe
|
460 |
-
are never automatically escaped:
|
461 |
-
|
462 |
-
.. code-block:: jinja
|
463 |
-
|
464 |
-
{{ foo ? "Twig<br />" : "<br />Twig" }} {# won't be escaped #}
|
465 |
-
|
466 |
-
{% set text = "Twig<br />" %}
|
467 |
-
{{ foo ? text : "<br />Twig" }} {# will be escaped #}
|
468 |
-
|
469 |
-
{% set text = "Twig<br />" %}
|
470 |
-
{{ foo ? text|raw : "<br />Twig" }} {# won't be escaped #}
|
471 |
-
|
472 |
-
{% set text = "Twig<br />" %}
|
473 |
-
{{ foo ? text|escape : "<br />Twig" }} {# the result of the expression won't be escaped #}
|
474 |
-
|
475 |
-
* Escaping is applied before printing, after any other filter is applied:
|
476 |
-
|
477 |
-
.. code-block:: jinja
|
478 |
-
|
479 |
-
{{ var|upper }} {# is equivalent to {{ var|upper|escape }} #}
|
480 |
-
|
481 |
-
* The `raw` filter should only be used at the end of the filter chain:
|
482 |
-
|
483 |
-
.. code-block:: jinja
|
484 |
-
|
485 |
-
{{ var|raw|upper }} {# will be escaped #}
|
486 |
-
|
487 |
-
{{ var|upper|raw }} {# won't be escaped #}
|
488 |
-
|
489 |
-
* Automatic escaping is not applied if the last filter in the chain is marked
|
490 |
-
safe for the current context (e.g. ``html`` or ``js``). ``escaper`` and
|
491 |
-
``escaper('html')`` are marked safe for html, ``escaper('js')`` is marked
|
492 |
-
safe for javascript, ``raw`` is marked safe for everything.
|
493 |
-
|
494 |
-
.. code-block:: jinja
|
495 |
-
|
496 |
-
{% autoescape 'js' %}
|
497 |
-
{{ var|escape('html') }} {# will be escaped for html and javascript #}
|
498 |
-
{{ var }} {# will be escaped for javascript #}
|
499 |
-
{{ var|escape('js') }} {# won't be double-escaped #}
|
500 |
-
{% endautoescape %}
|
501 |
-
|
502 |
-
.. note::
|
503 |
-
|
504 |
-
Note that autoescaping has some limitations as escaping is applied on
|
505 |
-
expressions after evaluation. For instance, when working with
|
506 |
-
concatenation, ``{{ foo|raw ~ bar }}`` won't give the expected result as
|
507 |
-
escaping is applied on the result of the concatenation, not on the
|
508 |
-
individual variables (so, the ``raw`` filter won't have any effect here).
|
509 |
-
|
510 |
-
Sandbox Extension
|
511 |
-
~~~~~~~~~~~~~~~~~
|
512 |
-
|
513 |
-
The ``sandbox`` extension can be used to evaluate untrusted code. Access to
|
514 |
-
unsafe attributes and methods is prohibited. The sandbox security is managed
|
515 |
-
by a policy instance. By default, Twig comes with one policy class:
|
516 |
-
``Twig_Sandbox_SecurityPolicy``. This class allows you to white-list some
|
517 |
-
tags, filters, properties, and methods::
|
518 |
-
|
519 |
-
$tags = array('if');
|
520 |
-
$filters = array('upper');
|
521 |
-
$methods = array(
|
522 |
-
'Article' => array('getTitle', 'getBody'),
|
523 |
-
);
|
524 |
-
$properties = array(
|
525 |
-
'Article' => array('title', 'body'),
|
526 |
-
);
|
527 |
-
$functions = array('range');
|
528 |
-
$policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions);
|
529 |
-
|
530 |
-
With the previous configuration, the security policy will only allow usage of
|
531 |
-
the ``if`` tag, and the ``upper`` filter. Moreover, the templates will only be
|
532 |
-
able to call the ``getTitle()`` and ``getBody()`` methods on ``Article``
|
533 |
-
objects, and the ``title`` and ``body`` public properties. Everything else
|
534 |
-
won't be allowed and will generate a ``Twig_Sandbox_SecurityError`` exception.
|
535 |
-
|
536 |
-
The policy object is the first argument of the sandbox constructor::
|
537 |
-
|
538 |
-
$sandbox = new Twig_Extension_Sandbox($policy);
|
539 |
-
$twig->addExtension($sandbox);
|
540 |
-
|
541 |
-
By default, the sandbox mode is disabled and should be enabled when including
|
542 |
-
untrusted template code by using the ``sandbox`` tag:
|
543 |
-
|
544 |
-
.. code-block:: jinja
|
545 |
-
|
546 |
-
{% sandbox %}
|
547 |
-
{% include 'user.html' %}
|
548 |
-
{% endsandbox %}
|
549 |
-
|
550 |
-
You can sandbox all templates by passing ``true`` as the second argument of
|
551 |
-
the extension constructor::
|
552 |
-
|
553 |
-
$sandbox = new Twig_Extension_Sandbox($policy, true);
|
554 |
-
|
555 |
-
Optimizer Extension
|
556 |
-
~~~~~~~~~~~~~~~~~~~
|
557 |
-
|
558 |
-
The ``optimizer`` extension optimizes the node tree before compilation::
|
559 |
-
|
560 |
-
$twig->addExtension(new Twig_Extension_Optimizer());
|
561 |
-
|
562 |
-
By default, all optimizations are turned on. You can select the ones you want
|
563 |
-
to enable by passing them to the constructor::
|
564 |
-
|
565 |
-
$optimizer = new Twig_Extension_Optimizer(Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR);
|
566 |
-
|
567 |
-
$twig->addExtension($optimizer);
|
568 |
-
|
569 |
-
Exceptions
|
570 |
-
----------
|
571 |
-
|
572 |
-
Twig can throw exceptions:
|
573 |
-
|
574 |
-
* ``Twig_Error``: The base exception for all errors.
|
575 |
-
|
576 |
-
* ``Twig_Error_Syntax``: Thrown to tell the user that there is a problem with
|
577 |
-
the template syntax.
|
578 |
-
|
579 |
-
* ``Twig_Error_Runtime``: Thrown when an error occurs at runtime (when a filter
|
580 |
-
does not exist for instance).
|
581 |
-
|
582 |
-
* ``Twig_Error_Loader``: Thrown when an error occurs during template loading.
|
583 |
-
|
584 |
-
* ``Twig_Sandbox_SecurityError``: Thrown when an unallowed tag, filter, or
|
585 |
-
method is called in a sandboxed template.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/coding_standards.rst
DELETED
@@ -1,101 +0,0 @@
|
|
1 |
-
Coding Standards
|
2 |
-
================
|
3 |
-
|
4 |
-
When writing Twig templates, we recommend you to follow these official coding
|
5 |
-
standards:
|
6 |
-
|
7 |
-
* Put one (and only one) space after the start of a delimiter (``{{``, ``{%``,
|
8 |
-
and ``{#``) and before the end of a delimiter (``}}``, ``%}``, and ``#}``):
|
9 |
-
|
10 |
-
.. code-block:: jinja
|
11 |
-
|
12 |
-
{{ foo }}
|
13 |
-
{# comment #}
|
14 |
-
{% if foo %}{% endif %}
|
15 |
-
|
16 |
-
When using the whitespace control character, do not put any spaces between
|
17 |
-
it and the delimiter:
|
18 |
-
|
19 |
-
.. code-block:: jinja
|
20 |
-
|
21 |
-
{{- foo -}}
|
22 |
-
{#- comment -#}
|
23 |
-
{%- if foo -%}{%- endif -%}
|
24 |
-
|
25 |
-
* Put one (and only one) space before and after the following operators:
|
26 |
-
comparison operators (``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``), math
|
27 |
-
operators (``+``, ``-``, ``/``, ``*``, ``%``, ``//``, ``**``), logic
|
28 |
-
operators (``not``, ``and``, ``or``), ``~``, ``is``, ``in``, and the ternary
|
29 |
-
operator (``?:``):
|
30 |
-
|
31 |
-
.. code-block:: jinja
|
32 |
-
|
33 |
-
{{ 1 + 2 }}
|
34 |
-
{{ foo ~ bar }}
|
35 |
-
{{ true ? true : false }}
|
36 |
-
|
37 |
-
* Put one (and only one) space after the ``:`` sign in hashes and ``,`` in
|
38 |
-
arrays and hashes:
|
39 |
-
|
40 |
-
.. code-block:: jinja
|
41 |
-
|
42 |
-
{{ [1, 2, 3] }}
|
43 |
-
{{ {'foo': 'bar'} }}
|
44 |
-
|
45 |
-
* Do not put any spaces after an opening parenthesis and before a closing
|
46 |
-
parenthesis in expressions:
|
47 |
-
|
48 |
-
.. code-block:: jinja
|
49 |
-
|
50 |
-
{{ 1 + (2 * 3) }}
|
51 |
-
|
52 |
-
* Do not put any spaces before and after string delimiters:
|
53 |
-
|
54 |
-
.. code-block:: jinja
|
55 |
-
|
56 |
-
{{ 'foo' }}
|
57 |
-
{{ "foo" }}
|
58 |
-
|
59 |
-
* Do not put any spaces before and after the following operators: ``|``,
|
60 |
-
``.``, ``..``, ``[]``:
|
61 |
-
|
62 |
-
.. code-block:: jinja
|
63 |
-
|
64 |
-
{{ foo|upper|lower }}
|
65 |
-
{{ user.name }}
|
66 |
-
{{ user[name] }}
|
67 |
-
{% for i in 1..12 %}{% endfor %}
|
68 |
-
|
69 |
-
* Do not put any spaces before and after the parenthesis used for filter and
|
70 |
-
function calls:
|
71 |
-
|
72 |
-
.. code-block:: jinja
|
73 |
-
|
74 |
-
{{ foo|default('foo') }}
|
75 |
-
{{ range(1..10) }}
|
76 |
-
|
77 |
-
* Do not put any spaces before and after the opening and the closing of arrays
|
78 |
-
and hashes:
|
79 |
-
|
80 |
-
.. code-block:: jinja
|
81 |
-
|
82 |
-
{{ [1, 2, 3] }}
|
83 |
-
{{ {'foo': 'bar'} }}
|
84 |
-
|
85 |
-
* Use lower cased and underscored variable names:
|
86 |
-
|
87 |
-
.. code-block:: jinja
|
88 |
-
|
89 |
-
{% set foo = 'foo' %}
|
90 |
-
{% set foo_bar = 'foo' %}
|
91 |
-
|
92 |
-
* Indent your code inside tags (use the same indentation as the one used for
|
93 |
-
the main language of the file):
|
94 |
-
|
95 |
-
.. code-block:: jinja
|
96 |
-
|
97 |
-
{% block foo %}
|
98 |
-
{% if true %}
|
99 |
-
true
|
100 |
-
{% endif %}
|
101 |
-
{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/deprecated.rst
DELETED
@@ -1,98 +0,0 @@
|
|
1 |
-
Deprecated Features
|
2 |
-
===================
|
3 |
-
|
4 |
-
This document lists all deprecated features in Twig. Deprecated features are
|
5 |
-
kept for backward compatibility and removed in the next major release (a
|
6 |
-
feature that was deprecated in Twig 1.x is removed in Twig 2.0).
|
7 |
-
|
8 |
-
Token Parsers
|
9 |
-
-------------
|
10 |
-
|
11 |
-
* As of Twig 1.x, the token parser broker sub-system is deprecated. The
|
12 |
-
following class and interface will be removed in 2.0:
|
13 |
-
|
14 |
-
* ``Twig_TokenParserBrokerInterface``
|
15 |
-
* ``Twig_TokenParserBroker``
|
16 |
-
|
17 |
-
Extensions
|
18 |
-
----------
|
19 |
-
|
20 |
-
* As of Twig 1.x, the ability to remove an extension is deprecated and the
|
21 |
-
``Twig_Environment::removeExtension()`` method will be removed in 2.0.
|
22 |
-
|
23 |
-
PEAR
|
24 |
-
----
|
25 |
-
|
26 |
-
PEAR support will be discontinued in Twig 2.0, and no PEAR packages will be
|
27 |
-
provided. Use Composer instead.
|
28 |
-
|
29 |
-
Filters
|
30 |
-
-------
|
31 |
-
|
32 |
-
* As of Twig 1.x, use ``Twig_SimpleFilter`` to add a filter. The following
|
33 |
-
classes and interfaces will be removed in 2.0:
|
34 |
-
|
35 |
-
* ``Twig_FilterInterface``
|
36 |
-
* ``Twig_FilterCallableInterface``
|
37 |
-
* ``Twig_Filter``
|
38 |
-
* ``Twig_Filter_Function``
|
39 |
-
* ``Twig_Filter_Method``
|
40 |
-
* ``Twig_Filter_Node``
|
41 |
-
|
42 |
-
* As of Twig 2.x, the ``Twig_SimpleFilter`` class is deprecated and will be
|
43 |
-
removed in Twig 3.x (use ``Twig_Filter`` instead). In Twig 2.x,
|
44 |
-
``Twig_SimpleFilter`` is just an alias for ``Twig_Filter``.
|
45 |
-
|
46 |
-
Functions
|
47 |
-
---------
|
48 |
-
|
49 |
-
* As of Twig 1.x, use ``Twig_SimpleFunction`` to add a function. The following
|
50 |
-
classes and interfaces will be removed in 2.0:
|
51 |
-
|
52 |
-
* ``Twig_FunctionInterface``
|
53 |
-
* ``Twig_FunctionCallableInterface``
|
54 |
-
* ``Twig_Function``
|
55 |
-
* ``Twig_Function_Function``
|
56 |
-
* ``Twig_Function_Method``
|
57 |
-
* ``Twig_Function_Node``
|
58 |
-
|
59 |
-
* As of Twig 2.x, the ``Twig_SimpleFunction`` class is deprecated and will be
|
60 |
-
removed in Twig 3.x (use ``Twig_Function`` instead). In Twig 2.x,
|
61 |
-
``Twig_SimpleFunction`` is just an alias for ``Twig_Function``.
|
62 |
-
|
63 |
-
Tests
|
64 |
-
-----
|
65 |
-
|
66 |
-
* As of Twig 1.x, use ``Twig_SimpleTest`` to add a test. The following classes
|
67 |
-
and interfaces will be removed in 2.0:
|
68 |
-
|
69 |
-
* ``Twig_TestInterface``
|
70 |
-
* ``Twig_TestCallableInterface``
|
71 |
-
* ``Twig_Test``
|
72 |
-
* ``Twig_Test_Function``
|
73 |
-
* ``Twig_Test_Method``
|
74 |
-
* ``Twig_Test_Node``
|
75 |
-
|
76 |
-
* As of Twig 2.x, the ``Twig_SimpleTest`` class is deprecated and will be
|
77 |
-
removed in Twig 3.x (use ``Twig_Test`` instead). In Twig 2.x,
|
78 |
-
``Twig_SimpleTest`` is just an alias for ``Twig_Test``.
|
79 |
-
|
80 |
-
Interfaces
|
81 |
-
----------
|
82 |
-
|
83 |
-
* As of Twig 2.x, the following interfaces are deprecated and empty (they will
|
84 |
-
be removed in Twig 3.0):
|
85 |
-
|
86 |
-
* ``Twig_CompilerInterface`` (use ``Twig_Compiler`` instead)
|
87 |
-
* ``Twig_LexerInterface`` (use ``Twig_Lexer`` instead)
|
88 |
-
* ``Twig_NodeInterface`` (use ``Twig_Node`` instead)
|
89 |
-
* ``Twig_ParserInterface`` (use ``Twig_Parser`` instead)
|
90 |
-
* ``Twig_ExistsLoaderInterface`` (merged with ``Twig_LoaderInterface``)
|
91 |
-
* ``Twig_TemplateInterface`` (use ``Twig_Template`` instead)
|
92 |
-
|
93 |
-
Globals
|
94 |
-
-------
|
95 |
-
|
96 |
-
* As of Twig 2.x, the ability to register a global variable after the runtime
|
97 |
-
or the extensions have been initialized is not possible anymore (but
|
98 |
-
changing the value of an already registered global is possible).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/abs.rst
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
``abs``
|
2 |
-
=======
|
3 |
-
|
4 |
-
The ``abs`` filter returns the absolute value.
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{# number = -5 #}
|
9 |
-
|
10 |
-
{{ number|abs }}
|
11 |
-
|
12 |
-
{# outputs 5 #}
|
13 |
-
|
14 |
-
.. note::
|
15 |
-
|
16 |
-
Internally, Twig uses the PHP `abs`_ function.
|
17 |
-
|
18 |
-
.. _`abs`: http://php.net/abs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/capitalize.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``capitalize``
|
2 |
-
==============
|
3 |
-
|
4 |
-
The ``capitalize`` filter capitalizes a value. The first character will be
|
5 |
-
uppercase, all others lowercase:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{{ 'my first car'|capitalize }}
|
10 |
-
|
11 |
-
{# outputs 'My first car' #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/convert_encoding.rst
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
``convert_encoding``
|
2 |
-
====================
|
3 |
-
|
4 |
-
.. versionadded:: 1.4
|
5 |
-
The ``convert_encoding`` filter was added in Twig 1.4.
|
6 |
-
|
7 |
-
The ``convert_encoding`` filter converts a string from one encoding to
|
8 |
-
another. The first argument is the expected output charset and the second one
|
9 |
-
is the input charset:
|
10 |
-
|
11 |
-
.. code-block:: jinja
|
12 |
-
|
13 |
-
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
|
14 |
-
|
15 |
-
.. note::
|
16 |
-
|
17 |
-
This filter relies on the `iconv`_ or `mbstring`_ extension, so one of
|
18 |
-
them must be installed. In case both are installed, `mbstring`_ is used by
|
19 |
-
default (Twig before 1.8.1 uses `iconv`_ by default).
|
20 |
-
|
21 |
-
Arguments
|
22 |
-
---------
|
23 |
-
|
24 |
-
* ``from``: The input charset
|
25 |
-
* ``to``: The output charset
|
26 |
-
|
27 |
-
.. _`iconv`: http://php.net/iconv
|
28 |
-
.. _`mbstring`: http://php.net/mbstring
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/date.rst
DELETED
@@ -1,88 +0,0 @@
|
|
1 |
-
``date``
|
2 |
-
========
|
3 |
-
|
4 |
-
.. versionadded:: 1.1
|
5 |
-
The timezone support has been added in Twig 1.1.
|
6 |
-
|
7 |
-
.. versionadded:: 1.5
|
8 |
-
The default date format support has been added in Twig 1.5.
|
9 |
-
|
10 |
-
.. versionadded:: 1.6.1
|
11 |
-
The default timezone support has been added in Twig 1.6.1.
|
12 |
-
|
13 |
-
.. versionadded:: 1.11.0
|
14 |
-
The introduction of the false value for the timezone was introduced in Twig 1.11.0
|
15 |
-
|
16 |
-
The ``date`` filter formats a date to a given format:
|
17 |
-
|
18 |
-
.. code-block:: jinja
|
19 |
-
|
20 |
-
{{ post.published_at|date("m/d/Y") }}
|
21 |
-
|
22 |
-
The ``date`` filter accepts strings (it must be in a format supported by the
|
23 |
-
`strtotime`_ function), `DateTime`_ instances, or `DateInterval`_ instances. For
|
24 |
-
instance, to display the current date, filter the word "now":
|
25 |
-
|
26 |
-
.. code-block:: jinja
|
27 |
-
|
28 |
-
{{ "now"|date("m/d/Y") }}
|
29 |
-
|
30 |
-
To escape words and characters in the date format use ``\\`` in front of each
|
31 |
-
character:
|
32 |
-
|
33 |
-
.. code-block:: jinja
|
34 |
-
|
35 |
-
{{ post.published_at|date("F jS \\a\\t g:ia") }}
|
36 |
-
|
37 |
-
If the value passed to the ``date`` filter is ``null``, it will return the
|
38 |
-
current date by default. If an empty string is desired instead of the current
|
39 |
-
date, use a ternary operator:
|
40 |
-
|
41 |
-
.. code-block:: jinja
|
42 |
-
|
43 |
-
{{ post.published_at is empty ? "" : post.published_at|date("m/d/Y") }}
|
44 |
-
|
45 |
-
If no format is provided, Twig will use the default one: ``F j, Y H:i``. This
|
46 |
-
default can be easily changed by calling the ``setDateFormat()`` method on the
|
47 |
-
``core`` extension instance. The first argument is the default format for
|
48 |
-
dates and the second one is the default format for date intervals:
|
49 |
-
|
50 |
-
.. code-block:: php
|
51 |
-
|
52 |
-
$twig = new Twig_Environment($loader);
|
53 |
-
$twig->getExtension('core')->setDateFormat('d/m/Y', '%d days');
|
54 |
-
|
55 |
-
Timezone
|
56 |
-
--------
|
57 |
-
|
58 |
-
By default, the date is displayed by applying the default timezone (the one
|
59 |
-
specified in php.ini or declared in Twig -- see below), but you can override
|
60 |
-
it by explicitly specifying a timezone:
|
61 |
-
|
62 |
-
.. code-block:: jinja
|
63 |
-
|
64 |
-
{{ post.published_at|date("m/d/Y", "Europe/Paris") }}
|
65 |
-
|
66 |
-
If the date is already a DateTime object, and if you want to keep its current
|
67 |
-
timezone, pass ``false`` as the timezone value:
|
68 |
-
|
69 |
-
.. code-block:: jinja
|
70 |
-
|
71 |
-
{{ post.published_at|date("m/d/Y", false) }}
|
72 |
-
|
73 |
-
The default timezone can also be set globally by calling ``setTimezone()``:
|
74 |
-
|
75 |
-
.. code-block:: php
|
76 |
-
|
77 |
-
$twig = new Twig_Environment($loader);
|
78 |
-
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
79 |
-
|
80 |
-
Arguments
|
81 |
-
---------
|
82 |
-
|
83 |
-
* ``format``: The date format
|
84 |
-
* ``timezone``: The date timezone
|
85 |
-
|
86 |
-
.. _`strtotime`: http://www.php.net/strtotime
|
87 |
-
.. _`DateTime`: http://www.php.net/DateTime
|
88 |
-
.. _`DateInterval`: http://www.php.net/DateInterval
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/date_modify.rst
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
``date_modify``
|
2 |
-
===============
|
3 |
-
|
4 |
-
.. versionadded:: 1.9.0
|
5 |
-
The date_modify filter has been added in Twig 1.9.0.
|
6 |
-
|
7 |
-
The ``date_modify`` filter modifies a date with a given modifier string:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{{ post.published_at|date_modify("+1 day")|date("m/d/Y") }}
|
12 |
-
|
13 |
-
The ``date_modify`` filter accepts strings (it must be in a format supported
|
14 |
-
by the `strtotime`_ function) or `DateTime`_ instances. You can easily combine
|
15 |
-
it with the :doc:`date<date>` filter for formatting.
|
16 |
-
|
17 |
-
Arguments
|
18 |
-
---------
|
19 |
-
|
20 |
-
* ``modifier``: The modifier
|
21 |
-
|
22 |
-
.. _`strtotime`: http://www.php.net/strtotime
|
23 |
-
.. _`DateTime`: http://www.php.net/DateTime
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/default.rst
DELETED
@@ -1,33 +0,0 @@
|
|
1 |
-
``default``
|
2 |
-
===========
|
3 |
-
|
4 |
-
The ``default`` filter returns the passed default value if the value is
|
5 |
-
undefined or empty, otherwise the value of the variable:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{{ var|default('var is not defined') }}
|
10 |
-
|
11 |
-
{{ var.foo|default('foo item on var is not defined') }}
|
12 |
-
|
13 |
-
{{ var['foo']|default('foo item on var is not defined') }}
|
14 |
-
|
15 |
-
{{ ''|default('passed var is empty') }}
|
16 |
-
|
17 |
-
When using the ``default`` filter on an expression that uses variables in some
|
18 |
-
method calls, be sure to use the ``default`` filter whenever a variable can be
|
19 |
-
undefined:
|
20 |
-
|
21 |
-
.. code-block:: jinja
|
22 |
-
|
23 |
-
{{ var.method(foo|default('foo'))|default('foo') }}
|
24 |
-
|
25 |
-
.. note::
|
26 |
-
|
27 |
-
Read the documentation for the :doc:`defined<../tests/defined>` and
|
28 |
-
:doc:`empty<../tests/empty>` tests to learn more about their semantics.
|
29 |
-
|
30 |
-
Arguments
|
31 |
-
---------
|
32 |
-
|
33 |
-
* ``default``: The default value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/escape.rst
DELETED
@@ -1,93 +0,0 @@
|
|
1 |
-
``escape``
|
2 |
-
==========
|
3 |
-
|
4 |
-
.. versionadded:: 1.9.0
|
5 |
-
The ``css``, ``url``, and ``html_attr`` strategies were added in Twig
|
6 |
-
1.9.0.
|
7 |
-
|
8 |
-
The ``escape`` filter escapes a string for safe insertion into the final
|
9 |
-
output. It supports different escaping strategies depending on the template
|
10 |
-
context.
|
11 |
-
|
12 |
-
By default, it uses the HTML escaping strategy:
|
13 |
-
|
14 |
-
.. code-block:: jinja
|
15 |
-
|
16 |
-
{{ user.username|escape }}
|
17 |
-
|
18 |
-
For convenience, the ``e`` filter is defined as an alias:
|
19 |
-
|
20 |
-
.. code-block:: jinja
|
21 |
-
|
22 |
-
{{ user.username|e }}
|
23 |
-
|
24 |
-
The ``escape`` filter can also be used in other contexts than HTML thanks to
|
25 |
-
an optional argument which defines the escaping strategy to use:
|
26 |
-
|
27 |
-
.. code-block:: jinja
|
28 |
-
|
29 |
-
{{ user.username|e }}
|
30 |
-
{# is equivalent to #}
|
31 |
-
{{ user.username|e('html') }}
|
32 |
-
|
33 |
-
And here is how to escape variables included in JavaScript code:
|
34 |
-
|
35 |
-
.. code-block:: jinja
|
36 |
-
|
37 |
-
{{ user.username|escape('js') }}
|
38 |
-
{{ user.username|e('js') }}
|
39 |
-
|
40 |
-
The ``escape`` filter supports the following escaping strategies:
|
41 |
-
|
42 |
-
* ``html``: escapes a string for the **HTML body** context.
|
43 |
-
|
44 |
-
* ``js``: escapes a string for the **JavaScript context**.
|
45 |
-
|
46 |
-
* ``css``: escapes a string for the **CSS context**. CSS escaping can be
|
47 |
-
applied to any string being inserted into CSS and escapes everything except
|
48 |
-
alphanumerics.
|
49 |
-
|
50 |
-
* ``url``: escapes a string for the **URI or parameter contexts**. This should
|
51 |
-
not be used to escape an entire URI; only a subcomponent being inserted.
|
52 |
-
|
53 |
-
* ``html_attr``: escapes a string for the **HTML attribute** context.
|
54 |
-
|
55 |
-
.. note::
|
56 |
-
|
57 |
-
Internally, ``escape`` uses the PHP native `htmlspecialchars`_ function
|
58 |
-
for the HTML escaping strategy.
|
59 |
-
|
60 |
-
.. caution::
|
61 |
-
|
62 |
-
When using automatic escaping, Twig tries to not double-escape a variable
|
63 |
-
when the automatic escaping strategy is the same as the one applied by the
|
64 |
-
escape filter; but that does not work when using a variable as the
|
65 |
-
escaping strategy:
|
66 |
-
|
67 |
-
.. code-block:: jinja
|
68 |
-
|
69 |
-
{% set strategy = 'html' %}
|
70 |
-
|
71 |
-
{% autoescape 'html' %}
|
72 |
-
{{ var|escape('html') }} {# won't be double-escaped #}
|
73 |
-
{{ var|escape(strategy) }} {# will be double-escaped #}
|
74 |
-
{% endautoescape %}
|
75 |
-
|
76 |
-
When using a variable as the escaping strategy, you should disable
|
77 |
-
automatic escaping:
|
78 |
-
|
79 |
-
.. code-block:: jinja
|
80 |
-
|
81 |
-
{% set strategy = 'html' %}
|
82 |
-
|
83 |
-
{% autoescape 'html' %}
|
84 |
-
{{ var|escape(strategy)|raw }} {# won't be double-escaped #}
|
85 |
-
{% endautoescape %}
|
86 |
-
|
87 |
-
Arguments
|
88 |
-
---------
|
89 |
-
|
90 |
-
* ``strategy``: The escaping strategy
|
91 |
-
* ``charset``: The string charset
|
92 |
-
|
93 |
-
.. _`htmlspecialchars`: http://php.net/htmlspecialchars
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/format.rst
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
``format``
|
2 |
-
==========
|
3 |
-
|
4 |
-
The ``format`` filter formats a given string by replacing the placeholders
|
5 |
-
(placeholders follows the `printf`_ notation):
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{{ "I like %s and %s."|format(foo, "bar") }}
|
10 |
-
|
11 |
-
{# returns I like foo and bar
|
12 |
-
if the foo parameter equals to the foo string. #}
|
13 |
-
|
14 |
-
.. _`printf`: http://www.php.net/printf
|
15 |
-
|
16 |
-
.. seealso:: :doc:`replace<replace>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/index.rst
DELETED
@@ -1,33 +0,0 @@
|
|
1 |
-
Filters
|
2 |
-
=======
|
3 |
-
|
4 |
-
.. toctree::
|
5 |
-
:maxdepth: 1
|
6 |
-
|
7 |
-
date
|
8 |
-
date_modify
|
9 |
-
format
|
10 |
-
replace
|
11 |
-
number_format
|
12 |
-
url_encode
|
13 |
-
json_encode
|
14 |
-
convert_encoding
|
15 |
-
title
|
16 |
-
capitalize
|
17 |
-
nl2br
|
18 |
-
upper
|
19 |
-
lower
|
20 |
-
striptags
|
21 |
-
join
|
22 |
-
split
|
23 |
-
reverse
|
24 |
-
abs
|
25 |
-
length
|
26 |
-
sort
|
27 |
-
default
|
28 |
-
keys
|
29 |
-
escape
|
30 |
-
raw
|
31 |
-
merge
|
32 |
-
slice
|
33 |
-
trim
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/join.rst
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
``join``
|
2 |
-
========
|
3 |
-
|
4 |
-
The ``join`` filter returns a string which is the concatenation of the items
|
5 |
-
of a sequence:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{{ [1, 2, 3]|join }}
|
10 |
-
{# returns 123 #}
|
11 |
-
|
12 |
-
The separator between elements is an empty string per default, but you can
|
13 |
-
define it with the optional first parameter:
|
14 |
-
|
15 |
-
.. code-block:: jinja
|
16 |
-
|
17 |
-
{{ [1, 2, 3]|join('|') }}
|
18 |
-
{# returns 1|2|3 #}
|
19 |
-
|
20 |
-
Arguments
|
21 |
-
---------
|
22 |
-
|
23 |
-
* ``glue``: The separator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/json_encode.rst
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
``json_encode``
|
2 |
-
===============
|
3 |
-
|
4 |
-
The ``json_encode`` filter returns the JSON representation of a string:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ data|json_encode() }}
|
9 |
-
|
10 |
-
.. note::
|
11 |
-
|
12 |
-
Internally, Twig uses the PHP `json_encode`_ function.
|
13 |
-
|
14 |
-
Arguments
|
15 |
-
---------
|
16 |
-
|
17 |
-
* ``options``: The options
|
18 |
-
|
19 |
-
.. _`json_encode`: http://php.net/json_encode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/keys.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``keys``
|
2 |
-
========
|
3 |
-
|
4 |
-
The ``keys`` filter returns the keys of an array. It is useful when you want to
|
5 |
-
iterate over the keys of an array:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% for key in array|keys %}
|
10 |
-
...
|
11 |
-
{% endfor %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/length.rst
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
``length``
|
2 |
-
==========
|
3 |
-
|
4 |
-
The ``length`` filters returns the number of items of a sequence or mapping, or
|
5 |
-
the length of a string:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% if users|length > 10 %}
|
10 |
-
...
|
11 |
-
{% endif %}
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/lower.rst
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
``lower``
|
2 |
-
=========
|
3 |
-
|
4 |
-
The ``lower`` filter converts a value to lowercase:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ 'WELCOME'|lower }}
|
9 |
-
|
10 |
-
{# outputs 'welcome' #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/merge.rst
DELETED
@@ -1,41 +0,0 @@
|
|
1 |
-
``merge``
|
2 |
-
=========
|
3 |
-
|
4 |
-
The ``merge`` filter merges an array with the another array:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{% set values = [1, 2] %}
|
9 |
-
|
10 |
-
{% set values = values|merge(['apple', 'orange']) %}
|
11 |
-
|
12 |
-
{# values now contains [1, 2, 'apple', 'orange'] #}
|
13 |
-
|
14 |
-
New values are added at the end of the existing ones.
|
15 |
-
|
16 |
-
The ``merge`` filter also works on hashes:
|
17 |
-
|
18 |
-
.. code-block:: jinja
|
19 |
-
|
20 |
-
{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}
|
21 |
-
|
22 |
-
{% set items = items|merge({ 'peugeot': 'car', 'renault': 'car' }) %}
|
23 |
-
|
24 |
-
{# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car', 'renault': 'car' } #}
|
25 |
-
|
26 |
-
For hashes, the merging process occurs on the keys: if the key does not
|
27 |
-
already exist, it is added but if the key already exists, its value is
|
28 |
-
overridden.
|
29 |
-
|
30 |
-
.. tip::
|
31 |
-
|
32 |
-
If you want to ensure that some values are defined in an array (by given
|
33 |
-
default values), reverse the two elements in the call:
|
34 |
-
|
35 |
-
.. code-block:: jinja
|
36 |
-
|
37 |
-
{% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
|
38 |
-
|
39 |
-
{% set items = { 'apple': 'unknown' }|merge(items) %}
|
40 |
-
|
41 |
-
{# items now contains { 'apple': 'fruit', 'orange': 'fruit' } #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/nl2br.rst
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
``nl2br``
|
2 |
-
=========
|
3 |
-
|
4 |
-
.. versionadded:: 1.5
|
5 |
-
The nl2br filter was added in Twig 1.5.
|
6 |
-
|
7 |
-
The ``nl2br`` filter inserts HTML line breaks before all newlines in a string:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{{ "I like Twig.\nYou will like it too."|nl2br }}
|
12 |
-
{# outputs
|
13 |
-
|
14 |
-
I like Twig.<br />
|
15 |
-
You will like it too.
|
16 |
-
|
17 |
-
#}
|
18 |
-
|
19 |
-
.. note::
|
20 |
-
|
21 |
-
The ``nl2br`` filter pre-escapes the input before applying the
|
22 |
-
transformation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/number_format.rst
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
``number_format``
|
2 |
-
=================
|
3 |
-
|
4 |
-
.. versionadded:: 1.5
|
5 |
-
The number_format filter was added in Twig 1.5
|
6 |
-
|
7 |
-
The ``number_format`` filter formats numbers. It is a wrapper around PHP's
|
8 |
-
`number_format`_ function:
|
9 |
-
|
10 |
-
.. code-block:: jinja
|
11 |
-
|
12 |
-
{{ 200.35|number_format }}
|
13 |
-
|
14 |
-
You can control the number of decimal places, decimal point, and thousands
|
15 |
-
separator using the additional arguments:
|
16 |
-
|
17 |
-
.. code-block:: jinja
|
18 |
-
|
19 |
-
{{ 9800.333|number_format(2, '.', ',') }}
|
20 |
-
|
21 |
-
If no formatting options are provided then Twig will use the default formatting
|
22 |
-
options of:
|
23 |
-
|
24 |
-
- 0 decimal places.
|
25 |
-
- ``.`` as the decimal point.
|
26 |
-
- ``,`` as the thousands separator.
|
27 |
-
|
28 |
-
These defaults can be easily changed through the core extension:
|
29 |
-
|
30 |
-
.. code-block:: php
|
31 |
-
|
32 |
-
$twig = new Twig_Environment($loader);
|
33 |
-
$twig->getExtension('core')->setNumberFormat(3, '.', ',');
|
34 |
-
|
35 |
-
The defaults set for ``number_format`` can be over-ridden upon each call using the
|
36 |
-
additional parameters.
|
37 |
-
|
38 |
-
Arguments
|
39 |
-
---------
|
40 |
-
|
41 |
-
* ``decimal``: The number of decimal points to display
|
42 |
-
* ``decimal_point``: The character(s) to use for the decimal point
|
43 |
-
* ``decimal_sep``: The character(s) to use for the thousands separator
|
44 |
-
|
45 |
-
.. _`number_format`: http://php.net/number_format
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/raw.rst
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
``raw``
|
2 |
-
=======
|
3 |
-
|
4 |
-
The ``raw`` filter marks the value as being "safe", which means that in an
|
5 |
-
environment with automatic escaping enabled this variable will not be escaped
|
6 |
-
if ``raw`` is the last filter applied to it:
|
7 |
-
|
8 |
-
.. code-block:: jinja
|
9 |
-
|
10 |
-
{% autoescape true %}
|
11 |
-
{{ var|raw }} {# var won't be escaped #}
|
12 |
-
{% endautoescape %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/replace.rst
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
``replace``
|
2 |
-
===========
|
3 |
-
|
4 |
-
The ``replace`` filter formats a given string by replacing the placeholders
|
5 |
-
(placeholders are free-form):
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{{ "I like %this% and %that%."|replace({'%this%': foo, '%that%': "bar"}) }}
|
10 |
-
|
11 |
-
{# returns I like foo and bar
|
12 |
-
if the foo parameter equals to the foo string. #}
|
13 |
-
|
14 |
-
Arguments
|
15 |
-
---------
|
16 |
-
|
17 |
-
* ``replace_pairs``: The placeholder values
|
18 |
-
|
19 |
-
.. seealso:: :doc:`format<format>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/reverse.rst
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
``reverse``
|
2 |
-
===========
|
3 |
-
|
4 |
-
.. versionadded:: 1.6
|
5 |
-
Support for strings has been added in Twig 1.6.
|
6 |
-
|
7 |
-
The ``reverse`` filter reverses a sequence, a mapping, or a string:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{% for use in users|reverse %}
|
12 |
-
...
|
13 |
-
{% endfor %}
|
14 |
-
|
15 |
-
{{ '1234'|reverse }}
|
16 |
-
|
17 |
-
{# outputs 4321 #}
|
18 |
-
|
19 |
-
.. note::
|
20 |
-
|
21 |
-
It also works with objects implementing the `Traversable`_ interface.
|
22 |
-
|
23 |
-
.. _`Traversable`: http://php.net/Traversable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/slice.rst
DELETED
@@ -1,70 +0,0 @@
|
|
1 |
-
``slice``
|
2 |
-
===========
|
3 |
-
|
4 |
-
.. versionadded:: 1.6
|
5 |
-
The slice filter was added in Twig 1.6.
|
6 |
-
|
7 |
-
The ``slice`` filter extracts a slice of a sequence, a mapping, or a string:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{% for i in [1, 2, 3, 4]|slice(1, 2) %}
|
12 |
-
{# will iterate over 2 and 3 #}
|
13 |
-
{% endfor %}
|
14 |
-
|
15 |
-
{{ '1234'|slice(1, 2) }}
|
16 |
-
|
17 |
-
{# outputs 23 #}
|
18 |
-
|
19 |
-
You can use any valid expression for both the start and the length:
|
20 |
-
|
21 |
-
.. code-block:: jinja
|
22 |
-
|
23 |
-
{% for i in [1, 2, 3, 4]|slice(start, length) %}
|
24 |
-
{# ... #}
|
25 |
-
{% endfor %}
|
26 |
-
|
27 |
-
As syntactic sugar, you can also use the ``[]`` notation:
|
28 |
-
|
29 |
-
.. code-block:: jinja
|
30 |
-
|
31 |
-
{% for i in [1, 2, 3, 4][start:length] %}
|
32 |
-
{# ... #}
|
33 |
-
{% endfor %}
|
34 |
-
|
35 |
-
{{ '1234'[1:2] }}
|
36 |
-
|
37 |
-
{# you can omit the first argument -- which is the same as 0 #}
|
38 |
-
{{ '1234'[:2] }} {# will display "12" #}
|
39 |
-
|
40 |
-
{# you can omit the last argument -- which will select everything till the end #}
|
41 |
-
{{ '1234'[2:] }} {# will display "34 #}
|
42 |
-
|
43 |
-
The ``slice`` filter works as the `array_slice`_ PHP function for arrays and
|
44 |
-
`substr`_ for strings.
|
45 |
-
|
46 |
-
If the start is non-negative, the sequence will start at that start in the
|
47 |
-
variable. If start is negative, the sequence will start that far from the end
|
48 |
-
of the variable.
|
49 |
-
|
50 |
-
If length is given and is positive, then the sequence will have up to that
|
51 |
-
many elements in it. If the variable is shorter than the length, then only the
|
52 |
-
available variable elements will be present. If length is given and is
|
53 |
-
negative then the sequence will stop that many elements from the end of the
|
54 |
-
variable. If it is omitted, then the sequence will have everything from offset
|
55 |
-
up until the end of the variable.
|
56 |
-
|
57 |
-
.. note::
|
58 |
-
|
59 |
-
It also works with objects implementing the `Traversable`_ interface.
|
60 |
-
|
61 |
-
Arguments
|
62 |
-
---------
|
63 |
-
|
64 |
-
* ``start``: The start of the slice
|
65 |
-
* ``length``: The size of the slice
|
66 |
-
* ``preserve_keys``: Whether to preserve key or not (when the input is an array)
|
67 |
-
|
68 |
-
.. _`Traversable`: http://php.net/manual/en/class.traversable.php
|
69 |
-
.. _`array_slice`: http://php.net/array_slice
|
70 |
-
.. _`substr`: http://php.net/substr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/sort.rst
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
``sort``
|
2 |
-
========
|
3 |
-
|
4 |
-
The ``sort`` filter sorts an array:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{% for use in users|sort %}
|
9 |
-
...
|
10 |
-
{% endfor %}
|
11 |
-
|
12 |
-
.. note::
|
13 |
-
|
14 |
-
Internally, Twig uses the PHP `asort`_ function to maintain index
|
15 |
-
association.
|
16 |
-
|
17 |
-
.. _`asort`: http://php.net/asort
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/split.rst
DELETED
@@ -1,53 +0,0 @@
|
|
1 |
-
``split``
|
2 |
-
=========
|
3 |
-
|
4 |
-
.. versionadded:: 1.10.3
|
5 |
-
The split filter was added in Twig 1.10.3.
|
6 |
-
|
7 |
-
The ``split`` filter splits a string by the given delimiter and returns a list
|
8 |
-
of strings:
|
9 |
-
|
10 |
-
.. code-block:: jinja
|
11 |
-
|
12 |
-
{{ "one,two,three"|split(',') }}
|
13 |
-
{# returns ['one', 'two', 'three'] #}
|
14 |
-
|
15 |
-
You can also pass a ``limit`` argument:
|
16 |
-
|
17 |
-
* If ``limit`` is positive, the returned array will contain a maximum of
|
18 |
-
limit elements with the last element containing the rest of string;
|
19 |
-
|
20 |
-
* If ``limit`` is negative, all components except the last -limit are
|
21 |
-
returned;
|
22 |
-
|
23 |
-
* If ``limit`` is zero, then this is treated as 1.
|
24 |
-
|
25 |
-
.. code-block:: jinja
|
26 |
-
|
27 |
-
{{ "one,two,three,four,five"|split(',', 3) }}
|
28 |
-
{# returns ['one', 'two', 'three,four,five'] #}
|
29 |
-
|
30 |
-
If the ``delimiter`` is an empty string, then value will be split by equal
|
31 |
-
chunks. Length is set by the ``limit`` argument (one character by default).
|
32 |
-
|
33 |
-
.. code-block:: jinja
|
34 |
-
|
35 |
-
{{ "123"|split('') }}
|
36 |
-
{# returns ['1', '2', '3'] #}
|
37 |
-
|
38 |
-
{{ "aabbcc"|split('', 2) }}
|
39 |
-
{# returns ['aa', 'bb', 'cc'] #}
|
40 |
-
|
41 |
-
.. note::
|
42 |
-
|
43 |
-
Internally, Twig uses the PHP `explode`_ or `str_split`_ (if delimiter is
|
44 |
-
empty) functions for string splitting.
|
45 |
-
|
46 |
-
Arguments
|
47 |
-
---------
|
48 |
-
|
49 |
-
* ``delimiter``: The delimiter
|
50 |
-
* ``limit``: The limit argument
|
51 |
-
|
52 |
-
.. _`explode`: http://php.net/explode
|
53 |
-
.. _`str_split`: http://php.net/str_split
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/striptags.rst
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
``striptags``
|
2 |
-
=============
|
3 |
-
|
4 |
-
The ``striptags`` filter strips SGML/XML tags and replace adjacent whitespace
|
5 |
-
by one space:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% some_html|striptags %}
|
10 |
-
|
11 |
-
.. note::
|
12 |
-
|
13 |
-
Internally, Twig uses the PHP `strip_tags`_ function.
|
14 |
-
|
15 |
-
.. _`strip_tags`: http://php.net/strip_tags
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/title.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``title``
|
2 |
-
=========
|
3 |
-
|
4 |
-
The ``title`` filter returns a titlecased version of the value. Words will
|
5 |
-
start with uppercase letters, all remaining characters are lowercase:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{{ 'my first car'|title }}
|
10 |
-
|
11 |
-
{# outputs 'My First Car' #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/trim.rst
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
``trim``
|
2 |
-
========
|
3 |
-
|
4 |
-
.. versionadded:: 1.6.2
|
5 |
-
The trim filter was added in Twig 1.6.2.
|
6 |
-
|
7 |
-
The ``trim`` filter strips whitespace (or other characters) from the beginning
|
8 |
-
and end of a string:
|
9 |
-
|
10 |
-
.. code-block:: jinja
|
11 |
-
|
12 |
-
{{ ' I like Twig. '|trim }}
|
13 |
-
|
14 |
-
{# outputs 'I like Twig.' #}
|
15 |
-
|
16 |
-
{{ ' I like Twig.'|trim('.') }}
|
17 |
-
|
18 |
-
{# outputs ' I like Twig' #}
|
19 |
-
|
20 |
-
.. note::
|
21 |
-
|
22 |
-
Internally, Twig uses the PHP `trim`_ function.
|
23 |
-
|
24 |
-
Arguments
|
25 |
-
---------
|
26 |
-
|
27 |
-
* ``character_mask``: The characters to strip
|
28 |
-
|
29 |
-
.. _`trim`: http://php.net/trim
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/upper.rst
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
``upper``
|
2 |
-
=========
|
3 |
-
|
4 |
-
The ``upper`` filter converts a value to uppercase:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ 'welcome'|upper }}
|
9 |
-
|
10 |
-
{# outputs 'WELCOME' #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/filters/url_encode.rst
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
``url_encode``
|
2 |
-
==============
|
3 |
-
|
4 |
-
The ``url_encode`` filter URL encodes a given string:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ data|url_encode() }}
|
9 |
-
|
10 |
-
.. note::
|
11 |
-
|
12 |
-
Internally, Twig uses the PHP `urlencode`_ function.
|
13 |
-
|
14 |
-
.. _`urlencode`: http://php.net/urlencode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/attribute.rst
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
``attribute``
|
2 |
-
=============
|
3 |
-
|
4 |
-
.. versionadded:: 1.2
|
5 |
-
The ``attribute`` function was added in Twig 1.2.
|
6 |
-
|
7 |
-
``attribute`` can be used to access a "dynamic" attribute of a variable:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{{ attribute(object, method) }}
|
12 |
-
{{ attribute(object, method, arguments) }}
|
13 |
-
{{ attribute(array, item) }}
|
14 |
-
|
15 |
-
.. note::
|
16 |
-
|
17 |
-
The resolution algorithm is the same as the one used for the ``.``
|
18 |
-
notation, except that the item can be any valid expression.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/block.rst
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
``block``
|
2 |
-
=========
|
3 |
-
|
4 |
-
When a template uses inheritance and if you want to print a block multiple
|
5 |
-
times, use the ``block`` function:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
<title>{% block title %}{% endblock %}</title>
|
10 |
-
|
11 |
-
<h1>{{ block('title') }}</h1>
|
12 |
-
|
13 |
-
{% block body %}{% endblock %}
|
14 |
-
|
15 |
-
.. seealso:: :doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/constant.rst
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
``constant``
|
2 |
-
============
|
3 |
-
|
4 |
-
.. versionadded: 1.12.1
|
5 |
-
constant now accepts object instances as the second argument.
|
6 |
-
|
7 |
-
``constant`` returns the constant value for a given string:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{{ some_date|date(constant('DATE_W3C')) }}
|
12 |
-
{{ constant('Namespace\\Classname::CONSTANT_NAME') }}
|
13 |
-
|
14 |
-
As of 1.12.1 you can read constants from object instances as well:
|
15 |
-
|
16 |
-
.. code-block:: jinja
|
17 |
-
|
18 |
-
{{ constant('RSS', date) }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/cycle.rst
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
``cycle``
|
2 |
-
=========
|
3 |
-
|
4 |
-
The ``cycle`` function cycles on an array of values:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{% for i in 0..10 %}
|
9 |
-
{{ cycle(['odd', 'even'], i) }}
|
10 |
-
{% endfor %}
|
11 |
-
|
12 |
-
The array can contain any number of values:
|
13 |
-
|
14 |
-
.. code-block:: jinja
|
15 |
-
|
16 |
-
{% set fruits = ['apple', 'orange', 'citrus'] %}
|
17 |
-
|
18 |
-
{% for i in 0..10 %}
|
19 |
-
{{ cycle(fruits, i) }}
|
20 |
-
{% endfor %}
|
21 |
-
|
22 |
-
Arguments
|
23 |
-
---------
|
24 |
-
|
25 |
-
* ``position``: The cycle position
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/date.rst
DELETED
@@ -1,52 +0,0 @@
|
|
1 |
-
``date``
|
2 |
-
========
|
3 |
-
|
4 |
-
.. versionadded:: 1.6
|
5 |
-
The date function has been added in Twig 1.6.
|
6 |
-
|
7 |
-
.. versionadded:: 1.6.1
|
8 |
-
The default timezone support has been added in Twig 1.6.1.
|
9 |
-
|
10 |
-
Converts an argument to a date to allow date comparison:
|
11 |
-
|
12 |
-
.. code-block:: jinja
|
13 |
-
|
14 |
-
{% if date(user.created_at) < date('+2days') %}
|
15 |
-
{# do something #}
|
16 |
-
{% endif %}
|
17 |
-
|
18 |
-
The argument must be in a format supported by the `date`_ function.
|
19 |
-
|
20 |
-
You can pass a timezone as the second argument:
|
21 |
-
|
22 |
-
.. code-block:: jinja
|
23 |
-
|
24 |
-
{% if date(user.created_at) < date('+2days', 'Europe/Paris') %}
|
25 |
-
{# do something #}
|
26 |
-
{% endif %}
|
27 |
-
|
28 |
-
If no argument is passed, the function returns the current date:
|
29 |
-
|
30 |
-
.. code-block:: jinja
|
31 |
-
|
32 |
-
{% if date(user.created_at) < date() %}
|
33 |
-
{# always! #}
|
34 |
-
{% endif %}
|
35 |
-
|
36 |
-
.. note::
|
37 |
-
|
38 |
-
You can set the default timezone globally by calling ``setTimezone()`` on
|
39 |
-
the ``core`` extension instance:
|
40 |
-
|
41 |
-
.. code-block:: php
|
42 |
-
|
43 |
-
$twig = new Twig_Environment($loader);
|
44 |
-
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
45 |
-
|
46 |
-
Arguments
|
47 |
-
---------
|
48 |
-
|
49 |
-
* ``date``: The date
|
50 |
-
* ``timezone``: The timezone
|
51 |
-
|
52 |
-
.. _`date`: http://www.php.net/date
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/dump.rst
DELETED
@@ -1,69 +0,0 @@
|
|
1 |
-
``dump``
|
2 |
-
========
|
3 |
-
|
4 |
-
.. versionadded:: 1.5
|
5 |
-
The dump function was added in Twig 1.5.
|
6 |
-
|
7 |
-
The ``dump`` function dumps information about a template variable. This is
|
8 |
-
mostly useful to debug a template that does not behave as expected by
|
9 |
-
introspecting its variables:
|
10 |
-
|
11 |
-
.. code-block:: jinja
|
12 |
-
|
13 |
-
{{ dump(user) }}
|
14 |
-
|
15 |
-
.. note::
|
16 |
-
|
17 |
-
The ``dump`` function is not available by default. You must add the
|
18 |
-
``Twig_Extension_Debug`` extension explicitly when creating your Twig
|
19 |
-
environment::
|
20 |
-
|
21 |
-
$twig = new Twig_Environment($loader, array(
|
22 |
-
'debug' => true,
|
23 |
-
// ...
|
24 |
-
));
|
25 |
-
$twig->addExtension(new Twig_Extension_Debug());
|
26 |
-
|
27 |
-
Even when enabled, the ``dump`` function won't display anything if the
|
28 |
-
``debug`` option on the environment is not enabled (to avoid leaking debug
|
29 |
-
information on a production server).
|
30 |
-
|
31 |
-
In an HTML context, wrap the output with a ``pre`` tag to make it easier to
|
32 |
-
read:
|
33 |
-
|
34 |
-
.. code-block:: jinja
|
35 |
-
|
36 |
-
<pre>
|
37 |
-
{{ dump(user) }}
|
38 |
-
</pre>
|
39 |
-
|
40 |
-
.. tip::
|
41 |
-
|
42 |
-
Using a ``pre`` tag is not needed when `XDebug`_ is enabled and
|
43 |
-
``html_errors`` is ``on``; as a bonus, the output is also nicer with
|
44 |
-
XDebug enabled.
|
45 |
-
|
46 |
-
You can debug several variables by passing them as additional arguments:
|
47 |
-
|
48 |
-
.. code-block:: jinja
|
49 |
-
|
50 |
-
{{ dump(user, categories) }}
|
51 |
-
|
52 |
-
If you don't pass any value, all variables from the current context are
|
53 |
-
dumped:
|
54 |
-
|
55 |
-
.. code-block:: jinja
|
56 |
-
|
57 |
-
{{ dump() }}
|
58 |
-
|
59 |
-
.. note::
|
60 |
-
|
61 |
-
Internally, Twig uses the PHP `var_dump`_ function.
|
62 |
-
|
63 |
-
Arguments
|
64 |
-
---------
|
65 |
-
|
66 |
-
* ``context``: The context to dump
|
67 |
-
|
68 |
-
.. _`XDebug`: http://xdebug.org/docs/display
|
69 |
-
.. _`var_dump`: http://php.net/var_dump
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/include.rst
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
``include``
|
2 |
-
===========
|
3 |
-
|
4 |
-
.. versionadded:: 1.12
|
5 |
-
The include function was added in Twig 1.12.
|
6 |
-
|
7 |
-
The ``include`` function returns the rendered content of a template:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{{ include('template.html') }}
|
12 |
-
{{ include(some_var) }}
|
13 |
-
|
14 |
-
Included templates have access to the variables of the active context.
|
15 |
-
|
16 |
-
If you are using the filesystem loader, the templates are looked for in the
|
17 |
-
paths defined by it.
|
18 |
-
|
19 |
-
The context is passed by default to the template but you can also pass
|
20 |
-
additional variables:
|
21 |
-
|
22 |
-
.. code-block:: jinja
|
23 |
-
|
24 |
-
{# template.html will have access to the variables from the current context and the additional ones provided #}
|
25 |
-
{{ include('template.html', {foo: 'bar'}) }}
|
26 |
-
|
27 |
-
You can disable access to the context by setting ``with_context`` to
|
28 |
-
``false``:
|
29 |
-
|
30 |
-
.. code-block:: jinja
|
31 |
-
|
32 |
-
{# only the foo variable will be accessible #}
|
33 |
-
{{ include('template.html', {foo: 'bar'}, with_context = false) }}
|
34 |
-
|
35 |
-
.. code-block:: jinja
|
36 |
-
|
37 |
-
{# no variables will be accessible #}
|
38 |
-
{{ include('template.html', with_context = false) }}
|
39 |
-
|
40 |
-
And if the expression evaluates to a ``Twig_Template`` object, Twig will use it
|
41 |
-
directly::
|
42 |
-
|
43 |
-
// {{ include(template) }}
|
44 |
-
|
45 |
-
$template = $twig->loadTemplate('some_template.twig');
|
46 |
-
|
47 |
-
$twig->loadTemplate('template.twig')->display(array('template' => $template));
|
48 |
-
|
49 |
-
When you set the ``ignore_missing`` flag, Twig will return an empty string if
|
50 |
-
the template does not exist:
|
51 |
-
|
52 |
-
.. code-block:: jinja
|
53 |
-
|
54 |
-
{{ include('sidebar.html', ignore_missing = true) }}
|
55 |
-
|
56 |
-
You can also provide a list of templates that are checked for existence before
|
57 |
-
inclusion. The first template that exists will be rendered:
|
58 |
-
|
59 |
-
.. code-block:: jinja
|
60 |
-
|
61 |
-
{{ include(['page_detailed.html', 'page.html']) }}
|
62 |
-
|
63 |
-
If ``ignore_missing`` is set, it will fall back to rendering nothing if none
|
64 |
-
of the templates exist, otherwise it will throw an exception.
|
65 |
-
|
66 |
-
When including a template created by an end user, you should consider
|
67 |
-
sandboxing it:
|
68 |
-
|
69 |
-
.. code-block:: jinja
|
70 |
-
|
71 |
-
{{ include('page.html', sandboxed = true) }}
|
72 |
-
|
73 |
-
Arguments
|
74 |
-
---------
|
75 |
-
|
76 |
-
* ``template``: The template to render
|
77 |
-
* ``variables``: The variables to pass to the template
|
78 |
-
* ``with_context``: Whether to pass the current context variables or not
|
79 |
-
* ``ignore_missing``: Whether to ignore missing templates or not
|
80 |
-
* ``sandboxed``: Whether to sandbox the template or not
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/index.rst
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
Functions
|
2 |
-
=========
|
3 |
-
|
4 |
-
.. toctree::
|
5 |
-
:maxdepth: 1
|
6 |
-
|
7 |
-
range
|
8 |
-
cycle
|
9 |
-
constant
|
10 |
-
random
|
11 |
-
attribute
|
12 |
-
block
|
13 |
-
parent
|
14 |
-
dump
|
15 |
-
date
|
16 |
-
template_from_string
|
17 |
-
include
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/parent.rst
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
``parent``
|
2 |
-
==========
|
3 |
-
|
4 |
-
When a template uses inheritance, it's possible to render the contents of the
|
5 |
-
parent block when overriding a block by using the ``parent`` function:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% extends "base.html" %}
|
10 |
-
|
11 |
-
{% block sidebar %}
|
12 |
-
<h3>Table Of Contents</h3>
|
13 |
-
...
|
14 |
-
{{ parent() }}
|
15 |
-
{% endblock %}
|
16 |
-
|
17 |
-
The ``parent()`` call will return the content of the ``sidebar`` block as
|
18 |
-
defined in the ``base.html`` template.
|
19 |
-
|
20 |
-
.. seealso:: :doc:`extends<../tags/extends>`, :doc:`block<../functions/block>`, :doc:`block<../tags/block>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/random.rst
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
``random``
|
2 |
-
==========
|
3 |
-
|
4 |
-
.. versionadded:: 1.5
|
5 |
-
The random function was added in Twig 1.5.
|
6 |
-
|
7 |
-
.. versionadded:: 1.6
|
8 |
-
String and integer handling was added in Twig 1.6.
|
9 |
-
|
10 |
-
The ``random`` function returns a random value depending on the supplied
|
11 |
-
parameter type:
|
12 |
-
|
13 |
-
* a random item from a sequence;
|
14 |
-
* a random character from a string;
|
15 |
-
* a random integer between 0 and the integer parameter (inclusive).
|
16 |
-
|
17 |
-
.. code-block:: jinja
|
18 |
-
|
19 |
-
{{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
|
20 |
-
{{ random('ABC') }} {# example output: C #}
|
21 |
-
{{ random() }} {# example output: 15386094 (works as native PHP `mt_rand`_ function) #}
|
22 |
-
{{ random(5) }} {# example output: 3 #}
|
23 |
-
|
24 |
-
Arguments
|
25 |
-
---------
|
26 |
-
|
27 |
-
* ``values``: The values
|
28 |
-
|
29 |
-
.. _`mt_rand`: http://php.net/mt_rand
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/range.rst
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
``range``
|
2 |
-
=========
|
3 |
-
|
4 |
-
Returns a list containing an arithmetic progression of integers:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{% for i in range(0, 3) %}
|
9 |
-
{{ i }},
|
10 |
-
{% endfor %}
|
11 |
-
|
12 |
-
{# returns 0, 1, 2, 3 #}
|
13 |
-
|
14 |
-
When step is given (as the third parameter), it specifies the increment (or
|
15 |
-
decrement):
|
16 |
-
|
17 |
-
.. code-block:: jinja
|
18 |
-
|
19 |
-
{% for i in range(0, 6, 2) %}
|
20 |
-
{{ i }},
|
21 |
-
{% endfor %}
|
22 |
-
|
23 |
-
{# returns 0, 2, 4, 6 #}
|
24 |
-
|
25 |
-
The Twig built-in ``..`` operator is just syntactic sugar for the ``range``
|
26 |
-
function (with a step of 1):
|
27 |
-
|
28 |
-
.. code-block:: jinja
|
29 |
-
|
30 |
-
{% for i in 0..3 %}
|
31 |
-
{{ i }},
|
32 |
-
{% endfor %}
|
33 |
-
|
34 |
-
.. tip::
|
35 |
-
|
36 |
-
The ``range`` function works as the native PHP `range`_ function.
|
37 |
-
|
38 |
-
Arguments
|
39 |
-
---------
|
40 |
-
|
41 |
-
* ``low``: The first value of the sequence.
|
42 |
-
* ``high``: The highest possible value of the sequence.
|
43 |
-
* ``step``: The increment between elements of the sequence.
|
44 |
-
|
45 |
-
.. _`range`: http://php.net/range
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/functions/template_from_string.rst
DELETED
@@ -1,32 +0,0 @@
|
|
1 |
-
``template_from_string``
|
2 |
-
========================
|
3 |
-
|
4 |
-
.. versionadded:: 1.11
|
5 |
-
The template_from_string function was added in Twig 1.11.
|
6 |
-
|
7 |
-
The ``template_from_string`` function loads a template from a string:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{% include template_from_string("Hello {{ name }}") %}
|
12 |
-
{% include template_from_string(page.template) %}
|
13 |
-
|
14 |
-
.. note::
|
15 |
-
|
16 |
-
The ``template_from_string`` function is not available by default. You
|
17 |
-
must add the ``Twig_Extension_StringLoader`` extension explicitly when
|
18 |
-
creating your Twig environment::
|
19 |
-
|
20 |
-
$twig = new Twig_Environment(...);
|
21 |
-
$twig->addExtension(new Twig_Extension_StringLoader());
|
22 |
-
|
23 |
-
.. note::
|
24 |
-
|
25 |
-
Even if you will probably always use the ``template_from_string`` function
|
26 |
-
with the ``include`` tag, you can use it with any tag or function that
|
27 |
-
takes a template as an argument (like the ``embed`` or ``extends`` tags).
|
28 |
-
|
29 |
-
Arguments
|
30 |
-
---------
|
31 |
-
|
32 |
-
* ``template``: The template
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/index.rst
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
Twig
|
2 |
-
====
|
3 |
-
|
4 |
-
.. toctree::
|
5 |
-
:maxdepth: 2
|
6 |
-
|
7 |
-
intro
|
8 |
-
templates
|
9 |
-
api
|
10 |
-
advanced
|
11 |
-
internals
|
12 |
-
recipes
|
13 |
-
coding_standards
|
14 |
-
tags/index
|
15 |
-
filters/index
|
16 |
-
functions/index
|
17 |
-
tests/index
|
18 |
-
deprecated
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/internals.rst
DELETED
@@ -1,140 +0,0 @@
|
|
1 |
-
Twig Internals
|
2 |
-
==============
|
3 |
-
|
4 |
-
Twig is very extensible and you can easily hack it. Keep in mind that you
|
5 |
-
should probably try to create an extension before hacking the core, as most
|
6 |
-
features and enhancements can be done with extensions. This chapter is also
|
7 |
-
useful for people who want to understand how Twig works under the hood.
|
8 |
-
|
9 |
-
How Twig works?
|
10 |
-
---------------
|
11 |
-
|
12 |
-
The rendering of a Twig template can be summarized into four key steps:
|
13 |
-
|
14 |
-
* **Load** the template: If the template is already compiled, load it and go
|
15 |
-
to the *evaluation* step, otherwise:
|
16 |
-
|
17 |
-
* First, the **lexer** tokenizes the template source code into small pieces
|
18 |
-
for easier processing;
|
19 |
-
* Then, the **parser** converts the token stream into a meaningful tree
|
20 |
-
of nodes (the Abstract Syntax Tree);
|
21 |
-
* Eventually, the *compiler* transforms the AST into PHP code;
|
22 |
-
|
23 |
-
* **Evaluate** the template: It basically means calling the ``display()``
|
24 |
-
method of the compiled template and passing it the context.
|
25 |
-
|
26 |
-
The Lexer
|
27 |
-
---------
|
28 |
-
|
29 |
-
The lexer tokenizes a template source code into a token stream (each token is
|
30 |
-
an instance of ``Twig_Token``, and the stream is an instance of
|
31 |
-
``Twig_TokenStream``). The default lexer recognizes 13 different token types:
|
32 |
-
|
33 |
-
* ``Twig_Token::BLOCK_START_TYPE``, ``Twig_Token::BLOCK_END_TYPE``: Delimiters for blocks (``{% %}``)
|
34 |
-
* ``Twig_Token::VAR_START_TYPE``, ``Twig_Token::VAR_END_TYPE``: Delimiters for variables (``{{ }}``)
|
35 |
-
* ``Twig_Token::TEXT_TYPE``: A text outside an expression;
|
36 |
-
* ``Twig_Token::NAME_TYPE``: A name in an expression;
|
37 |
-
* ``Twig_Token::NUMBER_TYPE``: A number in an expression;
|
38 |
-
* ``Twig_Token::STRING_TYPE``: A string in an expression;
|
39 |
-
* ``Twig_Token::OPERATOR_TYPE``: An operator;
|
40 |
-
* ``Twig_Token::PUNCTUATION_TYPE``: A punctuation sign;
|
41 |
-
* ``Twig_Token::INTERPOLATION_START_TYPE``, ``Twig_Token::INTERPOLATION_END_TYPE`` (as of Twig 1.5): Delimiters for string interpolation;
|
42 |
-
* ``Twig_Token::EOF_TYPE``: Ends of template.
|
43 |
-
|
44 |
-
You can manually convert a source code into a token stream by calling the
|
45 |
-
``tokenize()`` of an environment::
|
46 |
-
|
47 |
-
$stream = $twig->tokenize($source, $identifier);
|
48 |
-
|
49 |
-
As the stream has a ``__toString()`` method, you can have a textual
|
50 |
-
representation of it by echoing the object::
|
51 |
-
|
52 |
-
echo $stream."\n";
|
53 |
-
|
54 |
-
Here is the output for the ``Hello {{ name }}`` template:
|
55 |
-
|
56 |
-
.. code-block:: text
|
57 |
-
|
58 |
-
TEXT_TYPE(Hello )
|
59 |
-
VAR_START_TYPE()
|
60 |
-
NAME_TYPE(name)
|
61 |
-
VAR_END_TYPE()
|
62 |
-
EOF_TYPE()
|
63 |
-
|
64 |
-
.. note::
|
65 |
-
|
66 |
-
You can change the default lexer use by Twig (``Twig_Lexer``) by calling
|
67 |
-
the ``setLexer()`` method::
|
68 |
-
|
69 |
-
$twig->setLexer($lexer);
|
70 |
-
|
71 |
-
The Parser
|
72 |
-
----------
|
73 |
-
|
74 |
-
The parser converts the token stream into an AST (Abstract Syntax Tree), or a
|
75 |
-
node tree (an instance of ``Twig_Node_Module``). The core extension defines
|
76 |
-
the basic nodes like: ``for``, ``if``, ... and the expression nodes.
|
77 |
-
|
78 |
-
You can manually convert a token stream into a node tree by calling the
|
79 |
-
``parse()`` method of an environment::
|
80 |
-
|
81 |
-
$nodes = $twig->parse($stream);
|
82 |
-
|
83 |
-
Echoing the node object gives you a nice representation of the tree::
|
84 |
-
|
85 |
-
echo $nodes."\n";
|
86 |
-
|
87 |
-
Here is the output for the ``Hello {{ name }}`` template:
|
88 |
-
|
89 |
-
.. code-block:: text
|
90 |
-
|
91 |
-
Twig_Node_Module(
|
92 |
-
Twig_Node_Text(Hello )
|
93 |
-
Twig_Node_Print(
|
94 |
-
Twig_Node_Expression_Name(name)
|
95 |
-
)
|
96 |
-
)
|
97 |
-
|
98 |
-
.. note::
|
99 |
-
|
100 |
-
The default parser (``Twig_TokenParser``) can be also changed by calling the
|
101 |
-
``setParser()`` method::
|
102 |
-
|
103 |
-
$twig->setParser($parser);
|
104 |
-
|
105 |
-
The Compiler
|
106 |
-
------------
|
107 |
-
|
108 |
-
The last step is done by the compiler. It takes a node tree as an input and
|
109 |
-
generates PHP code usable for runtime execution of the template.
|
110 |
-
|
111 |
-
You can call the compiler by hand with the ``compile()`` method of an
|
112 |
-
environment::
|
113 |
-
|
114 |
-
$php = $twig->compile($nodes);
|
115 |
-
|
116 |
-
The ``compile()`` method returns the PHP source code representing the node.
|
117 |
-
|
118 |
-
The generated template for a ``Hello {{ name }}`` template reads as follows
|
119 |
-
(the actual output can differ depending on the version of Twig you are
|
120 |
-
using)::
|
121 |
-
|
122 |
-
/* Hello {{ name }} */
|
123 |
-
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Twig_Template
|
124 |
-
{
|
125 |
-
protected function doDisplay(array $context, array $blocks = array())
|
126 |
-
{
|
127 |
-
// line 1
|
128 |
-
echo "Hello ";
|
129 |
-
echo twig_escape_filter($this->env, $this->getContext($context, "name"), "ndex", null, true);
|
130 |
-
}
|
131 |
-
|
132 |
-
// some more code
|
133 |
-
}
|
134 |
-
|
135 |
-
.. note::
|
136 |
-
|
137 |
-
As for the lexer and the parser, the default compiler (``Twig_Compiler``) can
|
138 |
-
be changed by calling the ``setCompiler()`` method::
|
139 |
-
|
140 |
-
$twig->setCompiler($compiler);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/intro.rst
DELETED
@@ -1,164 +0,0 @@
|
|
1 |
-
Introduction
|
2 |
-
============
|
3 |
-
|
4 |
-
This is the documentation for Twig, the flexible, fast, and secure template
|
5 |
-
engine for PHP.
|
6 |
-
|
7 |
-
If you have any exposure to other text-based template languages, such as
|
8 |
-
Smarty, Django, or Jinja, you should feel right at home with Twig. It's both
|
9 |
-
designer and developer friendly by sticking to PHP's principles and adding
|
10 |
-
functionality useful for templating environments.
|
11 |
-
|
12 |
-
The key-features are...
|
13 |
-
|
14 |
-
* *Fast*: Twig compiles templates down to plain optimized PHP code. The
|
15 |
-
overhead compared to regular PHP code was reduced to the very minimum.
|
16 |
-
|
17 |
-
* *Secure*: Twig has a sandbox mode to evaluate untrusted template code. This
|
18 |
-
allows Twig to be used as a template language for applications where users
|
19 |
-
may modify the template design.
|
20 |
-
|
21 |
-
* *Flexible*: Twig is powered by a flexible lexer and parser. This allows the
|
22 |
-
developer to define its own custom tags and filters, and create its own DSL.
|
23 |
-
|
24 |
-
Prerequisites
|
25 |
-
-------------
|
26 |
-
|
27 |
-
Twig needs at least **PHP 5.2.4** to run.
|
28 |
-
|
29 |
-
Installation
|
30 |
-
------------
|
31 |
-
|
32 |
-
You have multiple ways to install Twig.
|
33 |
-
|
34 |
-
Installing via Composer (recommended)
|
35 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
36 |
-
|
37 |
-
1. Install composer in your project:
|
38 |
-
|
39 |
-
.. code-block:: bash
|
40 |
-
|
41 |
-
curl -s http://getcomposer.org/installer | php
|
42 |
-
|
43 |
-
2. Create a ``composer.json`` file in your project root:
|
44 |
-
|
45 |
-
.. code-block:: javascript
|
46 |
-
|
47 |
-
{
|
48 |
-
"require": {
|
49 |
-
"twig/twig": "1.*"
|
50 |
-
}
|
51 |
-
}
|
52 |
-
|
53 |
-
3. Install via composer
|
54 |
-
|
55 |
-
.. code-block:: bash
|
56 |
-
|
57 |
-
php composer.phar install
|
58 |
-
|
59 |
-
.. note::
|
60 |
-
If you want to learn more about Composer, the ``composer.json`` file syntax
|
61 |
-
and its usage, you can read the `online documentation`_.
|
62 |
-
|
63 |
-
Installing from the tarball release
|
64 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
65 |
-
|
66 |
-
1. Download the most recent tarball from the `download page`_
|
67 |
-
2. Unpack the tarball
|
68 |
-
3. Move the files somewhere in your project
|
69 |
-
|
70 |
-
Installing the development version
|
71 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
72 |
-
|
73 |
-
1. Install Git
|
74 |
-
2. ``git clone git://github.com/fabpot/Twig.git``
|
75 |
-
|
76 |
-
Installing the PEAR package
|
77 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
78 |
-
|
79 |
-
1. Install PEAR
|
80 |
-
2. ``pear channel-discover pear.twig-project.org``
|
81 |
-
3. ``pear install twig/Twig`` (or ``pear install twig/Twig-beta``)
|
82 |
-
|
83 |
-
|
84 |
-
Installing the C extension
|
85 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
86 |
-
|
87 |
-
.. versionadded:: 1.4
|
88 |
-
The C extension was added in Twig 1.4.
|
89 |
-
|
90 |
-
Twig comes with a C extension that enhances the performance of the Twig
|
91 |
-
runtime engine. You can install it like any other PHP extension:
|
92 |
-
|
93 |
-
.. code-block:: bash
|
94 |
-
|
95 |
-
$ cd ext/twig
|
96 |
-
$ phpize
|
97 |
-
$ ./configure
|
98 |
-
$ make
|
99 |
-
$ make install
|
100 |
-
|
101 |
-
Finally, enable the extension in your ``php.ini`` configuration file:
|
102 |
-
|
103 |
-
.. code-block:: ini
|
104 |
-
|
105 |
-
extension=twig.so
|
106 |
-
|
107 |
-
And from now on, Twig will automatically compile your templates to take
|
108 |
-
advantage of the C extension. Note that this extension does not replace the
|
109 |
-
PHP code but only provides an optimized version of the
|
110 |
-
``Twig_Template::getAttribute()`` method.
|
111 |
-
|
112 |
-
.. tip::
|
113 |
-
|
114 |
-
On Windows, you can also simply download and install a `pre-build DLL`_.
|
115 |
-
|
116 |
-
Basic API Usage
|
117 |
-
---------------
|
118 |
-
|
119 |
-
This section gives you a brief introduction to the PHP API for Twig.
|
120 |
-
|
121 |
-
The first step to use Twig is to register its autoloader::
|
122 |
-
|
123 |
-
require_once '/path/to/lib/Twig/Autoloader.php';
|
124 |
-
Twig_Autoloader::register();
|
125 |
-
|
126 |
-
Replace the ``/path/to/lib/`` path with the path you used for Twig
|
127 |
-
installation.
|
128 |
-
|
129 |
-
If you have installed Twig via Composer you can take advantage of Composer's
|
130 |
-
autoload mechanism by replacing the previous snippet for::
|
131 |
-
|
132 |
-
require_once '/path/to/vendor/autoload.php'
|
133 |
-
|
134 |
-
.. note::
|
135 |
-
|
136 |
-
Twig follows the PEAR convention names for its classes, which means you
|
137 |
-
can easily integrate Twig classes loading in your own autoloader.
|
138 |
-
|
139 |
-
.. code-block:: php
|
140 |
-
|
141 |
-
$loader = new Twig_Loader_String();
|
142 |
-
$twig = new Twig_Environment($loader);
|
143 |
-
|
144 |
-
echo $twig->render('Hello {{ name }}!', array('name' => 'Fabien'));
|
145 |
-
|
146 |
-
Twig uses a loader (``Twig_Loader_String``) to locate templates, and an
|
147 |
-
environment (``Twig_Environment``) to store the configuration.
|
148 |
-
|
149 |
-
The ``render()`` method loads the template passed as a first argument and
|
150 |
-
renders it with the variables passed as a second argument.
|
151 |
-
|
152 |
-
As templates are generally stored on the filesystem, Twig also comes with a
|
153 |
-
filesystem loader::
|
154 |
-
|
155 |
-
$loader = new Twig_Loader_Filesystem('/path/to/templates');
|
156 |
-
$twig = new Twig_Environment($loader, array(
|
157 |
-
'cache' => '/path/to/compilation_cache',
|
158 |
-
));
|
159 |
-
|
160 |
-
echo $twig->render('index.html', array('name' => 'Fabien'));
|
161 |
-
|
162 |
-
.. _`download page`: https://github.com/fabpot/Twig/tags
|
163 |
-
.. _`online documentation`: http://getcomposer.org/doc
|
164 |
-
.. _`pre-build DLL`: https://github.com/stealth35/stealth35.github.com/downloads
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/recipes.rst
DELETED
@@ -1,474 +0,0 @@
|
|
1 |
-
Recipes
|
2 |
-
=======
|
3 |
-
|
4 |
-
Making a Layout conditional
|
5 |
-
---------------------------
|
6 |
-
|
7 |
-
Working with Ajax means that the same content is sometimes displayed as is,
|
8 |
-
and sometimes decorated with a layout. As Twig layout template names can be
|
9 |
-
any valid expression, you can pass a variable that evaluates to ``true`` when
|
10 |
-
the request is made via Ajax and choose the layout accordingly:
|
11 |
-
|
12 |
-
.. code-block:: jinja
|
13 |
-
|
14 |
-
{% extends request.ajax ? "base_ajax.html" : "base.html" %}
|
15 |
-
|
16 |
-
{% block content %}
|
17 |
-
This is the content to be displayed.
|
18 |
-
{% endblock %}
|
19 |
-
|
20 |
-
Making an Include dynamic
|
21 |
-
-------------------------
|
22 |
-
|
23 |
-
When including a template, its name does not need to be a string. For
|
24 |
-
instance, the name can depend on the value of a variable:
|
25 |
-
|
26 |
-
.. code-block:: jinja
|
27 |
-
|
28 |
-
{% include var ~ '_foo.html' %}
|
29 |
-
|
30 |
-
If ``var`` evaluates to ``index``, the ``index_foo.html`` template will be
|
31 |
-
rendered.
|
32 |
-
|
33 |
-
As a matter of fact, the template name can be any valid expression, such as
|
34 |
-
the following:
|
35 |
-
|
36 |
-
.. code-block:: jinja
|
37 |
-
|
38 |
-
{% include var|default('index') ~ '_foo.html' %}
|
39 |
-
|
40 |
-
Overriding a Template that also extends itself
|
41 |
-
----------------------------------------------
|
42 |
-
|
43 |
-
A template can be customized in two different ways:
|
44 |
-
|
45 |
-
* *Inheritance*: A template *extends* a parent template and overrides some
|
46 |
-
blocks;
|
47 |
-
|
48 |
-
* *Replacement*: If you use the filesystem loader, Twig loads the first
|
49 |
-
template it finds in a list of configured directories; a template found in a
|
50 |
-
directory *replaces* another one from a directory further in the list.
|
51 |
-
|
52 |
-
But how do you combine both: *replace* a template that also extends itself
|
53 |
-
(aka a template in a directory further in the list)?
|
54 |
-
|
55 |
-
Let's say that your templates are loaded from both ``.../templates/mysite``
|
56 |
-
and ``.../templates/default`` in this order. The ``page.twig`` template,
|
57 |
-
stored in ``.../templates/default`` reads as follows:
|
58 |
-
|
59 |
-
.. code-block:: jinja
|
60 |
-
|
61 |
-
{# page.twig #}
|
62 |
-
{% extends "layout.twig" %}
|
63 |
-
|
64 |
-
{% block content %}
|
65 |
-
{% endblock %}
|
66 |
-
|
67 |
-
You can replace this template by putting a file with the same name in
|
68 |
-
``.../templates/mysite``. And if you want to extend the original template, you
|
69 |
-
might be tempted to write the following:
|
70 |
-
|
71 |
-
.. code-block:: jinja
|
72 |
-
|
73 |
-
{# page.twig in .../templates/mysite #}
|
74 |
-
{% extends "page.twig" %} {# from .../templates/default #}
|
75 |
-
|
76 |
-
Of course, this will not work as Twig will always load the template from
|
77 |
-
``.../templates/mysite``.
|
78 |
-
|
79 |
-
It turns out it is possible to get this to work, by adding a directory right
|
80 |
-
at the end of your template directories, which is the parent of all of the
|
81 |
-
other directories: ``.../templates`` in our case. This has the effect of
|
82 |
-
making every template file within our system uniquely addressable. Most of the
|
83 |
-
time you will use the "normal" paths, but in the special case of wanting to
|
84 |
-
extend a template with an overriding version of itself we can reference its
|
85 |
-
parent's full, unambiguous template path in the extends tag:
|
86 |
-
|
87 |
-
.. code-block:: jinja
|
88 |
-
|
89 |
-
{# page.twig in .../templates/mysite #}
|
90 |
-
{% extends "default/page.twig" %} {# from .../templates #}
|
91 |
-
|
92 |
-
.. note::
|
93 |
-
|
94 |
-
This recipe was inspired by the following Django wiki page:
|
95 |
-
http://code.djangoproject.com/wiki/ExtendingTemplates
|
96 |
-
|
97 |
-
Customizing the Syntax
|
98 |
-
----------------------
|
99 |
-
|
100 |
-
Twig allows some syntax customization for the block delimiters. It's not
|
101 |
-
recommended to use this feature as templates will be tied with your custom
|
102 |
-
syntax. But for specific projects, it can make sense to change the defaults.
|
103 |
-
|
104 |
-
To change the block delimiters, you need to create your own lexer object::
|
105 |
-
|
106 |
-
$twig = new Twig_Environment();
|
107 |
-
|
108 |
-
$lexer = new Twig_Lexer($twig, array(
|
109 |
-
'tag_comment' => array('{#', '#}'),
|
110 |
-
'tag_block' => array('{%', '%}'),
|
111 |
-
'tag_variable' => array('{{', '}}'),
|
112 |
-
));
|
113 |
-
$twig->setLexer($lexer);
|
114 |
-
|
115 |
-
Here are some configuration example that simulates some other template engines
|
116 |
-
syntax::
|
117 |
-
|
118 |
-
// Ruby erb syntax
|
119 |
-
$lexer = new Twig_Lexer($twig, array(
|
120 |
-
'tag_comment' => array('<%#', '%>'),
|
121 |
-
'tag_block' => array('<%', '%>'),
|
122 |
-
'tag_variable' => array('<%=', '%>'),
|
123 |
-
));
|
124 |
-
|
125 |
-
// SGML Comment Syntax
|
126 |
-
$lexer = new Twig_Lexer($twig, array(
|
127 |
-
'tag_comment' => array('<!--#', '-->'),
|
128 |
-
'tag_block' => array('<!--', '-->'),
|
129 |
-
'tag_variable' => array('${', '}'),
|
130 |
-
));
|
131 |
-
|
132 |
-
// Smarty like
|
133 |
-
$lexer = new Twig_Lexer($twig, array(
|
134 |
-
'tag_comment' => array('{*', '*}'),
|
135 |
-
'tag_block' => array('{', '}'),
|
136 |
-
'tag_variable' => array('{$', '}'),
|
137 |
-
));
|
138 |
-
|
139 |
-
Using dynamic Object Properties
|
140 |
-
-------------------------------
|
141 |
-
|
142 |
-
When Twig encounters a variable like ``article.title``, it tries to find a
|
143 |
-
``title`` public property in the ``article`` object.
|
144 |
-
|
145 |
-
It also works if the property does not exist but is rather defined dynamically
|
146 |
-
thanks to the magic ``__get()`` method; you just need to also implement the
|
147 |
-
``__isset()`` magic method like shown in the following snippet of code::
|
148 |
-
|
149 |
-
class Article
|
150 |
-
{
|
151 |
-
public function __get($name)
|
152 |
-
{
|
153 |
-
if ('title' == $name) {
|
154 |
-
return 'The title';
|
155 |
-
}
|
156 |
-
|
157 |
-
// throw some kind of error
|
158 |
-
}
|
159 |
-
|
160 |
-
public function __isset($name)
|
161 |
-
{
|
162 |
-
if ('title' == $name) {
|
163 |
-
return true;
|
164 |
-
}
|
165 |
-
|
166 |
-
return false;
|
167 |
-
}
|
168 |
-
}
|
169 |
-
|
170 |
-
Accessing the parent Context in Nested Loops
|
171 |
-
--------------------------------------------
|
172 |
-
|
173 |
-
Sometimes, when using nested loops, you need to access the parent context. The
|
174 |
-
parent context is always accessible via the ``loop.parent`` variable. For
|
175 |
-
instance, if you have the following template data::
|
176 |
-
|
177 |
-
$data = array(
|
178 |
-
'topics' => array(
|
179 |
-
'topic1' => array('Message 1 of topic 1', 'Message 2 of topic 1'),
|
180 |
-
'topic2' => array('Message 1 of topic 2', 'Message 2 of topic 2'),
|
181 |
-
),
|
182 |
-
);
|
183 |
-
|
184 |
-
And the following template to display all messages in all topics:
|
185 |
-
|
186 |
-
.. code-block:: jinja
|
187 |
-
|
188 |
-
{% for topic, messages in topics %}
|
189 |
-
* {{ loop.index }}: {{ topic }}
|
190 |
-
{% for message in messages %}
|
191 |
-
- {{ loop.parent.loop.index }}.{{ loop.index }}: {{ message }}
|
192 |
-
{% endfor %}
|
193 |
-
{% endfor %}
|
194 |
-
|
195 |
-
The output will be similar to:
|
196 |
-
|
197 |
-
.. code-block:: text
|
198 |
-
|
199 |
-
* 1: topic1
|
200 |
-
- 1.1: The message 1 of topic 1
|
201 |
-
- 1.2: The message 2 of topic 1
|
202 |
-
* 2: topic2
|
203 |
-
- 2.1: The message 1 of topic 2
|
204 |
-
- 2.2: The message 2 of topic 2
|
205 |
-
|
206 |
-
In the inner loop, the ``loop.parent`` variable is used to access the outer
|
207 |
-
context. So, the index of the current ``topic`` defined in the outer for loop
|
208 |
-
is accessible via the ``loop.parent.loop.index`` variable.
|
209 |
-
|
210 |
-
Defining undefined Functions and Filters on the Fly
|
211 |
-
---------------------------------------------------
|
212 |
-
|
213 |
-
When a function (or a filter) is not defined, Twig defaults to throw a
|
214 |
-
``Twig_Error_Syntax`` exception. However, it can also call a `callback`_ (any
|
215 |
-
valid PHP callable) which should return a function (or a filter).
|
216 |
-
|
217 |
-
For filters, register callbacks with ``registerUndefinedFilterCallback()``.
|
218 |
-
For functions, use ``registerUndefinedFunctionCallback()``::
|
219 |
-
|
220 |
-
// auto-register all native PHP functions as Twig functions
|
221 |
-
// don't try this at home as it's not secure at all!
|
222 |
-
$twig->registerUndefinedFunctionCallback(function ($name) {
|
223 |
-
if (function_exists($name)) {
|
224 |
-
return new Twig_Function_Function($name);
|
225 |
-
}
|
226 |
-
|
227 |
-
return false;
|
228 |
-
});
|
229 |
-
|
230 |
-
If the callable is not able to return a valid function (or filter), it must
|
231 |
-
return ``false``.
|
232 |
-
|
233 |
-
If you register more than one callback, Twig will call them in turn until one
|
234 |
-
does not return ``false``.
|
235 |
-
|
236 |
-
.. tip::
|
237 |
-
|
238 |
-
As the resolution of functions and filters is done during compilation,
|
239 |
-
there is no overhead when registering these callbacks.
|
240 |
-
|
241 |
-
Validating the Template Syntax
|
242 |
-
------------------------------
|
243 |
-
|
244 |
-
When template code is providing by a third-party (through a web interface for
|
245 |
-
instance), it might be interesting to validate the template syntax before
|
246 |
-
saving it. If the template code is stored in a `$template` variable, here is
|
247 |
-
how you can do it::
|
248 |
-
|
249 |
-
try {
|
250 |
-
$twig->parse($twig->tokenize($template));
|
251 |
-
|
252 |
-
// the $template is valid
|
253 |
-
} catch (Twig_Error_Syntax $e) {
|
254 |
-
// $template contains one or more syntax errors
|
255 |
-
}
|
256 |
-
|
257 |
-
If you iterate over a set of files, you can pass the filename to the
|
258 |
-
``tokenize()`` method to get the filename in the exception message::
|
259 |
-
|
260 |
-
foreach ($files as $file) {
|
261 |
-
try {
|
262 |
-
$twig->parse($twig->tokenize($template, $file));
|
263 |
-
|
264 |
-
// the $template is valid
|
265 |
-
} catch (Twig_Error_Syntax $e) {
|
266 |
-
// $template contains one or more syntax errors
|
267 |
-
}
|
268 |
-
}
|
269 |
-
|
270 |
-
.. note::
|
271 |
-
|
272 |
-
This method won't catch any sandbox policy violations because the policy
|
273 |
-
is enforced during template rendering (as Twig needs the context for some
|
274 |
-
checks like allowed methods on objects).
|
275 |
-
|
276 |
-
Refreshing modified Templates when APC is enabled and apc.stat = 0
|
277 |
-
------------------------------------------------------------------
|
278 |
-
|
279 |
-
When using APC with ``apc.stat`` set to ``0`` and Twig cache enabled, clearing
|
280 |
-
the template cache won't update the APC cache. To get around this, one can
|
281 |
-
extend ``Twig_Environment`` and force the update of the APC cache when Twig
|
282 |
-
rewrites the cache::
|
283 |
-
|
284 |
-
class Twig_Environment_APC extends Twig_Environment
|
285 |
-
{
|
286 |
-
protected function writeCacheFile($file, $content)
|
287 |
-
{
|
288 |
-
parent::writeCacheFile($file, $content);
|
289 |
-
|
290 |
-
// Compile cached file into bytecode cache
|
291 |
-
apc_compile_file($file);
|
292 |
-
}
|
293 |
-
}
|
294 |
-
|
295 |
-
Reusing a stateful Node Visitor
|
296 |
-
-------------------------------
|
297 |
-
|
298 |
-
When attaching a visitor to a ``Twig_Environment`` instance, Twig uses it to
|
299 |
-
visit *all* templates it compiles. If you need to keep some state information
|
300 |
-
around, you probably want to reset it when visiting a new template.
|
301 |
-
|
302 |
-
This can be easily achieved with the following code::
|
303 |
-
|
304 |
-
protected $someTemplateState = array();
|
305 |
-
|
306 |
-
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
307 |
-
{
|
308 |
-
if ($node instanceof Twig_Node_Module) {
|
309 |
-
// reset the state as we are entering a new template
|
310 |
-
$this->someTemplateState = array();
|
311 |
-
}
|
312 |
-
|
313 |
-
// ...
|
314 |
-
|
315 |
-
return $node;
|
316 |
-
}
|
317 |
-
|
318 |
-
Using the Template name to set the default Escaping Strategy
|
319 |
-
------------------------------------------------------------
|
320 |
-
|
321 |
-
.. versionadded:: 1.8
|
322 |
-
This recipe requires Twig 1.8 or later.
|
323 |
-
|
324 |
-
The ``autoescape`` option determines the default escaping strategy to use when
|
325 |
-
no escaping is applied on a variable. When Twig is used to mostly generate
|
326 |
-
HTML files, you can set it to ``html`` and explicitly change it to ``js`` when
|
327 |
-
you have some dynamic JavaScript files thanks to the ``autoescape`` tag:
|
328 |
-
|
329 |
-
.. code-block:: jinja
|
330 |
-
|
331 |
-
{% autoescape 'js' %}
|
332 |
-
... some JS ...
|
333 |
-
{% endautoescape %}
|
334 |
-
|
335 |
-
But if you have many HTML and JS files, and if your template names follow some
|
336 |
-
conventions, you can instead determine the default escaping strategy to use
|
337 |
-
based on the template name. Let's say that your template names always ends
|
338 |
-
with ``.html`` for HTML files, ``.js`` for JavaScript ones, and ``.css`` for
|
339 |
-
stylesheets, here is how you can configure Twig::
|
340 |
-
|
341 |
-
class TwigEscapingGuesser
|
342 |
-
{
|
343 |
-
function guess($filename)
|
344 |
-
{
|
345 |
-
// get the format
|
346 |
-
$format = substr($filename, strrpos($filename, '.') + 1);
|
347 |
-
|
348 |
-
switch ($format) {
|
349 |
-
case 'js':
|
350 |
-
return 'js';
|
351 |
-
case 'css':
|
352 |
-
return 'css';
|
353 |
-
case 'html':
|
354 |
-
default:
|
355 |
-
return 'html';
|
356 |
-
}
|
357 |
-
}
|
358 |
-
}
|
359 |
-
|
360 |
-
$loader = new Twig_Loader_Filesystem('/path/to/templates');
|
361 |
-
$twig = new Twig_Environment($loader, array(
|
362 |
-
'autoescape' => array(new TwigEscapingGuesser(), 'guess'),
|
363 |
-
));
|
364 |
-
|
365 |
-
This dynamic strategy does not incur any overhead at runtime as auto-escaping
|
366 |
-
is done at compilation time.
|
367 |
-
|
368 |
-
Using a Database to store Templates
|
369 |
-
-----------------------------------
|
370 |
-
|
371 |
-
If you are developing a CMS, templates are usually stored in a database. This
|
372 |
-
recipe gives you a simple PDO template loader you can use as a starting point
|
373 |
-
for your own.
|
374 |
-
|
375 |
-
First, let's create a temporary in-memory SQLite3 database to work with::
|
376 |
-
|
377 |
-
$dbh = new PDO('sqlite::memory:');
|
378 |
-
$dbh->exec('CREATE TABLE templates (name STRING, source STRING, last_modified INTEGER)');
|
379 |
-
$base = '{% block content %}{% endblock %}';
|
380 |
-
$index = '
|
381 |
-
{% extends "base.twig" %}
|
382 |
-
{% block content %}Hello {{ name }}{% endblock %}
|
383 |
-
';
|
384 |
-
$now = time();
|
385 |
-
$dbh->exec("INSERT INTO templates (name, source, last_modified) VALUES ('base.twig', '$base', $now)");
|
386 |
-
$dbh->exec("INSERT INTO templates (name, source, last_modified) VALUES ('index.twig', '$index', $now)");
|
387 |
-
|
388 |
-
We have created a simple ``templates`` table that hosts two templates:
|
389 |
-
``base.twig`` and ``index.twig``.
|
390 |
-
|
391 |
-
Now, let's define a loader able to use this database::
|
392 |
-
|
393 |
-
class DatabaseTwigLoader implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
394 |
-
{
|
395 |
-
protected $dbh;
|
396 |
-
|
397 |
-
public function __construct(PDO $dbh)
|
398 |
-
{
|
399 |
-
$this->dbh = $dbh;
|
400 |
-
}
|
401 |
-
|
402 |
-
public function getSource($name)
|
403 |
-
{
|
404 |
-
if (false === $source = $this->getValue('source', $name)) {
|
405 |
-
throw new Twig_Error_Loader(sprintf('Template "%s" does not exist.', $name));
|
406 |
-
}
|
407 |
-
|
408 |
-
return $source;
|
409 |
-
}
|
410 |
-
|
411 |
-
// Twig_ExistsLoaderInterface as of Twig 1.11
|
412 |
-
public function exists($name)
|
413 |
-
{
|
414 |
-
return $name === $this->getValue('name', $name);
|
415 |
-
}
|
416 |
-
|
417 |
-
public function getCacheKey($name)
|
418 |
-
{
|
419 |
-
return $name;
|
420 |
-
}
|
421 |
-
|
422 |
-
public function isFresh($name, $time)
|
423 |
-
{
|
424 |
-
if (false === $lastModified = $this->getValue('last_modified', $name)) {
|
425 |
-
return false;
|
426 |
-
}
|
427 |
-
|
428 |
-
return $lastModified <= $time;
|
429 |
-
}
|
430 |
-
|
431 |
-
protected function getValue($column, $name)
|
432 |
-
{
|
433 |
-
$sth = $this->dbh->prepare('SELECT '.$column.' FROM templates WHERE name = :name');
|
434 |
-
$sth->execute(array(':name' => (string) $name));
|
435 |
-
|
436 |
-
return $sth->fetchColumn();
|
437 |
-
}
|
438 |
-
}
|
439 |
-
|
440 |
-
Finally, here is an example on how you can use it::
|
441 |
-
|
442 |
-
$loader = new DatabaseTwigLoader($dbh);
|
443 |
-
$twig = new Twig_Environment($loader);
|
444 |
-
|
445 |
-
echo $twig->render('index.twig', array('name' => 'Fabien'));
|
446 |
-
|
447 |
-
Using different Template Sources
|
448 |
-
--------------------------------
|
449 |
-
|
450 |
-
This recipe is the continuation of the previous one. Even if you store the
|
451 |
-
contributed templates in a database, you might want to keep the original/base
|
452 |
-
templates on the filesystem. When templates can be loaded from different
|
453 |
-
sources, you need to use the ``Twig_Loader_Chain`` loader.
|
454 |
-
|
455 |
-
As you can see in the previous recipe, we reference the template in the exact
|
456 |
-
same way as we would have done it with a regular filesystem loader. This is
|
457 |
-
the key to be able to mix and match templates coming from the database, the
|
458 |
-
filesystem, or any other loader for that matter: the template name should be a
|
459 |
-
logical name, and not the path from the filesystem::
|
460 |
-
|
461 |
-
$loader1 = new DatabaseTwigLoader($dbh);
|
462 |
-
$loader2 = new Twig_Loader_Array(array(
|
463 |
-
'base.twig' => '{% block content %}{% endblock %}',
|
464 |
-
));
|
465 |
-
$loader = new Twig_Loader_Chain(array($loader1, $loader2));
|
466 |
-
|
467 |
-
$twig = new Twig_Environment($loader);
|
468 |
-
|
469 |
-
echo $twig->render('index.twig', array('name' => 'Fabien'));
|
470 |
-
|
471 |
-
Now that the ``base.twig`` templates is defined in an array loader, you can
|
472 |
-
remove it from the database, and everything else will still work as before.
|
473 |
-
|
474 |
-
.. _callback: http://www.php.net/manual/en/function.is-callable.php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/autoescape.rst
DELETED
@@ -1,71 +0,0 @@
|
|
1 |
-
``autoescape``
|
2 |
-
==============
|
3 |
-
|
4 |
-
Whether automatic escaping is enabled or not, you can mark a section of a
|
5 |
-
template to be escaped or not by using the ``autoescape`` tag:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{# The following syntax works as of Twig 1.8 -- see the note below for previous versions #}
|
10 |
-
|
11 |
-
{% autoescape %}
|
12 |
-
Everything will be automatically escaped in this block
|
13 |
-
using the HTML strategy
|
14 |
-
{% endautoescape %}
|
15 |
-
|
16 |
-
{% autoescape 'html' %}
|
17 |
-
Everything will be automatically escaped in this block
|
18 |
-
using the HTML strategy
|
19 |
-
{% endautoescape %}
|
20 |
-
|
21 |
-
{% autoescape 'js' %}
|
22 |
-
Everything will be automatically escaped in this block
|
23 |
-
using the js escaping strategy
|
24 |
-
{% endautoescape %}
|
25 |
-
|
26 |
-
{% autoescape false %}
|
27 |
-
Everything will be outputted as is in this block
|
28 |
-
{% endautoescape %}
|
29 |
-
|
30 |
-
.. note::
|
31 |
-
|
32 |
-
Before Twig 1.8, the syntax was different:
|
33 |
-
|
34 |
-
.. code-block:: jinja
|
35 |
-
|
36 |
-
{% autoescape true %}
|
37 |
-
Everything will be automatically escaped in this block
|
38 |
-
using the HTML strategy
|
39 |
-
{% endautoescape %}
|
40 |
-
|
41 |
-
{% autoescape false %}
|
42 |
-
Everything will be outputted as is in this block
|
43 |
-
{% endautoescape %}
|
44 |
-
|
45 |
-
{% autoescape true js %}
|
46 |
-
Everything will be automatically escaped in this block
|
47 |
-
using the js escaping strategy
|
48 |
-
{% endautoescape %}
|
49 |
-
|
50 |
-
When automatic escaping is enabled everything is escaped by default except for
|
51 |
-
values explicitly marked as safe. Those can be marked in the template by using
|
52 |
-
the :doc:`raw<../filters/raw>` filter:
|
53 |
-
|
54 |
-
.. code-block:: jinja
|
55 |
-
|
56 |
-
{% autoescape %}
|
57 |
-
{{ safe_value|raw }}
|
58 |
-
{% endautoescape %}
|
59 |
-
|
60 |
-
Functions returning template data (like :doc:`macros<macro>` and
|
61 |
-
:doc:`parent<../functions/parent>`) always return safe markup.
|
62 |
-
|
63 |
-
.. note::
|
64 |
-
|
65 |
-
Twig is smart enough to not escape an already escaped value by the
|
66 |
-
:doc:`escape<../filters/escape>` filter.
|
67 |
-
|
68 |
-
.. note::
|
69 |
-
|
70 |
-
The chapter :doc:`Twig for Developers<../api>` gives more information
|
71 |
-
about when and how automatic escaping is applied.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/block.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``block``
|
2 |
-
=========
|
3 |
-
|
4 |
-
Blocks are used for inheritance and act as placeholders and replacements at
|
5 |
-
the same time. They are documented in detail in the documentation for the
|
6 |
-
:doc:`extends<../tags/extends>` tag.
|
7 |
-
|
8 |
-
Block names should consist of alphanumeric characters, and underscores. Dashes
|
9 |
-
are not permitted.
|
10 |
-
|
11 |
-
.. seealso:: :doc:`block<../functions/block>`, :doc:`parent<../functions/parent>`, :doc:`use<../tags/use>`, :doc:`extends<../tags/extends>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/do.rst
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
``do``
|
2 |
-
======
|
3 |
-
|
4 |
-
.. versionadded:: 1.5
|
5 |
-
The do tag was added in Twig 1.5.
|
6 |
-
|
7 |
-
The ``do`` tag works exactly like the regular variable expression (``{{ ...
|
8 |
-
}}``) just that it doesn't print anything:
|
9 |
-
|
10 |
-
.. code-block:: jinja
|
11 |
-
|
12 |
-
{% do 1 + 2 %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/embed.rst
DELETED
@@ -1,178 +0,0 @@
|
|
1 |
-
``embed``
|
2 |
-
=========
|
3 |
-
|
4 |
-
.. versionadded:: 1.8
|
5 |
-
The ``embed`` tag was added in Twig 1.8.
|
6 |
-
|
7 |
-
The ``embed`` tag combines the behaviour of :doc:`include<include>` and
|
8 |
-
:doc:`extends<extends>`.
|
9 |
-
It allows you to include another template's contents, just like ``include``
|
10 |
-
does. But it also allows you to override any block defined inside the
|
11 |
-
included template, like when extending a template.
|
12 |
-
|
13 |
-
Think of an embedded template as a "micro layout skeleton".
|
14 |
-
|
15 |
-
.. code-block:: jinja
|
16 |
-
|
17 |
-
{% embed "teasers_skeleton.twig" %}
|
18 |
-
{# These blocks are defined in "teasers_skeleton.twig" #}
|
19 |
-
{# and we override them right here: #}
|
20 |
-
{% block left_teaser %}
|
21 |
-
Some content for the left teaser box
|
22 |
-
{% endblock %}
|
23 |
-
{% block right_teaser %}
|
24 |
-
Some content for the right teaser box
|
25 |
-
{% endblock %}
|
26 |
-
{% endembed %}
|
27 |
-
|
28 |
-
The ``embed`` tag takes the idea of template inheritance to the level of
|
29 |
-
content fragments. While template inheritance allows for "document skeletons",
|
30 |
-
which are filled with life by child templates, the ``embed`` tag allows you to
|
31 |
-
create "skeletons" for smaller units of content and re-use and fill them
|
32 |
-
anywhere you like.
|
33 |
-
|
34 |
-
Since the use case may not be obvious, let's look at a simplified example.
|
35 |
-
Imagine a base template shared by multiple HTML pages, defining a single block
|
36 |
-
named "content":
|
37 |
-
|
38 |
-
.. code-block:: text
|
39 |
-
|
40 |
-
┌─── page layout ─────────────────────┐
|
41 |
-
│ │
|
42 |
-
│ ┌── block "content" ──┐ │
|
43 |
-
│ │ │ │
|
44 |
-
│ │ │ │
|
45 |
-
│ │ (child template to │ │
|
46 |
-
│ │ put content here) │ │
|
47 |
-
│ │ │ │
|
48 |
-
│ │ │ │
|
49 |
-
│ └─────────────────────┘ │
|
50 |
-
│ │
|
51 |
-
└─────────────────────────────────────┘
|
52 |
-
|
53 |
-
Some pages ("foo" and "bar") share the same content structure -
|
54 |
-
two vertically stacked boxes:
|
55 |
-
|
56 |
-
.. code-block:: text
|
57 |
-
|
58 |
-
┌─── page layout ─────────────────────┐
|
59 |
-
│ │
|
60 |
-
│ ┌── block "content" ──┐ │
|
61 |
-
│ │ ┌─ block "top" ───┐ │ │
|
62 |
-
│ │ │ │ │ │
|
63 |
-
│ │ └─────────────────┘ │ │
|
64 |
-
│ │ ┌─ block "bottom" ┐ │ │
|
65 |
-
│ │ │ │ │ │
|
66 |
-
│ │ └─────────────────┘ │ │
|
67 |
-
│ └─────────────────────┘ │
|
68 |
-
│ │
|
69 |
-
└─────────────────────────────────────┘
|
70 |
-
|
71 |
-
While other pages ("boom" and "baz") share a different content structure -
|
72 |
-
two boxes side by side:
|
73 |
-
|
74 |
-
.. code-block:: text
|
75 |
-
|
76 |
-
┌─── page layout ─────────────────────┐
|
77 |
-
│ │
|
78 |
-
│ ┌── block "content" ──┐ │
|
79 |
-
│ │ │ │
|
80 |
-
│ │ ┌ block ┐ ┌ block ┐ │ │
|
81 |
-
│ │ │"left" │ │"right"│ │ │
|
82 |
-
│ │ │ │ │ │ │ │
|
83 |
-
│ │ │ │ │ │ │ │
|
84 |
-
│ │ └───────┘ └───────┘ │ │
|
85 |
-
│ └─────────────────────┘ │
|
86 |
-
│ │
|
87 |
-
└─────────────────────────────────────┘
|
88 |
-
|
89 |
-
Without the ``embed`` tag, you have two ways to design your templates:
|
90 |
-
|
91 |
-
* Create two "intermediate" base templates that extend the master layout
|
92 |
-
template: one with vertically stacked boxes to be used by the "foo" and
|
93 |
-
"bar" pages and another one with side-by-side boxes for the "boom" and
|
94 |
-
"baz" pages.
|
95 |
-
|
96 |
-
* Embed the markup for the top/bottom and left/right boxes into each page
|
97 |
-
template directly.
|
98 |
-
|
99 |
-
These two solutions do not scale well because they each have a major drawback:
|
100 |
-
|
101 |
-
* The first solution may indeed work for this simplified example. But imagine
|
102 |
-
we add a sidebar, which may again contain different, recurring structures
|
103 |
-
of content. Now we would need to create intermediate base templates for
|
104 |
-
all occurring combinations of content structure and sidebar structure...
|
105 |
-
and so on.
|
106 |
-
|
107 |
-
* The second solution involves duplication of common code with all its negative
|
108 |
-
consequences: any change involves finding and editing all affected copies
|
109 |
-
of the structure, correctness has to be verified for each copy, copies may
|
110 |
-
go out of sync by careless modifications etc.
|
111 |
-
|
112 |
-
In such a situation, the ``embed`` tag comes in handy. The common layout
|
113 |
-
code can live in a single base template, and the two different content structures,
|
114 |
-
let's call them "micro layouts" go into separate templates which are embedded
|
115 |
-
as necessary:
|
116 |
-
|
117 |
-
Page template ``foo.twig``:
|
118 |
-
|
119 |
-
.. code-block:: jinja
|
120 |
-
|
121 |
-
{% extends "layout_skeleton.twig" %}
|
122 |
-
|
123 |
-
{% block content %}
|
124 |
-
{% embed "vertical_boxes_skeleton.twig" %}
|
125 |
-
{% block top %}
|
126 |
-
Some content for the top box
|
127 |
-
{% endblock %}
|
128 |
-
|
129 |
-
{% block bottom %}
|
130 |
-
Some content for the bottom box
|
131 |
-
{% endblock %}
|
132 |
-
{% endembed %}
|
133 |
-
{% endblock %}
|
134 |
-
|
135 |
-
And here is the code for ``vertical_boxes_skeleton.twig``:
|
136 |
-
|
137 |
-
.. code-block:: html+jinja
|
138 |
-
|
139 |
-
<div class="top_box">
|
140 |
-
{% block top %}
|
141 |
-
Top box default content
|
142 |
-
{% endblock %}
|
143 |
-
</div>
|
144 |
-
|
145 |
-
<div class="bottom_box">
|
146 |
-
{% block bottom %}
|
147 |
-
Bottom box default content
|
148 |
-
{% endblock %}
|
149 |
-
</div>
|
150 |
-
|
151 |
-
The goal of the ``vertical_boxes_skeleton.twig`` template being to factor
|
152 |
-
out the HTML markup for the boxes.
|
153 |
-
|
154 |
-
The ``embed`` tag takes the exact same arguments as the ``include`` tag:
|
155 |
-
|
156 |
-
.. code-block:: jinja
|
157 |
-
|
158 |
-
{% embed "base" with {'foo': 'bar'} %}
|
159 |
-
...
|
160 |
-
{% endembed %}
|
161 |
-
|
162 |
-
{% embed "base" with {'foo': 'bar'} only %}
|
163 |
-
...
|
164 |
-
{% endembed %}
|
165 |
-
|
166 |
-
{% embed "base" ignore missing %}
|
167 |
-
...
|
168 |
-
{% endembed %}
|
169 |
-
|
170 |
-
.. warning::
|
171 |
-
|
172 |
-
As embedded templates do not have "names", auto-escaping strategies based
|
173 |
-
on the template "filename" won't work as expected if you change the
|
174 |
-
context (for instance, if you embed a CSS/JavaScript template into an HTML
|
175 |
-
one). In that case, explicitly set the default auto-escaping strategy with
|
176 |
-
the ``autoescape`` tag.
|
177 |
-
|
178 |
-
.. seealso:: :doc:`include<../tags/include>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/extends.rst
DELETED
@@ -1,268 +0,0 @@
|
|
1 |
-
``extends``
|
2 |
-
===========
|
3 |
-
|
4 |
-
The ``extends`` tag can be used to extend a template from another one.
|
5 |
-
|
6 |
-
.. note::
|
7 |
-
|
8 |
-
Like PHP, Twig does not support multiple inheritance. So you can only have
|
9 |
-
one extends tag called per rendering. However, Twig supports horizontal
|
10 |
-
:doc:`reuse<use>`.
|
11 |
-
|
12 |
-
Let's define a base template, ``base.html``, which defines a simple HTML
|
13 |
-
skeleton document:
|
14 |
-
|
15 |
-
.. code-block:: html+jinja
|
16 |
-
|
17 |
-
<!DOCTYPE html>
|
18 |
-
<html>
|
19 |
-
<head>
|
20 |
-
{% block head %}
|
21 |
-
<link rel="stylesheet" href="style.css" />
|
22 |
-
<title>{% block title %}{% endblock %} - My Webpage</title>
|
23 |
-
{% endblock %}
|
24 |
-
</head>
|
25 |
-
<body>
|
26 |
-
<div id="content">{% block content %}{% endblock %}</div>
|
27 |
-
<div id="footer">
|
28 |
-
{% block footer %}
|
29 |
-
© Copyright 2011 by <a href="http://domain.invalid/">you</a>.
|
30 |
-
{% endblock %}
|
31 |
-
</div>
|
32 |
-
</body>
|
33 |
-
</html>
|
34 |
-
|
35 |
-
In this example, the :doc:`block<block>` tags define four blocks that child
|
36 |
-
templates can fill in.
|
37 |
-
|
38 |
-
All the ``block`` tag does is to tell the template engine that a child
|
39 |
-
template may override those portions of the template.
|
40 |
-
|
41 |
-
Child Template
|
42 |
-
--------------
|
43 |
-
|
44 |
-
A child template might look like this:
|
45 |
-
|
46 |
-
.. code-block:: jinja
|
47 |
-
|
48 |
-
{% extends "base.html" %}
|
49 |
-
|
50 |
-
{% block title %}Index{% endblock %}
|
51 |
-
{% block head %}
|
52 |
-
{{ parent() }}
|
53 |
-
<style type="text/css">
|
54 |
-
.important { color: #336699; }
|
55 |
-
</style>
|
56 |
-
{% endblock %}
|
57 |
-
{% block content %}
|
58 |
-
<h1>Index</h1>
|
59 |
-
<p class="important">
|
60 |
-
Welcome on my awesome homepage.
|
61 |
-
</p>
|
62 |
-
{% endblock %}
|
63 |
-
|
64 |
-
The ``extends`` tag is the key here. It tells the template engine that this
|
65 |
-
template "extends" another template. When the template system evaluates this
|
66 |
-
template, first it locates the parent. The extends tag should be the first tag
|
67 |
-
in the template.
|
68 |
-
|
69 |
-
Note that since the child template doesn't define the ``footer`` block, the
|
70 |
-
value from the parent template is used instead.
|
71 |
-
|
72 |
-
You can't define multiple ``block`` tags with the same name in the same
|
73 |
-
template. This limitation exists because a block tag works in "both"
|
74 |
-
directions. That is, a block tag doesn't just provide a hole to fill - it also
|
75 |
-
defines the content that fills the hole in the *parent*. If there were two
|
76 |
-
similarly-named ``block`` tags in a template, that template's parent wouldn't
|
77 |
-
know which one of the blocks' content to use.
|
78 |
-
|
79 |
-
If you want to print a block multiple times you can however use the
|
80 |
-
``block`` function:
|
81 |
-
|
82 |
-
.. code-block:: jinja
|
83 |
-
|
84 |
-
<title>{% block title %}{% endblock %}</title>
|
85 |
-
<h1>{{ block('title') }}</h1>
|
86 |
-
{% block body %}{% endblock %}
|
87 |
-
|
88 |
-
Parent Blocks
|
89 |
-
-------------
|
90 |
-
|
91 |
-
It's possible to render the contents of the parent block by using the
|
92 |
-
:doc:`parent<../functions/parent>` function. This gives back the results of
|
93 |
-
the parent block:
|
94 |
-
|
95 |
-
.. code-block:: jinja
|
96 |
-
|
97 |
-
{% block sidebar %}
|
98 |
-
<h3>Table Of Contents</h3>
|
99 |
-
...
|
100 |
-
{{ parent() }}
|
101 |
-
{% endblock %}
|
102 |
-
|
103 |
-
Named Block End-Tags
|
104 |
-
--------------------
|
105 |
-
|
106 |
-
Twig allows you to put the name of the block after the end tag for better
|
107 |
-
readability:
|
108 |
-
|
109 |
-
.. code-block:: jinja
|
110 |
-
|
111 |
-
{% block sidebar %}
|
112 |
-
{% block inner_sidebar %}
|
113 |
-
...
|
114 |
-
{% endblock inner_sidebar %}
|
115 |
-
{% endblock sidebar %}
|
116 |
-
|
117 |
-
Of course, the name after the ``endblock`` word must match the block name.
|
118 |
-
|
119 |
-
Block Nesting and Scope
|
120 |
-
-----------------------
|
121 |
-
|
122 |
-
Blocks can be nested for more complex layouts. Per default, blocks have access
|
123 |
-
to variables from outer scopes:
|
124 |
-
|
125 |
-
.. code-block:: jinja
|
126 |
-
|
127 |
-
{% for item in seq %}
|
128 |
-
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
|
129 |
-
{% endfor %}
|
130 |
-
|
131 |
-
Block Shortcuts
|
132 |
-
---------------
|
133 |
-
|
134 |
-
For blocks with few content, it's possible to use a shortcut syntax. The
|
135 |
-
following constructs do the same:
|
136 |
-
|
137 |
-
.. code-block:: jinja
|
138 |
-
|
139 |
-
{% block title %}
|
140 |
-
{{ page_title|title }}
|
141 |
-
{% endblock %}
|
142 |
-
|
143 |
-
.. code-block:: jinja
|
144 |
-
|
145 |
-
{% block title page_title|title %}
|
146 |
-
|
147 |
-
Dynamic Inheritance
|
148 |
-
-------------------
|
149 |
-
|
150 |
-
Twig supports dynamic inheritance by using a variable as the base template:
|
151 |
-
|
152 |
-
.. code-block:: jinja
|
153 |
-
|
154 |
-
{% extends some_var %}
|
155 |
-
|
156 |
-
If the variable evaluates to a ``Twig_Template`` object, Twig will use it as
|
157 |
-
the parent template::
|
158 |
-
|
159 |
-
// {% extends layout %}
|
160 |
-
|
161 |
-
$layout = $twig->loadTemplate('some_layout_template.twig');
|
162 |
-
|
163 |
-
$twig->display('template.twig', array('layout' => $layout));
|
164 |
-
|
165 |
-
.. versionadded:: 1.2
|
166 |
-
The possibility to pass an array of templates has been added in Twig 1.2.
|
167 |
-
|
168 |
-
You can also provide a list of templates that are checked for existence. The
|
169 |
-
first template that exists will be used as a parent:
|
170 |
-
|
171 |
-
.. code-block:: jinja
|
172 |
-
|
173 |
-
{% extends ['layout.html', 'base_layout.html'] %}
|
174 |
-
|
175 |
-
Conditional Inheritance
|
176 |
-
-----------------------
|
177 |
-
|
178 |
-
As the template name for the parent can be any valid Twig expression, it's
|
179 |
-
possible to make the inheritance mechanism conditional:
|
180 |
-
|
181 |
-
.. code-block:: jinja
|
182 |
-
|
183 |
-
{% extends standalone ? "minimum.html" : "base.html" %}
|
184 |
-
|
185 |
-
In this example, the template will extend the "minimum.html" layout template
|
186 |
-
if the ``standalone`` variable evaluates to ``true``, and "base.html"
|
187 |
-
otherwise.
|
188 |
-
|
189 |
-
How blocks work?
|
190 |
-
----------------
|
191 |
-
|
192 |
-
A block provides a way to change how a certain part of a template is rendered
|
193 |
-
but it does not interfere in any way with the logic around it.
|
194 |
-
|
195 |
-
Let's take the following example to illustrate how a block work and more
|
196 |
-
importantly, how it does not work:
|
197 |
-
|
198 |
-
.. code-block:: jinja
|
199 |
-
|
200 |
-
{# base.twig #}
|
201 |
-
|
202 |
-
{% for post in posts %}
|
203 |
-
{% block post %}
|
204 |
-
<h1>{{ post.title }}</h1>
|
205 |
-
<p>{{ post.body }}</p>
|
206 |
-
{% endblock %}
|
207 |
-
{% endfor %}
|
208 |
-
|
209 |
-
If you render this template, the result would be exactly the same with or
|
210 |
-
without the ``block`` tag. The ``block`` inside the ``for`` loop is just a way
|
211 |
-
to make it overridable by a child template:
|
212 |
-
|
213 |
-
.. code-block:: jinja
|
214 |
-
|
215 |
-
{# child.twig #}
|
216 |
-
|
217 |
-
{% extends "base.twig" %}
|
218 |
-
|
219 |
-
{% block post %}
|
220 |
-
<article>
|
221 |
-
<header>{{ post.title }}</header>
|
222 |
-
<section>{{ post.text }}</section>
|
223 |
-
</article>
|
224 |
-
{% endblock %}
|
225 |
-
|
226 |
-
Now, when rendering the child template, the loop is going to use the block
|
227 |
-
defined in the child template instead of the one defined in the base one; the
|
228 |
-
executed template is then equivalent to the following one:
|
229 |
-
|
230 |
-
.. code-block:: jinja
|
231 |
-
|
232 |
-
{% for post in posts %}
|
233 |
-
<article>
|
234 |
-
<header>{{ post.title }}</header>
|
235 |
-
<section>{{ post.text }}</section>
|
236 |
-
</article>
|
237 |
-
{% endfor %}
|
238 |
-
|
239 |
-
Let's take another example: a block included within an ``if`` statement:
|
240 |
-
|
241 |
-
.. code-block:: jinja
|
242 |
-
|
243 |
-
{% if posts is empty %}
|
244 |
-
{% block head %}
|
245 |
-
{{ parent() }}
|
246 |
-
|
247 |
-
<meta name="robots" content="noindex, follow">
|
248 |
-
{% endblock head %}
|
249 |
-
{% endif %}
|
250 |
-
|
251 |
-
Contrary to what you might think, this template does not define a block
|
252 |
-
conditionally; it just makes overridable by a child template the output of
|
253 |
-
what will be rendered when the condition is ``true``.
|
254 |
-
|
255 |
-
If you want the output to be displayed conditionally, use the following
|
256 |
-
instead:
|
257 |
-
|
258 |
-
.. code-block:: jinja
|
259 |
-
|
260 |
-
{% block head %}
|
261 |
-
{{ parent() }}
|
262 |
-
|
263 |
-
{% if posts is empty %}
|
264 |
-
<meta name="robots" content="noindex, follow">
|
265 |
-
{% endif %}
|
266 |
-
{% endblock head %}
|
267 |
-
|
268 |
-
.. seealso:: :doc:`block<../functions/block>`, :doc:`block<../tags/block>`, :doc:`parent<../functions/parent>`, :doc:`use<../tags/use>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/filter.rst
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
``filter``
|
2 |
-
==========
|
3 |
-
|
4 |
-
Filter sections allow you to apply regular Twig filters on a block of template
|
5 |
-
data. Just wrap the code in the special ``filter`` section:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% filter upper %}
|
10 |
-
This text becomes uppercase
|
11 |
-
{% endfilter %}
|
12 |
-
|
13 |
-
You can also chain filters:
|
14 |
-
|
15 |
-
.. code-block:: jinja
|
16 |
-
|
17 |
-
{% filter lower|escape %}
|
18 |
-
<strong>SOME TEXT</strong>
|
19 |
-
{% endfilter %}
|
20 |
-
|
21 |
-
{# outputs "<strong>some text</strong>" #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/flush.rst
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
``flush``
|
2 |
-
=========
|
3 |
-
|
4 |
-
.. versionadded:: 1.5
|
5 |
-
The flush tag was added in Twig 1.5.
|
6 |
-
|
7 |
-
The ``flush`` tag tells Twig to flush the output buffer:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{% flush %}
|
12 |
-
|
13 |
-
.. note::
|
14 |
-
|
15 |
-
Internally, Twig uses the PHP `flush`_ function.
|
16 |
-
|
17 |
-
.. _`flush`: http://php.net/flush
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/for.rst
DELETED
@@ -1,157 +0,0 @@
|
|
1 |
-
``for``
|
2 |
-
=======
|
3 |
-
|
4 |
-
Loop over each item in a sequence. For example, to display a list of users
|
5 |
-
provided in a variable called ``users``:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
<h1>Members</h1>
|
10 |
-
<ul>
|
11 |
-
{% for user in users %}
|
12 |
-
<li>{{ user.username|e }}</li>
|
13 |
-
{% endfor %}
|
14 |
-
</ul>
|
15 |
-
|
16 |
-
.. note::
|
17 |
-
|
18 |
-
A sequence can be either an array or an object implementing the
|
19 |
-
``Traversable`` interface.
|
20 |
-
|
21 |
-
If you do need to iterate over a sequence of numbers, you can use the ``..``
|
22 |
-
operator:
|
23 |
-
|
24 |
-
.. code-block:: jinja
|
25 |
-
|
26 |
-
{% for i in 0..10 %}
|
27 |
-
* {{ i }}
|
28 |
-
{% endfor %}
|
29 |
-
|
30 |
-
The above snippet of code would print all numbers from 0 to 10.
|
31 |
-
|
32 |
-
It can be also useful with letters:
|
33 |
-
|
34 |
-
.. code-block:: jinja
|
35 |
-
|
36 |
-
{% for letter in 'a'..'z' %}
|
37 |
-
* {{ letter }}
|
38 |
-
{% endfor %}
|
39 |
-
|
40 |
-
The ``..`` operator can take any expression at both sides:
|
41 |
-
|
42 |
-
.. code-block:: jinja
|
43 |
-
|
44 |
-
{% for letter in 'a'|upper..'z'|upper %}
|
45 |
-
* {{ letter }}
|
46 |
-
{% endfor %}
|
47 |
-
|
48 |
-
.. tip:
|
49 |
-
|
50 |
-
If you need a step different from 1, you can use the ``range`` function
|
51 |
-
instead.
|
52 |
-
|
53 |
-
The `loop` variable
|
54 |
-
-------------------
|
55 |
-
|
56 |
-
Inside of a ``for`` loop block you can access some special variables:
|
57 |
-
|
58 |
-
===================== =============================================================
|
59 |
-
Variable Description
|
60 |
-
===================== =============================================================
|
61 |
-
``loop.index`` The current iteration of the loop. (1 indexed)
|
62 |
-
``loop.index0`` The current iteration of the loop. (0 indexed)
|
63 |
-
``loop.revindex`` The number of iterations from the end of the loop (1 indexed)
|
64 |
-
``loop.revindex0`` The number of iterations from the end of the loop (0 indexed)
|
65 |
-
``loop.first`` True if first iteration
|
66 |
-
``loop.last`` True if last iteration
|
67 |
-
``loop.length`` The number of items in the sequence
|
68 |
-
``loop.parent`` The parent context
|
69 |
-
===================== =============================================================
|
70 |
-
|
71 |
-
.. code-block:: jinja
|
72 |
-
|
73 |
-
{% for user in users %}
|
74 |
-
{{ loop.index }} - {{ user.username }}
|
75 |
-
{% endfor %}
|
76 |
-
|
77 |
-
.. note::
|
78 |
-
|
79 |
-
The ``loop.length``, ``loop.revindex``, ``loop.revindex0``, and
|
80 |
-
``loop.last`` variables are only available for PHP arrays, or objects that
|
81 |
-
implement the ``Countable`` interface. They are also not available when
|
82 |
-
looping with a condition.
|
83 |
-
|
84 |
-
.. versionadded:: 1.2
|
85 |
-
The ``if`` modifier support has been added in Twig 1.2.
|
86 |
-
|
87 |
-
Adding a condition
|
88 |
-
------------------
|
89 |
-
|
90 |
-
Unlike in PHP, it's not possible to ``break`` or ``continue`` in a loop. You
|
91 |
-
can however filter the sequence during iteration which allows you to skip
|
92 |
-
items. The following example skips all the users which are not active:
|
93 |
-
|
94 |
-
.. code-block:: jinja
|
95 |
-
|
96 |
-
<ul>
|
97 |
-
{% for user in users if user.active %}
|
98 |
-
<li>{{ user.username|e }}</li>
|
99 |
-
{% endfor %}
|
100 |
-
</ul>
|
101 |
-
|
102 |
-
The advantage is that the special loop variable will count correctly thus not
|
103 |
-
counting the users not iterated over. Keep in mind that properties like
|
104 |
-
``loop.last`` will not be defined when using loop conditions.
|
105 |
-
|
106 |
-
.. note::
|
107 |
-
|
108 |
-
Using the ``loop`` variable within the condition is not recommended as it
|
109 |
-
will probably not be doing what you expect it to. For instance, adding a
|
110 |
-
condition like ``loop.index > 4`` won't work as the index is only
|
111 |
-
incremented when the condition is true (so the condition will never
|
112 |
-
match).
|
113 |
-
|
114 |
-
The `else` Clause
|
115 |
-
-----------------
|
116 |
-
|
117 |
-
If no iteration took place because the sequence was empty, you can render a
|
118 |
-
replacement block by using ``else``:
|
119 |
-
|
120 |
-
.. code-block:: jinja
|
121 |
-
|
122 |
-
<ul>
|
123 |
-
{% for user in users %}
|
124 |
-
<li>{{ user.username|e }}</li>
|
125 |
-
{% else %}
|
126 |
-
<li><em>no user found</em></li>
|
127 |
-
{% endfor %}
|
128 |
-
</ul>
|
129 |
-
|
130 |
-
Iterating over Keys
|
131 |
-
-------------------
|
132 |
-
|
133 |
-
By default, a loop iterates over the values of the sequence. You can iterate
|
134 |
-
on keys by using the ``keys`` filter:
|
135 |
-
|
136 |
-
.. code-block:: jinja
|
137 |
-
|
138 |
-
<h1>Members</h1>
|
139 |
-
<ul>
|
140 |
-
{% for key in users|keys %}
|
141 |
-
<li>{{ key }}</li>
|
142 |
-
{% endfor %}
|
143 |
-
</ul>
|
144 |
-
|
145 |
-
Iterating over Keys and Values
|
146 |
-
------------------------------
|
147 |
-
|
148 |
-
You can also access both keys and values:
|
149 |
-
|
150 |
-
.. code-block:: jinja
|
151 |
-
|
152 |
-
<h1>Members</h1>
|
153 |
-
<ul>
|
154 |
-
{% for key, user in users %}
|
155 |
-
<li>{{ key }}: {{ user.username|e }}</li>
|
156 |
-
{% endfor %}
|
157 |
-
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/from.rst
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
``from``
|
2 |
-
========
|
3 |
-
|
4 |
-
The ``from`` tags import :doc:`macro<../tags/macro>` names into the current
|
5 |
-
namespace. The tag is documented in detail in the documentation for the
|
6 |
-
:doc:`import<../tags/import>` tag.
|
7 |
-
|
8 |
-
.. seealso:: :doc:`macro<../tags/macro>`, :doc:`import<../tags/import>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/if.rst
DELETED
@@ -1,43 +0,0 @@
|
|
1 |
-
``if``
|
2 |
-
======
|
3 |
-
|
4 |
-
The ``if`` statement in Twig is comparable with the if statements of PHP.
|
5 |
-
|
6 |
-
In the simplest form you can use it to test if an expression evaluates to
|
7 |
-
``true``:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{% if online == false %}
|
12 |
-
<p>Our website is in maintenance mode. Please, come back later.</p>
|
13 |
-
{% endif %}
|
14 |
-
|
15 |
-
You can also test if an array is not empty:
|
16 |
-
|
17 |
-
.. code-block:: jinja
|
18 |
-
|
19 |
-
{% if users %}
|
20 |
-
<ul>
|
21 |
-
{% for user in users %}
|
22 |
-
<li>{{ user.username|e }}</li>
|
23 |
-
{% endfor %}
|
24 |
-
</ul>
|
25 |
-
{% endif %}
|
26 |
-
|
27 |
-
.. note::
|
28 |
-
|
29 |
-
If you want to test if the variable is defined, use ``if users is
|
30 |
-
defined`` instead.
|
31 |
-
|
32 |
-
For multiple branches ``elseif`` and ``else`` can be used like in PHP. You can use
|
33 |
-
more complex ``expressions`` there too:
|
34 |
-
|
35 |
-
.. code-block:: jinja
|
36 |
-
|
37 |
-
{% if kenny.sick %}
|
38 |
-
Kenny is sick.
|
39 |
-
{% elseif kenny.dead %}
|
40 |
-
You killed Kenny! You bastard!!!
|
41 |
-
{% else %}
|
42 |
-
Kenny looks okay --- so far
|
43 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/import.rst
DELETED
@@ -1,57 +0,0 @@
|
|
1 |
-
``import``
|
2 |
-
==========
|
3 |
-
|
4 |
-
Twig supports putting often used code into :doc:`macros<../tags/macro>`. These
|
5 |
-
macros can go into different templates and get imported from there.
|
6 |
-
|
7 |
-
There are two ways to import templates. You can import the complete template
|
8 |
-
into a variable or request specific macros from it.
|
9 |
-
|
10 |
-
Imagine we have a helper module that renders forms (called ``forms.html``):
|
11 |
-
|
12 |
-
.. code-block:: jinja
|
13 |
-
|
14 |
-
{% macro input(name, value, type, size) %}
|
15 |
-
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
|
16 |
-
{% endmacro %}
|
17 |
-
|
18 |
-
{% macro textarea(name, value, rows) %}
|
19 |
-
<textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
|
20 |
-
{% endmacro %}
|
21 |
-
|
22 |
-
The easiest and most flexible is importing the whole module into a variable.
|
23 |
-
That way you can access the attributes:
|
24 |
-
|
25 |
-
.. code-block:: jinja
|
26 |
-
|
27 |
-
{% import 'forms.html' as forms %}
|
28 |
-
|
29 |
-
<dl>
|
30 |
-
<dt>Username</dt>
|
31 |
-
<dd>{{ forms.input('username') }}</dd>
|
32 |
-
<dt>Password</dt>
|
33 |
-
<dd>{{ forms.input('password', null, 'password') }}</dd>
|
34 |
-
</dl>
|
35 |
-
<p>{{ forms.textarea('comment') }}</p>
|
36 |
-
|
37 |
-
Alternatively you can import names from the template into the current
|
38 |
-
namespace:
|
39 |
-
|
40 |
-
.. code-block:: jinja
|
41 |
-
|
42 |
-
{% from 'forms.html' import input as input_field, textarea %}
|
43 |
-
|
44 |
-
<dl>
|
45 |
-
<dt>Username</dt>
|
46 |
-
<dd>{{ input_field('username') }}</dd>
|
47 |
-
<dt>Password</dt>
|
48 |
-
<dd>{{ input_field('password', '', 'password') }}</dd>
|
49 |
-
</dl>
|
50 |
-
<p>{{ textarea('comment') }}</p>
|
51 |
-
|
52 |
-
.. tip::
|
53 |
-
|
54 |
-
To import macros from the current file, use the special ``_self`` variable
|
55 |
-
for the source.
|
56 |
-
|
57 |
-
.. seealso:: :doc:`macro<../tags/macro>`, :doc:`from<../tags/from>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/include.rst
DELETED
@@ -1,86 +0,0 @@
|
|
1 |
-
``include``
|
2 |
-
===========
|
3 |
-
|
4 |
-
The ``include`` statement includes a template and return the rendered content
|
5 |
-
of that file into the current namespace:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% include 'header.html' %}
|
10 |
-
Body
|
11 |
-
{% include 'footer.html' %}
|
12 |
-
|
13 |
-
Included templates have access to the variables of the active context.
|
14 |
-
|
15 |
-
If you are using the filesystem loader, the templates are looked for in the
|
16 |
-
paths defined by it.
|
17 |
-
|
18 |
-
You can add additional variables by passing them after the ``with`` keyword:
|
19 |
-
|
20 |
-
.. code-block:: jinja
|
21 |
-
|
22 |
-
{# template.html will have access to the variables from the current context and the additional ones provided #}
|
23 |
-
{% include 'template.html' with {'foo': 'bar'} %}
|
24 |
-
|
25 |
-
{% set vars = {'foo': 'bar'} %}
|
26 |
-
{% include 'template.html' with vars %}
|
27 |
-
|
28 |
-
You can disable access to the context by appending the ``only`` keyword:
|
29 |
-
|
30 |
-
.. code-block:: jinja
|
31 |
-
|
32 |
-
{# only the foo variable will be accessible #}
|
33 |
-
{% include 'template.html' with {'foo': 'bar'} only %}
|
34 |
-
|
35 |
-
.. code-block:: jinja
|
36 |
-
|
37 |
-
{# no variables will be accessible #}
|
38 |
-
{% include 'template.html' only %}
|
39 |
-
|
40 |
-
.. tip::
|
41 |
-
|
42 |
-
When including a template created by an end user, you should consider
|
43 |
-
sandboxing it. More information in the :doc:`Twig for Developers<../api>`
|
44 |
-
chapter and in the :doc:`sandbox<../tags/sandbox>` tag documentation.
|
45 |
-
|
46 |
-
The template name can be any valid Twig expression:
|
47 |
-
|
48 |
-
.. code-block:: jinja
|
49 |
-
|
50 |
-
{% include some_var %}
|
51 |
-
{% include ajax ? 'ajax.html' : 'not_ajax.html' %}
|
52 |
-
|
53 |
-
And if the expression evaluates to a ``Twig_Template`` object, Twig will use it
|
54 |
-
directly::
|
55 |
-
|
56 |
-
// {% include template %}
|
57 |
-
|
58 |
-
$template = $twig->loadTemplate('some_template.twig');
|
59 |
-
|
60 |
-
$twig->loadTemplate('template.twig')->display(array('template' => $template));
|
61 |
-
|
62 |
-
.. versionadded:: 1.2
|
63 |
-
The ``ignore missing`` feature has been added in Twig 1.2.
|
64 |
-
|
65 |
-
You can mark an include with ``ignore missing`` in which case Twig will ignore
|
66 |
-
the statement if the template to be ignored does not exist. It has to be
|
67 |
-
placed just after the template name. Here some valid examples:
|
68 |
-
|
69 |
-
.. code-block:: jinja
|
70 |
-
|
71 |
-
{% include 'sidebar.html' ignore missing %}
|
72 |
-
{% include 'sidebar.html' ignore missing with {'foo': 'bar'} %}
|
73 |
-
{% include 'sidebar.html' ignore missing only %}
|
74 |
-
|
75 |
-
.. versionadded:: 1.2
|
76 |
-
The possibility to pass an array of templates has been added in Twig 1.2.
|
77 |
-
|
78 |
-
You can also provide a list of templates that are checked for existence before
|
79 |
-
inclusion. The first template that exists will be included:
|
80 |
-
|
81 |
-
.. code-block:: jinja
|
82 |
-
|
83 |
-
{% include ['page_detailed.html', 'page.html'] %}
|
84 |
-
|
85 |
-
If ``ignore missing`` is given, it will fall back to rendering nothing if none
|
86 |
-
of the templates exist, otherwise it will throw an exception.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/index.rst
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
Tags
|
2 |
-
====
|
3 |
-
|
4 |
-
.. toctree::
|
5 |
-
:maxdepth: 1
|
6 |
-
|
7 |
-
for
|
8 |
-
if
|
9 |
-
macro
|
10 |
-
filter
|
11 |
-
set
|
12 |
-
extends
|
13 |
-
block
|
14 |
-
include
|
15 |
-
import
|
16 |
-
from
|
17 |
-
use
|
18 |
-
spaceless
|
19 |
-
autoescape
|
20 |
-
verbatim
|
21 |
-
flush
|
22 |
-
do
|
23 |
-
sandbox
|
24 |
-
embed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/macro.rst
DELETED
@@ -1,83 +0,0 @@
|
|
1 |
-
``macro``
|
2 |
-
=========
|
3 |
-
|
4 |
-
Macros are comparable with functions in regular programming languages. They
|
5 |
-
are useful to put often used HTML idioms into reusable elements to not repeat
|
6 |
-
yourself.
|
7 |
-
|
8 |
-
Here is a small example of a macro that renders a form element:
|
9 |
-
|
10 |
-
.. code-block:: jinja
|
11 |
-
|
12 |
-
{% macro input(name, value, type, size) %}
|
13 |
-
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
|
14 |
-
{% endmacro %}
|
15 |
-
|
16 |
-
Macros differs from native PHP functions in a few ways:
|
17 |
-
|
18 |
-
* Default argument values are defined by using the ``default`` filter in the
|
19 |
-
macro body;
|
20 |
-
|
21 |
-
* Arguments of a macro are always optional.
|
22 |
-
|
23 |
-
But as PHP functions, macros don't have access to the current template
|
24 |
-
variables.
|
25 |
-
|
26 |
-
.. tip::
|
27 |
-
|
28 |
-
You can pass the whole context as an argument by using the special
|
29 |
-
``_context`` variable.
|
30 |
-
|
31 |
-
Macros can be defined in any template, and need to be "imported" before being
|
32 |
-
used (see the documentation for the :doc:`import<../tags/import>` tag for more
|
33 |
-
information):
|
34 |
-
|
35 |
-
.. code-block:: jinja
|
36 |
-
|
37 |
-
{% import "forms.html" as forms %}
|
38 |
-
|
39 |
-
The above ``import`` call imports the "forms.html" file (which can contain only
|
40 |
-
macros, or a template and some macros), and import the functions as items of
|
41 |
-
the ``forms`` variable.
|
42 |
-
|
43 |
-
The macro can then be called at will:
|
44 |
-
|
45 |
-
.. code-block:: jinja
|
46 |
-
|
47 |
-
<p>{{ forms.input('username') }}</p>
|
48 |
-
<p>{{ forms.input('password', null, 'password') }}</p>
|
49 |
-
|
50 |
-
If macros are defined and used in the same template, you can use the
|
51 |
-
special ``_self`` variable to import them:
|
52 |
-
|
53 |
-
.. code-block:: jinja
|
54 |
-
|
55 |
-
{% import _self as forms %}
|
56 |
-
|
57 |
-
<p>{{ forms.input('username') }}</p>
|
58 |
-
|
59 |
-
.. warning::
|
60 |
-
|
61 |
-
When you define a macro in the template where you are going to use it, you
|
62 |
-
might be tempted to call the macro directly via ``_self.input()`` instead
|
63 |
-
of importing it; even if seems to work, this is just a side-effect of the
|
64 |
-
current implementation and it won't work anymore in Twig 2.x.
|
65 |
-
|
66 |
-
When you want to use a macro in another macro from the same file, you need to
|
67 |
-
import it locally:
|
68 |
-
|
69 |
-
.. code-block:: jinja
|
70 |
-
|
71 |
-
{% macro input(name, value, type, size) %}
|
72 |
-
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
|
73 |
-
{% endmacro %}
|
74 |
-
|
75 |
-
{% macro wrapped_input(name, value, type, size) %}
|
76 |
-
{% import _self as forms %}
|
77 |
-
|
78 |
-
<div class="field">
|
79 |
-
{{ forms.input(name, value, type, size) }}
|
80 |
-
</div>
|
81 |
-
{% endmacro %}
|
82 |
-
|
83 |
-
.. seealso:: :doc:`from<../tags/from>`, :doc:`import<../tags/import>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/sandbox.rst
DELETED
@@ -1,30 +0,0 @@
|
|
1 |
-
``sandbox``
|
2 |
-
===========
|
3 |
-
|
4 |
-
The ``sandbox`` tag can be used to enable the sandboxing mode for an included
|
5 |
-
template, when sandboxing is not enabled globally for the Twig environment:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% sandbox %}
|
10 |
-
{% include 'user.html' %}
|
11 |
-
{% endsandbox %}
|
12 |
-
|
13 |
-
.. warning::
|
14 |
-
|
15 |
-
The ``sandbox`` tag is only available when the sandbox extension is
|
16 |
-
enabled (see the :doc:`Twig for Developers<../api>` chapter).
|
17 |
-
|
18 |
-
.. note::
|
19 |
-
|
20 |
-
The ``sandbox`` tag can only be used to sandbox an include tag and it
|
21 |
-
cannot be used to sandbox a section of a template. The following example
|
22 |
-
won't work:
|
23 |
-
|
24 |
-
.. code-block:: jinja
|
25 |
-
|
26 |
-
{% sandbox %}
|
27 |
-
{% for i in 1..2 %}
|
28 |
-
{{ i }}
|
29 |
-
{% endfor %}
|
30 |
-
{% endsandbox %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/set.rst
DELETED
@@ -1,32 +0,0 @@
|
|
1 |
-
``set``
|
2 |
-
=======
|
3 |
-
|
4 |
-
Inside code blocks you can also assign values to variables. Assignments use
|
5 |
-
the ``set`` tag and can have multiple targets:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% set foo = 'foo' %}
|
10 |
-
|
11 |
-
{% set foo = [1, 2] %}
|
12 |
-
|
13 |
-
{% set foo = {'foo': 'bar'} %}
|
14 |
-
|
15 |
-
{% set foo = 'foo' ~ 'bar' %}
|
16 |
-
|
17 |
-
{% set foo, bar = 'foo', 'bar' %}
|
18 |
-
|
19 |
-
The ``set`` tag can also be used to 'capture' chunks of text:
|
20 |
-
|
21 |
-
.. code-block:: jinja
|
22 |
-
|
23 |
-
{% set foo %}
|
24 |
-
<div id="pagination">
|
25 |
-
...
|
26 |
-
</div>
|
27 |
-
{% endset %}
|
28 |
-
|
29 |
-
.. caution::
|
30 |
-
|
31 |
-
If you enable automatic output escaping, Twig will only consider the
|
32 |
-
content to be safe when capturing chunks of text.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/spaceless.rst
DELETED
@@ -1,37 +0,0 @@
|
|
1 |
-
``spaceless``
|
2 |
-
=============
|
3 |
-
|
4 |
-
Use the ``spaceless`` tag to remove whitespace *between HTML tags*, not
|
5 |
-
whitespace within HTML tags or whitespace in plain text:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% spaceless %}
|
10 |
-
<div>
|
11 |
-
<strong>foo</strong>
|
12 |
-
</div>
|
13 |
-
{% endspaceless %}
|
14 |
-
|
15 |
-
{# output will be <div><strong>foo</strong></div> #}
|
16 |
-
|
17 |
-
This tag is not meant to "optimize" the size of the generated HTML content but
|
18 |
-
merely to avoid extra whitespace between HTML tags to avoid browser rendering
|
19 |
-
quirks under some circumstances.
|
20 |
-
|
21 |
-
.. tip::
|
22 |
-
|
23 |
-
If you want to optimize the size of the generated HTML content, gzip
|
24 |
-
compress the output instead.
|
25 |
-
|
26 |
-
.. tip::
|
27 |
-
|
28 |
-
If you want to create a tag that actually removes all extra whitespace in
|
29 |
-
an HTML string, be warned that this is not as easy as it seems to be
|
30 |
-
(think of ``textarea`` or ``pre`` tags for instance). Using a third-party
|
31 |
-
library like Tidy is probably a better idea.
|
32 |
-
|
33 |
-
.. tip::
|
34 |
-
|
35 |
-
For more information on whitespace control, read the
|
36 |
-
:doc:`dedicated<../templates>` section of the documentation and learn how
|
37 |
-
you can also use the whitespace control modifier on your tags.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/use.rst
DELETED
@@ -1,123 +0,0 @@
|
|
1 |
-
``use``
|
2 |
-
=======
|
3 |
-
|
4 |
-
.. versionadded:: 1.1
|
5 |
-
Horizontal reuse was added in Twig 1.1.
|
6 |
-
|
7 |
-
.. note::
|
8 |
-
|
9 |
-
Horizontal reuse is an advanced Twig feature that is hardly ever needed in
|
10 |
-
regular templates. It is mainly used by projects that need to make
|
11 |
-
template blocks reusable without using inheritance.
|
12 |
-
|
13 |
-
Template inheritance is one of the most powerful Twig's feature but it is
|
14 |
-
limited to single inheritance; a template can only extend one other template.
|
15 |
-
This limitation makes template inheritance simple to understand and easy to
|
16 |
-
debug:
|
17 |
-
|
18 |
-
.. code-block:: jinja
|
19 |
-
|
20 |
-
{% extends "base.html" %}
|
21 |
-
|
22 |
-
{% block title %}{% endblock %}
|
23 |
-
{% block content %}{% endblock %}
|
24 |
-
|
25 |
-
Horizontal reuse is a way to achieve the same goal as multiple inheritance,
|
26 |
-
but without the associated complexity:
|
27 |
-
|
28 |
-
.. code-block:: jinja
|
29 |
-
|
30 |
-
{% extends "base.html" %}
|
31 |
-
|
32 |
-
{% use "blocks.html" %}
|
33 |
-
|
34 |
-
{% block title %}{% endblock %}
|
35 |
-
{% block content %}{% endblock %}
|
36 |
-
|
37 |
-
The ``use`` statement tells Twig to import the blocks defined in
|
38 |
-
```blocks.html`` into the current template (it's like macros, but for blocks):
|
39 |
-
|
40 |
-
.. code-block:: jinja
|
41 |
-
|
42 |
-
# blocks.html
|
43 |
-
{% block sidebar %}{% endblock %}
|
44 |
-
|
45 |
-
In this example, the ``use`` statement imports the ``sidebar`` block into the
|
46 |
-
main template. The code is mostly equivalent to the following one (the
|
47 |
-
imported blocks are not outputted automatically):
|
48 |
-
|
49 |
-
.. code-block:: jinja
|
50 |
-
|
51 |
-
{% extends "base.html" %}
|
52 |
-
|
53 |
-
{% block sidebar %}{% endblock %}
|
54 |
-
{% block title %}{% endblock %}
|
55 |
-
{% block content %}{% endblock %}
|
56 |
-
|
57 |
-
.. note::
|
58 |
-
|
59 |
-
The ``use`` tag only imports a template if it does not extend another
|
60 |
-
template, if it does not define macros, and if the body is empty. But it
|
61 |
-
can *use* other templates.
|
62 |
-
|
63 |
-
.. note::
|
64 |
-
|
65 |
-
Because ``use`` statements are resolved independently of the context
|
66 |
-
passed to the template, the template reference cannot be an expression.
|
67 |
-
|
68 |
-
The main template can also override any imported block. If the template
|
69 |
-
already defines the ``sidebar`` block, then the one defined in ``blocks.html``
|
70 |
-
is ignored. To avoid name conflicts, you can rename imported blocks:
|
71 |
-
|
72 |
-
.. code-block:: jinja
|
73 |
-
|
74 |
-
{% extends "base.html" %}
|
75 |
-
|
76 |
-
{% use "blocks.html" with sidebar as base_sidebar %}
|
77 |
-
|
78 |
-
{% block sidebar %}{% endblock %}
|
79 |
-
{% block title %}{% endblock %}
|
80 |
-
{% block content %}{% endblock %}
|
81 |
-
|
82 |
-
.. versionadded:: 1.3
|
83 |
-
The ``parent()`` support was added in Twig 1.3.
|
84 |
-
|
85 |
-
The ``parent()`` function automatically determines the correct inheritance
|
86 |
-
tree, so it can be used when overriding a block defined in an imported
|
87 |
-
template:
|
88 |
-
|
89 |
-
.. code-block:: jinja
|
90 |
-
|
91 |
-
{% extends "base.html" %}
|
92 |
-
|
93 |
-
{% use "blocks.html" %}
|
94 |
-
|
95 |
-
{% block sidebar %}
|
96 |
-
{{ parent() }}
|
97 |
-
{% endblock %}
|
98 |
-
|
99 |
-
{% block title %}{% endblock %}
|
100 |
-
{% block content %}{% endblock %}
|
101 |
-
|
102 |
-
In this example, ``parent()`` will correctly call the ``sidebar`` block from
|
103 |
-
the ``blocks.html`` template.
|
104 |
-
|
105 |
-
.. tip::
|
106 |
-
|
107 |
-
In Twig 1.2, renaming allows you to simulate inheritance by calling the
|
108 |
-
"parent" block:
|
109 |
-
|
110 |
-
.. code-block:: jinja
|
111 |
-
|
112 |
-
{% extends "base.html" %}
|
113 |
-
|
114 |
-
{% use "blocks.html" with sidebar as parent_sidebar %}
|
115 |
-
|
116 |
-
{% block sidebar %}
|
117 |
-
{{ block('parent_sidebar') }}
|
118 |
-
{% endblock %}
|
119 |
-
|
120 |
-
.. note::
|
121 |
-
|
122 |
-
You can use as many ``use`` statements as you want in any given template.
|
123 |
-
If two imported templates define the same block, the latest one wins.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tags/verbatim.rst
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
``verbatim``
|
2 |
-
============
|
3 |
-
|
4 |
-
.. versionadded:: 1.12
|
5 |
-
The ``verbatim`` tag was added in Twig 1.12 (it was named ``raw`` before).
|
6 |
-
|
7 |
-
The ``verbatim`` tag marks sections as being raw text that should not be
|
8 |
-
parsed. For example to put Twig syntax as example into a template you can use
|
9 |
-
this snippet:
|
10 |
-
|
11 |
-
.. code-block:: jinja
|
12 |
-
|
13 |
-
{% verbatim %}
|
14 |
-
<ul>
|
15 |
-
{% for item in seq %}
|
16 |
-
<li>{{ item }}</li>
|
17 |
-
{% endfor %}
|
18 |
-
</ul>
|
19 |
-
{% endverbatim %}
|
20 |
-
|
21 |
-
.. note::
|
22 |
-
|
23 |
-
The ``verbatim`` tag works in the exact same way as the old ``raw`` tag,
|
24 |
-
but was renamed to avoid confusion with the ``raw`` filter.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/templates.rst
DELETED
@@ -1,837 +0,0 @@
|
|
1 |
-
Twig for Template Designers
|
2 |
-
===========================
|
3 |
-
|
4 |
-
This document describes the syntax and semantics of the template engine and
|
5 |
-
will be most useful as reference to those creating Twig templates.
|
6 |
-
|
7 |
-
Synopsis
|
8 |
-
--------
|
9 |
-
|
10 |
-
A template is simply a text file. It can generate any text-based format (HTML,
|
11 |
-
XML, CSV, LaTeX, etc.). It doesn't have a specific extension, ``.html`` or
|
12 |
-
``.xml`` are just fine.
|
13 |
-
|
14 |
-
A template contains **variables** or **expressions**, which get replaced with
|
15 |
-
values when the template is evaluated, and **tags**, which control the logic
|
16 |
-
of the template.
|
17 |
-
|
18 |
-
Below is a minimal template that illustrates a few basics. We will cover the
|
19 |
-
details later on:
|
20 |
-
|
21 |
-
.. code-block:: html+jinja
|
22 |
-
|
23 |
-
<!DOCTYPE html>
|
24 |
-
<html>
|
25 |
-
<head>
|
26 |
-
<title>My Webpage</title>
|
27 |
-
</head>
|
28 |
-
<body>
|
29 |
-
<ul id="navigation">
|
30 |
-
{% for item in navigation %}
|
31 |
-
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
|
32 |
-
{% endfor %}
|
33 |
-
</ul>
|
34 |
-
|
35 |
-
<h1>My Webpage</h1>
|
36 |
-
{{ a_variable }}
|
37 |
-
</body>
|
38 |
-
</html>
|
39 |
-
|
40 |
-
There are two kinds of delimiters: ``{% ... %}`` and ``{{ ... }}``. The first
|
41 |
-
one is used to execute statements such as for-loops, the latter prints the
|
42 |
-
result of an expression to the template.
|
43 |
-
|
44 |
-
IDEs Integration
|
45 |
-
----------------
|
46 |
-
|
47 |
-
Many IDEs support syntax highlighting and auto-completion for Twig:
|
48 |
-
|
49 |
-
* *Textmate* via the `Twig bundle`_
|
50 |
-
* *Vim* via the `Jinja syntax plugin`_
|
51 |
-
* *Netbeans* via the `Twig syntax plugin`_ (until 7.1, native as of 7.2)
|
52 |
-
* *PhpStorm* (native as of 2.1)
|
53 |
-
* *Eclipse* via the `Twig plugin`_
|
54 |
-
* *Sublime Text* via the `Twig bundle`_
|
55 |
-
* *GtkSourceView* via the `Twig language definition`_ (used by gedit and other projects)
|
56 |
-
* *Coda* and *SubEthaEdit* via the `Twig syntax mode`_
|
57 |
-
* *Coda 2* via the `other Twig syntax mode`_
|
58 |
-
* *Komodo* and *Komodo Edit* via the Twig highlight/syntax check mode
|
59 |
-
* *Notepad++* via the `Notepad++ Twig Highlighter`_
|
60 |
-
* *Emacs* via `web-mode.el`_
|
61 |
-
|
62 |
-
Variables
|
63 |
-
---------
|
64 |
-
|
65 |
-
The application passes variables to the templates you can mess around in the
|
66 |
-
template. Variables may have attributes or elements on them you can access
|
67 |
-
too. How a variable looks like heavily depends on the application providing
|
68 |
-
those.
|
69 |
-
|
70 |
-
You can use a dot (``.``) to access attributes of a variable (methods or
|
71 |
-
properties of a PHP object, or items of a PHP array), or the so-called
|
72 |
-
"subscript" syntax (``[]``):
|
73 |
-
|
74 |
-
.. code-block:: jinja
|
75 |
-
|
76 |
-
{{ foo.bar }}
|
77 |
-
{{ foo['bar'] }}
|
78 |
-
|
79 |
-
When the attribute contains special characters (like ``-`` that would be
|
80 |
-
interpreted as the minus operator), use the ``attribute`` function instead to
|
81 |
-
access the variable attribute:
|
82 |
-
|
83 |
-
.. code-block:: jinja
|
84 |
-
|
85 |
-
{# equivalent to the non-working foo.data-foo #}
|
86 |
-
{{ attribute(foo, 'data-foo') }}
|
87 |
-
|
88 |
-
.. note::
|
89 |
-
|
90 |
-
It's important to know that the curly braces are *not* part of the
|
91 |
-
variable but the print statement. If you access variables inside tags
|
92 |
-
don't put the braces around.
|
93 |
-
|
94 |
-
If a variable or attribute does not exist, you will get back a ``null`` value
|
95 |
-
when the ``strict_variables`` option is set to ``false``, otherwise Twig will
|
96 |
-
throw an error (see :ref:`environment options<environment_options>`).
|
97 |
-
|
98 |
-
.. sidebar:: Implementation
|
99 |
-
|
100 |
-
For convenience sake ``foo.bar`` does the following things on the PHP
|
101 |
-
layer:
|
102 |
-
|
103 |
-
* check if ``foo`` is an array and ``bar`` a valid element;
|
104 |
-
* if not, and if ``foo`` is an object, check that ``bar`` is a valid property;
|
105 |
-
* if not, and if ``foo`` is an object, check that ``bar`` is a valid method
|
106 |
-
(even if ``bar`` is the constructor - use ``__construct()`` instead);
|
107 |
-
* if not, and if ``foo`` is an object, check that ``getBar`` is a valid method;
|
108 |
-
* if not, and if ``foo`` is an object, check that ``isBar`` is a valid method;
|
109 |
-
* if not, return a ``null`` value.
|
110 |
-
|
111 |
-
``foo['bar']`` on the other hand only works with PHP arrays:
|
112 |
-
|
113 |
-
* check if ``foo`` is an array and ``bar`` a valid element;
|
114 |
-
* if not, return a ``null`` value.
|
115 |
-
|
116 |
-
.. note::
|
117 |
-
|
118 |
-
If you want to get a dynamic attribute on a variable, use the
|
119 |
-
:doc:`attribute<functions/attribute>` function instead.
|
120 |
-
|
121 |
-
Global Variables
|
122 |
-
~~~~~~~~~~~~~~~~
|
123 |
-
|
124 |
-
The following variables are always available in templates:
|
125 |
-
|
126 |
-
* ``_self``: references the current template;
|
127 |
-
* ``_context``: references the current context;
|
128 |
-
* ``_charset``: references the current charset.
|
129 |
-
|
130 |
-
Setting Variables
|
131 |
-
~~~~~~~~~~~~~~~~~
|
132 |
-
|
133 |
-
You can assign values to variables inside code blocks. Assignments use the
|
134 |
-
:doc:`set<tags/set>` tag:
|
135 |
-
|
136 |
-
.. code-block:: jinja
|
137 |
-
|
138 |
-
{% set foo = 'foo' %}
|
139 |
-
{% set foo = [1, 2] %}
|
140 |
-
{% set foo = {'foo': 'bar'} %}
|
141 |
-
|
142 |
-
Filters
|
143 |
-
-------
|
144 |
-
|
145 |
-
Variables can be modified by **filters**. Filters are separated from the
|
146 |
-
variable by a pipe symbol (``|``) and may have optional arguments in
|
147 |
-
parentheses. Multiple filters can be chained. The output of one filter is
|
148 |
-
applied to the next.
|
149 |
-
|
150 |
-
The following example removes all HTML tags from the ``name`` and title-cases
|
151 |
-
it:
|
152 |
-
|
153 |
-
.. code-block:: jinja
|
154 |
-
|
155 |
-
{{ name|striptags|title }}
|
156 |
-
|
157 |
-
Filters that accept arguments have parentheses around the arguments. This
|
158 |
-
example will join a list by commas:
|
159 |
-
|
160 |
-
.. code-block:: jinja
|
161 |
-
|
162 |
-
{{ list|join(', ') }}
|
163 |
-
|
164 |
-
To apply a filter on a section of code, wrap it with the
|
165 |
-
:doc:`filter<tags/filter>` tag:
|
166 |
-
|
167 |
-
.. code-block:: jinja
|
168 |
-
|
169 |
-
{% filter upper %}
|
170 |
-
This text becomes uppercase
|
171 |
-
{% endfilter %}
|
172 |
-
|
173 |
-
Go to the :doc:`filters<filters/index>` page to learn more about the built-in
|
174 |
-
filters.
|
175 |
-
|
176 |
-
Functions
|
177 |
-
---------
|
178 |
-
|
179 |
-
Functions can be called to generate content. Functions are called by their
|
180 |
-
name followed by parentheses (``()``) and may have arguments.
|
181 |
-
|
182 |
-
For instance, the ``range`` function returns a list containing an arithmetic
|
183 |
-
progression of integers:
|
184 |
-
|
185 |
-
.. code-block:: jinja
|
186 |
-
|
187 |
-
{% for i in range(0, 3) %}
|
188 |
-
{{ i }},
|
189 |
-
{% endfor %}
|
190 |
-
|
191 |
-
Go to the :doc:`functions<functions/index>` page to learn more about the
|
192 |
-
built-in functions.
|
193 |
-
|
194 |
-
Named Arguments
|
195 |
-
---------------
|
196 |
-
|
197 |
-
.. versionadded:: 1.12
|
198 |
-
Support for named arguments was added in Twig 1.12.
|
199 |
-
|
200 |
-
Arguments for filters and functions can also be passed as *named arguments*:
|
201 |
-
|
202 |
-
.. code-block:: jinja
|
203 |
-
|
204 |
-
{% for i in range(low=1, high=10, step=2) %}
|
205 |
-
{{ i }},
|
206 |
-
{% endfor %}
|
207 |
-
|
208 |
-
Using named arguments makes your templates more explicit about the meaning of
|
209 |
-
the values you pass as arguments:
|
210 |
-
|
211 |
-
.. code-block:: jinja
|
212 |
-
|
213 |
-
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
|
214 |
-
|
215 |
-
{# versus #}
|
216 |
-
|
217 |
-
{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}
|
218 |
-
|
219 |
-
Named arguments also allow you to skip some arguments for which you don't want
|
220 |
-
to change the default value:
|
221 |
-
|
222 |
-
.. code-block:: jinja
|
223 |
-
|
224 |
-
{# the first argument is the date format, which defaults to the global date format if null is passed #}
|
225 |
-
{{ "now"|date(null, "Europe/Paris") }}
|
226 |
-
|
227 |
-
{# or skip the format value by using a named argument for the timezone #}
|
228 |
-
{{ "now"|date(timezone="Europe/Paris") }}
|
229 |
-
|
230 |
-
You can also use both positional and named arguments in one call, which is not
|
231 |
-
recommended as it can be confusing:
|
232 |
-
|
233 |
-
.. code-block:: jinja
|
234 |
-
|
235 |
-
{# both work #}
|
236 |
-
{{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}
|
237 |
-
{{ "now"|date(timezone="Europe/Paris", 'd/m/Y H:i') }}
|
238 |
-
|
239 |
-
.. tip::
|
240 |
-
|
241 |
-
Each function and filter documentation page has a section where the names
|
242 |
-
of all arguments are listed when supported.
|
243 |
-
|
244 |
-
Control Structure
|
245 |
-
-----------------
|
246 |
-
|
247 |
-
A control structure refers to all those things that control the flow of a
|
248 |
-
program - conditionals (i.e. ``if``/``elseif``/``else``), ``for``-loops, as
|
249 |
-
well as things like blocks. Control structures appear inside ``{% ... %}``
|
250 |
-
blocks.
|
251 |
-
|
252 |
-
For example, to display a list of users provided in a variable called
|
253 |
-
``users``, use the :doc:`for<tags/for>` tag:
|
254 |
-
|
255 |
-
.. code-block:: jinja
|
256 |
-
|
257 |
-
<h1>Members</h1>
|
258 |
-
<ul>
|
259 |
-
{% for user in users %}
|
260 |
-
<li>{{ user.username|e }}</li>
|
261 |
-
{% endfor %}
|
262 |
-
</ul>
|
263 |
-
|
264 |
-
The :doc:`if<tags/if>` tag can be used to test an expression:
|
265 |
-
|
266 |
-
.. code-block:: jinja
|
267 |
-
|
268 |
-
{% if users|length > 0 %}
|
269 |
-
<ul>
|
270 |
-
{% for user in users %}
|
271 |
-
<li>{{ user.username|e }}</li>
|
272 |
-
{% endfor %}
|
273 |
-
</ul>
|
274 |
-
{% endif %}
|
275 |
-
|
276 |
-
Go to the :doc:`tags<tags/index>` page to learn more about the built-in tags.
|
277 |
-
|
278 |
-
Comments
|
279 |
-
--------
|
280 |
-
|
281 |
-
To comment-out part of a line in a template, use the comment syntax ``{# ...
|
282 |
-
#}``. This is useful for debugging or to add information for other template
|
283 |
-
designers or yourself:
|
284 |
-
|
285 |
-
.. code-block:: jinja
|
286 |
-
|
287 |
-
{# note: disabled template because we no longer use this
|
288 |
-
{% for user in users %}
|
289 |
-
...
|
290 |
-
{% endfor %}
|
291 |
-
#}
|
292 |
-
|
293 |
-
Including other Templates
|
294 |
-
-------------------------
|
295 |
-
|
296 |
-
The :doc:`include<tags/include>` tag is useful to include a template and
|
297 |
-
return the rendered content of that template into the current one:
|
298 |
-
|
299 |
-
.. code-block:: jinja
|
300 |
-
|
301 |
-
{% include 'sidebar.html' %}
|
302 |
-
|
303 |
-
Per default included templates are passed the current context.
|
304 |
-
|
305 |
-
The context that is passed to the included template includes variables defined
|
306 |
-
in the template:
|
307 |
-
|
308 |
-
.. code-block:: jinja
|
309 |
-
|
310 |
-
{% for box in boxes %}
|
311 |
-
{% include "render_box.html" %}
|
312 |
-
{% endfor %}
|
313 |
-
|
314 |
-
The included template ``render_box.html`` is able to access ``box``.
|
315 |
-
|
316 |
-
The filename of the template depends on the template loader. For instance, the
|
317 |
-
``Twig_Loader_Filesystem`` allows you to access other templates by giving the
|
318 |
-
filename. You can access templates in subdirectories with a slash:
|
319 |
-
|
320 |
-
.. code-block:: jinja
|
321 |
-
|
322 |
-
{% include "sections/articles/sidebar.html" %}
|
323 |
-
|
324 |
-
This behavior depends on the application embedding Twig.
|
325 |
-
|
326 |
-
Template Inheritance
|
327 |
-
--------------------
|
328 |
-
|
329 |
-
The most powerful part of Twig is template inheritance. Template inheritance
|
330 |
-
allows you to build a base "skeleton" template that contains all the common
|
331 |
-
elements of your site and defines **blocks** that child templates can
|
332 |
-
override.
|
333 |
-
|
334 |
-
Sounds complicated but is very basic. It's easier to understand it by
|
335 |
-
starting with an example.
|
336 |
-
|
337 |
-
Let's define a base template, ``base.html``, which defines a simple HTML
|
338 |
-
skeleton document that you might use for a simple two-column page:
|
339 |
-
|
340 |
-
.. code-block:: html+jinja
|
341 |
-
|
342 |
-
<!DOCTYPE html>
|
343 |
-
<html>
|
344 |
-
<head>
|
345 |
-
{% block head %}
|
346 |
-
<link rel="stylesheet" href="style.css" />
|
347 |
-
<title>{% block title %}{% endblock %} - My Webpage</title>
|
348 |
-
{% endblock %}
|
349 |
-
</head>
|
350 |
-
<body>
|
351 |
-
<div id="content">{% block content %}{% endblock %}</div>
|
352 |
-
<div id="footer">
|
353 |
-
{% block footer %}
|
354 |
-
© Copyright 2011 by <a href="http://domain.invalid/">you</a>.
|
355 |
-
{% endblock %}
|
356 |
-
</div>
|
357 |
-
</body>
|
358 |
-
</html>
|
359 |
-
|
360 |
-
In this example, the :doc:`block<tags/block>` tags define four blocks that
|
361 |
-
child templates can fill in. All the ``block`` tag does is to tell the
|
362 |
-
template engine that a child template may override those portions of the
|
363 |
-
template.
|
364 |
-
|
365 |
-
A child template might look like this:
|
366 |
-
|
367 |
-
.. code-block:: jinja
|
368 |
-
|
369 |
-
{% extends "base.html" %}
|
370 |
-
|
371 |
-
{% block title %}Index{% endblock %}
|
372 |
-
{% block head %}
|
373 |
-
{{ parent() }}
|
374 |
-
<style type="text/css">
|
375 |
-
.important { color: #336699; }
|
376 |
-
</style>
|
377 |
-
{% endblock %}
|
378 |
-
{% block content %}
|
379 |
-
<h1>Index</h1>
|
380 |
-
<p class="important">
|
381 |
-
Welcome to my awesome homepage.
|
382 |
-
</p>
|
383 |
-
{% endblock %}
|
384 |
-
|
385 |
-
The :doc:`extends<tags/extends>` tag is the key here. It tells the template
|
386 |
-
engine that this template "extends" another template. When the template system
|
387 |
-
evaluates this template, first it locates the parent. The extends tag should
|
388 |
-
be the first tag in the template.
|
389 |
-
|
390 |
-
Note that since the child template doesn't define the ``footer`` block, the
|
391 |
-
value from the parent template is used instead.
|
392 |
-
|
393 |
-
It's possible to render the contents of the parent block by using the
|
394 |
-
:doc:`parent<functions/parent>` function. This gives back the results of the
|
395 |
-
parent block:
|
396 |
-
|
397 |
-
.. code-block:: jinja
|
398 |
-
|
399 |
-
{% block sidebar %}
|
400 |
-
<h3>Table Of Contents</h3>
|
401 |
-
...
|
402 |
-
{{ parent() }}
|
403 |
-
{% endblock %}
|
404 |
-
|
405 |
-
.. tip::
|
406 |
-
|
407 |
-
The documentation page for the :doc:`extends<tags/extends>` tag describes
|
408 |
-
more advanced features like block nesting, scope, dynamic inheritance, and
|
409 |
-
conditional inheritance.
|
410 |
-
|
411 |
-
.. note::
|
412 |
-
|
413 |
-
Twig also supports multiple inheritance with the so called horizontal reuse
|
414 |
-
with the help of the :doc:`use<tags/use>` tag. This is an advanced feature
|
415 |
-
hardly ever needed in regular templates.
|
416 |
-
|
417 |
-
HTML Escaping
|
418 |
-
-------------
|
419 |
-
|
420 |
-
When generating HTML from templates, there's always a risk that a variable
|
421 |
-
will include characters that affect the resulting HTML. There are two
|
422 |
-
approaches: manually escaping each variable or automatically escaping
|
423 |
-
everything by default.
|
424 |
-
|
425 |
-
Twig supports both, automatic escaping is enabled by default.
|
426 |
-
|
427 |
-
.. note::
|
428 |
-
|
429 |
-
Automatic escaping is only supported if the *escaper* extension has been
|
430 |
-
enabled (which is the default).
|
431 |
-
|
432 |
-
Working with Manual Escaping
|
433 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
434 |
-
|
435 |
-
If manual escaping is enabled, it is **your** responsibility to escape
|
436 |
-
variables if needed. What to escape? Any variable you don't trust.
|
437 |
-
|
438 |
-
Escaping works by piping the variable through the
|
439 |
-
:doc:`escape<filters/escape>` or ``e`` filter:
|
440 |
-
|
441 |
-
.. code-block:: jinja
|
442 |
-
|
443 |
-
{{ user.username|e }}
|
444 |
-
|
445 |
-
By default, the ``escape`` filter uses the ``html`` strategy, but depending on
|
446 |
-
the escaping context, you might want to explicitly use any other available
|
447 |
-
strategies:
|
448 |
-
|
449 |
-
{{ user.username|e('js') }}
|
450 |
-
{{ user.username|e('css') }}
|
451 |
-
{{ user.username|e('url') }}
|
452 |
-
{{ user.username|e('html_attr') }}
|
453 |
-
|
454 |
-
Working with Automatic Escaping
|
455 |
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
456 |
-
|
457 |
-
Whether automatic escaping is enabled or not, you can mark a section of a
|
458 |
-
template to be escaped or not by using the :doc:`autoescape<tags/autoescape>`
|
459 |
-
tag:
|
460 |
-
|
461 |
-
.. code-block:: jinja
|
462 |
-
|
463 |
-
{% autoescape %}
|
464 |
-
Everything will be automatically escaped in this block (using the HTML strategy)
|
465 |
-
{% endautoescape %}
|
466 |
-
|
467 |
-
By default, auto-escaping uses the ``html`` escaping strategy. If you output
|
468 |
-
variables in other contexts, you need to explicitly escape them with the
|
469 |
-
appropriate escaping strategy:
|
470 |
-
|
471 |
-
.. code-block:: jinja
|
472 |
-
|
473 |
-
{% autoescape 'js' %}
|
474 |
-
Everything will be automatically escaped in this block (using the JS strategy)
|
475 |
-
{% endautoescape %}
|
476 |
-
|
477 |
-
Escaping
|
478 |
-
--------
|
479 |
-
|
480 |
-
It is sometimes desirable or even necessary to have Twig ignore parts it would
|
481 |
-
otherwise handle as variables or blocks. For example if the default syntax is
|
482 |
-
used and you want to use ``{{`` as raw string in the template and not start a
|
483 |
-
variable you have to use a trick.
|
484 |
-
|
485 |
-
The easiest way is to output the variable delimiter (``{{``) by using a variable
|
486 |
-
expression:
|
487 |
-
|
488 |
-
.. code-block:: jinja
|
489 |
-
|
490 |
-
{{ '{{' }}
|
491 |
-
|
492 |
-
For bigger sections it makes sense to mark a block
|
493 |
-
:doc:`verbatim<tags/verbatim>`.
|
494 |
-
|
495 |
-
Macros
|
496 |
-
------
|
497 |
-
|
498 |
-
.. versionadded:: 1.12
|
499 |
-
Support for default argument values was added in Twig 1.12.
|
500 |
-
|
501 |
-
Macros are comparable with functions in regular programming languages. They
|
502 |
-
are useful to reuse often used HTML fragments to not repeat yourself.
|
503 |
-
|
504 |
-
A macro is defined via the :doc:`macro<tags/macro>` tag. Here is a small example
|
505 |
-
(subsequently called ``forms.html``) of a macro that renders a form element:
|
506 |
-
|
507 |
-
.. code-block:: jinja
|
508 |
-
|
509 |
-
{% macro input(name, value, type, size) %}
|
510 |
-
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
|
511 |
-
{% endmacro %}
|
512 |
-
|
513 |
-
Macros can be defined in any template, and need to be "imported" via the
|
514 |
-
:doc:`import<tags/import>` tag before being used:
|
515 |
-
|
516 |
-
.. code-block:: jinja
|
517 |
-
|
518 |
-
{% import "forms.html" as forms %}
|
519 |
-
|
520 |
-
<p>{{ forms.input('username') }}</p>
|
521 |
-
|
522 |
-
Alternatively, you can import individual macro names from a template into the
|
523 |
-
current namespace via the :doc:`from<tags/from>` tag and optionally alias them:
|
524 |
-
|
525 |
-
.. code-block:: jinja
|
526 |
-
|
527 |
-
{% from 'forms.html' import input as input_field %}
|
528 |
-
|
529 |
-
<dl>
|
530 |
-
<dt>Username</dt>
|
531 |
-
<dd>{{ input_field('username') }}</dd>
|
532 |
-
<dt>Password</dt>
|
533 |
-
<dd>{{ input_field('password', '', 'password') }}</dd>
|
534 |
-
</dl>
|
535 |
-
|
536 |
-
A default value can also be defined for macro arguments when not provided in a
|
537 |
-
macro call:
|
538 |
-
|
539 |
-
.. code-block:: jinja
|
540 |
-
|
541 |
-
{% macro input(name, value = "", type = "text", size = 20) %}
|
542 |
-
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
543 |
-
{% endmacro %}
|
544 |
-
|
545 |
-
Expressions
|
546 |
-
-----------
|
547 |
-
|
548 |
-
Twig allows expressions everywhere. These work very similar to regular PHP and
|
549 |
-
even if you're not working with PHP you should feel comfortable with it.
|
550 |
-
|
551 |
-
.. note::
|
552 |
-
|
553 |
-
The operator precedence is as follows, with the lowest-precedence
|
554 |
-
operators listed first: ``b-and``, ``b-xor``, ``b-or``, ``or``, ``and``,
|
555 |
-
``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``, ``in``, ``..``, ``+``,
|
556 |
-
``-``, ``~``, ``*``, ``/``, ``//``, ``%``, ``is``, and ``**``.
|
557 |
-
|
558 |
-
Literals
|
559 |
-
~~~~~~~~
|
560 |
-
|
561 |
-
.. versionadded:: 1.5
|
562 |
-
Support for hash keys as names and expressions was added in Twig 1.5.
|
563 |
-
|
564 |
-
The simplest form of expressions are literals. Literals are representations
|
565 |
-
for PHP types such as strings, numbers, and arrays. The following literals
|
566 |
-
exist:
|
567 |
-
|
568 |
-
* ``"Hello World"``: Everything between two double or single quotes is a
|
569 |
-
string. They are useful whenever you need a string in the template (for
|
570 |
-
example as arguments to function calls, filters or just to extend or
|
571 |
-
include a template).
|
572 |
-
|
573 |
-
* ``42`` / ``42.23``: Integers and floating point numbers are created by just
|
574 |
-
writing the number down. If a dot is present the number is a float,
|
575 |
-
otherwise an integer.
|
576 |
-
|
577 |
-
* ``["foo", "bar"]``: Arrays are defined by a sequence of expressions
|
578 |
-
separated by a comma (``,``) and wrapped with squared brackets (``[]``).
|
579 |
-
|
580 |
-
* ``{"foo": "bar"}``: Hashes are defined by a list of keys and values
|
581 |
-
separated by a comma (``,``) and wrapped with curly braces (``{}``):
|
582 |
-
|
583 |
-
.. code-block:: jinja
|
584 |
-
|
585 |
-
{# keys as string #}
|
586 |
-
{ 'foo': 'foo', 'bar': 'bar' }
|
587 |
-
|
588 |
-
{# keys as names (equivalent to the previous hash) -- as of Twig 1.5 #}
|
589 |
-
{ foo: 'foo', bar: 'bar' }
|
590 |
-
|
591 |
-
{# keys as integer #}
|
592 |
-
{ 2: 'foo', 4: 'bar' }
|
593 |
-
|
594 |
-
{# keys as expressions (the expression must be enclosed into parentheses) -- as of Twig 1.5 #}
|
595 |
-
{ (1 + 1): 'foo', (a ~ 'b'): 'bar' }
|
596 |
-
|
597 |
-
* ``true`` / ``false``: ``true`` represents the true value, ``false``
|
598 |
-
represents the false value.
|
599 |
-
|
600 |
-
* ``null``: ``null`` represents no specific value. This is the value returned
|
601 |
-
when a variable does not exist. ``none`` is an alias for ``null``.
|
602 |
-
|
603 |
-
Arrays and hashes can be nested:
|
604 |
-
|
605 |
-
.. code-block:: jinja
|
606 |
-
|
607 |
-
{% set foo = [1, {"foo": "bar"}] %}
|
608 |
-
|
609 |
-
.. tip::
|
610 |
-
|
611 |
-
Using double-quoted or single-quoted strings has no impact on performance
|
612 |
-
but string interpolation is only supported in double-quoted strings.
|
613 |
-
|
614 |
-
Math
|
615 |
-
~~~~
|
616 |
-
|
617 |
-
Twig allows you to calculate with values. This is rarely useful in templates
|
618 |
-
but exists for completeness' sake. The following operators are supported:
|
619 |
-
|
620 |
-
* ``+``: Adds two objects together (the operands are casted to numbers). ``{{
|
621 |
-
1 + 1 }}`` is ``2``.
|
622 |
-
|
623 |
-
* ``-``: Subtracts the second number from the first one. ``{{ 3 - 2 }}`` is
|
624 |
-
``1``.
|
625 |
-
|
626 |
-
* ``/``: Divides two numbers. The returned value will be a floating point
|
627 |
-
number. ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
|
628 |
-
|
629 |
-
* ``%``: Calculates the remainder of an integer division. ``{{ 11 % 7 }}`` is
|
630 |
-
``4``.
|
631 |
-
|
632 |
-
* ``//``: Divides two numbers and returns the truncated integer result. ``{{
|
633 |
-
20 // 7 }}`` is ``2``.
|
634 |
-
|
635 |
-
* ``*``: Multiplies the left operand with the right one. ``{{ 2 * 2 }}`` would
|
636 |
-
return ``4``.
|
637 |
-
|
638 |
-
* ``**``: Raises the left operand to the power of the right operand. ``{{ 2 **
|
639 |
-
3 }}`` would return ``8``.
|
640 |
-
|
641 |
-
Logic
|
642 |
-
~~~~~
|
643 |
-
|
644 |
-
You can combine multiple expressions with the following operators:
|
645 |
-
|
646 |
-
* ``and``: Returns true if the left and the right operands are both true.
|
647 |
-
|
648 |
-
* ``or``: Returns true if the left or the right operand is true.
|
649 |
-
|
650 |
-
* ``not``: Negates a statement.
|
651 |
-
|
652 |
-
* ``(expr)``: Groups an expression.
|
653 |
-
|
654 |
-
.. note::
|
655 |
-
|
656 |
-
Twig also support bitwise operators (``b-and``, ``b-xor``, and ``b-or``).
|
657 |
-
|
658 |
-
Comparisons
|
659 |
-
~~~~~~~~~~~
|
660 |
-
|
661 |
-
The following comparison operators are supported in any expression: ``==``,
|
662 |
-
``!=``, ``<``, ``>``, ``>=``, and ``<=``.
|
663 |
-
|
664 |
-
Containment Operator
|
665 |
-
~~~~~~~~~~~~~~~~~~~~
|
666 |
-
|
667 |
-
The ``in`` operator performs containment test.
|
668 |
-
|
669 |
-
It returns ``true`` if the left operand is contained in the right:
|
670 |
-
|
671 |
-
.. code-block:: jinja
|
672 |
-
|
673 |
-
{# returns true #}
|
674 |
-
|
675 |
-
{{ 1 in [1, 2, 3] }}
|
676 |
-
|
677 |
-
{{ 'cd' in 'abcde' }}
|
678 |
-
|
679 |
-
.. tip::
|
680 |
-
|
681 |
-
You can use this filter to perform a containment test on strings, arrays,
|
682 |
-
or objects implementing the ``Traversable`` interface.
|
683 |
-
|
684 |
-
To perform a negative test, use the ``not in`` operator:
|
685 |
-
|
686 |
-
.. code-block:: jinja
|
687 |
-
|
688 |
-
{% if 1 not in [1, 2, 3] %}
|
689 |
-
|
690 |
-
{# is equivalent to #}
|
691 |
-
{% if not (1 in [1, 2, 3]) %}
|
692 |
-
|
693 |
-
Test Operator
|
694 |
-
~~~~~~~~~~~~~
|
695 |
-
|
696 |
-
The ``is`` operator performs tests. Tests can be used to test a variable against
|
697 |
-
a common expression. The right operand is name of the test:
|
698 |
-
|
699 |
-
.. code-block:: jinja
|
700 |
-
|
701 |
-
{# find out if a variable is odd #}
|
702 |
-
|
703 |
-
{{ name is odd }}
|
704 |
-
|
705 |
-
Tests can accept arguments too:
|
706 |
-
|
707 |
-
.. code-block:: jinja
|
708 |
-
|
709 |
-
{% if loop.index is divisibleby(3) %}
|
710 |
-
|
711 |
-
Tests can be negated by using the ``is not`` operator:
|
712 |
-
|
713 |
-
.. code-block:: jinja
|
714 |
-
|
715 |
-
{% if loop.index is not divisibleby(3) %}
|
716 |
-
|
717 |
-
{# is equivalent to #}
|
718 |
-
{% if not (loop.index is divisibleby(3)) %}
|
719 |
-
|
720 |
-
Go to the :doc:`tests<tests/index>` page to learn more about the built-in
|
721 |
-
tests.
|
722 |
-
|
723 |
-
Other Operators
|
724 |
-
~~~~~~~~~~~~~~~
|
725 |
-
|
726 |
-
.. versionadded:: 1.12.0
|
727 |
-
Support for the extended ternary operator was added in Twig 1.12.0.
|
728 |
-
|
729 |
-
The following operators are very useful but don't fit into any of the other
|
730 |
-
categories:
|
731 |
-
|
732 |
-
* ``..``: Creates a sequence based on the operand before and after the
|
733 |
-
operator (this is just syntactic sugar for the :doc:`range<functions/range>`
|
734 |
-
function).
|
735 |
-
|
736 |
-
* ``|``: Applies a filter.
|
737 |
-
|
738 |
-
* ``~``: Converts all operands into strings and concatenates them. ``{{ "Hello
|
739 |
-
" ~ name ~ "!" }}`` would return (assuming ``name`` is ``'John'``) ``Hello
|
740 |
-
John!``.
|
741 |
-
|
742 |
-
* ``.``, ``[]``: Gets an attribute of an object.
|
743 |
-
|
744 |
-
* ``?:``: The ternary operator:
|
745 |
-
|
746 |
-
.. code-block:: jinja
|
747 |
-
|
748 |
-
{{ foo ? 'yes' : 'no' }}
|
749 |
-
|
750 |
-
{# as of Twig 1.12.0 #}
|
751 |
-
{{ foo ?: 'no' }} == {{ foo ? foo : 'no' }}
|
752 |
-
{{ foo ? 'yes' }} == {{ foo ? 'yes' : '' }}
|
753 |
-
|
754 |
-
String Interpolation
|
755 |
-
~~~~~~~~~~~~~~~~~~~~
|
756 |
-
|
757 |
-
.. versionadded:: 1.5
|
758 |
-
String interpolation was added in Twig 1.5.
|
759 |
-
|
760 |
-
String interpolation (`#{expression}`) allows any valid expression to appear
|
761 |
-
within a *double-quoted string*. The result of evaluating that expression is
|
762 |
-
inserted into the string:
|
763 |
-
|
764 |
-
.. code-block:: jinja
|
765 |
-
|
766 |
-
{{ "foo #{bar} baz" }}
|
767 |
-
{{ "foo #{1 + 2} baz" }}
|
768 |
-
|
769 |
-
Whitespace Control
|
770 |
-
------------------
|
771 |
-
|
772 |
-
.. versionadded:: 1.1
|
773 |
-
Tag level whitespace control was added in Twig 1.1.
|
774 |
-
|
775 |
-
The first newline after a template tag is removed automatically (like in PHP.)
|
776 |
-
Whitespace is not further modified by the template engine, so each whitespace
|
777 |
-
(spaces, tabs, newlines etc.) is returned unchanged.
|
778 |
-
|
779 |
-
Use the ``spaceless`` tag to remove whitespace *between HTML tags*:
|
780 |
-
|
781 |
-
.. code-block:: jinja
|
782 |
-
|
783 |
-
{% spaceless %}
|
784 |
-
<div>
|
785 |
-
<strong>foo</strong>
|
786 |
-
</div>
|
787 |
-
{% endspaceless %}
|
788 |
-
|
789 |
-
{# output will be <div><strong>foo</strong></div> #}
|
790 |
-
|
791 |
-
In addition to the spaceless tag you can also control whitespace on a per tag
|
792 |
-
level. By using the whitespace control modifier on your tags, you can trim
|
793 |
-
leading and or trailing whitespace:
|
794 |
-
|
795 |
-
.. code-block:: jinja
|
796 |
-
|
797 |
-
{% set value = 'no spaces' %}
|
798 |
-
{#- No leading/trailing whitespace -#}
|
799 |
-
{%- if true -%}
|
800 |
-
{{- value -}}
|
801 |
-
{%- endif -%}
|
802 |
-
|
803 |
-
{# output 'no spaces' #}
|
804 |
-
|
805 |
-
The above sample shows the default whitespace control modifier, and how you can
|
806 |
-
use it to remove whitespace around tags. Trimming space will consume all whitespace
|
807 |
-
for that side of the tag. It is possible to use whitespace trimming on one side
|
808 |
-
of a tag:
|
809 |
-
|
810 |
-
.. code-block:: jinja
|
811 |
-
|
812 |
-
{% set value = 'no spaces' %}
|
813 |
-
<li> {{- value }} </li>
|
814 |
-
|
815 |
-
{# outputs '<li>no spaces </li>' #}
|
816 |
-
|
817 |
-
Extensions
|
818 |
-
----------
|
819 |
-
|
820 |
-
Twig can be easily extended.
|
821 |
-
|
822 |
-
If you are looking for new tags, filters, or functions, have a look at the Twig official
|
823 |
-
`extension repository`_.
|
824 |
-
|
825 |
-
If you want to create your own, read the :ref:`Creating an
|
826 |
-
Extension<creating_extensions>` chapter.
|
827 |
-
|
828 |
-
.. _`Twig bundle`: https://github.com/Anomareh/PHP-Twig.tmbundle
|
829 |
-
.. _`Jinja syntax plugin`: http://jinja.pocoo.org/2/documentation/integration
|
830 |
-
.. _`Twig syntax plugin`: http://plugins.netbeans.org/plugin/37069/php-twig
|
831 |
-
.. _`Twig plugin`: https://github.com/pulse00/Twig-Eclipse-Plugin
|
832 |
-
.. _`Twig language definition`: https://github.com/gabrielcorpse/gedit-twig-template-language
|
833 |
-
.. _`extension repository`: http://github.com/fabpot/Twig-extensions
|
834 |
-
.. _`Twig syntax mode`: https://github.com/bobthecow/Twig-HTML.mode
|
835 |
-
.. _`other Twig syntax mode`: https://github.com/muxx/Twig-HTML.mode
|
836 |
-
.. _`Notepad++ Twig Highlighter`: https://github.com/Banane9/notepadplusplus-twig
|
837 |
-
.. _`web-mode.el`: http://web-mode.org/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/constant.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``constant``
|
2 |
-
============
|
3 |
-
|
4 |
-
``constant`` checks if a variable has the exact same value as a constant. You
|
5 |
-
can use either global constants or class constants:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% if post.status is constant('Post::PUBLISHED') %}
|
10 |
-
the status attribute is exactly the same as Post::PUBLISHED
|
11 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/defined.rst
DELETED
@@ -1,30 +0,0 @@
|
|
1 |
-
``defined``
|
2 |
-
===========
|
3 |
-
|
4 |
-
``defined`` checks if a variable is defined in the current context. This is very
|
5 |
-
useful if you use the ``strict_variables`` option:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{# defined works with variable names #}
|
10 |
-
{% if foo is defined %}
|
11 |
-
...
|
12 |
-
{% endif %}
|
13 |
-
|
14 |
-
{# and attributes on variables names #}
|
15 |
-
{% if foo.bar is defined %}
|
16 |
-
...
|
17 |
-
{% endif %}
|
18 |
-
|
19 |
-
{% if foo['bar'] is defined %}
|
20 |
-
...
|
21 |
-
{% endif %}
|
22 |
-
|
23 |
-
When using the ``defined`` test on an expression that uses variables in some
|
24 |
-
method calls, be sure that they are all defined first:
|
25 |
-
|
26 |
-
.. code-block:: jinja
|
27 |
-
|
28 |
-
{% if var is defined and foo.method(var) is defined %}
|
29 |
-
...
|
30 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/divisibleby.rst
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
``divisibleby``
|
2 |
-
===============
|
3 |
-
|
4 |
-
``divisibleby`` checks if a variable is divisible by a number:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{% if loop.index is divisibleby(3) %}
|
9 |
-
...
|
10 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/empty.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``empty``
|
2 |
-
=========
|
3 |
-
|
4 |
-
``empty`` checks if a variable is empty:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{# evaluates to true if the foo variable is null, false, an empty array, or the empty string #}
|
9 |
-
{% if foo is empty %}
|
10 |
-
...
|
11 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/even.rst
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
``even``
|
2 |
-
========
|
3 |
-
|
4 |
-
``even`` returns ``true`` if the given number is even:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ var is even }}
|
9 |
-
|
10 |
-
.. seealso:: :doc:`odd<../tests/odd>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/index.rst
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
Tests
|
2 |
-
=====
|
3 |
-
|
4 |
-
.. toctree::
|
5 |
-
:maxdepth: 1
|
6 |
-
|
7 |
-
divisibleby
|
8 |
-
null
|
9 |
-
even
|
10 |
-
odd
|
11 |
-
sameas
|
12 |
-
constant
|
13 |
-
defined
|
14 |
-
empty
|
15 |
-
iterable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/iterable.rst
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
``iterable``
|
2 |
-
============
|
3 |
-
|
4 |
-
.. versionadded:: 1.7
|
5 |
-
The iterable test was added in Twig 1.7.
|
6 |
-
|
7 |
-
``iterable`` checks if a variable is an array or a traversable object:
|
8 |
-
|
9 |
-
.. code-block:: jinja
|
10 |
-
|
11 |
-
{# evaluates to true if the foo variable is iterable #}
|
12 |
-
{% if users is iterable %}
|
13 |
-
{% for user in users %}
|
14 |
-
Hello {{ user }}!
|
15 |
-
{% endfor %}
|
16 |
-
{% else %}
|
17 |
-
{# users is probably a string #}
|
18 |
-
Hello {{ users }}!
|
19 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/null.rst
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
``null``
|
2 |
-
========
|
3 |
-
|
4 |
-
``null`` returns ``true`` if the variable is ``null``:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ var is null }}
|
9 |
-
|
10 |
-
.. note::
|
11 |
-
|
12 |
-
``none`` is an alias for ``null``.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/odd.rst
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
``odd``
|
2 |
-
=======
|
3 |
-
|
4 |
-
``odd`` returns ``true`` if the given number is odd:
|
5 |
-
|
6 |
-
.. code-block:: jinja
|
7 |
-
|
8 |
-
{{ var is odd }}
|
9 |
-
|
10 |
-
.. seealso:: :doc:`even<../tests/even>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/doc/tests/sameas.rst
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
``sameas``
|
2 |
-
==========
|
3 |
-
|
4 |
-
``sameas`` checks if a variable points to the same memory address than another
|
5 |
-
variable:
|
6 |
-
|
7 |
-
.. code-block:: jinja
|
8 |
-
|
9 |
-
{% if foo.attribute is sameas(false) %}
|
10 |
-
the foo attribute really is the ``false`` PHP value
|
11 |
-
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/ext/twig/.gitignore
DELETED
@@ -1,30 +0,0 @@
|
|
1 |
-
*.sw*
|
2 |
-
.deps
|
3 |
-
Makefile
|
4 |
-
Makefile.fragments
|
5 |
-
Makefile.global
|
6 |
-
Makefile.objects
|
7 |
-
acinclude.m4
|
8 |
-
aclocal.m4
|
9 |
-
build/
|
10 |
-
config.cache
|
11 |
-
config.guess
|
12 |
-
config.h
|
13 |
-
config.h.in
|
14 |
-
config.log
|
15 |
-
config.nice
|
16 |
-
config.status
|
17 |
-
config.sub
|
18 |
-
configure
|
19 |
-
configure.in
|
20 |
-
install-sh
|
21 |
-
libtool
|
22 |
-
ltmain.sh
|
23 |
-
missing
|
24 |
-
mkinstalldirs
|
25 |
-
run-tests.php
|
26 |
-
twig.loT
|
27 |
-
.libs/
|
28 |
-
modules/
|
29 |
-
twig.la
|
30 |
-
twig.lo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/ext/twig/LICENSE
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
Copyright (c) 2011, Derick Rethans <derick@derickrethans.nl>
|
2 |
-
All rights reserved.
|
3 |
-
|
4 |
-
Redistribution and use in source and binary forms, with or without
|
5 |
-
modification, are permitted provided that the following conditions are met:
|
6 |
-
|
7 |
-
* Redistributions of source code must retain the above copyright notice,
|
8 |
-
this list of conditions and the following disclaimer.
|
9 |
-
* Redistributions in binary form must reproduce the above copyright
|
10 |
-
notice, this list of conditions and the following disclaimer in the
|
11 |
-
documentation and/or other materials provided with the distribution.
|
12 |
-
|
13 |
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
14 |
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
15 |
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16 |
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
17 |
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
18 |
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
19 |
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
20 |
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
21 |
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
22 |
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/ext/twig/config.m4
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
dnl config.m4 for extension twig
|
2 |
-
|
3 |
-
PHP_ARG_ENABLE(twig, whether to enable twig support,
|
4 |
-
[ --enable-twig Enable twig support])
|
5 |
-
|
6 |
-
if test "$PHP_TWIG" != "no"; then
|
7 |
-
PHP_NEW_EXTENSION(twig, twig.c, $ext_shared)
|
8 |
-
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/ext/twig/config.w32
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
// vim:ft=javascript
|
2 |
-
|
3 |
-
ARG_ENABLE("twig", "Twig support", "no");
|
4 |
-
|
5 |
-
if (PHP_TWIG != "no") {
|
6 |
-
AC_DEFINE('HAVE_TWIG', 1);
|
7 |
-
EXTENSION('twig', 'twig.c');
|
8 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/ext/twig/php_twig.h
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
+----------------------------------------------------------------------+
|
3 |
-
| Twig Extension |
|
4 |
-
+----------------------------------------------------------------------+
|
5 |
-
| Copyright (c) 2011 Derick Rethans |
|
6 |
-
+----------------------------------------------------------------------+
|
7 |
-
| Redistribution and use in source and binary forms, with or without |
|
8 |
-
| modification, are permitted provided that the conditions mentioned |
|
9 |
-
| in the accompanying LICENSE file are met (BSD, revised). |
|
10 |
-
+----------------------------------------------------------------------+
|
11 |
-
| Author: Derick Rethans <derick@derickrethans.nl> |
|
12 |
-
+----------------------------------------------------------------------+
|
13 |
-
*/
|
14 |
-
|
15 |
-
#ifndef PHP_TWIG_H
|
16 |
-
#define PHP_TWIG_H
|
17 |
-
|
18 |
-
#define PHP_TWIG_VERSION "1.12.2-DEV"
|
19 |
-
|
20 |
-
#include "php.h"
|
21 |
-
|
22 |
-
extern zend_module_entry twig_module_entry;
|
23 |
-
#define phpext_twig_ptr &twig_module_entry
|
24 |
-
|
25 |
-
#ifdef ZTS
|
26 |
-
#include "TSRM.h"
|
27 |
-
#endif
|
28 |
-
|
29 |
-
PHP_FUNCTION(twig_template_get_attributes);
|
30 |
-
|
31 |
-
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/ext/twig/twig.c
DELETED
@@ -1,1051 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
+----------------------------------------------------------------------+
|
3 |
-
| Twig Extension |
|
4 |
-
+----------------------------------------------------------------------+
|
5 |
-
| Copyright (c) 2011 Derick Rethans |
|
6 |
-
+----------------------------------------------------------------------+
|
7 |
-
| Redistribution and use in source and binary forms, with or without |
|
8 |
-
| modification, are permitted provided that the conditions mentioned |
|
9 |
-
| in the accompanying LICENSE file are met (BSD, revised). |
|
10 |
-
+----------------------------------------------------------------------+
|
11 |
-
| Author: Derick Rethans <derick@derickrethans.nl> |
|
12 |
-
+----------------------------------------------------------------------+
|
13 |
-
*/
|
14 |
-
|
15 |
-
#ifdef HAVE_CONFIG_H
|
16 |
-
#include "config.h"
|
17 |
-
#endif
|
18 |
-
|
19 |
-
#include "php.h"
|
20 |
-
#include "php_twig.h"
|
21 |
-
#include "ext/standard/php_string.h"
|
22 |
-
#include "ext/standard/php_smart_str.h"
|
23 |
-
|
24 |
-
#include "Zend/zend_object_handlers.h"
|
25 |
-
#include "Zend/zend_interfaces.h"
|
26 |
-
#include "Zend/zend_exceptions.h"
|
27 |
-
|
28 |
-
#ifndef Z_ADDREF_P
|
29 |
-
#define Z_ADDREF_P(pz) (pz)->refcount++
|
30 |
-
#endif
|
31 |
-
|
32 |
-
#define FREE_DTOR(z) \
|
33 |
-
zval_dtor(z); \
|
34 |
-
efree(z);
|
35 |
-
|
36 |
-
#if PHP_VERSION_ID >= 50300
|
37 |
-
#define APPLY_TSRMLS_DC TSRMLS_DC
|
38 |
-
#define APPLY_TSRMLS_CC TSRMLS_CC
|
39 |
-
#define APPLY_TSRMLS_FETCH()
|
40 |
-
#else
|
41 |
-
#define APPLY_TSRMLS_DC
|
42 |
-
#define APPLY_TSRMLS_CC
|
43 |
-
#define APPLY_TSRMLS_FETCH() TSRMLS_FETCH()
|
44 |
-
#endif
|
45 |
-
|
46 |
-
ZEND_BEGIN_ARG_INFO_EX(twig_template_get_attribute_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 6)
|
47 |
-
ZEND_ARG_INFO(0, template)
|
48 |
-
ZEND_ARG_INFO(0, object)
|
49 |
-
ZEND_ARG_INFO(0, item)
|
50 |
-
ZEND_ARG_INFO(0, arguments)
|
51 |
-
ZEND_ARG_INFO(0, type)
|
52 |
-
ZEND_ARG_INFO(0, isDefinedTest)
|
53 |
-
ZEND_END_ARG_INFO()
|
54 |
-
|
55 |
-
zend_function_entry twig_functions[] = {
|
56 |
-
PHP_FE(twig_template_get_attributes, twig_template_get_attribute_args)
|
57 |
-
{NULL, NULL, NULL}
|
58 |
-
};
|
59 |
-
|
60 |
-
|
61 |
-
zend_module_entry twig_module_entry = {
|
62 |
-
STANDARD_MODULE_HEADER,
|
63 |
-
"twig",
|
64 |
-
twig_functions,
|
65 |
-
NULL,
|
66 |
-
NULL,
|
67 |
-
NULL,
|
68 |
-
NULL,
|
69 |
-
NULL,
|
70 |
-
PHP_TWIG_VERSION,
|
71 |
-
STANDARD_MODULE_PROPERTIES
|
72 |
-
};
|
73 |
-
|
74 |
-
|
75 |
-
#ifdef COMPILE_DL_TWIG
|
76 |
-
ZEND_GET_MODULE(twig)
|
77 |
-
#endif
|
78 |
-
|
79 |
-
int TWIG_ARRAY_KEY_EXISTS(zval *array, char* key, int key_len)
|
80 |
-
{
|
81 |
-
if (Z_TYPE_P(array) != IS_ARRAY) {
|
82 |
-
return 0;
|
83 |
-
}
|
84 |
-
return zend_symtable_exists(Z_ARRVAL_P(array), key, key_len + 1);
|
85 |
-
}
|
86 |
-
|
87 |
-
int TWIG_INSTANCE_OF(zval *object, zend_class_entry *interface TSRMLS_DC)
|
88 |
-
{
|
89 |
-
if (Z_TYPE_P(object) != IS_OBJECT) {
|
90 |
-
return 0;
|
91 |
-
}
|
92 |
-
return instanceof_function(Z_OBJCE_P(object), interface TSRMLS_CC);
|
93 |
-
}
|
94 |
-
|
95 |
-
int TWIG_INSTANCE_OF_USERLAND(zval *object, char *interface TSRMLS_DC)
|
96 |
-
{
|
97 |
-
zend_class_entry **pce;
|
98 |
-
if (Z_TYPE_P(object) != IS_OBJECT) {
|
99 |
-
return 0;
|
100 |
-
}
|
101 |
-
if (zend_lookup_class(interface, strlen(interface), &pce TSRMLS_CC) == FAILURE) {
|
102 |
-
return 0;
|
103 |
-
}
|
104 |
-
return instanceof_function(Z_OBJCE_P(object), *pce TSRMLS_CC);
|
105 |
-
}
|
106 |
-
|
107 |
-
zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
108 |
-
{
|
109 |
-
zend_class_entry *ce = Z_OBJCE_P(object);
|
110 |
-
zval *retval;
|
111 |
-
|
112 |
-
if (Z_TYPE_P(object) == IS_OBJECT) {
|
113 |
-
SEPARATE_ARG_IF_REF(offset);
|
114 |
-
zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
|
115 |
-
|
116 |
-
zval_ptr_dtor(&offset);
|
117 |
-
|
118 |
-
if (!retval) {
|
119 |
-
if (!EG(exception)) {
|
120 |
-
zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
|
121 |
-
}
|
122 |
-
return NULL;
|
123 |
-
}
|
124 |
-
|
125 |
-
return retval;
|
126 |
-
}
|
127 |
-
return NULL;
|
128 |
-
}
|
129 |
-
|
130 |
-
int TWIG_ISSET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
131 |
-
{
|
132 |
-
zend_class_entry *ce = Z_OBJCE_P(object);
|
133 |
-
zval *retval;
|
134 |
-
|
135 |
-
if (Z_TYPE_P(object) == IS_OBJECT) {
|
136 |
-
SEPARATE_ARG_IF_REF(offset);
|
137 |
-
zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset);
|
138 |
-
|
139 |
-
zval_ptr_dtor(&offset);
|
140 |
-
|
141 |
-
if (!retval) {
|
142 |
-
if (!EG(exception)) {
|
143 |
-
zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
|
144 |
-
}
|
145 |
-
return 0;
|
146 |
-
}
|
147 |
-
|
148 |
-
return (retval && Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval));
|
149 |
-
}
|
150 |
-
return 0;
|
151 |
-
}
|
152 |
-
|
153 |
-
char *TWIG_STRTOLOWER(const char *str, int str_len)
|
154 |
-
{
|
155 |
-
char *item_dup;
|
156 |
-
|
157 |
-
item_dup = estrndup(str, str_len);
|
158 |
-
php_strtolower(item_dup, str_len);
|
159 |
-
return item_dup;
|
160 |
-
}
|
161 |
-
|
162 |
-
zval *TWIG_CALL_USER_FUNC_ARRAY(zval *object, char *function, zval *arguments TSRMLS_DC)
|
163 |
-
{
|
164 |
-
zend_fcall_info fci;
|
165 |
-
zval ***args = NULL;
|
166 |
-
int arg_count = 0;
|
167 |
-
HashTable *table;
|
168 |
-
HashPosition pos;
|
169 |
-
int i = 0;
|
170 |
-
zval *retval_ptr;
|
171 |
-
zval *zfunction;
|
172 |
-
|
173 |
-
if (arguments) {
|
174 |
-
table = HASH_OF(arguments);
|
175 |
-
args = safe_emalloc(sizeof(zval **), table->nNumOfElements, 0);
|
176 |
-
|
177 |
-
zend_hash_internal_pointer_reset_ex(table, &pos);
|
178 |
-
|
179 |
-
while (zend_hash_get_current_data_ex(table, (void **)&args[i], &pos) == SUCCESS) {
|
180 |
-
i++;
|
181 |
-
zend_hash_move_forward_ex(table, &pos);
|
182 |
-
}
|
183 |
-
arg_count = table->nNumOfElements;
|
184 |
-
}
|
185 |
-
|
186 |
-
MAKE_STD_ZVAL(zfunction);
|
187 |
-
ZVAL_STRING(zfunction, function, 1);
|
188 |
-
fci.size = sizeof(fci);
|
189 |
-
fci.function_table = EG(function_table);
|
190 |
-
fci.function_name = zfunction;
|
191 |
-
fci.symbol_table = NULL;
|
192 |
-
#if PHP_VERSION_ID >= 50300
|
193 |
-
fci.object_ptr = object;
|
194 |
-
#else
|
195 |
-
fci.object_pp = &object;
|
196 |
-
#endif
|
197 |
-
fci.retval_ptr_ptr = &retval_ptr;
|
198 |
-
fci.param_count = arg_count;
|
199 |
-
fci.params = args;
|
200 |
-
fci.no_separation = 0;
|
201 |
-
|
202 |
-
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
|
203 |
-
FREE_DTOR(zfunction)
|
204 |
-
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", zend_get_class_entry(object TSRMLS_CC)->name, function TSRMLS_CC);
|
205 |
-
}
|
206 |
-
|
207 |
-
if (args) {
|
208 |
-
efree(fci.params);
|
209 |
-
}
|
210 |
-
FREE_DTOR(zfunction);
|
211 |
-
return retval_ptr;
|
212 |
-
}
|
213 |
-
|
214 |
-
int TWIG_CALL_BOOLEAN(zval *object, char *functionName TSRMLS_DC)
|
215 |
-
{
|
216 |
-
zval *ret;
|
217 |
-
int res;
|
218 |
-
|
219 |
-
ret = TWIG_CALL_USER_FUNC_ARRAY(object, functionName, NULL TSRMLS_CC);
|
220 |
-
res = Z_LVAL_P(ret);
|
221 |
-
zval_ptr_dtor(&ret);
|
222 |
-
return res;
|
223 |
-
}
|
224 |
-
|
225 |
-
zval *TWIG_GET_STATIC_PROPERTY(zval *class, char *prop_name TSRMLS_DC)
|
226 |
-
{
|
227 |
-
zval **tmp_zval;
|
228 |
-
zend_class_entry *ce;
|
229 |
-
|
230 |
-
if (class == NULL || Z_TYPE_P(class) != IS_OBJECT) {
|
231 |
-
return NULL;
|
232 |
-
}
|
233 |
-
|
234 |
-
ce = zend_get_class_entry(class TSRMLS_CC);
|
235 |
-
#if PHP_VERSION_ID >= 50400
|
236 |
-
tmp_zval = zend_std_get_static_property(ce, prop_name, strlen(prop_name), 0, NULL TSRMLS_CC);
|
237 |
-
#else
|
238 |
-
tmp_zval = zend_std_get_static_property(ce, prop_name, strlen(prop_name), 0 TSRMLS_CC);
|
239 |
-
#endif
|
240 |
-
return *tmp_zval;
|
241 |
-
}
|
242 |
-
|
243 |
-
zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
|
244 |
-
{
|
245 |
-
zval **tmp_zval;
|
246 |
-
char *tmp_name;
|
247 |
-
|
248 |
-
if (class == NULL || Z_TYPE_P(class) != IS_ARRAY || Z_TYPE_P(prop_name) != IS_STRING) {
|
249 |
-
if (class != NULL && Z_TYPE_P(class) == IS_OBJECT && TWIG_INSTANCE_OF(class, zend_ce_arrayaccess TSRMLS_CC)) {
|
250 |
-
// array access object
|
251 |
-
return TWIG_GET_ARRAYOBJECT_ELEMENT(class, prop_name TSRMLS_CC);
|
252 |
-
}
|
253 |
-
return NULL;
|
254 |
-
}
|
255 |
-
|
256 |
-
convert_to_string(prop_name);
|
257 |
-
tmp_name = Z_STRVAL_P(prop_name);
|
258 |
-
if (zend_symtable_find(HASH_OF(class), tmp_name, strlen(tmp_name)+1, (void**) &tmp_zval) == SUCCESS) {
|
259 |
-
return *tmp_zval;
|
260 |
-
}
|
261 |
-
return NULL;
|
262 |
-
}
|
263 |
-
|
264 |
-
zval *TWIG_GET_ARRAY_ELEMENT(zval *class, char *prop_name, int prop_name_length TSRMLS_DC)
|
265 |
-
{
|
266 |
-
zval **tmp_zval;
|
267 |
-
|
268 |
-
if (class == NULL/* || Z_TYPE_P(class) != IS_ARRAY*/) {
|
269 |
-
return NULL;
|
270 |
-
}
|
271 |
-
|
272 |
-
if (class != NULL && Z_TYPE_P(class) == IS_OBJECT && TWIG_INSTANCE_OF(class, zend_ce_arrayaccess TSRMLS_CC)) {
|
273 |
-
// array access object
|
274 |
-
zval *tmp_name_zval;
|
275 |
-
zval *tmp_ret_zval;
|
276 |
-
|
277 |
-
ALLOC_INIT_ZVAL(tmp_name_zval);
|
278 |
-
ZVAL_STRING(tmp_name_zval, prop_name, 1);
|
279 |
-
tmp_ret_zval = TWIG_GET_ARRAYOBJECT_ELEMENT(class, tmp_name_zval TSRMLS_CC);
|
280 |
-
FREE_DTOR(tmp_name_zval);
|
281 |
-
return tmp_ret_zval;
|
282 |
-
}
|
283 |
-
|
284 |
-
if (zend_symtable_find(HASH_OF(class), prop_name, prop_name_length+1, (void**)&tmp_zval) == SUCCESS) {
|
285 |
-
return *tmp_zval;
|
286 |
-
}
|
287 |
-
return NULL;
|
288 |
-
}
|
289 |
-
|
290 |
-
zval *TWIG_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
291 |
-
{
|
292 |
-
zval *tmp = NULL;
|
293 |
-
|
294 |
-
if (Z_OBJ_HT_P(object)->read_property) {
|
295 |
-
#if PHP_VERSION_ID >= 50400
|
296 |
-
tmp = Z_OBJ_HT_P(object)->read_property(object, propname, BP_VAR_IS, NULL TSRMLS_CC);
|
297 |
-
#else
|
298 |
-
tmp = Z_OBJ_HT_P(object)->read_property(object, propname, BP_VAR_IS TSRMLS_CC);
|
299 |
-
#endif
|
300 |
-
if (tmp != EG(uninitialized_zval_ptr)) {
|
301 |
-
return tmp;
|
302 |
-
} else {
|
303 |
-
return NULL;
|
304 |
-
}
|
305 |
-
}
|
306 |
-
return tmp;
|
307 |
-
}
|
308 |
-
|
309 |
-
int TWIG_HAS_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
310 |
-
{
|
311 |
-
if (Z_OBJ_HT_P(object)->has_property) {
|
312 |
-
#if PHP_VERSION_ID >= 50400
|
313 |
-
return Z_OBJ_HT_P(object)->has_property(object, propname, 0, NULL TSRMLS_CC);
|
314 |
-
#else
|
315 |
-
return Z_OBJ_HT_P(object)->has_property(object, propname, 0 TSRMLS_CC);
|
316 |
-
#endif
|
317 |
-
}
|
318 |
-
return 0;
|
319 |
-
}
|
320 |
-
|
321 |
-
int TWIG_HAS_DYNAMIC_PROPERTY(zval *object, char *prop, int prop_len TSRMLS_DC)
|
322 |
-
{
|
323 |
-
if (Z_OBJ_HT_P(object)->get_properties) {
|
324 |
-
return zend_hash_quick_exists(
|
325 |
-
Z_OBJ_HT_P(object)->get_properties(object TSRMLS_CC), // the properties hash
|
326 |
-
prop, // property name
|
327 |
-
prop_len + 1, // property length
|
328 |
-
zend_get_hash_value(prop, prop_len + 1) // hash value
|
329 |
-
);
|
330 |
-
}
|
331 |
-
return 0;
|
332 |
-
}
|
333 |
-
|
334 |
-
zval *TWIG_PROPERTY_CHAR(zval *object, char *propname TSRMLS_DC)
|
335 |
-
{
|
336 |
-
zval *tmp_name_zval, *tmp;
|
337 |
-
|
338 |
-
ALLOC_INIT_ZVAL(tmp_name_zval);
|
339 |
-
ZVAL_STRING(tmp_name_zval, propname, 1);
|
340 |
-
tmp = TWIG_PROPERTY(object, tmp_name_zval TSRMLS_CC);
|
341 |
-
FREE_DTOR(tmp_name_zval);
|
342 |
-
return tmp;
|
343 |
-
}
|
344 |
-
|
345 |
-
int TWIG_CALL_B_0(zval *object, char *method)
|
346 |
-
{
|
347 |
-
return 0;
|
348 |
-
}
|
349 |
-
|
350 |
-
zval *TWIG_CALL_S(zval *object, char *method, char *arg0 TSRMLS_DC)
|
351 |
-
{
|
352 |
-
zend_fcall_info fci;
|
353 |
-
zval **args[1];
|
354 |
-
zval *argument;
|
355 |
-
zval *zfunction;
|
356 |
-
zval *retval_ptr;
|
357 |
-
|
358 |
-
MAKE_STD_ZVAL(argument);
|
359 |
-
ZVAL_STRING(argument, arg0, 1);
|
360 |
-
args[0] = &argument;
|
361 |
-
|
362 |
-
MAKE_STD_ZVAL(zfunction);
|
363 |
-
ZVAL_STRING(zfunction, method, 1);
|
364 |
-
fci.size = sizeof(fci);
|
365 |
-
fci.function_table = EG(function_table);
|
366 |
-
fci.function_name = zfunction;
|
367 |
-
fci.symbol_table = NULL;
|
368 |
-
#if PHP_VERSION_ID >= 50300
|
369 |
-
fci.object_ptr = object;
|
370 |
-
#else
|
371 |
-
fci.object_pp = &object;
|
372 |
-
#endif
|
373 |
-
fci.retval_ptr_ptr = &retval_ptr;
|
374 |
-
fci.param_count = 1;
|
375 |
-
fci.params = args;
|
376 |
-
fci.no_separation = 0;
|
377 |
-
|
378 |
-
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
|
379 |
-
FREE_DTOR(zfunction);
|
380 |
-
zval_ptr_dtor(&argument);
|
381 |
-
return 0;
|
382 |
-
}
|
383 |
-
FREE_DTOR(zfunction);
|
384 |
-
zval_ptr_dtor(&argument);
|
385 |
-
return retval_ptr;
|
386 |
-
}
|
387 |
-
|
388 |
-
int TWIG_CALL_SB(zval *object, char *method, char *arg0 TSRMLS_DC)
|
389 |
-
{
|
390 |
-
zval *retval_ptr;
|
391 |
-
int success;
|
392 |
-
|
393 |
-
retval_ptr = TWIG_CALL_S(object, method, arg0 TSRMLS_CC);
|
394 |
-
success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));
|
395 |
-
|
396 |
-
if (retval_ptr) {
|
397 |
-
zval_ptr_dtor(&retval_ptr);
|
398 |
-
}
|
399 |
-
|
400 |
-
return success;
|
401 |
-
}
|
402 |
-
|
403 |
-
int TWIG_CALL_Z(zval *object, char *method, zval *arg1 TSRMLS_DC)
|
404 |
-
{
|
405 |
-
zend_fcall_info fci;
|
406 |
-
zval **args[1];
|
407 |
-
zval *zfunction;
|
408 |
-
zval *retval_ptr;
|
409 |
-
int success;
|
410 |
-
|
411 |
-
args[0] = &arg1;
|
412 |
-
|
413 |
-
MAKE_STD_ZVAL(zfunction);
|
414 |
-
ZVAL_STRING(zfunction, method, 1);
|
415 |
-
fci.size = sizeof(fci);
|
416 |
-
fci.function_table = EG(function_table);
|
417 |
-
fci.function_name = zfunction;
|
418 |
-
fci.symbol_table = NULL;
|
419 |
-
#if PHP_VERSION_ID >= 50300
|
420 |
-
fci.object_ptr = object;
|
421 |
-
#else
|
422 |
-
fci.object_pp = &object;
|
423 |
-
#endif
|
424 |
-
fci.retval_ptr_ptr = &retval_ptr;
|
425 |
-
fci.param_count = 1;
|
426 |
-
fci.params = args;
|
427 |
-
fci.no_separation = 0;
|
428 |
-
|
429 |
-
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
|
430 |
-
FREE_DTOR(zfunction);
|
431 |
-
if (retval_ptr) {
|
432 |
-
zval_ptr_dtor(&retval_ptr);
|
433 |
-
}
|
434 |
-
return 0;
|
435 |
-
}
|
436 |
-
|
437 |
-
FREE_DTOR(zfunction);
|
438 |
-
|
439 |
-
success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));
|
440 |
-
if (retval_ptr) {
|
441 |
-
zval_ptr_dtor(&retval_ptr);
|
442 |
-
}
|
443 |
-
|
444 |
-
return success;
|
445 |
-
}
|
446 |
-
|
447 |
-
int TWIG_CALL_ZZ(zval *object, char *method, zval *arg1, zval *arg2 TSRMLS_DC)
|
448 |
-
{
|
449 |
-
zend_fcall_info fci;
|
450 |
-
zval **args[2];
|
451 |
-
zval *zfunction;
|
452 |
-
zval *retval_ptr;
|
453 |
-
int success;
|
454 |
-
|
455 |
-
args[0] = &arg1;
|
456 |
-
args[1] = &arg2;
|
457 |
-
|
458 |
-
MAKE_STD_ZVAL(zfunction);
|
459 |
-
ZVAL_STRING(zfunction, method, 1);
|
460 |
-
fci.size = sizeof(fci);
|
461 |
-
fci.function_table = EG(function_table);
|
462 |
-
fci.function_name = zfunction;
|
463 |
-
fci.symbol_table = NULL;
|
464 |
-
#if PHP_VERSION_ID >= 50300
|
465 |
-
fci.object_ptr = object;
|
466 |
-
#else
|
467 |
-
fci.object_pp = &object;
|
468 |
-
#endif
|
469 |
-
fci.retval_ptr_ptr = &retval_ptr;
|
470 |
-
fci.param_count = 2;
|
471 |
-
fci.params = args;
|
472 |
-
fci.no_separation = 0;
|
473 |
-
|
474 |
-
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
|
475 |
-
FREE_DTOR(zfunction);
|
476 |
-
return 0;
|
477 |
-
}
|
478 |
-
|
479 |
-
FREE_DTOR(zfunction);
|
480 |
-
|
481 |
-
success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));
|
482 |
-
if (retval_ptr) {
|
483 |
-
zval_ptr_dtor(&retval_ptr);
|
484 |
-
}
|
485 |
-
|
486 |
-
return success;
|
487 |
-
}
|
488 |
-
|
489 |
-
#ifndef Z_SET_REFCOUNT_P
|
490 |
-
# define Z_SET_REFCOUNT_P(pz, rc) pz->refcount = rc
|
491 |
-
# define Z_UNSET_ISREF_P(pz) pz->is_ref = 0
|
492 |
-
#endif
|
493 |
-
|
494 |
-
void TWIG_NEW(zval *object, char *class, zval *arg0, zval *arg1 TSRMLS_DC)
|
495 |
-
{
|
496 |
-
zend_class_entry **pce;
|
497 |
-
|
498 |
-
if (zend_lookup_class(class, strlen(class), &pce TSRMLS_CC) == FAILURE) {
|
499 |
-
return;
|
500 |
-
}
|
501 |
-
|
502 |
-
Z_TYPE_P(object) = IS_OBJECT;
|
503 |
-
object_init_ex(object, *pce);
|
504 |
-
Z_SET_REFCOUNT_P(object, 1);
|
505 |
-
Z_UNSET_ISREF_P(object);
|
506 |
-
|
507 |
-
TWIG_CALL_ZZ(object, "__construct", arg0, arg1 TSRMLS_CC);
|
508 |
-
}
|
509 |
-
|
510 |
-
static int twig_add_array_key_to_string(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
511 |
-
{
|
512 |
-
smart_str *buf;
|
513 |
-
char *joiner;
|
514 |
-
|
515 |
-
buf = va_arg(args, smart_str*);
|
516 |
-
joiner = va_arg(args, char*);
|
517 |
-
|
518 |
-
if (buf->len != 0) {
|
519 |
-
smart_str_appends(buf, joiner);
|
520 |
-
}
|
521 |
-
|
522 |
-
if (hash_key->nKeyLength == 0) {
|
523 |
-
smart_str_append_long(buf, (long) hash_key->h);
|
524 |
-
} else {
|
525 |
-
char *key, *tmp_str;
|
526 |
-
int key_len, tmp_len;
|
527 |
-
key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
|
528 |
-
tmp_str = php_str_to_str_ex(key, key_len, "\0", 1, "' . \"\\0\" . '", 12, &tmp_len, 0, NULL);
|
529 |
-
|
530 |
-
smart_str_appendl(buf, tmp_str, tmp_len);
|
531 |
-
efree(key);
|
532 |
-
efree(tmp_str);
|
533 |
-
}
|
534 |
-
|
535 |
-
return 0;
|
536 |
-
}
|
537 |
-
|
538 |
-
char *TWIG_IMPLODE_ARRAY_KEYS(char *joiner, zval *array TSRMLS_DC)
|
539 |
-
{
|
540 |
-
smart_str collector = { 0, 0, 0 };
|
541 |
-
|
542 |
-
smart_str_appendl(&collector, "", 0);
|
543 |
-
zend_hash_apply_with_arguments(HASH_OF(array) APPLY_TSRMLS_CC, twig_add_array_key_to_string, 2, &collector, joiner);
|
544 |
-
smart_str_0(&collector);
|
545 |
-
|
546 |
-
return collector.c;
|
547 |
-
}
|
548 |
-
|
549 |
-
static void TWIG_THROW_EXCEPTION(char *exception_name TSRMLS_DC, char *message, ...)
|
550 |
-
{
|
551 |
-
char *buffer;
|
552 |
-
va_list args;
|
553 |
-
zend_class_entry **pce;
|
554 |
-
|
555 |
-
if (zend_lookup_class(exception_name, strlen(exception_name), &pce TSRMLS_CC) == FAILURE) {
|
556 |
-
return;
|
557 |
-
}
|
558 |
-
|
559 |
-
va_start(args, message);
|
560 |
-
vspprintf(&buffer, 0, message, args);
|
561 |
-
va_end(args);
|
562 |
-
|
563 |
-
zend_throw_exception_ex(*pce, 0 TSRMLS_CC, buffer);
|
564 |
-
efree(buffer);
|
565 |
-
}
|
566 |
-
|
567 |
-
static void TWIG_RUNTIME_ERROR(zval *template TSRMLS_DC, char *message, ...)
|
568 |
-
{
|
569 |
-
char *buffer;
|
570 |
-
va_list args;
|
571 |
-
zend_class_entry **pce;
|
572 |
-
zval *ex;
|
573 |
-
zval *constructor;
|
574 |
-
zval *zmessage;
|
575 |
-
zval *lineno;
|
576 |
-
zval *filename_func;
|
577 |
-
zval *filename;
|
578 |
-
zval *constructor_args[3];
|
579 |
-
zval *constructor_retval;
|
580 |
-
|
581 |
-
if (zend_lookup_class("Twig_Error_Runtime", strlen("Twig_Error_Runtime"), &pce TSRMLS_CC) == FAILURE) {
|
582 |
-
return;
|
583 |
-
}
|
584 |
-
|
585 |
-
va_start(args, message);
|
586 |
-
vspprintf(&buffer, 0, message, args);
|
587 |
-
va_end(args);
|
588 |
-
|
589 |
-
MAKE_STD_ZVAL(ex);
|
590 |
-
object_init_ex(ex, *pce);
|
591 |
-
|
592 |
-
// Call Twig_Error constructor
|
593 |
-
MAKE_STD_ZVAL(constructor);
|
594 |
-
MAKE_STD_ZVAL(zmessage);
|
595 |
-
MAKE_STD_ZVAL(lineno);
|
596 |
-
MAKE_STD_ZVAL(filename);
|
597 |
-
MAKE_STD_ZVAL(filename_func);
|
598 |
-
MAKE_STD_ZVAL(constructor_retval);
|
599 |
-
|
600 |
-
ZVAL_STRINGL(constructor, "__construct", sizeof("__construct")-1, 1);
|
601 |
-
ZVAL_STRING(zmessage, buffer, 1);
|
602 |
-
ZVAL_LONG(lineno, -1);
|
603 |
-
|
604 |
-
// Get template filename
|
605 |
-
ZVAL_STRINGL(filename_func, "getTemplateName", sizeof("getTemplateName")-1, 1);
|
606 |
-
call_user_function(EG(function_table), &template, filename_func, filename, 0, 0 TSRMLS_CC);
|
607 |
-
|
608 |
-
constructor_args[0] = zmessage;
|
609 |
-
constructor_args[1] = lineno;
|
610 |
-
constructor_args[2] = filename;
|
611 |
-
call_user_function(EG(function_table), &ex, constructor, constructor_retval, 3, constructor_args TSRMLS_CC);
|
612 |
-
|
613 |
-
zval_ptr_dtor(&constructor_retval);
|
614 |
-
zval_ptr_dtor(&zmessage);
|
615 |
-
zval_ptr_dtor(&lineno);
|
616 |
-
zval_ptr_dtor(&filename);
|
617 |
-
FREE_DTOR(constructor);
|
618 |
-
FREE_DTOR(filename_func);
|
619 |
-
efree(buffer);
|
620 |
-
|
621 |
-
zend_throw_exception_object(ex TSRMLS_CC);
|
622 |
-
}
|
623 |
-
|
624 |
-
static char *TWIG_GET_CLASS_NAME(zval *object TSRMLS_DC)
|
625 |
-
{
|
626 |
-
char *class_name;
|
627 |
-
zend_uint class_name_len;
|
628 |
-
|
629 |
-
if (Z_TYPE_P(object) != IS_OBJECT) {
|
630 |
-
return "";
|
631 |
-
}
|
632 |
-
#if PHP_API_VERSION >= 20100412
|
633 |
-
zend_get_object_classname(object, (const char **) &class_name, &class_name_len TSRMLS_CC);
|
634 |
-
#else
|
635 |
-
zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
|
636 |
-
#endif
|
637 |
-
return class_name;
|
638 |
-
}
|
639 |
-
|
640 |
-
static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
641 |
-
{
|
642 |
-
zval *retval;
|
643 |
-
char *item;
|
644 |
-
size_t item_len;
|
645 |
-
zend_function *mptr = (zend_function *) pDest;
|
646 |
-
|
647 |
-
if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)) {
|
648 |
-
return 0;
|
649 |
-
}
|
650 |
-
|
651 |
-
retval = va_arg(args, zval*);
|
652 |
-
|
653 |
-
item_len = strlen(mptr->common.function_name);
|
654 |
-
item = estrndup(mptr->common.function_name, item_len);
|
655 |
-
php_strtolower(item, item_len);
|
656 |
-
|
657 |
-
add_assoc_stringl_ex(retval, item, item_len+1, item, item_len, 0);
|
658 |
-
|
659 |
-
return 0;
|
660 |
-
}
|
661 |
-
|
662 |
-
static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
663 |
-
{
|
664 |
-
zend_class_entry *ce;
|
665 |
-
zval *retval;
|
666 |
-
char *class_name, *prop_name;
|
667 |
-
zend_property_info *pptr = (zend_property_info *) pDest;
|
668 |
-
|
669 |
-
if (!(pptr->flags & ZEND_ACC_PUBLIC)) {
|
670 |
-
return 0;
|
671 |
-
}
|
672 |
-
|
673 |
-
ce = *va_arg(args, zend_class_entry**);
|
674 |
-
retval = va_arg(args, zval*);
|
675 |
-
|
676 |
-
#if PHP_API_VERSION >= 20100412
|
677 |
-
zend_unmangle_property_name(pptr->name, pptr->name_length, (const char **) &class_name, (const char **) &prop_name);
|
678 |
-
#else
|
679 |
-
zend_unmangle_property_name(pptr->name, pptr->name_length, &class_name, &prop_name);
|
680 |
-
#endif
|
681 |
-
|
682 |
-
add_assoc_string(retval, prop_name, prop_name, 1);
|
683 |
-
|
684 |
-
return 0;
|
685 |
-
}
|
686 |
-
|
687 |
-
static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name TSRMLS_DC)
|
688 |
-
{
|
689 |
-
zval *class_info, *class_methods, *class_properties;
|
690 |
-
zend_class_entry *class_ce;
|
691 |
-
|
692 |
-
class_ce = zend_get_class_entry(object TSRMLS_CC);
|
693 |
-
|
694 |
-
ALLOC_INIT_ZVAL(class_info);
|
695 |
-
ALLOC_INIT_ZVAL(class_methods);
|
696 |
-
ALLOC_INIT_ZVAL(class_properties);
|
697 |
-
array_init(class_info);
|
698 |
-
array_init(class_methods);
|
699 |
-
array_init(class_properties);
|
700 |
-
// add all methods to self::cache[$class]['methods']
|
701 |
-
zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class, 1, class_methods);
|
702 |
-
zend_hash_apply_with_arguments(&class_ce->properties_info APPLY_TSRMLS_CC, twig_add_property_to_class, 2, &class_ce, class_properties);
|
703 |
-
|
704 |
-
add_assoc_zval(class_info, "methods", class_methods);
|
705 |
-
add_assoc_zval(class_info, "properties", class_properties);
|
706 |
-
add_assoc_zval(cache, class_name, class_info);
|
707 |
-
}
|
708 |
-
|
709 |
-
/* {{{ proto mixed twig_template_get_attributes(TwigTemplate template, mixed object, mixed item, array arguments, string type, boolean isDefinedTest, boolean ignoreStrictCheck)
|
710 |
-
A C implementation of TwigTemplate::getAttribute() */
|
711 |
-
PHP_FUNCTION(twig_template_get_attributes)
|
712 |
-
{
|
713 |
-
zval *template;
|
714 |
-
zval *object;
|
715 |
-
char *item;
|
716 |
-
int item_len;
|
717 |
-
zval zitem;
|
718 |
-
zval *arguments = NULL;
|
719 |
-
zval *ret = NULL;
|
720 |
-
char *type = NULL;
|
721 |
-
int type_len = 0;
|
722 |
-
zend_bool isDefinedTest = 0;
|
723 |
-
zend_bool ignoreStrictCheck = 0;
|
724 |
-
int free_ret = 0;
|
725 |
-
zval *tmp_self_cache;
|
726 |
-
|
727 |
-
|
728 |
-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ozs|asbb", &template, &object, &item, &item_len, &arguments, &type, &type_len, &isDefinedTest, &ignoreStrictCheck) == FAILURE) {
|
729 |
-
return;
|
730 |
-
}
|
731 |
-
|
732 |
-
INIT_PZVAL(&zitem);
|
733 |
-
ZVAL_STRINGL(&zitem, item, item_len, 0);
|
734 |
-
|
735 |
-
switch (is_numeric_string(item, item_len, &Z_LVAL(zitem), &Z_DVAL(zitem), 0)) {
|
736 |
-
case IS_LONG:
|
737 |
-
Z_TYPE(zitem) = IS_LONG;
|
738 |
-
break;
|
739 |
-
case IS_DOUBLE:
|
740 |
-
Z_TYPE(zitem) = IS_DOUBLE;
|
741 |
-
convert_to_long(&zitem);
|
742 |
-
break;
|
743 |
-
}
|
744 |
-
|
745 |
-
if (!type) {
|
746 |
-
type = "any";
|
747 |
-
}
|
748 |
-
|
749 |
-
/*
|
750 |
-
// array
|
751 |
-
if (Twig_TemplateInterface::METHOD_CALL !== $type) {
|
752 |
-
if ((is_array($object) && array_key_exists($item, $object))
|
753 |
-
|| ($object instanceof ArrayAccess && isset($object[$item]))
|
754 |
-
) {
|
755 |
-
if ($isDefinedTest) {
|
756 |
-
return true;
|
757 |
-
}
|
758 |
-
|
759 |
-
return $object[$item];
|
760 |
-
}
|
761 |
-
*/
|
762 |
-
if (strcmp("method", type) != 0) {
|
763 |
-
// printf("XXXmethod: %s\n", type);
|
764 |
-
if ((TWIG_ARRAY_KEY_EXISTS(object, item, item_len))
|
765 |
-
|| (TWIG_INSTANCE_OF(object, zend_ce_arrayaccess TSRMLS_CC) && TWIG_ISSET_ARRAYOBJECT_ELEMENT(object, &zitem TSRMLS_CC))
|
766 |
-
) {
|
767 |
-
zval *ret;
|
768 |
-
|
769 |
-
if (isDefinedTest) {
|
770 |
-
RETURN_TRUE;
|
771 |
-
}
|
772 |
-
|
773 |
-
ret = TWIG_GET_ARRAY_ELEMENT(object, item, item_len TSRMLS_CC);
|
774 |
-
if (!ret) {
|
775 |
-
ret = &EG(uninitialized_zval);
|
776 |
-
}
|
777 |
-
RETVAL_ZVAL(ret, 1, 0);
|
778 |
-
if (free_ret) {
|
779 |
-
zval_ptr_dtor(&ret);
|
780 |
-
}
|
781 |
-
return;
|
782 |
-
}
|
783 |
-
/*
|
784 |
-
if (Twig_TemplateInterface::ARRAY_CALL === $type) {
|
785 |
-
if ($isDefinedTest) {
|
786 |
-
return false;
|
787 |
-
}
|
788 |
-
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
789 |
-
return null;
|
790 |
-
}
|
791 |
-
*/
|
792 |
-
if (strcmp("array", type) == 0) {
|
793 |
-
if (isDefinedTest) {
|
794 |
-
RETURN_FALSE;
|
795 |
-
}
|
796 |
-
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
797 |
-
return;
|
798 |
-
}
|
799 |
-
/*
|
800 |
-
if (is_object($object)) {
|
801 |
-
throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
|
802 |
-
} elseif (is_array($object)) {
|
803 |
-
throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $item, implode(', ', array_keys($object))), -1, $this->getTemplateName());
|
804 |
-
} else {
|
805 |
-
throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a "%s" variable', $item, gettype($object)), -1, $this->getTemplateName());
|
806 |
-
}
|
807 |
-
}
|
808 |
-
}
|
809 |
-
*/
|
810 |
-
if (Z_TYPE_P(object) == IS_OBJECT) {
|
811 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" in object (with ArrayAccess) of type \"%s\" does not exist", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
812 |
-
} else if (Z_TYPE_P(object) == IS_ARRAY) {
|
813 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist", item, TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC));
|
814 |
-
} else {
|
815 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to access a key (\"%s\") on a \"%s\" variable", item, zend_zval_type_name(object));
|
816 |
-
}
|
817 |
-
return;
|
818 |
-
}
|
819 |
-
}
|
820 |
-
|
821 |
-
/*
|
822 |
-
if (!is_object($object)) {
|
823 |
-
if ($isDefinedTest) {
|
824 |
-
return false;
|
825 |
-
}
|
826 |
-
*/
|
827 |
-
|
828 |
-
if (Z_TYPE_P(object) != IS_OBJECT) {
|
829 |
-
if (isDefinedTest) {
|
830 |
-
RETURN_FALSE;
|
831 |
-
}
|
832 |
-
/*
|
833 |
-
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
834 |
-
return null;
|
835 |
-
}
|
836 |
-
throw new Twig_Error_Runtime(sprintf('Item "%s" for "%s" does not exist', $item, implode(', ', array_keys($object))));
|
837 |
-
}
|
838 |
-
*/
|
839 |
-
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
840 |
-
RETURN_FALSE;
|
841 |
-
}
|
842 |
-
if (Z_TYPE_P(object) == IS_ARRAY) {
|
843 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Item \"%s\" for \"Array\" does not exist", item);
|
844 |
-
} else {
|
845 |
-
Z_ADDREF_P(object);
|
846 |
-
convert_to_string_ex(&object);
|
847 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Item \"%s\" for \"%s\" does not exist", item, Z_STRVAL_P(object));
|
848 |
-
zval_ptr_dtor(&object);
|
849 |
-
}
|
850 |
-
return;
|
851 |
-
}
|
852 |
-
/*
|
853 |
-
// get some information about the object
|
854 |
-
$class = get_class($object);
|
855 |
-
if (!isset(self::$cache[$class])) {
|
856 |
-
$r = new ReflectionClass($class);
|
857 |
-
self::$cache[$class] = array('methods' => array(), 'properties' => array());
|
858 |
-
foreach ($r->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
859 |
-
self::$cache[$class]['methods'][strtolower($method->getName())] = true;
|
860 |
-
}
|
861 |
-
|
862 |
-
foreach ($r->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
|
863 |
-
self::$cache[$class]['properties'][$property->getName()] = true;
|
864 |
-
}
|
865 |
-
}
|
866 |
-
*/
|
867 |
-
if (Z_TYPE_P(object) == IS_OBJECT) {
|
868 |
-
char *class_name = NULL;
|
869 |
-
|
870 |
-
class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
|
871 |
-
tmp_self_cache = TWIG_GET_STATIC_PROPERTY(template, "cache" TSRMLS_CC);
|
872 |
-
|
873 |
-
if (!TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC)) {
|
874 |
-
twig_add_class_to_cache(tmp_self_cache, object, class_name TSRMLS_CC);
|
875 |
-
}
|
876 |
-
efree(class_name);
|
877 |
-
}
|
878 |
-
|
879 |
-
/*
|
880 |
-
// object property
|
881 |
-
if (Twig_TemplateInterface::METHOD_CALL !== $type) {
|
882 |
-
if (isset(self::$cache[$class]['properties'][$item])
|
883 |
-
|| isset($object->$item) || array_key_exists($item, $object)
|
884 |
-
) {
|
885 |
-
if ($isDefinedTest) {
|
886 |
-
return true;
|
887 |
-
}
|
888 |
-
if ($this->env->hasExtension('sandbox')) {
|
889 |
-
$this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
|
890 |
-
}
|
891 |
-
|
892 |
-
return $object->$item;
|
893 |
-
}
|
894 |
-
}
|
895 |
-
*/
|
896 |
-
if (strcmp("method", type) != 0) {
|
897 |
-
zval *tmp_class, *tmp_properties, *tmp_item;
|
898 |
-
char *class_name = NULL;
|
899 |
-
|
900 |
-
class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
|
901 |
-
tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
|
902 |
-
tmp_properties = TWIG_GET_ARRAY_ELEMENT(tmp_class, "properties", strlen("properties") TSRMLS_CC);
|
903 |
-
tmp_item = TWIG_GET_ARRAY_ELEMENT(tmp_properties, item, item_len TSRMLS_CC);
|
904 |
-
|
905 |
-
efree(class_name);
|
906 |
-
|
907 |
-
if (tmp_item || TWIG_HAS_PROPERTY(object, &zitem TSRMLS_CC) || TWIG_HAS_DYNAMIC_PROPERTY(object, item, item_len TSRMLS_CC)) {
|
908 |
-
if (isDefinedTest) {
|
909 |
-
RETURN_TRUE;
|
910 |
-
}
|
911 |
-
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
|
912 |
-
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkPropertyAllowed", object, &zitem TSRMLS_CC);
|
913 |
-
}
|
914 |
-
if (EG(exception)) {
|
915 |
-
return;
|
916 |
-
}
|
917 |
-
|
918 |
-
ret = TWIG_PROPERTY(object, &zitem TSRMLS_CC);
|
919 |
-
RETURN_ZVAL(ret, 1, 0);
|
920 |
-
}
|
921 |
-
}
|
922 |
-
/*
|
923 |
-
// object method
|
924 |
-
$lcItem = strtolower($item);
|
925 |
-
if (isset(self::$cache[$class]['methods'][$lcItem])) {
|
926 |
-
$method = $item;
|
927 |
-
} elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
|
928 |
-
$method = 'get'.$item;
|
929 |
-
} elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
|
930 |
-
$method = 'is'.$item;
|
931 |
-
} elseif (isset(self::$cache[$class]['methods']['__call'])) {
|
932 |
-
$method = $item;
|
933 |
-
*/
|
934 |
-
{
|
935 |
-
char *lcItem = TWIG_STRTOLOWER(item, item_len);
|
936 |
-
int lcItem_length;
|
937 |
-
char *method = NULL;
|
938 |
-
char *tmp_method_name_get;
|
939 |
-
char *tmp_method_name_is;
|
940 |
-
zval *tmp_class, *tmp_methods;
|
941 |
-
char *class_name = NULL;
|
942 |
-
|
943 |
-
class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
|
944 |
-
lcItem_length = strlen(lcItem);
|
945 |
-
tmp_method_name_get = emalloc(4 + lcItem_length);
|
946 |
-
tmp_method_name_is = emalloc(3 + lcItem_length);
|
947 |
-
|
948 |
-
sprintf(tmp_method_name_get, "get%s", lcItem);
|
949 |
-
sprintf(tmp_method_name_is, "is%s", lcItem);
|
950 |
-
|
951 |
-
tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
|
952 |
-
tmp_methods = TWIG_GET_ARRAY_ELEMENT(tmp_class, "methods", strlen("methods") TSRMLS_CC);
|
953 |
-
efree(class_name);
|
954 |
-
|
955 |
-
if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, lcItem, lcItem_length TSRMLS_CC)) {
|
956 |
-
method = item;
|
957 |
-
} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, tmp_method_name_get, lcItem_length + 3 TSRMLS_CC)) {
|
958 |
-
method = tmp_method_name_get;
|
959 |
-
} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, tmp_method_name_is, lcItem_length + 2 TSRMLS_CC)) {
|
960 |
-
method = tmp_method_name_is;
|
961 |
-
} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, "__call", 6 TSRMLS_CC)) {
|
962 |
-
method = item;
|
963 |
-
/*
|
964 |
-
} else {
|
965 |
-
if ($isDefinedTest) {
|
966 |
-
return false;
|
967 |
-
}
|
968 |
-
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
969 |
-
return null;
|
970 |
-
}
|
971 |
-
throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)));
|
972 |
-
}
|
973 |
-
if ($isDefinedTest) {
|
974 |
-
return true;
|
975 |
-
}
|
976 |
-
*/
|
977 |
-
} else {
|
978 |
-
efree(tmp_method_name_get);
|
979 |
-
efree(tmp_method_name_is);
|
980 |
-
efree(lcItem);
|
981 |
-
|
982 |
-
if (isDefinedTest) {
|
983 |
-
RETURN_FALSE;
|
984 |
-
}
|
985 |
-
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
986 |
-
return;
|
987 |
-
}
|
988 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Method \"%s\" for object \"%s\" does not exist", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
989 |
-
return;
|
990 |
-
}
|
991 |
-
|
992 |
-
if (isDefinedTest) {
|
993 |
-
efree(tmp_method_name_get);
|
994 |
-
efree(tmp_method_name_is);
|
995 |
-
efree(lcItem);
|
996 |
-
RETURN_TRUE;
|
997 |
-
}
|
998 |
-
/*
|
999 |
-
if ($this->env->hasExtension('sandbox')) {
|
1000 |
-
$this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
|
1001 |
-
}
|
1002 |
-
*/
|
1003 |
-
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
|
1004 |
-
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkMethodAllowed", object, &zitem TSRMLS_CC);
|
1005 |
-
}
|
1006 |
-
if (EG(exception)) {
|
1007 |
-
efree(tmp_method_name_get);
|
1008 |
-
efree(tmp_method_name_is);
|
1009 |
-
efree(lcItem);
|
1010 |
-
return;
|
1011 |
-
}
|
1012 |
-
/*
|
1013 |
-
$ret = call_user_func_array(array($object, $method), $arguments);
|
1014 |
-
*/
|
1015 |
-
if (Z_TYPE_P(object) == IS_OBJECT) {
|
1016 |
-
ret = TWIG_CALL_USER_FUNC_ARRAY(object, method, arguments TSRMLS_CC);
|
1017 |
-
free_ret = 1;
|
1018 |
-
}
|
1019 |
-
efree(tmp_method_name_get);
|
1020 |
-
efree(tmp_method_name_is);
|
1021 |
-
efree(lcItem);
|
1022 |
-
}
|
1023 |
-
/*
|
1024 |
-
if ($object instanceof Twig_TemplateInterface) {
|
1025 |
-
return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
|
1026 |
-
}
|
1027 |
-
|
1028 |
-
return $ret;
|
1029 |
-
*/
|
1030 |
-
// ret can be null, if e.g. the called method throws an exception
|
1031 |
-
if (ret) {
|
1032 |
-
if (TWIG_INSTANCE_OF_USERLAND(object, "Twig_TemplateInterface" TSRMLS_CC)) {
|
1033 |
-
if (Z_STRLEN_P(ret) == 0) {
|
1034 |
-
free_ret = 1;
|
1035 |
-
} else {
|
1036 |
-
zval *charset = TWIG_CALL_USER_FUNC_ARRAY(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getCharset", NULL TSRMLS_CC);
|
1037 |
-
TWIG_NEW(return_value, "Twig_Markup", ret, charset TSRMLS_CC);
|
1038 |
-
zval_ptr_dtor(&charset);
|
1039 |
-
if (ret) {
|
1040 |
-
zval_ptr_dtor(&ret);
|
1041 |
-
}
|
1042 |
-
return;
|
1043 |
-
}
|
1044 |
-
}
|
1045 |
-
|
1046 |
-
RETVAL_ZVAL(ret, 1, 0);
|
1047 |
-
if (free_ret) {
|
1048 |
-
zval_ptr_dtor(&ret);
|
1049 |
-
}
|
1050 |
-
}
|
1051 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/lib/Twig/Autoloader.php
CHANGED
@@ -12,18 +12,22 @@
|
|
12 |
/**
|
13 |
* Autoloads Twig classes.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Autoloader
|
19 |
{
|
20 |
/**
|
21 |
* Registers Twig_Autoloader as an SPL autoloader.
|
|
|
|
|
22 |
*/
|
23 |
-
public static function register()
|
24 |
{
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
27 |
}
|
28 |
|
29 |
/**
|
12 |
/**
|
13 |
* Autoloads Twig classes.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Autoloader
|
18 |
{
|
19 |
/**
|
20 |
* Registers Twig_Autoloader as an SPL autoloader.
|
21 |
+
*
|
22 |
+
* @param Boolean $prepend Whether to prepend the autoloader or not.
|
23 |
*/
|
24 |
+
public static function register($prepend = false)
|
25 |
{
|
26 |
+
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
27 |
+
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
|
28 |
+
} else {
|
29 |
+
spl_autoload_register(array(new self, 'autoload'));
|
30 |
+
}
|
31 |
}
|
32 |
|
33 |
/**
|
Twig/lib/Twig/Compiler.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Compiles a node to PHP code.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Compiler implements Twig_CompilerInterface
|
20 |
{
|
13 |
/**
|
14 |
* Compiles a node to PHP code.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Compiler implements Twig_CompilerInterface
|
19 |
{
|
Twig/lib/Twig/CompilerInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface implemented by compiler classes.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_CompilerInterface
|
12 |
/**
|
13 |
* Interface implemented by compiler classes.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_CompilerInterface
|
Twig/lib/Twig/Environment.php
CHANGED
@@ -12,12 +12,11 @@
|
|
12 |
/**
|
13 |
* Stores the Twig configuration.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Environment
|
19 |
{
|
20 |
-
const VERSION = '1.
|
21 |
|
22 |
protected $charset;
|
23 |
protected $loader;
|
@@ -54,7 +53,7 @@ class Twig_Environment
|
|
54 |
* * debug: When set to true, it automatically set "auto_reload" to true as
|
55 |
* well (default to false).
|
56 |
*
|
57 |
-
* * charset: The charset used by the templates (default to
|
58 |
*
|
59 |
* * base_template_class: The base template class to use for generated
|
60 |
* templates (default to Twig_Template).
|
@@ -100,7 +99,7 @@ class Twig_Environment
|
|
100 |
), $options);
|
101 |
|
102 |
$this->debug = (bool) $options['debug'];
|
103 |
-
$this->charset = $options['charset'];
|
104 |
$this->baseTemplateClass = $options['base_template_class'];
|
105 |
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
|
106 |
$this->strictVariables = (bool) $options['strict_variables'];
|
@@ -263,7 +262,7 @@ class Twig_Environment
|
|
263 |
*/
|
264 |
public function getTemplateClass($name, $index = null)
|
265 |
{
|
266 |
-
return $this->templateClassPrefix.md5($this->
|
267 |
}
|
268 |
|
269 |
/**
|
@@ -318,10 +317,10 @@ class Twig_Environment
|
|
318 |
|
319 |
if (!class_exists($cls, false)) {
|
320 |
if (false === $cache = $this->getCacheFilename($name)) {
|
321 |
-
eval('?>'.$this->compileSource($this->
|
322 |
} else {
|
323 |
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
|
324 |
-
$this->writeCacheFile($cache, $this->compileSource($this->
|
325 |
}
|
326 |
|
327 |
require_once $cache;
|
@@ -356,7 +355,7 @@ class Twig_Environment
|
|
356 |
}
|
357 |
}
|
358 |
|
359 |
-
return $this->
|
360 |
}
|
361 |
|
362 |
public function resolveTemplate($names)
|
@@ -553,6 +552,10 @@ class Twig_Environment
|
|
553 |
*/
|
554 |
public function getLoader()
|
555 |
{
|
|
|
|
|
|
|
|
|
556 |
return $this->loader;
|
557 |
}
|
558 |
|
@@ -563,7 +566,7 @@ class Twig_Environment
|
|
563 |
*/
|
564 |
public function setCharset($charset)
|
565 |
{
|
566 |
-
$this->charset = $charset;
|
567 |
}
|
568 |
|
569 |
/**
|
@@ -753,10 +756,6 @@ class Twig_Environment
|
|
753 |
*/
|
754 |
public function addFilter($name, $filter = null)
|
755 |
{
|
756 |
-
if ($this->extensionInitialized) {
|
757 |
-
throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
|
758 |
-
}
|
759 |
-
|
760 |
if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
|
761 |
throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
|
762 |
}
|
@@ -765,7 +764,11 @@ class Twig_Environment
|
|
765 |
$filter = $name;
|
766 |
$name = $filter->getName();
|
767 |
}
|
768 |
-
|
|
|
|
|
|
|
|
|
769 |
$this->staging->addFilter($name, $filter);
|
770 |
}
|
771 |
|
@@ -842,10 +845,6 @@ class Twig_Environment
|
|
842 |
*/
|
843 |
public function addTest($name, $test = null)
|
844 |
{
|
845 |
-
if ($this->extensionInitialized) {
|
846 |
-
throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
|
847 |
-
}
|
848 |
-
|
849 |
if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
|
850 |
throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
|
851 |
}
|
@@ -854,6 +853,10 @@ class Twig_Environment
|
|
854 |
$test = $name;
|
855 |
$name = $test->getName();
|
856 |
}
|
|
|
|
|
|
|
|
|
857 |
|
858 |
$this->staging->addTest($name, $test);
|
859 |
}
|
@@ -900,10 +903,6 @@ class Twig_Environment
|
|
900 |
*/
|
901 |
public function addFunction($name, $function = null)
|
902 |
{
|
903 |
-
if ($this->extensionInitialized) {
|
904 |
-
throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
|
905 |
-
}
|
906 |
-
|
907 |
if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
|
908 |
throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
|
909 |
}
|
@@ -912,7 +911,11 @@ class Twig_Environment
|
|
912 |
$function = $name;
|
913 |
$name = $function->getName();
|
914 |
}
|
915 |
-
|
|
|
|
|
|
|
|
|
916 |
$this->staging->addFunction($name, $function);
|
917 |
}
|
918 |
|
@@ -994,7 +997,7 @@ class Twig_Environment
|
|
994 |
{
|
995 |
if ($this->extensionInitialized || $this->runtimeInitialized) {
|
996 |
if (null === $this->globals) {
|
997 |
-
$this->initGlobals();
|
998 |
}
|
999 |
|
1000 |
/* This condition must be uncommented in Twig 2.0
|
@@ -1019,8 +1022,12 @@ class Twig_Environment
|
|
1019 |
*/
|
1020 |
public function getGlobals()
|
1021 |
{
|
1022 |
-
if (
|
1023 |
-
$this->initGlobals();
|
|
|
|
|
|
|
|
|
1024 |
}
|
1025 |
|
1026 |
return $this->globals;
|
@@ -1090,11 +1097,19 @@ class Twig_Environment
|
|
1090 |
|
1091 |
protected function initGlobals()
|
1092 |
{
|
1093 |
-
$
|
1094 |
foreach ($this->extensions as $extension) {
|
1095 |
-
$
|
|
|
|
|
|
|
|
|
|
|
1096 |
}
|
1097 |
-
|
|
|
|
|
|
|
1098 |
}
|
1099 |
|
1100 |
protected function initExtensions()
|
12 |
/**
|
13 |
* Stores the Twig configuration.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
+
const VERSION = '1.13.1';
|
20 |
|
21 |
protected $charset;
|
22 |
protected $loader;
|
53 |
* * debug: When set to true, it automatically set "auto_reload" to true as
|
54 |
* well (default to false).
|
55 |
*
|
56 |
+
* * charset: The charset used by the templates (default to UTF-8).
|
57 |
*
|
58 |
* * base_template_class: The base template class to use for generated
|
59 |
* templates (default to Twig_Template).
|
99 |
), $options);
|
100 |
|
101 |
$this->debug = (bool) $options['debug'];
|
102 |
+
$this->charset = strtoupper($options['charset']);
|
103 |
$this->baseTemplateClass = $options['base_template_class'];
|
104 |
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
|
105 |
$this->strictVariables = (bool) $options['strict_variables'];
|
262 |
*/
|
263 |
public function getTemplateClass($name, $index = null)
|
264 |
{
|
265 |
+
return $this->templateClassPrefix.md5($this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
|
266 |
}
|
267 |
|
268 |
/**
|
317 |
|
318 |
if (!class_exists($cls, false)) {
|
319 |
if (false === $cache = $this->getCacheFilename($name)) {
|
320 |
+
eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
|
321 |
} else {
|
322 |
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
|
323 |
+
$this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
|
324 |
}
|
325 |
|
326 |
require_once $cache;
|
355 |
}
|
356 |
}
|
357 |
|
358 |
+
return $this->getLoader()->isFresh($name, $time);
|
359 |
}
|
360 |
|
361 |
public function resolveTemplate($names)
|
552 |
*/
|
553 |
public function getLoader()
|
554 |
{
|
555 |
+
if (null === $this->loader) {
|
556 |
+
throw new LogicException('You must set a loader first.');
|
557 |
+
}
|
558 |
+
|
559 |
return $this->loader;
|
560 |
}
|
561 |
|
566 |
*/
|
567 |
public function setCharset($charset)
|
568 |
{
|
569 |
+
$this->charset = strtoupper($charset);
|
570 |
}
|
571 |
|
572 |
/**
|
756 |
*/
|
757 |
public function addFilter($name, $filter = null)
|
758 |
{
|
|
|
|
|
|
|
|
|
759 |
if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
|
760 |
throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
|
761 |
}
|
764 |
$filter = $name;
|
765 |
$name = $filter->getName();
|
766 |
}
|
767 |
+
|
768 |
+
if ($this->extensionInitialized) {
|
769 |
+
throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
|
770 |
+
}
|
771 |
+
|
772 |
$this->staging->addFilter($name, $filter);
|
773 |
}
|
774 |
|
845 |
*/
|
846 |
public function addTest($name, $test = null)
|
847 |
{
|
|
|
|
|
|
|
|
|
848 |
if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
|
849 |
throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
|
850 |
}
|
853 |
$test = $name;
|
854 |
$name = $test->getName();
|
855 |
}
|
856 |
+
|
857 |
+
if ($this->extensionInitialized) {
|
858 |
+
throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
|
859 |
+
}
|
860 |
|
861 |
$this->staging->addTest($name, $test);
|
862 |
}
|
903 |
*/
|
904 |
public function addFunction($name, $function = null)
|
905 |
{
|
|
|
|
|
|
|
|
|
906 |
if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
|
907 |
throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
|
908 |
}
|
911 |
$function = $name;
|
912 |
$name = $function->getName();
|
913 |
}
|
914 |
+
|
915 |
+
if ($this->extensionInitialized) {
|
916 |
+
throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
|
917 |
+
}
|
918 |
+
|
919 |
$this->staging->addFunction($name, $function);
|
920 |
}
|
921 |
|
997 |
{
|
998 |
if ($this->extensionInitialized || $this->runtimeInitialized) {
|
999 |
if (null === $this->globals) {
|
1000 |
+
$this->globals = $this->initGlobals();
|
1001 |
}
|
1002 |
|
1003 |
/* This condition must be uncommented in Twig 2.0
|
1022 |
*/
|
1023 |
public function getGlobals()
|
1024 |
{
|
1025 |
+
if (!$this->runtimeInitialized && !$this->extensionInitialized) {
|
1026 |
+
return $this->initGlobals();
|
1027 |
+
}
|
1028 |
+
|
1029 |
+
if (null === $this->globals) {
|
1030 |
+
$this->globals = $this->initGlobals();
|
1031 |
}
|
1032 |
|
1033 |
return $this->globals;
|
1097 |
|
1098 |
protected function initGlobals()
|
1099 |
{
|
1100 |
+
$globals = array();
|
1101 |
foreach ($this->extensions as $extension) {
|
1102 |
+
$extGlob = $extension->getGlobals();
|
1103 |
+
if (!is_array($extGlob)) {
|
1104 |
+
throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
|
1105 |
+
}
|
1106 |
+
|
1107 |
+
$globals[] = $extGlob;
|
1108 |
}
|
1109 |
+
|
1110 |
+
$globals[] = $this->staging->getGlobals();
|
1111 |
+
|
1112 |
+
return call_user_func_array('array_merge', $globals);
|
1113 |
}
|
1114 |
|
1115 |
protected function initExtensions()
|
Twig/lib/Twig/Error.php
CHANGED
@@ -29,8 +29,7 @@
|
|
29 |
* can be disabled by passing false for both the filename and the line number
|
30 |
* when creating a new instance of this class.
|
31 |
*
|
32 |
-
* @
|
33 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
34 |
*/
|
35 |
class Twig_Error extends Exception
|
36 |
{
|
@@ -187,7 +186,14 @@ class Twig_Error extends Exception
|
|
187 |
protected function guessTemplateInfo()
|
188 |
{
|
189 |
$template = null;
|
190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
|
192 |
if (null === $this->filename || $this->filename == $trace['object']->getTemplateName()) {
|
193 |
$template = $trace['object'];
|
29 |
* can be disabled by passing false for both the filename and the line number
|
30 |
* when creating a new instance of this class.
|
31 |
*
|
32 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
33 |
*/
|
34 |
class Twig_Error extends Exception
|
35 |
{
|
186 |
protected function guessTemplateInfo()
|
187 |
{
|
188 |
$template = null;
|
189 |
+
|
190 |
+
if (version_compare(phpversion(), '5.3.6', '>=')) {
|
191 |
+
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
|
192 |
+
} else {
|
193 |
+
$backtrace = debug_backtrace();
|
194 |
+
}
|
195 |
+
|
196 |
+
foreach ($backtrace as $trace) {
|
197 |
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
|
198 |
if (null === $this->filename || $this->filename == $trace['object']->getTemplateName()) {
|
199 |
$template = $trace['object'];
|
Twig/lib/Twig/Error/Loader.php
CHANGED
@@ -20,8 +20,7 @@
|
|
20 |
*
|
21 |
* This strategy makes Twig_Environment::resolveTemplate() much faster.
|
22 |
*
|
23 |
-
* @
|
24 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
25 |
*/
|
26 |
class Twig_Error_Loader extends Twig_Error
|
27 |
{
|
20 |
*
|
21 |
* This strategy makes Twig_Environment::resolveTemplate() much faster.
|
22 |
*
|
23 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
24 |
*/
|
25 |
class Twig_Error_Loader extends Twig_Error
|
26 |
{
|
Twig/lib/Twig/Error/Runtime.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Exception thrown when an error occurs at runtime.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Error_Runtime extends Twig_Error
|
20 |
{
|
13 |
/**
|
14 |
* Exception thrown when an error occurs at runtime.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Error_Runtime extends Twig_Error
|
19 |
{
|
Twig/lib/Twig/Error/Syntax.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Exception thrown when a syntax error occurs during lexing or parsing of a template.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Error_Syntax extends Twig_Error
|
20 |
{
|
13 |
/**
|
14 |
* Exception thrown when a syntax error occurs during lexing or parsing of a template.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Error_Syntax extends Twig_Error
|
19 |
{
|
Twig/lib/Twig/ExistsLoaderInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Adds an exists() method for loaders.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Florin Patan <florinpatan@gmail.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_ExistsLoaderInterface
|
12 |
/**
|
13 |
* Adds an exists() method for loaders.
|
14 |
*
|
15 |
+
* @author Florin Patan <florinpatan@gmail.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_ExistsLoaderInterface
|
Twig/lib/Twig/ExpressionParser.php
CHANGED
@@ -18,8 +18,7 @@
|
|
18 |
* @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
|
19 |
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
20 |
*
|
21 |
-
* @
|
22 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
class Twig_ExpressionParser
|
25 |
{
|
@@ -366,7 +365,7 @@ class Twig_ExpressionParser
|
|
366 |
throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
|
367 |
}
|
368 |
|
369 |
-
if ($node instanceof Twig_Node_Expression_Name && null !== $
|
370 |
if (!$arg instanceof Twig_Node_Expression_Constant) {
|
371 |
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
372 |
}
|
18 |
* @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
|
19 |
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
20 |
*
|
21 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
22 |
*/
|
23 |
class Twig_ExpressionParser
|
24 |
{
|
365 |
throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
|
366 |
}
|
367 |
|
368 |
+
if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
369 |
if (!$arg instanceof Twig_Node_Expression_Constant) {
|
370 |
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
371 |
}
|
Twig/lib/Twig/Extension/Core.php
CHANGED
@@ -152,11 +152,14 @@ class Twig_Extension_Core extends Twig_Extension
|
|
152 |
new Twig_SimpleFilter('split', 'twig_split_filter'),
|
153 |
new Twig_SimpleFilter('sort', 'twig_sort_filter'),
|
154 |
new Twig_SimpleFilter('merge', 'twig_array_merge'),
|
|
|
155 |
|
156 |
// string/array filters
|
157 |
new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
|
158 |
new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
|
159 |
new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
|
|
|
|
|
160 |
|
161 |
// iteration and runtime
|
162 |
new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
|
@@ -168,8 +171,8 @@ class Twig_Extension_Core extends Twig_Extension
|
|
168 |
);
|
169 |
|
170 |
if (function_exists('mb_get_info')) {
|
171 |
-
$filters[
|
172 |
-
$filters[
|
173 |
}
|
174 |
|
175 |
return $filters;
|
@@ -188,7 +191,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|
188 |
new Twig_SimpleFunction('cycle', 'twig_cycle'),
|
189 |
new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
|
190 |
new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
|
191 |
-
new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true)),
|
192 |
);
|
193 |
}
|
194 |
|
@@ -467,13 +470,15 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
|
|
467 |
|
468 |
$asString = (string) $date;
|
469 |
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
470 |
-
$date =
|
471 |
-
|
472 |
|
473 |
-
|
|
|
|
|
474 |
}
|
475 |
|
476 |
-
return
|
477 |
}
|
478 |
|
479 |
/**
|
@@ -510,15 +515,19 @@ function twig_number_format_filter(Twig_Environment $env, $number, $decimal = nu
|
|
510 |
}
|
511 |
|
512 |
/**
|
513 |
-
* URL encodes a string.
|
514 |
*
|
515 |
-
* @param string $url A URL
|
516 |
-
* @param bool
|
517 |
*
|
518 |
* @return string The URL encoded value
|
519 |
*/
|
520 |
function twig_urlencode_filter($url, $raw = false)
|
521 |
{
|
|
|
|
|
|
|
|
|
522 |
if ($raw) {
|
523 |
return rawurlencode($url);
|
524 |
}
|
@@ -628,6 +637,36 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese
|
|
628 |
return null === $length ? substr($item, $start) : substr($item, $start, $length);
|
629 |
}
|
630 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
631 |
/**
|
632 |
* Joins the values to a string.
|
633 |
*
|
@@ -808,21 +847,62 @@ function twig_in_filter($value, $compare)
|
|
808 |
*/
|
809 |
function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
|
810 |
{
|
811 |
-
if ($autoescape &&
|
812 |
return $string;
|
813 |
}
|
814 |
|
815 |
-
if (!is_string($string)
|
816 |
-
|
|
|
|
|
|
|
|
|
817 |
}
|
818 |
|
819 |
if (null === $charset) {
|
820 |
$charset = $env->getCharset();
|
821 |
}
|
822 |
|
823 |
-
$string = (string) $string;
|
824 |
-
|
825 |
switch ($strategy) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
826 |
case 'js':
|
827 |
// escape all non-alphanumeric characters
|
828 |
// into their \xHH or \uHHHH representations
|
@@ -876,40 +956,10 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
876 |
|
877 |
return $string;
|
878 |
|
879 |
-
case 'html':
|
880 |
-
// see http://php.net/htmlspecialchars
|
881 |
-
|
882 |
-
// Using a static variable to avoid initializing the array
|
883 |
-
// each time the function is called. Moving the declaration on the
|
884 |
-
// top of the function slow downs other escaping strategies.
|
885 |
-
static $htmlspecialcharsCharsets = array(
|
886 |
-
'iso-8859-1' => true, 'iso8859-1' => true,
|
887 |
-
'iso-8859-15' => true, 'iso8859-15' => true,
|
888 |
-
'utf-8' => true,
|
889 |
-
'cp866' => true, 'ibm866' => true, '866' => true,
|
890 |
-
'cp1251' => true, 'windows-1251' => true, 'win-1251' => true,
|
891 |
-
'1251' => true,
|
892 |
-
'cp1252' => true, 'windows-1252' => true, '1252' => true,
|
893 |
-
'koi8-r' => true, 'koi8-ru' => true, 'koi8r' => true,
|
894 |
-
'big5' => true, '950' => true,
|
895 |
-
'gb2312' => true, '936' => true,
|
896 |
-
'big5-hkscs' => true,
|
897 |
-
'shift_jis' => true, 'sjis' => true, '932' => true,
|
898 |
-
'euc-jp' => true, 'eucjp' => true,
|
899 |
-
'iso8859-5' => true, 'iso-8859-5' => true, 'macroman' => true,
|
900 |
-
);
|
901 |
-
|
902 |
-
if (isset($htmlspecialcharsCharsets[strtolower($charset)])) {
|
903 |
-
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
|
904 |
-
}
|
905 |
-
|
906 |
-
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
907 |
-
$string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
908 |
-
|
909 |
-
return twig_convert_encoding($string, $charset, 'UTF-8');
|
910 |
-
|
911 |
case 'url':
|
912 |
-
|
|
|
|
|
913 |
return str_replace('%7E', '~', rawurlencode($string));
|
914 |
}
|
915 |
|
@@ -1223,11 +1273,11 @@ function twig_test_iterable($value)
|
|
1223 |
/**
|
1224 |
* Renders a template.
|
1225 |
*
|
1226 |
-
* @param string template The template to render
|
1227 |
-
* @param array variables The variables to pass to the template
|
1228 |
-
* @param Boolean with_context Whether to pass the current context variables or not
|
1229 |
-
* @param Boolean ignore_missing Whether to ignore missing templates or not
|
1230 |
-
* @param Boolean sandboxed Whether to sandbox the template or not
|
1231 |
*
|
1232 |
* @return string The rendered template
|
1233 |
*/
|
@@ -1245,7 +1295,7 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|
1245 |
}
|
1246 |
|
1247 |
try {
|
1248 |
-
return $env->resolveTemplate($template)->
|
1249 |
} catch (Twig_Error_Loader $e) {
|
1250 |
if (!$ignoreMissing) {
|
1251 |
throw $e;
|
@@ -1267,10 +1317,39 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|
1267 |
*/
|
1268 |
function twig_constant($constant, $object = null)
|
1269 |
{
|
1270 |
-
if (
|
1271 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1272 |
}
|
1273 |
-
$class = get_class($object);
|
1274 |
|
1275 |
-
return
|
1276 |
}
|
152 |
new Twig_SimpleFilter('split', 'twig_split_filter'),
|
153 |
new Twig_SimpleFilter('sort', 'twig_sort_filter'),
|
154 |
new Twig_SimpleFilter('merge', 'twig_array_merge'),
|
155 |
+
new Twig_SimpleFilter('batch', 'twig_array_batch'),
|
156 |
|
157 |
// string/array filters
|
158 |
new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
|
159 |
new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
|
160 |
new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
|
161 |
+
new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)),
|
162 |
+
new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)),
|
163 |
|
164 |
// iteration and runtime
|
165 |
new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
|
171 |
);
|
172 |
|
173 |
if (function_exists('mb_get_info')) {
|
174 |
+
$filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true));
|
175 |
+
$filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true));
|
176 |
}
|
177 |
|
178 |
return $filters;
|
191 |
new Twig_SimpleFunction('cycle', 'twig_cycle'),
|
192 |
new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
|
193 |
new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
|
194 |
+
new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))),
|
195 |
);
|
196 |
}
|
197 |
|
470 |
|
471 |
$asString = (string) $date;
|
472 |
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
473 |
+
$date = '@'.$date;
|
474 |
+
}
|
475 |
|
476 |
+
$date = new DateTime($date, $defaultTimezone);
|
477 |
+
if (false !== $timezone) {
|
478 |
+
$date->setTimezone($defaultTimezone);
|
479 |
}
|
480 |
|
481 |
+
return $date;
|
482 |
}
|
483 |
|
484 |
/**
|
515 |
}
|
516 |
|
517 |
/**
|
518 |
+
* URL encodes a string as a path segment or an array as a query string.
|
519 |
*
|
520 |
+
* @param string|array $url A URL or an array of query parameters
|
521 |
+
* @param bool $raw true to use rawurlencode() instead of urlencode
|
522 |
*
|
523 |
* @return string The URL encoded value
|
524 |
*/
|
525 |
function twig_urlencode_filter($url, $raw = false)
|
526 |
{
|
527 |
+
if (is_array($url)) {
|
528 |
+
return http_build_query($url, '', '&');
|
529 |
+
}
|
530 |
+
|
531 |
if ($raw) {
|
532 |
return rawurlencode($url);
|
533 |
}
|
637 |
return null === $length ? substr($item, $start) : substr($item, $start, $length);
|
638 |
}
|
639 |
|
640 |
+
/**
|
641 |
+
* Returns the first element of the item.
|
642 |
+
*
|
643 |
+
* @param Twig_Environment $env A Twig_Environment instance
|
644 |
+
* @param mixed $item A variable
|
645 |
+
*
|
646 |
+
* @return mixed The first element of the item
|
647 |
+
*/
|
648 |
+
function twig_first(Twig_Environment $env, $item)
|
649 |
+
{
|
650 |
+
$elements = twig_slice($env, $item, 0, 1, false);
|
651 |
+
|
652 |
+
return is_string($elements) ? $elements[0] : current($elements);
|
653 |
+
}
|
654 |
+
|
655 |
+
/**
|
656 |
+
* Returns the last element of the item.
|
657 |
+
*
|
658 |
+
* @param Twig_Environment $env A Twig_Environment instance
|
659 |
+
* @param mixed $item A variable
|
660 |
+
*
|
661 |
+
* @return mixed The last element of the item
|
662 |
+
*/
|
663 |
+
function twig_last(Twig_Environment $env, $item)
|
664 |
+
{
|
665 |
+
$elements = twig_slice($env, $item, -1, 1, false);
|
666 |
+
|
667 |
+
return is_string($elements) ? $elements[0] : current($elements);
|
668 |
+
}
|
669 |
+
|
670 |
/**
|
671 |
* Joins the values to a string.
|
672 |
*
|
847 |
*/
|
848 |
function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
|
849 |
{
|
850 |
+
if ($autoescape && $string instanceof Twig_Markup) {
|
851 |
return $string;
|
852 |
}
|
853 |
|
854 |
+
if (!is_string($string)) {
|
855 |
+
if (is_object($string) && method_exists($string, '__toString')) {
|
856 |
+
$string = (string) $string;
|
857 |
+
} else {
|
858 |
+
return $string;
|
859 |
+
}
|
860 |
}
|
861 |
|
862 |
if (null === $charset) {
|
863 |
$charset = $env->getCharset();
|
864 |
}
|
865 |
|
|
|
|
|
866 |
switch ($strategy) {
|
867 |
+
case 'html':
|
868 |
+
// see http://php.net/htmlspecialchars
|
869 |
+
|
870 |
+
// Using a static variable to avoid initializing the array
|
871 |
+
// each time the function is called. Moving the declaration on the
|
872 |
+
// top of the function slow downs other escaping strategies.
|
873 |
+
static $htmlspecialcharsCharsets = array(
|
874 |
+
'ISO-8859-1' => true, 'ISO8859-1' => true,
|
875 |
+
'ISO-8859-15' => true, 'ISO8859-15' => true,
|
876 |
+
'utf-8' => true, 'UTF-8' => true,
|
877 |
+
'CP866' => true, 'IBM866' => true, '866' => true,
|
878 |
+
'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
|
879 |
+
'1251' => true,
|
880 |
+
'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
|
881 |
+
'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
|
882 |
+
'BIG5' => true, '950' => true,
|
883 |
+
'GB2312' => true, '936' => true,
|
884 |
+
'BIG5-HKSCS' => true,
|
885 |
+
'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
|
886 |
+
'EUC-JP' => true, 'EUCJP' => true,
|
887 |
+
'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
|
888 |
+
);
|
889 |
+
|
890 |
+
if (isset($htmlspecialcharsCharsets[$charset])) {
|
891 |
+
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
|
892 |
+
}
|
893 |
+
|
894 |
+
if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
|
895 |
+
// cache the lowercase variant for future iterations
|
896 |
+
$htmlspecialcharsCharsets[$charset] = true;
|
897 |
+
|
898 |
+
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
|
899 |
+
}
|
900 |
+
|
901 |
+
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
902 |
+
$string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
903 |
+
|
904 |
+
return twig_convert_encoding($string, $charset, 'UTF-8');
|
905 |
+
|
906 |
case 'js':
|
907 |
// escape all non-alphanumeric characters
|
908 |
// into their \xHH or \uHHHH representations
|
956 |
|
957 |
return $string;
|
958 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
959 |
case 'url':
|
960 |
+
// hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.*
|
961 |
+
// at that point however PHP 5.2.* support can be removed
|
962 |
+
if (PHP_VERSION < '5.3.0') {
|
963 |
return str_replace('%7E', '~', rawurlencode($string));
|
964 |
}
|
965 |
|
1273 |
/**
|
1274 |
* Renders a template.
|
1275 |
*
|
1276 |
+
* @param string $template The template to render
|
1277 |
+
* @param array $variables The variables to pass to the template
|
1278 |
+
* @param Boolean $with_context Whether to pass the current context variables or not
|
1279 |
+
* @param Boolean $ignore_missing Whether to ignore missing templates or not
|
1280 |
+
* @param Boolean $sandboxed Whether to sandbox the template or not
|
1281 |
*
|
1282 |
* @return string The rendered template
|
1283 |
*/
|
1295 |
}
|
1296 |
|
1297 |
try {
|
1298 |
+
return $env->resolveTemplate($template)->render($variables);
|
1299 |
} catch (Twig_Error_Loader $e) {
|
1300 |
if (!$ignoreMissing) {
|
1301 |
throw $e;
|
1317 |
*/
|
1318 |
function twig_constant($constant, $object = null)
|
1319 |
{
|
1320 |
+
if (null !== $object) {
|
1321 |
+
$constant = get_class($object).'::'.$constant;
|
1322 |
+
}
|
1323 |
+
|
1324 |
+
return constant($constant);
|
1325 |
+
}
|
1326 |
+
|
1327 |
+
/**
|
1328 |
+
* Batches item.
|
1329 |
+
*
|
1330 |
+
* @param array $items An array of items
|
1331 |
+
* @param integer $size The size of the batch
|
1332 |
+
* @param string $fill A string to fill missing items
|
1333 |
+
*
|
1334 |
+
* @return array
|
1335 |
+
*/
|
1336 |
+
function twig_array_batch($items, $size, $fill = null)
|
1337 |
+
{
|
1338 |
+
if ($items instanceof Traversable) {
|
1339 |
+
$items = iterator_to_array($items, false);
|
1340 |
+
}
|
1341 |
+
|
1342 |
+
$size = ceil($size);
|
1343 |
+
|
1344 |
+
$result = array_chunk($items, $size, true);
|
1345 |
+
|
1346 |
+
if (null !== $fill) {
|
1347 |
+
$last = count($result) - 1;
|
1348 |
+
$result[$last] = array_merge(
|
1349 |
+
$result[$last],
|
1350 |
+
array_fill(0, $size - count($result[$last]), $fill)
|
1351 |
+
);
|
1352 |
}
|
|
|
1353 |
|
1354 |
+
return $result;
|
1355 |
}
|
Twig/lib/Twig/Extension/Debug.php
CHANGED
@@ -24,6 +24,7 @@ class Twig_Extension_Debug extends Twig_Extension
|
|
24 |
// false means that it was not set (and the default is on) or it explicitly enabled
|
25 |
// xdebug.overload_var_dump produces HTML only when html_errors is also enabled
|
26 |
&& (false === ini_get('html_errors') || ini_get('html_errors'))
|
|
|
27 |
;
|
28 |
|
29 |
return array(
|
24 |
// false means that it was not set (and the default is on) or it explicitly enabled
|
25 |
// xdebug.overload_var_dump produces HTML only when html_errors is also enabled
|
26 |
&& (false === ini_get('html_errors') || ini_get('html_errors'))
|
27 |
+
|| 'cli' === php_sapi_name()
|
28 |
;
|
29 |
|
30 |
return array(
|
Twig/lib/Twig/Extension/Staging.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* This class is used by Twig_Environment as a staging area and must not be used directly.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
class Twig_Extension_Staging extends Twig_Extension
|
21 |
{
|
14 |
*
|
15 |
* This class is used by Twig_Environment as a staging area and must not be used directly.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
*/
|
19 |
class Twig_Extension_Staging extends Twig_Extension
|
20 |
{
|
Twig/lib/Twig/Extension/StringLoader.php
CHANGED
@@ -33,7 +33,7 @@ class Twig_Extension_StringLoader extends Twig_Extension
|
|
33 |
* Loads a template from a string.
|
34 |
*
|
35 |
* <pre>
|
36 |
-
* {
|
37 |
* </pre>
|
38 |
*
|
39 |
* @param Twig_Environment $env A Twig_Environment instance
|
33 |
* Loads a template from a string.
|
34 |
*
|
35 |
* <pre>
|
36 |
+
* {{ include(template_from_string("Hello {{ name }}")) }}
|
37 |
* </pre>
|
38 |
*
|
39 |
* @param Twig_Environment $env A Twig_Environment instance
|
Twig/lib/Twig/ExtensionInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface implemented by extension classes.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
interface Twig_ExtensionInterface
|
19 |
{
|
12 |
/**
|
13 |
* Interface implemented by extension classes.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
interface Twig_ExtensionInterface
|
18 |
{
|
Twig/lib/Twig/Filter.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
@@ -63,8 +62,6 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI
|
|
63 |
if (isset($this->options['is_safe_callback'])) {
|
64 |
return call_user_func($this->options['is_safe_callback'], $filterArgs);
|
65 |
}
|
66 |
-
|
67 |
-
return null;
|
68 |
}
|
69 |
|
70 |
public function getPreservesSafety()
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
62 |
if (isset($this->options['is_safe_callback'])) {
|
63 |
return call_user_func($this->options['is_safe_callback'], $filterArgs);
|
64 |
}
|
|
|
|
|
65 |
}
|
66 |
|
67 |
public function getPreservesSafety()
|
Twig/lib/Twig/Filter/Function.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Filter_Function extends Twig_Filter
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Filter_Function extends Twig_Filter
|
Twig/lib/Twig/Filter/Method.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Filter_Method extends Twig_Filter
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Filter_Method extends Twig_Filter
|
Twig/lib/Twig/Filter/Node.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Filter_Node extends Twig_Filter
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Filter_Node extends Twig_Filter
|
Twig/lib/Twig/FilterCallableInterface.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FilterCallableInterface
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
interface Twig_FilterCallableInterface
|
Twig/lib/Twig/FilterInterface.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FilterInterface
|
14 |
*
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
interface Twig_FilterInterface
|
Twig/lib/Twig/Function.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
14 |
*
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
Twig/lib/Twig/Function/Function.php
CHANGED
@@ -15,8 +15,7 @@
|
|
15 |
*
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
-
* @
|
19 |
-
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
class Twig_Function_Function extends Twig_Function
|
15 |
*
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
+
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Function_Function extends Twig_Function
|
Twig/lib/Twig/Function/Method.php
CHANGED
@@ -15,8 +15,7 @@
|
|
15 |
*
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
-
* @
|
19 |
-
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
class Twig_Function_Method extends Twig_Function
|
15 |
*
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
+
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Function_Method extends Twig_Function
|
Twig/lib/Twig/Function/Node.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Function_Node extends Twig_Function
|
14 |
*
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Function_Node extends Twig_Function
|
Twig/lib/Twig/FunctionCallableInterface.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FunctionCallableInterface
|
14 |
*
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
interface Twig_FunctionCallableInterface
|
Twig/lib/Twig/FunctionInterface.php
CHANGED
@@ -15,8 +15,7 @@
|
|
15 |
*
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
-
* @
|
19 |
-
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
interface Twig_FunctionInterface
|
15 |
*
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
+
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FunctionInterface
|
Twig/lib/Twig/Lexer.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Lexes a template string.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Lexer implements Twig_LexerInterface
|
20 |
{
|
@@ -32,6 +31,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
32 |
protected $regexes;
|
33 |
protected $position;
|
34 |
protected $positions;
|
|
|
35 |
|
36 |
const STATE_DATA = 0;
|
37 |
const STATE_BLOCK = 1;
|
@@ -186,12 +186,14 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
186 |
} else {
|
187 |
$this->pushToken(Twig_Token::BLOCK_START_TYPE);
|
188 |
$this->pushState(self::STATE_BLOCK);
|
|
|
189 |
}
|
190 |
break;
|
191 |
|
192 |
case $this->options['tag_variable'][0]:
|
193 |
$this->pushToken(Twig_Token::VAR_START_TYPE);
|
194 |
$this->pushState(self::STATE_VAR);
|
|
|
195 |
break;
|
196 |
}
|
197 |
}
|
@@ -225,7 +227,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
225 |
$this->moveCursor($match[0]);
|
226 |
|
227 |
if ($this->cursor >= $this->end) {
|
228 |
-
throw new Twig_Error_Syntax(sprintf('
|
229 |
}
|
230 |
}
|
231 |
|
13 |
/**
|
14 |
* Lexes a template string.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Lexer implements Twig_LexerInterface
|
19 |
{
|
31 |
protected $regexes;
|
32 |
protected $position;
|
33 |
protected $positions;
|
34 |
+
protected $currentVarBlockLine;
|
35 |
|
36 |
const STATE_DATA = 0;
|
37 |
const STATE_BLOCK = 1;
|
186 |
} else {
|
187 |
$this->pushToken(Twig_Token::BLOCK_START_TYPE);
|
188 |
$this->pushState(self::STATE_BLOCK);
|
189 |
+
$this->currentVarBlockLine = $this->lineno;
|
190 |
}
|
191 |
break;
|
192 |
|
193 |
case $this->options['tag_variable'][0]:
|
194 |
$this->pushToken(Twig_Token::VAR_START_TYPE);
|
195 |
$this->pushState(self::STATE_VAR);
|
196 |
+
$this->currentVarBlockLine = $this->lineno;
|
197 |
break;
|
198 |
}
|
199 |
}
|
227 |
$this->moveCursor($match[0]);
|
228 |
|
229 |
if ($this->cursor >= $this->end) {
|
230 |
+
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->filename);
|
231 |
}
|
232 |
}
|
233 |
|
Twig/lib/Twig/LexerInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface implemented by lexer classes.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_LexerInterface
|
12 |
/**
|
13 |
* Interface implemented by lexer classes.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_LexerInterface
|
Twig/lib/Twig/Loader/Array.php
CHANGED
@@ -17,8 +17,7 @@
|
|
17 |
* source code of the template). If you don't want to see your cache grows out of
|
18 |
* control, you need to take care of clearing the old cache file by yourself.
|
19 |
*
|
20 |
-
* @
|
21 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
24 |
{
|
17 |
* source code of the template). If you don't want to see your cache grows out of
|
18 |
* control, you need to take care of clearing the old cache file by yourself.
|
19 |
*
|
20 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
21 |
*/
|
22 |
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
23 |
{
|
Twig/lib/Twig/Loader/Chain.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Loads templates from other loaders.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
19 |
{
|
@@ -77,8 +76,12 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
77 |
}
|
78 |
|
79 |
foreach ($this->loaders as $loader) {
|
80 |
-
if ($loader instanceof Twig_ExistsLoaderInterface
|
81 |
-
|
|
|
|
|
|
|
|
|
82 |
}
|
83 |
|
84 |
try {
|
12 |
/**
|
13 |
* Loads templates from other loaders.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
18 |
{
|
76 |
}
|
77 |
|
78 |
foreach ($this->loaders as $loader) {
|
79 |
+
if ($loader instanceof Twig_ExistsLoaderInterface) {
|
80 |
+
if ($loader->exists($name)) {
|
81 |
+
return $this->hasSourceCache[$name] = true;
|
82 |
+
}
|
83 |
+
|
84 |
+
continue;
|
85 |
}
|
86 |
|
87 |
try {
|
Twig/lib/Twig/Loader/Filesystem.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Loads template from the filesystem.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
19 |
{
|
@@ -25,9 +24,11 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
25 |
*
|
26 |
* @param string|array $paths A path or an array of paths where to look for templates
|
27 |
*/
|
28 |
-
public function __construct($paths)
|
29 |
{
|
30 |
-
|
|
|
|
|
31 |
}
|
32 |
|
33 |
/**
|
@@ -204,6 +205,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
204 |
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
|
205 |
}
|
206 |
|
|
|
207 |
$parts = explode('/', $name);
|
208 |
$level = 0;
|
209 |
foreach ($parts as $part) {
|
12 |
/**
|
13 |
* Loads template from the filesystem.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
18 |
{
|
24 |
*
|
25 |
* @param string|array $paths A path or an array of paths where to look for templates
|
26 |
*/
|
27 |
+
public function __construct($paths = array())
|
28 |
{
|
29 |
+
if ($paths) {
|
30 |
+
$this->setPaths($paths);
|
31 |
+
}
|
32 |
}
|
33 |
|
34 |
/**
|
205 |
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
|
206 |
}
|
207 |
|
208 |
+
$name = ltrim($name, '/');
|
209 |
$parts = explode('/', $name);
|
210 |
$level = 0;
|
211 |
foreach ($parts as $part) {
|
Twig/lib/Twig/Loader/String.php
CHANGED
@@ -21,8 +21,7 @@
|
|
21 |
* source code of the template). If you don't want to see your cache grows out of
|
22 |
* control, you need to take care of clearing the old cache file by yourself.
|
23 |
*
|
24 |
-
* @
|
25 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
26 |
*/
|
27 |
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
28 |
{
|
21 |
* source code of the template). If you don't want to see your cache grows out of
|
22 |
* control, you need to take care of clearing the old cache file by yourself.
|
23 |
*
|
24 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
25 |
*/
|
26 |
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
27 |
{
|
Twig/lib/Twig/LoaderInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface all loaders must implement.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
interface Twig_LoaderInterface
|
19 |
{
|
12 |
/**
|
13 |
* Interface all loaders must implement.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
interface Twig_LoaderInterface
|
18 |
{
|
Twig/lib/Twig/Markup.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Marks a content as safe.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Markup implements Countable
|
19 |
{
|
12 |
/**
|
13 |
* Marks a content as safe.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Markup implements Countable
|
18 |
{
|
Twig/lib/Twig/Node.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a node in the AST.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node implements Twig_NodeInterface
|
20 |
{
|
13 |
/**
|
14 |
* Represents a node in the AST.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node implements Twig_NodeInterface
|
19 |
{
|
Twig/lib/Twig/Node/AutoEscape.php
CHANGED
@@ -18,8 +18,7 @@
|
|
18 |
*
|
19 |
* If autoescaping is disabled, then the value is false.
|
20 |
*
|
21 |
-
* @
|
22 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
class Twig_Node_AutoEscape extends Twig_Node
|
25 |
{
|
18 |
*
|
19 |
* If autoescaping is disabled, then the value is false.
|
20 |
*
|
21 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
22 |
*/
|
23 |
class Twig_Node_AutoEscape extends Twig_Node
|
24 |
{
|
Twig/lib/Twig/Node/Block.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a block node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Block extends Twig_Node
|
20 |
{
|
13 |
/**
|
14 |
* Represents a block node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Block extends Twig_Node
|
19 |
{
|
Twig/lib/Twig/Node/BlockReference.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a block call node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
|
20 |
{
|
13 |
/**
|
14 |
* Represents a block call node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
|
19 |
{
|
Twig/lib/Twig/Node/Body.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a body node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Body extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents a body node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Body extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/Do.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a do node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Do extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents a do node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Do extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/Embed.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents an embed node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Embed extends Twig_Node_Include
|
19 |
{
|
12 |
/**
|
13 |
* Represents an embed node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Embed extends Twig_Node_Include
|
18 |
{
|
Twig/lib/Twig/Node/Expression.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Abstract class for all nodes that represents an expression.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
abstract class Twig_Node_Expression extends Twig_Node
|
20 |
{
|
13 |
/**
|
14 |
* Abstract class for all nodes that represents an expression.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
abstract class Twig_Node_Expression extends Twig_Node
|
19 |
{
|
Twig/lib/Twig/Node/Expression/BlockReference.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a block call node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
20 |
{
|
13 |
/**
|
14 |
* Represents a block call node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
19 |
{
|
Twig/lib/Twig/Node/Expression/Call.php
CHANGED
@@ -98,7 +98,10 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
98 |
if (!is_int($name)) {
|
99 |
$named = true;
|
100 |
$name = $this->normalizeName($name);
|
|
|
|
|
101 |
}
|
|
|
102 |
$parameters[$name] = $node;
|
103 |
}
|
104 |
|
@@ -142,6 +145,10 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
142 |
$name = $this->normalizeName($param->name);
|
143 |
|
144 |
if (array_key_exists($name, $parameters)) {
|
|
|
|
|
|
|
|
|
145 |
$arguments[] = $parameters[$name];
|
146 |
unset($parameters[$name]);
|
147 |
} elseif (array_key_exists($pos, $parameters)) {
|
98 |
if (!is_int($name)) {
|
99 |
$named = true;
|
100 |
$name = $this->normalizeName($name);
|
101 |
+
} elseif ($named) {
|
102 |
+
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
|
103 |
}
|
104 |
+
|
105 |
$parameters[$name] = $node;
|
106 |
}
|
107 |
|
145 |
$name = $this->normalizeName($param->name);
|
146 |
|
147 |
if (array_key_exists($name, $parameters)) {
|
148 |
+
if (array_key_exists($pos, $parameters)) {
|
149 |
+
throw new Twig_Error_Syntax(sprintf('Arguments "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
150 |
+
}
|
151 |
+
|
152 |
$arguments[] = $parameters[$name];
|
153 |
unset($parameters[$name]);
|
154 |
} elseif (array_key_exists($pos, $parameters)) {
|
Twig/lib/Twig/Node/Expression/ExtensionReference.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents an extension call node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
19 |
{
|
12 |
/**
|
13 |
* Represents an extension call node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
18 |
{
|
Twig/lib/Twig/Node/Expression/Filter/Default.php
CHANGED
@@ -16,8 +16,7 @@
|
|
16 |
* {{ var.foo|default('foo item on var is not defined') }}
|
17 |
* </pre>
|
18 |
*
|
19 |
-
* @
|
20 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
|
23 |
{
|
16 |
* {{ var.foo|default('foo item on var is not defined') }}
|
17 |
* </pre>
|
18 |
*
|
19 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
20 |
*/
|
21 |
class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
|
22 |
{
|
Twig/lib/Twig/Node/Expression/Parent.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a parent node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Expression_Parent extends Twig_Node_Expression
|
20 |
{
|
13 |
/**
|
14 |
* Represents a parent node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Expression_Parent extends Twig_Node_Expression
|
19 |
{
|
Twig/lib/Twig/Node/Expression/Test/Constant.php
CHANGED
@@ -18,8 +18,7 @@
|
|
18 |
* {% endif %}
|
19 |
* </pre>
|
20 |
*
|
21 |
-
* @
|
22 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
|
25 |
{
|
@@ -29,6 +28,17 @@ class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
|
|
29 |
->raw('(')
|
30 |
->subcompile($this->getNode('node'))
|
31 |
->raw(' === constant(')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
->subcompile($this->getNode('arguments')->getNode(0))
|
33 |
->raw('))')
|
34 |
;
|
18 |
* {% endif %}
|
19 |
* </pre>
|
20 |
*
|
21 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
22 |
*/
|
23 |
class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
|
24 |
{
|
28 |
->raw('(')
|
29 |
->subcompile($this->getNode('node'))
|
30 |
->raw(' === constant(')
|
31 |
+
;
|
32 |
+
|
33 |
+
if ($this->getNode('arguments')->hasNode(1)) {
|
34 |
+
$compiler
|
35 |
+
->raw('get_class(')
|
36 |
+
->subcompile($this->getNode('arguments')->getNode(1))
|
37 |
+
->raw(')."::".')
|
38 |
+
;
|
39 |
+
}
|
40 |
+
|
41 |
+
$compiler
|
42 |
->subcompile($this->getNode('arguments')->getNode(0))
|
43 |
->raw('))')
|
44 |
;
|
Twig/lib/Twig/Node/Expression/Test/Defined.php
CHANGED
@@ -19,8 +19,7 @@
|
|
19 |
* {% endif %}
|
20 |
* </pre>
|
21 |
*
|
22 |
-
* @
|
23 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
24 |
*/
|
25 |
class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
26 |
{
|
@@ -35,7 +34,7 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
|
35 |
|
36 |
$this->changeIgnoreStrictCheck($node);
|
37 |
} else {
|
38 |
-
throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine()
|
39 |
}
|
40 |
}
|
41 |
|
19 |
* {% endif %}
|
20 |
* </pre>
|
21 |
*
|
22 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
23 |
*/
|
24 |
class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
25 |
{
|
34 |
|
35 |
$this->changeIgnoreStrictCheck($node);
|
36 |
} else {
|
37 |
+
throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
|
38 |
}
|
39 |
}
|
40 |
|
Twig/lib/Twig/Node/Expression/Test/Divisibleby.php
CHANGED
@@ -16,8 +16,7 @@
|
|
16 |
* {% if loop.index is divisibleby(3) %}
|
17 |
* </pre>
|
18 |
*
|
19 |
-
* @
|
20 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
|
23 |
{
|
16 |
* {% if loop.index is divisibleby(3) %}
|
17 |
* </pre>
|
18 |
*
|
19 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
20 |
*/
|
21 |
class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
|
22 |
{
|
Twig/lib/Twig/Node/Expression/Test/Even.php
CHANGED
@@ -16,8 +16,7 @@
|
|
16 |
* {{ var is even }}
|
17 |
* </pre>
|
18 |
*
|
19 |
-
* @
|
20 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
|
23 |
{
|
16 |
* {{ var is even }}
|
17 |
* </pre>
|
18 |
*
|
19 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
20 |
*/
|
21 |
class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
|
22 |
{
|
Twig/lib/Twig/Node/Expression/Test/Null.php
CHANGED
@@ -16,8 +16,7 @@
|
|
16 |
* {{ var is none }}
|
17 |
* </pre>
|
18 |
*
|
19 |
-
* @
|
20 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
|
23 |
{
|
16 |
* {{ var is none }}
|
17 |
* </pre>
|
18 |
*
|
19 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
20 |
*/
|
21 |
class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
|
22 |
{
|
Twig/lib/Twig/Node/Expression/Test/Odd.php
CHANGED
@@ -16,8 +16,7 @@
|
|
16 |
* {{ var is odd }}
|
17 |
* </pre>
|
18 |
*
|
19 |
-
* @
|
20 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
|
23 |
{
|
16 |
* {{ var is odd }}
|
17 |
* </pre>
|
18 |
*
|
19 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
20 |
*/
|
21 |
class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
|
22 |
{
|
Twig/lib/Twig/Node/Expression/Test/Sameas.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Checks if a variable is the same as another one (=== in PHP).
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
|
19 |
{
|
12 |
/**
|
13 |
* Checks if a variable is the same as another one (=== in PHP).
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
|
18 |
{
|
Twig/lib/Twig/Node/Flush.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a flush node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Flush extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents a flush node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Flush extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/For.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a for node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_For extends Twig_Node
|
20 |
{
|
@@ -108,6 +107,6 @@ class Twig_Node_For extends Twig_Node
|
|
108 |
$compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
|
109 |
|
110 |
// keep the values set in the inner context for variables defined in the outer context
|
111 |
-
$compiler->write("\$context =
|
112 |
}
|
113 |
}
|
13 |
/**
|
14 |
* Represents a for node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_For extends Twig_Node
|
19 |
{
|
107 |
$compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
|
108 |
|
109 |
// keep the values set in the inner context for variables defined in the outer context
|
110 |
+
$compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
|
111 |
}
|
112 |
}
|
Twig/lib/Twig/Node/ForLoop.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Internal node used by the for node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_ForLoop extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Internal node used by the for node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_ForLoop extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/If.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents an if node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_If extends Twig_Node
|
20 |
{
|
13 |
/**
|
14 |
* Represents an if node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_If extends Twig_Node
|
19 |
{
|
Twig/lib/Twig/Node/Import.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents an import node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Import extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents an import node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Import extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/Include.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents an include node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
20 |
{
|
13 |
/**
|
14 |
* Represents an include node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
19 |
{
|
Twig/lib/Twig/Node/Macro.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a macro node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Macro extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents a macro node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Macro extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/Module.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a module node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Module extends Twig_Node
|
20 |
{
|
13 |
/**
|
14 |
* Represents a module node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Module extends Twig_Node
|
19 |
{
|
Twig/lib/Twig/Node/Print.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a node that outputs an expression.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
|
20 |
{
|
13 |
/**
|
14 |
* Represents a node that outputs an expression.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
|
19 |
{
|
Twig/lib/Twig/Node/Sandbox.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a sandbox node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Sandbox extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents a sandbox node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Sandbox extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/SandboxedModule.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a module node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_SandboxedModule extends Twig_Node_Module
|
20 |
{
|
13 |
/**
|
14 |
* Represents a module node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_SandboxedModule extends Twig_Node_Module
|
19 |
{
|
Twig/lib/Twig/Node/SandboxedPrint.php
CHANGED
@@ -17,8 +17,7 @@
|
|
17 |
* and if the sandbox is enabled, we need to check that the __toString()
|
18 |
* method is allowed if 'article' is an object.
|
19 |
*
|
20 |
-
* @
|
21 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
24 |
{
|
17 |
* and if the sandbox is enabled, we need to check that the __toString()
|
18 |
* method is allowed if 'article' is an object.
|
19 |
*
|
20 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
21 |
*/
|
22 |
class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
23 |
{
|
Twig/lib/Twig/Node/Set.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a set node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Node_Set extends Twig_Node
|
19 |
{
|
12 |
/**
|
13 |
* Represents a set node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Node_Set extends Twig_Node
|
18 |
{
|
Twig/lib/Twig/Node/Spaceless.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* It removes spaces between HTML tags.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
class Twig_Node_Spaceless extends Twig_Node
|
21 |
{
|
14 |
*
|
15 |
* It removes spaces between HTML tags.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
*/
|
19 |
class Twig_Node_Spaceless extends Twig_Node
|
20 |
{
|
Twig/lib/Twig/Node/Text.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a text node.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
|
20 |
{
|
13 |
/**
|
14 |
* Represents a text node.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
|
19 |
{
|
Twig/lib/Twig/NodeInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a node in the AST.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_NodeInterface extends Countable, IteratorAggregate
|
12 |
/**
|
13 |
* Represents a node in the AST.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_NodeInterface extends Countable, IteratorAggregate
|
Twig/lib/Twig/NodeOutputInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a displayable node in the AST.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
interface Twig_NodeOutputInterface
|
19 |
{
|
12 |
/**
|
13 |
* Represents a displayable node in the AST.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
interface Twig_NodeOutputInterface
|
18 |
{
|
Twig/lib/Twig/NodeTraverser.php
CHANGED
@@ -14,8 +14,7 @@
|
|
14 |
*
|
15 |
* It visits all nodes and their children and call the given visitor for each.
|
16 |
*
|
17 |
-
* @
|
18 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
class Twig_NodeTraverser
|
21 |
{
|
14 |
*
|
15 |
* It visits all nodes and their children and call the given visitor for each.
|
16 |
*
|
17 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
*/
|
19 |
class Twig_NodeTraverser
|
20 |
{
|
Twig/lib/Twig/NodeVisitor/Escaper.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Escaper implements output escaping.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
19 |
{
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Escaper implements output escaping.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
18 |
{
|
Twig/lib/Twig/NodeVisitor/Optimizer.php
CHANGED
@@ -17,8 +17,7 @@
|
|
17 |
* You can configure which optimizations you want to activate via the
|
18 |
* optimizer mode.
|
19 |
*
|
20 |
-
* @
|
21 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
24 |
{
|
17 |
* You can configure which optimizations you want to activate via the
|
18 |
* optimizer mode.
|
19 |
*
|
20 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
21 |
*/
|
22 |
class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
23 |
{
|
Twig/lib/Twig/NodeVisitor/SafeAnalysis.php
CHANGED
@@ -20,8 +20,6 @@ class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
|
|
20 |
}
|
21 |
}
|
22 |
}
|
23 |
-
|
24 |
-
return null;
|
25 |
}
|
26 |
|
27 |
protected function setSafe(Twig_NodeInterface $node, array $safe)
|
20 |
}
|
21 |
}
|
22 |
}
|
|
|
|
|
23 |
}
|
24 |
|
25 |
protected function setSafe(Twig_NodeInterface $node, array $safe)
|
Twig/lib/Twig/NodeVisitor/Sandbox.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Sandbox implements sandboxing.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
19 |
{
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Sandbox implements sandboxing.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
18 |
{
|
Twig/lib/Twig/NodeVisitorInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
interface Twig_NodeVisitorInterface
|
19 |
{
|
@@ -33,7 +32,7 @@ interface Twig_NodeVisitorInterface
|
|
33 |
* @param Twig_NodeInterface $node The node to visit
|
34 |
* @param Twig_Environment $env The Twig environment instance
|
35 |
*
|
36 |
-
* @return Twig_NodeInterface The modified node
|
37 |
*/
|
38 |
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
|
39 |
|
12 |
/**
|
13 |
* Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
interface Twig_NodeVisitorInterface
|
18 |
{
|
32 |
* @param Twig_NodeInterface $node The node to visit
|
33 |
* @param Twig_Environment $env The Twig environment instance
|
34 |
*
|
35 |
+
* @return Twig_NodeInterface|false The modified node or false if the node must be removed
|
36 |
*/
|
37 |
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
|
38 |
|
Twig/lib/Twig/Parser.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Default parser implementation.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Parser implements Twig_ParserInterface
|
20 |
{
|
13 |
/**
|
14 |
* Default parser implementation.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Parser implements Twig_ParserInterface
|
19 |
{
|
Twig/lib/Twig/ParserInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface implemented by parser classes.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_ParserInterface
|
12 |
/**
|
13 |
* Interface implemented by parser classes.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_ParserInterface
|
Twig/lib/Twig/Sandbox/SecurityError.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Exception thrown when a security error occurs at runtime.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Sandbox_SecurityError extends Twig_Error
|
19 |
{
|
12 |
/**
|
13 |
* Exception thrown when a security error occurs at runtime.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Sandbox_SecurityError extends Twig_Error
|
18 |
{
|
Twig/lib/Twig/Sandbox/SecurityPolicy.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a security policy which need to be enforced when sandbox mode is enabled.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface
|
19 |
{
|
12 |
/**
|
13 |
* Represents a security policy which need to be enforced when sandbox mode is enabled.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface
|
18 |
{
|
Twig/lib/Twig/Sandbox/SecurityPolicyInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interfaces that all security policy classes must implements.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
interface Twig_Sandbox_SecurityPolicyInterface
|
19 |
{
|
12 |
/**
|
13 |
* Interfaces that all security policy classes must implements.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
interface Twig_Sandbox_SecurityPolicyInterface
|
18 |
{
|
Twig/lib/Twig/SimpleFilter.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a template filter.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_SimpleFilter
|
19 |
{
|
@@ -81,8 +80,6 @@ class Twig_SimpleFilter
|
|
81 |
if (null !== $this->options['is_safe_callback']) {
|
82 |
return call_user_func($this->options['is_safe_callback'], $filterArgs);
|
83 |
}
|
84 |
-
|
85 |
-
return null;
|
86 |
}
|
87 |
|
88 |
public function getPreservesSafety()
|
12 |
/**
|
13 |
* Represents a template filter.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_SimpleFilter
|
18 |
{
|
80 |
if (null !== $this->options['is_safe_callback']) {
|
81 |
return call_user_func($this->options['is_safe_callback'], $filterArgs);
|
82 |
}
|
|
|
|
|
83 |
}
|
84 |
|
85 |
public function getPreservesSafety()
|
Twig/lib/Twig/SimpleFunction.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a template function.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_SimpleFunction
|
19 |
{
|
12 |
/**
|
13 |
* Represents a template function.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_SimpleFunction
|
18 |
{
|
Twig/lib/Twig/SimpleTest.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
class Twig_SimpleTest
|
19 |
{
|
12 |
/**
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
class Twig_SimpleTest
|
18 |
{
|
Twig/lib/Twig/Template.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Default base class for compiled templates.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
abstract class Twig_Template implements Twig_TemplateInterface
|
20 |
{
|
@@ -337,21 +336,21 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
337 |
*/
|
338 |
protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
339 |
{
|
340 |
-
$item = ctype_digit((string) $item) ? (int) $item : (string) $item;
|
341 |
-
|
342 |
// array
|
343 |
if (Twig_TemplateInterface::METHOD_CALL !== $type) {
|
344 |
-
|
345 |
-
|
|
|
|
|
346 |
) {
|
347 |
if ($isDefinedTest) {
|
348 |
return true;
|
349 |
}
|
350 |
|
351 |
-
return $object[$
|
352 |
}
|
353 |
|
354 |
-
if (Twig_TemplateInterface::ARRAY_CALL === $type) {
|
355 |
if ($isDefinedTest) {
|
356 |
return false;
|
357 |
}
|
@@ -361,11 +360,13 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
361 |
}
|
362 |
|
363 |
if (is_object($object)) {
|
364 |
-
throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $
|
365 |
} elseif (is_array($object)) {
|
366 |
-
throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $
|
|
|
|
|
367 |
} else {
|
368 |
-
throw new Twig_Error_Runtime(sprintf('Impossible to access
|
369 |
}
|
370 |
}
|
371 |
}
|
@@ -379,14 +380,14 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
379 |
return null;
|
380 |
}
|
381 |
|
382 |
-
throw new Twig_Error_Runtime(sprintf('
|
383 |
}
|
384 |
|
385 |
$class = get_class($object);
|
386 |
|
387 |
// object property
|
388 |
if (Twig_TemplateInterface::METHOD_CALL !== $type) {
|
389 |
-
if (isset($object->$item) || array_key_exists($item, $object)) {
|
390 |
if ($isDefinedTest) {
|
391 |
return true;
|
392 |
}
|
@@ -406,13 +407,13 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
406 |
|
407 |
$lcItem = strtolower($item);
|
408 |
if (isset(self::$cache[$class]['methods'][$lcItem])) {
|
409 |
-
$method = $item;
|
410 |
} elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
|
411 |
$method = 'get'.$item;
|
412 |
} elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
|
413 |
$method = 'is'.$item;
|
414 |
} elseif (isset(self::$cache[$class]['methods']['__call'])) {
|
415 |
-
$method = $item;
|
416 |
} else {
|
417 |
if ($isDefinedTest) {
|
418 |
return false;
|
13 |
/**
|
14 |
* Default base class for compiled templates.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
abstract class Twig_Template implements Twig_TemplateInterface
|
19 |
{
|
336 |
*/
|
337 |
protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
338 |
{
|
|
|
|
|
339 |
// array
|
340 |
if (Twig_TemplateInterface::METHOD_CALL !== $type) {
|
341 |
+
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
342 |
+
|
343 |
+
if ((is_array($object) && array_key_exists($arrayItem, $object))
|
344 |
+
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
345 |
) {
|
346 |
if ($isDefinedTest) {
|
347 |
return true;
|
348 |
}
|
349 |
|
350 |
+
return $object[$arrayItem];
|
351 |
}
|
352 |
|
353 |
+
if (Twig_TemplateInterface::ARRAY_CALL === $type || !is_object($object)) {
|
354 |
if ($isDefinedTest) {
|
355 |
return false;
|
356 |
}
|
360 |
}
|
361 |
|
362 |
if (is_object($object)) {
|
363 |
+
throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $arrayItem, get_class($object)), -1, $this->getTemplateName());
|
364 |
} elseif (is_array($object)) {
|
365 |
+
throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))), -1, $this->getTemplateName());
|
366 |
+
} elseif (Twig_TemplateInterface::ARRAY_CALL === $type) {
|
367 |
+
throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
|
368 |
} else {
|
369 |
+
throw new Twig_Error_Runtime(sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
|
370 |
}
|
371 |
}
|
372 |
}
|
380 |
return null;
|
381 |
}
|
382 |
|
383 |
+
throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
|
384 |
}
|
385 |
|
386 |
$class = get_class($object);
|
387 |
|
388 |
// object property
|
389 |
if (Twig_TemplateInterface::METHOD_CALL !== $type) {
|
390 |
+
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
391 |
if ($isDefinedTest) {
|
392 |
return true;
|
393 |
}
|
407 |
|
408 |
$lcItem = strtolower($item);
|
409 |
if (isset(self::$cache[$class]['methods'][$lcItem])) {
|
410 |
+
$method = (string) $item;
|
411 |
} elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
|
412 |
$method = 'get'.$item;
|
413 |
} elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
|
414 |
$method = 'is'.$item;
|
415 |
} elseif (isset(self::$cache[$class]['methods']['__call'])) {
|
416 |
+
$method = (string) $item;
|
417 |
} else {
|
418 |
if ($isDefinedTest) {
|
419 |
return false;
|
Twig/lib/Twig/TemplateInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface implemented by all compiled templates.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_TemplateInterface
|
12 |
/**
|
13 |
* Interface implemented by all compiled templates.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_TemplateInterface
|
Twig/lib/Twig/Test.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
|
12 |
/**
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
|
Twig/lib/Twig/Test/Function.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a function template test.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_Test_Function extends Twig_Test
|
12 |
/**
|
13 |
* Represents a function template test.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
class Twig_Test_Function extends Twig_Test
|
Twig/lib/Twig/Test/IntegrationTestCase.php
CHANGED
@@ -12,9 +12,8 @@
|
|
12 |
/**
|
13 |
* Integration test helper
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author
|
17 |
-
* @author Karma Dordrak <drak@zikula.org>
|
18 |
*/
|
19 |
abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
20 |
{
|
12 |
/**
|
13 |
* Integration test helper
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
* @author Karma Dordrak <drak@zikula.org>
|
|
|
17 |
*/
|
18 |
abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
19 |
{
|
Twig/lib/Twig/Test/Method.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a method template test.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_Test_Method extends Twig_Test
|
12 |
/**
|
13 |
* Represents a method template test.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
class Twig_Test_Method extends Twig_Test
|
Twig/lib/Twig/Test/Node.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a template test as a Node.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_Test_Node extends Twig_Test
|
12 |
/**
|
13 |
* Represents a template test as a Node.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
class Twig_Test_Node extends Twig_Test
|
Twig/lib/Twig/TestCallableInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a callable template test.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_TestCallableInterface
|
12 |
/**
|
13 |
* Represents a callable template test.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_TestCallableInterface
|
Twig/lib/Twig/TestInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_TestInterface
|
12 |
/**
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_TestInterface
|
Twig/lib/Twig/Token.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a Token.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_Token
|
20 |
{
|
13 |
/**
|
14 |
* Represents a Token.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_Token
|
19 |
{
|
Twig/lib/Twig/TokenParser.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Base class for all token parsers.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
abstract class Twig_TokenParser implements Twig_TokenParserInterface
|
19 |
{
|
12 |
/**
|
13 |
* Base class for all token parsers.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
abstract class Twig_TokenParser implements Twig_TokenParserInterface
|
18 |
{
|
Twig/lib/Twig/TokenParser/Do.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
-
* Evaluates an expression,
|
14 |
*/
|
15 |
class Twig_TokenParser_Do extends Twig_TokenParser
|
16 |
{
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
+
* Evaluates an expression, discarding the returned value.
|
14 |
*/
|
15 |
class Twig_TokenParser_Do extends Twig_TokenParser
|
16 |
{
|
Twig/lib/Twig/TokenParser/Extends.php
CHANGED
@@ -38,8 +38,6 @@ class Twig_TokenParser_Extends extends Twig_TokenParser
|
|
38 |
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
39 |
|
40 |
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
41 |
-
|
42 |
-
return null;
|
43 |
}
|
44 |
|
45 |
/**
|
38 |
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
39 |
|
40 |
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
|
|
|
|
41 |
}
|
42 |
|
43 |
/**
|
Twig/lib/Twig/TokenParser/Macro.php
CHANGED
@@ -49,8 +49,6 @@ class Twig_TokenParser_Macro extends Twig_TokenParser
|
|
49 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
50 |
|
51 |
$this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag()));
|
52 |
-
|
53 |
-
return null;
|
54 |
}
|
55 |
|
56 |
public function decideBlockEnd(Twig_Token $token)
|
49 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
50 |
|
51 |
$this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag()));
|
|
|
|
|
52 |
}
|
53 |
|
54 |
public function decideBlockEnd(Twig_Token $token)
|
Twig/lib/Twig/TokenParser/Set.php
CHANGED
@@ -49,7 +49,7 @@ class Twig_TokenParser_Set extends Twig_TokenParser
|
|
49 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
50 |
|
51 |
if (count($names) !== count($values)) {
|
52 |
-
throw new Twig_Error_Syntax("When using set, you must have the same number of variables and
|
53 |
}
|
54 |
} else {
|
55 |
$capture = true;
|
49 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
50 |
|
51 |
if (count($names) !== count($values)) {
|
52 |
+
throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignments.", $stream->getCurrent()->getLine(), $stream->getFilename());
|
53 |
}
|
54 |
} else {
|
55 |
$capture = true;
|
Twig/lib/Twig/TokenParser/Use.php
CHANGED
@@ -68,8 +68,6 @@ class Twig_TokenParser_Use extends Twig_TokenParser
|
|
68 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
69 |
|
70 |
$this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
|
71 |
-
|
72 |
-
return null;
|
73 |
}
|
74 |
|
75 |
/**
|
68 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
69 |
|
70 |
$this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
|
|
|
|
|
71 |
}
|
72 |
|
73 |
/**
|
Twig/lib/Twig/TokenParserBroker.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Default implementation of a token parser broker.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
@@ -112,8 +111,6 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
|
112 |
}
|
113 |
$broker = prev($this->brokers);
|
114 |
}
|
115 |
-
|
116 |
-
return null;
|
117 |
}
|
118 |
|
119 |
public function getParsers()
|
13 |
/**
|
14 |
* Default implementation of a token parser broker.
|
15 |
*
|
16 |
+
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
111 |
}
|
112 |
$broker = prev($this->brokers);
|
113 |
}
|
|
|
|
|
114 |
}
|
115 |
|
116 |
public function getParsers()
|
Twig/lib/Twig/TokenParserBrokerInterface.php
CHANGED
@@ -15,8 +15,7 @@
|
|
15 |
*
|
16 |
* Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
|
17 |
*
|
18 |
-
* @
|
19 |
-
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
interface Twig_TokenParserBrokerInterface
|
15 |
*
|
16 |
* Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
|
17 |
*
|
18 |
+
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_TokenParserBrokerInterface
|
Twig/lib/Twig/TokenParserInterface.php
CHANGED
@@ -12,8 +12,7 @@
|
|
12 |
/**
|
13 |
* Interface implemented by token parsers.
|
14 |
*
|
15 |
-
* @
|
16 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
interface Twig_TokenParserInterface
|
19 |
{
|
12 |
/**
|
13 |
* Interface implemented by token parsers.
|
14 |
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
*/
|
17 |
interface Twig_TokenParserInterface
|
18 |
{
|
Twig/lib/Twig/TokenStream.php
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
/**
|
14 |
* Represents a token stream.
|
15 |
*
|
16 |
-
* @
|
17 |
-
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
class Twig_TokenStream
|
20 |
{
|
13 |
/**
|
14 |
* Represents a token stream.
|
15 |
*
|
16 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
17 |
*/
|
18 |
class Twig_TokenStream
|
19 |
{
|
Twig/phpunit.xml.dist
DELETED
@@ -1,25 +0,0 @@
|
|
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="test/bootstrap.php"
|
13 |
-
>
|
14 |
-
<testsuites>
|
15 |
-
<testsuite name="Twig Test Suite">
|
16 |
-
<directory>./test/Twig/</directory>
|
17 |
-
</testsuite>
|
18 |
-
</testsuites>
|
19 |
-
|
20 |
-
<filter>
|
21 |
-
<whitelist>
|
22 |
-
<directory suffix=".php">./lib/Twig/</directory>
|
23 |
-
</whitelist>
|
24 |
-
</filter>
|
25 |
-
</phpunit>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/AutoloaderTest.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_AutoloaderTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testAutoload()
|
15 |
-
{
|
16 |
-
$this->assertFalse(class_exists('FooBarFoo'), '->autoload() does not try to load classes that does not begin with Twig');
|
17 |
-
|
18 |
-
$autoloader = new Twig_Autoloader();
|
19 |
-
$this->assertNull($autoloader->autoload('Foo'), '->autoload() returns false if it is not able to load a class');
|
20 |
-
}
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/CompilerTest.php
DELETED
@@ -1,33 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_CompilerTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testReprNumericValueWithLocale()
|
15 |
-
{
|
16 |
-
$compiler = new Twig_Compiler(new Twig_Environment());
|
17 |
-
|
18 |
-
$locale = setlocale(LC_NUMERIC, 0);
|
19 |
-
if (false === $locale) {
|
20 |
-
$this->markTestSkipped('Your platform does not support locales.');
|
21 |
-
}
|
22 |
-
|
23 |
-
$required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
|
24 |
-
if (false === setlocale(LC_ALL, $required_locales)) {
|
25 |
-
$this->markTestSkipped('Could not set any of required locales: ' . implode(", ", $required_locales));
|
26 |
-
}
|
27 |
-
|
28 |
-
$this->assertEquals('1.2', $compiler->repr(1.2)->getSource());
|
29 |
-
$this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0)));
|
30 |
-
|
31 |
-
setlocale(LC_ALL, $locale);
|
32 |
-
}
|
33 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/EnvironmentTest.php
DELETED
@@ -1,272 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testAutoescapeOption()
|
15 |
-
{
|
16 |
-
$loader = new Twig_Loader_Array(array(
|
17 |
-
'html' => '{{ foo }} {{ foo }}',
|
18 |
-
'js' => '{{ bar }} {{ bar }}',
|
19 |
-
));
|
20 |
-
|
21 |
-
$twig = new Twig_Environment($loader, array(
|
22 |
-
'debug' => true,
|
23 |
-
'cache' => false,
|
24 |
-
'autoescape' => array($this, 'escapingStrategyCallback'),
|
25 |
-
));
|
26 |
-
|
27 |
-
$this->assertEquals('foo<br/ > foo<br/ >', $twig->render('html', array('foo' => 'foo<br/ >')));
|
28 |
-
$this->assertEquals('foo\x3Cbr\x2F\x20\x3E foo\x3Cbr\x2F\x20\x3E', $twig->render('js', array('bar' => 'foo<br/ >')));
|
29 |
-
}
|
30 |
-
|
31 |
-
public function escapingStrategyCallback($filename)
|
32 |
-
{
|
33 |
-
return $filename;
|
34 |
-
}
|
35 |
-
|
36 |
-
public function testGlobals()
|
37 |
-
{
|
38 |
-
// globals can be added after calling getGlobals
|
39 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
40 |
-
$twig->addGlobal('foo', 'foo');
|
41 |
-
$globals = $twig->getGlobals();
|
42 |
-
$twig->addGlobal('foo', 'bar');
|
43 |
-
$globals = $twig->getGlobals();
|
44 |
-
$this->assertEquals('bar', $globals['foo']);
|
45 |
-
|
46 |
-
// globals can be modified after runtime init
|
47 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
48 |
-
$twig->addGlobal('foo', 'foo');
|
49 |
-
$globals = $twig->getGlobals();
|
50 |
-
$twig->initRuntime();
|
51 |
-
$twig->addGlobal('foo', 'bar');
|
52 |
-
$globals = $twig->getGlobals();
|
53 |
-
$this->assertEquals('bar', $globals['foo']);
|
54 |
-
|
55 |
-
// globals can be modified after extensions init
|
56 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
57 |
-
$twig->addGlobal('foo', 'foo');
|
58 |
-
$globals = $twig->getGlobals();
|
59 |
-
$twig->getFunctions();
|
60 |
-
$twig->addGlobal('foo', 'bar');
|
61 |
-
$globals = $twig->getGlobals();
|
62 |
-
$this->assertEquals('bar', $globals['foo']);
|
63 |
-
|
64 |
-
// globals can be modified after extensions and runtime init
|
65 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
66 |
-
$twig->addGlobal('foo', 'foo');
|
67 |
-
$globals = $twig->getGlobals();
|
68 |
-
$twig->getFunctions();
|
69 |
-
$twig->initRuntime();
|
70 |
-
$twig->addGlobal('foo', 'bar');
|
71 |
-
$globals = $twig->getGlobals();
|
72 |
-
$this->assertEquals('bar', $globals['foo']);
|
73 |
-
|
74 |
-
/* to be uncomment in Twig 2.0
|
75 |
-
// globals cannot be added after runtime init
|
76 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
77 |
-
$twig->addGlobal('foo', 'foo');
|
78 |
-
$globals = $twig->getGlobals();
|
79 |
-
$twig->initRuntime();
|
80 |
-
try {
|
81 |
-
$twig->addGlobal('bar', 'bar');
|
82 |
-
$this->fail();
|
83 |
-
} catch (LogicException $e) {
|
84 |
-
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
85 |
-
}
|
86 |
-
|
87 |
-
// globals cannot be added after extensions init
|
88 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
89 |
-
$twig->addGlobal('foo', 'foo');
|
90 |
-
$globals = $twig->getGlobals();
|
91 |
-
$twig->getFunctions();
|
92 |
-
try {
|
93 |
-
$twig->addGlobal('bar', 'bar');
|
94 |
-
$this->fail();
|
95 |
-
} catch (LogicException $e) {
|
96 |
-
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
97 |
-
}
|
98 |
-
|
99 |
-
// globals cannot be added after extensions and runtime init
|
100 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
101 |
-
$twig->addGlobal('foo', 'foo');
|
102 |
-
$globals = $twig->getGlobals();
|
103 |
-
$twig->getFunctions();
|
104 |
-
$twig->initRuntime();
|
105 |
-
try {
|
106 |
-
$twig->addGlobal('bar', 'bar');
|
107 |
-
$this->fail();
|
108 |
-
} catch (LogicException $e) {
|
109 |
-
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
110 |
-
}
|
111 |
-
|
112 |
-
// test adding globals after initRuntime without call to getGlobals
|
113 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
114 |
-
$twig->initRuntime();
|
115 |
-
try {
|
116 |
-
$twig->addGlobal('bar', 'bar');
|
117 |
-
$this->fail();
|
118 |
-
} catch (LogicException $e) {
|
119 |
-
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
120 |
-
}
|
121 |
-
*/
|
122 |
-
}
|
123 |
-
|
124 |
-
public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
|
125 |
-
{
|
126 |
-
$options = array('cache' => sys_get_temp_dir().'/twig', 'auto_reload' => false, 'debug' => false);
|
127 |
-
|
128 |
-
// force compilation
|
129 |
-
$twig = new Twig_Environment(new Twig_Loader_String(), $options);
|
130 |
-
$cache = $twig->getCacheFilename('{{ foo }}');
|
131 |
-
if (!is_dir(dirname($cache))) {
|
132 |
-
mkdir(dirname($cache), 0777, true);
|
133 |
-
}
|
134 |
-
file_put_contents($cache, $twig->compileSource('{{ foo }}', '{{ foo }}'));
|
135 |
-
|
136 |
-
// check that extensions won't be initialized when rendering a template that is already in the cache
|
137 |
-
$twig = $this
|
138 |
-
->getMockBuilder('Twig_Environment')
|
139 |
-
->setConstructorArgs(array(new Twig_Loader_String(), $options))
|
140 |
-
->setMethods(array('initExtensions'))
|
141 |
-
->getMock()
|
142 |
-
;
|
143 |
-
|
144 |
-
$twig->expects($this->never())->method('initExtensions');
|
145 |
-
|
146 |
-
// render template
|
147 |
-
$output = $twig->render('{{ foo }}', array('foo' => 'bar'));
|
148 |
-
$this->assertEquals('bar', $output);
|
149 |
-
|
150 |
-
unlink($cache);
|
151 |
-
}
|
152 |
-
|
153 |
-
public function testAddExtension()
|
154 |
-
{
|
155 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
156 |
-
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension());
|
157 |
-
|
158 |
-
$this->assertArrayHasKey('test', $twig->getTags());
|
159 |
-
$this->assertArrayHasKey('foo_filter', $twig->getFilters());
|
160 |
-
$this->assertArrayHasKey('foo_function', $twig->getFunctions());
|
161 |
-
$this->assertArrayHasKey('foo_test', $twig->getTests());
|
162 |
-
$this->assertArrayHasKey('foo_unary', $twig->getUnaryOperators());
|
163 |
-
$this->assertArrayHasKey('foo_binary', $twig->getBinaryOperators());
|
164 |
-
$this->assertArrayHasKey('foo_global', $twig->getGlobals());
|
165 |
-
$visitors = $twig->getNodeVisitors();
|
166 |
-
$this->assertEquals('Twig_Tests_EnvironmentTest_NodeVisitor', get_class($visitors[2]));
|
167 |
-
}
|
168 |
-
|
169 |
-
public function testRemoveExtension()
|
170 |
-
{
|
171 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
172 |
-
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension());
|
173 |
-
$twig->removeExtension('test');
|
174 |
-
|
175 |
-
$this->assertFalse(array_key_exists('test', $twig->getTags()));
|
176 |
-
$this->assertFalse(array_key_exists('foo_filter', $twig->getFilters()));
|
177 |
-
$this->assertFalse(array_key_exists('foo_function', $twig->getFunctions()));
|
178 |
-
$this->assertFalse(array_key_exists('foo_test', $twig->getTests()));
|
179 |
-
$this->assertFalse(array_key_exists('foo_unary', $twig->getUnaryOperators()));
|
180 |
-
$this->assertFalse(array_key_exists('foo_binary', $twig->getBinaryOperators()));
|
181 |
-
$this->assertFalse(array_key_exists('foo_global', $twig->getGlobals()));
|
182 |
-
$this->assertCount(2, $twig->getNodeVisitors());
|
183 |
-
}
|
184 |
-
}
|
185 |
-
|
186 |
-
class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension
|
187 |
-
{
|
188 |
-
public function getTokenParsers()
|
189 |
-
{
|
190 |
-
return array(
|
191 |
-
new Twig_Tests_EnvironmentTest_TokenParser(),
|
192 |
-
);
|
193 |
-
}
|
194 |
-
|
195 |
-
public function getNodeVisitors()
|
196 |
-
{
|
197 |
-
return array(
|
198 |
-
new Twig_Tests_EnvironmentTest_NodeVisitor(),
|
199 |
-
);
|
200 |
-
}
|
201 |
-
|
202 |
-
public function getFilters()
|
203 |
-
{
|
204 |
-
return array(
|
205 |
-
'foo_filter' => new Twig_Filter_Function('foo_filter'),
|
206 |
-
);
|
207 |
-
}
|
208 |
-
|
209 |
-
public function getTests()
|
210 |
-
{
|
211 |
-
return array(
|
212 |
-
'foo_test' => new Twig_Test_Function('foo_test'),
|
213 |
-
);
|
214 |
-
}
|
215 |
-
|
216 |
-
public function getFunctions()
|
217 |
-
{
|
218 |
-
return array(
|
219 |
-
'foo_function' => new Twig_Function_Function('foo_function'),
|
220 |
-
);
|
221 |
-
}
|
222 |
-
|
223 |
-
public function getOperators()
|
224 |
-
{
|
225 |
-
return array(
|
226 |
-
array('foo_unary' => array()),
|
227 |
-
array('foo_binary' => array()),
|
228 |
-
);
|
229 |
-
}
|
230 |
-
|
231 |
-
public function getGlobals()
|
232 |
-
{
|
233 |
-
return array(
|
234 |
-
'foo_global' => 'foo_global',
|
235 |
-
);
|
236 |
-
}
|
237 |
-
|
238 |
-
public function getName()
|
239 |
-
{
|
240 |
-
return 'test';
|
241 |
-
}
|
242 |
-
}
|
243 |
-
|
244 |
-
class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser
|
245 |
-
{
|
246 |
-
public function parse(Twig_Token $token)
|
247 |
-
{
|
248 |
-
}
|
249 |
-
|
250 |
-
public function getTag()
|
251 |
-
{
|
252 |
-
return 'test';
|
253 |
-
}
|
254 |
-
}
|
255 |
-
|
256 |
-
class Twig_Tests_EnvironmentTest_NodeVisitor implements Twig_NodeVisitorInterface
|
257 |
-
{
|
258 |
-
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
259 |
-
{
|
260 |
-
return $node;
|
261 |
-
}
|
262 |
-
|
263 |
-
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
264 |
-
{
|
265 |
-
return $node;
|
266 |
-
}
|
267 |
-
|
268 |
-
public function getPriority()
|
269 |
-
{
|
270 |
-
return 0;
|
271 |
-
}
|
272 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/ErrorTest.php
DELETED
@@ -1,159 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testErrorWithObjectFilename()
|
15 |
-
{
|
16 |
-
$error = new Twig_Error('foo');
|
17 |
-
$error->setTemplateFile(new SplFileInfo(__FILE__));
|
18 |
-
|
19 |
-
$this->assertContains('test'.DIRECTORY_SEPARATOR.'Twig'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage());
|
20 |
-
}
|
21 |
-
|
22 |
-
public function testErrorWithArrayFilename()
|
23 |
-
{
|
24 |
-
$error = new Twig_Error('foo');
|
25 |
-
$error->setTemplateFile(array('foo' => 'bar'));
|
26 |
-
|
27 |
-
$this->assertEquals('foo in {"foo":"bar"}', $error->getMessage());
|
28 |
-
}
|
29 |
-
|
30 |
-
public function testTwigExceptionAddsFileAndLineWhenMissing()
|
31 |
-
{
|
32 |
-
$loader = new Twig_Loader_Array(array('index' => "\n\n{{ foo.bar }}\n\n\n{{ 'foo' }}"));
|
33 |
-
$twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
|
34 |
-
|
35 |
-
$template = $twig->loadTemplate('index');
|
36 |
-
|
37 |
-
try {
|
38 |
-
$template->render(array());
|
39 |
-
|
40 |
-
$this->fail();
|
41 |
-
} catch (Twig_Error_Runtime $e) {
|
42 |
-
$this->assertEquals('Variable "foo" does not exist in "index" at line 3', $e->getMessage());
|
43 |
-
$this->assertEquals(3, $e->getTemplateLine());
|
44 |
-
$this->assertEquals('index', $e->getTemplateFile());
|
45 |
-
}
|
46 |
-
}
|
47 |
-
|
48 |
-
public function testRenderWrapsExceptions()
|
49 |
-
{
|
50 |
-
$loader = new Twig_Loader_Array(array('index' => "\n\n\n{{ foo.bar }}\n\n\n\n{{ 'foo' }}"));
|
51 |
-
$twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
|
52 |
-
|
53 |
-
$template = $twig->loadTemplate('index');
|
54 |
-
|
55 |
-
try {
|
56 |
-
$template->render(array('foo' => new Twig_Tests_ErrorTest_Foo()));
|
57 |
-
|
58 |
-
$this->fail();
|
59 |
-
} catch (Twig_Error_Runtime $e) {
|
60 |
-
$this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index" at line 4.', $e->getMessage());
|
61 |
-
$this->assertEquals(4, $e->getTemplateLine());
|
62 |
-
$this->assertEquals('index', $e->getTemplateFile());
|
63 |
-
}
|
64 |
-
}
|
65 |
-
|
66 |
-
public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritance()
|
67 |
-
{
|
68 |
-
$loader = new Twig_Loader_Array(array(
|
69 |
-
'index' => "{% extends 'base' %}
|
70 |
-
{% block content %}
|
71 |
-
{{ foo.bar }}
|
72 |
-
{% endblock %}
|
73 |
-
{% block foo %}
|
74 |
-
{{ foo.bar }}
|
75 |
-
{% endblock %}",
|
76 |
-
'base' => '{% block content %}{% endblock %}'
|
77 |
-
));
|
78 |
-
$twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
|
79 |
-
|
80 |
-
$template = $twig->loadTemplate('index');
|
81 |
-
try {
|
82 |
-
$template->render(array());
|
83 |
-
|
84 |
-
$this->fail();
|
85 |
-
} catch (Twig_Error_Runtime $e) {
|
86 |
-
$this->assertEquals('Variable "foo" does not exist in "index" at line 3', $e->getMessage());
|
87 |
-
$this->assertEquals(3, $e->getTemplateLine());
|
88 |
-
$this->assertEquals('index', $e->getTemplateFile());
|
89 |
-
}
|
90 |
-
|
91 |
-
try {
|
92 |
-
$template->render(array('foo' => new Twig_Tests_ErrorTest_Foo()));
|
93 |
-
|
94 |
-
$this->fail();
|
95 |
-
} catch (Twig_Error_Runtime $e) {
|
96 |
-
$this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index" at line 3.', $e->getMessage());
|
97 |
-
$this->assertEquals(3, $e->getTemplateLine());
|
98 |
-
$this->assertEquals('index', $e->getTemplateFile());
|
99 |
-
}
|
100 |
-
}
|
101 |
-
|
102 |
-
public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritanceAgain()
|
103 |
-
{
|
104 |
-
$loader = new Twig_Loader_Array(array(
|
105 |
-
'index' => "{% extends 'base' %}
|
106 |
-
{% block content %}
|
107 |
-
{{ parent() }}
|
108 |
-
{% endblock %}",
|
109 |
-
'base' => '{% block content %}{{ foo }}{% endblock %}'
|
110 |
-
));
|
111 |
-
$twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
|
112 |
-
|
113 |
-
$template = $twig->loadTemplate('index');
|
114 |
-
try {
|
115 |
-
$template->render(array());
|
116 |
-
|
117 |
-
$this->fail();
|
118 |
-
} catch (Twig_Error_Runtime $e) {
|
119 |
-
$this->assertEquals('Variable "foo" does not exist in "base" at line 1', $e->getMessage());
|
120 |
-
$this->assertEquals(1, $e->getTemplateLine());
|
121 |
-
$this->assertEquals('base', $e->getTemplateFile());
|
122 |
-
}
|
123 |
-
}
|
124 |
-
|
125 |
-
public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritanceOnDisk()
|
126 |
-
{
|
127 |
-
$loader = new Twig_Loader_Filesystem(dirname(__FILE__).'/Fixtures/errors');
|
128 |
-
$twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
|
129 |
-
|
130 |
-
$template = $twig->loadTemplate('index.html');
|
131 |
-
try {
|
132 |
-
$template->render(array());
|
133 |
-
|
134 |
-
$this->fail();
|
135 |
-
} catch (Twig_Error_Runtime $e) {
|
136 |
-
$this->assertEquals('Variable "foo" does not exist in "index.html" at line 3', $e->getMessage());
|
137 |
-
$this->assertEquals(3, $e->getTemplateLine());
|
138 |
-
$this->assertEquals('index.html', $e->getTemplateFile());
|
139 |
-
}
|
140 |
-
|
141 |
-
try {
|
142 |
-
$template->render(array('foo' => new Twig_Tests_ErrorTest_Foo()));
|
143 |
-
|
144 |
-
$this->fail();
|
145 |
-
} catch (Twig_Error_Runtime $e) {
|
146 |
-
$this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index.html" at line 3.', $e->getMessage());
|
147 |
-
$this->assertEquals(3, $e->getTemplateLine());
|
148 |
-
$this->assertEquals('index.html', $e->getTemplateFile());
|
149 |
-
}
|
150 |
-
}
|
151 |
-
}
|
152 |
-
|
153 |
-
class Twig_Tests_ErrorTest_Foo
|
154 |
-
{
|
155 |
-
public function bar()
|
156 |
-
{
|
157 |
-
throw new Exception('Runtime error...');
|
158 |
-
}
|
159 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/ExpressionParserTest.php
DELETED
@@ -1,332 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @expectedException Twig_Error_Syntax
|
16 |
-
* @dataProvider getFailingTestsForAssignment
|
17 |
-
*/
|
18 |
-
public function testCanOnlyAssignToNames($template)
|
19 |
-
{
|
20 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
21 |
-
$parser = new Twig_Parser($env);
|
22 |
-
|
23 |
-
$parser->parse($env->tokenize($template, 'index'));
|
24 |
-
}
|
25 |
-
|
26 |
-
public function getFailingTestsForAssignment()
|
27 |
-
{
|
28 |
-
return array(
|
29 |
-
array('{% set false = "foo" %}'),
|
30 |
-
array('{% set true = "foo" %}'),
|
31 |
-
array('{% set none = "foo" %}'),
|
32 |
-
array('{% set 3 = "foo" %}'),
|
33 |
-
array('{% set 1 + 2 = "foo" %}'),
|
34 |
-
array('{% set "bar" = "foo" %}'),
|
35 |
-
array('{% set %}{% endset %}')
|
36 |
-
);
|
37 |
-
}
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @dataProvider getTestsForArray
|
41 |
-
*/
|
42 |
-
public function testArrayExpression($template, $expected)
|
43 |
-
{
|
44 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
45 |
-
$stream = $env->tokenize($template, 'index');
|
46 |
-
$parser = new Twig_Parser($env);
|
47 |
-
|
48 |
-
$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr'));
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @expectedException Twig_Error_Syntax
|
53 |
-
* @dataProvider getFailingTestsForArray
|
54 |
-
*/
|
55 |
-
public function testArraySyntaxError($template)
|
56 |
-
{
|
57 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
58 |
-
$parser = new Twig_Parser($env);
|
59 |
-
|
60 |
-
$parser->parse($env->tokenize($template, 'index'));
|
61 |
-
}
|
62 |
-
|
63 |
-
public function getFailingTestsForArray()
|
64 |
-
{
|
65 |
-
return array(
|
66 |
-
array('{{ [1, "a": "b"] }}'),
|
67 |
-
array('{{ {"a": "b", 2} }}'),
|
68 |
-
);
|
69 |
-
}
|
70 |
-
|
71 |
-
public function getTestsForArray()
|
72 |
-
{
|
73 |
-
return array(
|
74 |
-
// simple array
|
75 |
-
array('{{ [1, 2] }}', new Twig_Node_Expression_Array(array(
|
76 |
-
new Twig_Node_Expression_Constant(0, 1),
|
77 |
-
new Twig_Node_Expression_Constant(1, 1),
|
78 |
-
|
79 |
-
new Twig_Node_Expression_Constant(1, 1),
|
80 |
-
new Twig_Node_Expression_Constant(2, 1),
|
81 |
-
), 1),
|
82 |
-
),
|
83 |
-
|
84 |
-
// array with trailing ,
|
85 |
-
array('{{ [1, 2, ] }}', new Twig_Node_Expression_Array(array(
|
86 |
-
new Twig_Node_Expression_Constant(0, 1),
|
87 |
-
new Twig_Node_Expression_Constant(1, 1),
|
88 |
-
|
89 |
-
new Twig_Node_Expression_Constant(1, 1),
|
90 |
-
new Twig_Node_Expression_Constant(2, 1),
|
91 |
-
), 1),
|
92 |
-
),
|
93 |
-
|
94 |
-
// simple hash
|
95 |
-
array('{{ {"a": "b", "b": "c"} }}', new Twig_Node_Expression_Array(array(
|
96 |
-
new Twig_Node_Expression_Constant('a', 1),
|
97 |
-
new Twig_Node_Expression_Constant('b', 1),
|
98 |
-
|
99 |
-
new Twig_Node_Expression_Constant('b', 1),
|
100 |
-
new Twig_Node_Expression_Constant('c', 1),
|
101 |
-
), 1),
|
102 |
-
),
|
103 |
-
|
104 |
-
// hash with trailing ,
|
105 |
-
array('{{ {"a": "b", "b": "c", } }}', new Twig_Node_Expression_Array(array(
|
106 |
-
new Twig_Node_Expression_Constant('a', 1),
|
107 |
-
new Twig_Node_Expression_Constant('b', 1),
|
108 |
-
|
109 |
-
new Twig_Node_Expression_Constant('b', 1),
|
110 |
-
new Twig_Node_Expression_Constant('c', 1),
|
111 |
-
), 1),
|
112 |
-
),
|
113 |
-
|
114 |
-
// hash in an array
|
115 |
-
array('{{ [1, {"a": "b", "b": "c"}] }}', new Twig_Node_Expression_Array(array(
|
116 |
-
new Twig_Node_Expression_Constant(0, 1),
|
117 |
-
new Twig_Node_Expression_Constant(1, 1),
|
118 |
-
|
119 |
-
new Twig_Node_Expression_Constant(1, 1),
|
120 |
-
new Twig_Node_Expression_Array(array(
|
121 |
-
new Twig_Node_Expression_Constant('a', 1),
|
122 |
-
new Twig_Node_Expression_Constant('b', 1),
|
123 |
-
|
124 |
-
new Twig_Node_Expression_Constant('b', 1),
|
125 |
-
new Twig_Node_Expression_Constant('c', 1),
|
126 |
-
), 1),
|
127 |
-
), 1),
|
128 |
-
),
|
129 |
-
|
130 |
-
// array in a hash
|
131 |
-
array('{{ {"a": [1, 2], "b": "c"} }}', new Twig_Node_Expression_Array(array(
|
132 |
-
new Twig_Node_Expression_Constant('a', 1),
|
133 |
-
new Twig_Node_Expression_Array(array(
|
134 |
-
new Twig_Node_Expression_Constant(0, 1),
|
135 |
-
new Twig_Node_Expression_Constant(1, 1),
|
136 |
-
|
137 |
-
new Twig_Node_Expression_Constant(1, 1),
|
138 |
-
new Twig_Node_Expression_Constant(2, 1),
|
139 |
-
), 1),
|
140 |
-
new Twig_Node_Expression_Constant('b', 1),
|
141 |
-
new Twig_Node_Expression_Constant('c', 1),
|
142 |
-
), 1),
|
143 |
-
),
|
144 |
-
);
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* @expectedException Twig_Error_Syntax
|
149 |
-
*/
|
150 |
-
public function testStringExpressionDoesNotConcatenateTwoConsecutiveStrings()
|
151 |
-
{
|
152 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
|
153 |
-
$stream = $env->tokenize('{{ "a" "b" }}', 'index');
|
154 |
-
$parser = new Twig_Parser($env);
|
155 |
-
|
156 |
-
$parser->parse($stream);
|
157 |
-
}
|
158 |
-
|
159 |
-
/**
|
160 |
-
* @dataProvider getTestsForString
|
161 |
-
*/
|
162 |
-
public function testStringExpression($template, $expected)
|
163 |
-
{
|
164 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
|
165 |
-
$stream = $env->tokenize($template, 'index');
|
166 |
-
$parser = new Twig_Parser($env);
|
167 |
-
|
168 |
-
$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr'));
|
169 |
-
}
|
170 |
-
|
171 |
-
public function getTestsForString()
|
172 |
-
{
|
173 |
-
return array(
|
174 |
-
array(
|
175 |
-
'{{ "foo" }}', new Twig_Node_Expression_Constant('foo', 1),
|
176 |
-
),
|
177 |
-
array(
|
178 |
-
'{{ "foo #{bar}" }}', new Twig_Node_Expression_Binary_Concat(
|
179 |
-
new Twig_Node_Expression_Constant('foo ', 1),
|
180 |
-
new Twig_Node_Expression_Name('bar', 1),
|
181 |
-
1
|
182 |
-
),
|
183 |
-
),
|
184 |
-
array(
|
185 |
-
'{{ "foo #{bar} baz" }}', new Twig_Node_Expression_Binary_Concat(
|
186 |
-
new Twig_Node_Expression_Binary_Concat(
|
187 |
-
new Twig_Node_Expression_Constant('foo ', 1),
|
188 |
-
new Twig_Node_Expression_Name('bar', 1),
|
189 |
-
1
|
190 |
-
),
|
191 |
-
new Twig_Node_Expression_Constant(' baz', 1),
|
192 |
-
1
|
193 |
-
)
|
194 |
-
),
|
195 |
-
|
196 |
-
array(
|
197 |
-
'{{ "foo #{"foo #{bar} baz"} baz" }}', new Twig_Node_Expression_Binary_Concat(
|
198 |
-
new Twig_Node_Expression_Binary_Concat(
|
199 |
-
new Twig_Node_Expression_Constant('foo ', 1),
|
200 |
-
new Twig_Node_Expression_Binary_Concat(
|
201 |
-
new Twig_Node_Expression_Binary_Concat(
|
202 |
-
new Twig_Node_Expression_Constant('foo ', 1),
|
203 |
-
new Twig_Node_Expression_Name('bar', 1),
|
204 |
-
1
|
205 |
-
),
|
206 |
-
new Twig_Node_Expression_Constant(' baz', 1),
|
207 |
-
1
|
208 |
-
),
|
209 |
-
1
|
210 |
-
),
|
211 |
-
new Twig_Node_Expression_Constant(' baz', 1),
|
212 |
-
1
|
213 |
-
),
|
214 |
-
),
|
215 |
-
);
|
216 |
-
}
|
217 |
-
|
218 |
-
/**
|
219 |
-
* @expectedException Twig_Error_Syntax
|
220 |
-
*/
|
221 |
-
public function testAttributeCallDoesNotSupportNamedArguments()
|
222 |
-
{
|
223 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
224 |
-
$parser = new Twig_Parser($env);
|
225 |
-
|
226 |
-
$parser->parse($env->tokenize('{{ foo.bar(name="Foo") }}', 'index'));
|
227 |
-
}
|
228 |
-
|
229 |
-
/**
|
230 |
-
* @expectedException Twig_Error_Syntax
|
231 |
-
*/
|
232 |
-
public function testMacroCallDoesNotSupportNamedArguments()
|
233 |
-
{
|
234 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
235 |
-
$parser = new Twig_Parser($env);
|
236 |
-
|
237 |
-
$parser->parse($env->tokenize('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index'));
|
238 |
-
}
|
239 |
-
|
240 |
-
/**
|
241 |
-
* @expectedException Twig_Error_Syntax
|
242 |
-
* @expectedExceptionMessage An argument must be a name. Unexpected token "string" of value "a" ("name" expected) in "index" at line 1
|
243 |
-
*/
|
244 |
-
public function testMacroDefinitionDoesNotSupportNonNameVariableName()
|
245 |
-
{
|
246 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
247 |
-
$parser = new Twig_Parser($env);
|
248 |
-
|
249 |
-
$parser->parse($env->tokenize('{% macro foo("a") %}{% endmacro %}', 'index'));
|
250 |
-
}
|
251 |
-
|
252 |
-
/**
|
253 |
-
* @expectedException Twig_Error_Syntax
|
254 |
-
* @expectedExceptionMessage A default value for an argument must be a constant (a boolean, a string, a number, or an array) in "index" at line 1
|
255 |
-
* @dataProvider getMacroDefinitionDoesNotSupportNonConstantDefaultValues
|
256 |
-
*/
|
257 |
-
public function testMacroDefinitionDoesNotSupportNonConstantDefaultValues($template)
|
258 |
-
{
|
259 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
260 |
-
$parser = new Twig_Parser($env);
|
261 |
-
|
262 |
-
$parser->parse($env->tokenize($template, 'index'));
|
263 |
-
}
|
264 |
-
|
265 |
-
public function getMacroDefinitionDoesNotSupportNonConstantDefaultValues()
|
266 |
-
{
|
267 |
-
return array(
|
268 |
-
array('{% macro foo(name = "a #{foo} a") %}{% endmacro %}'),
|
269 |
-
array('{% macro foo(name = [["b", "a #{foo} a"]]) %}{% endmacro %}'),
|
270 |
-
);
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* @dataProvider getMacroDefinitionSupportsConstantDefaultValues
|
275 |
-
*/
|
276 |
-
public function testMacroDefinitionSupportsConstantDefaultValues($template)
|
277 |
-
{
|
278 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
279 |
-
$parser = new Twig_Parser($env);
|
280 |
-
|
281 |
-
$parser->parse($env->tokenize($template, 'index'));
|
282 |
-
}
|
283 |
-
|
284 |
-
public function getMacroDefinitionSupportsConstantDefaultValues()
|
285 |
-
{
|
286 |
-
return array(
|
287 |
-
array('{% macro foo(name = "aa") %}{% endmacro %}'),
|
288 |
-
array('{% macro foo(name = 12) %}{% endmacro %}'),
|
289 |
-
array('{% macro foo(name = true) %}{% endmacro %}'),
|
290 |
-
array('{% macro foo(name = ["a"]) %}{% endmacro %}'),
|
291 |
-
array('{% macro foo(name = [["a"]]) %}{% endmacro %}'),
|
292 |
-
array('{% macro foo(name = {a: "a"}) %}{% endmacro %}'),
|
293 |
-
array('{% macro foo(name = {a: {b: "a"}}) %}{% endmacro %}'),
|
294 |
-
);
|
295 |
-
}
|
296 |
-
|
297 |
-
/**
|
298 |
-
* @expectedException Twig_Error_Syntax
|
299 |
-
* @expectedExceptionMessage The function "cycl" does not exist. Did you mean "cycle" in "index" at line 1
|
300 |
-
*/
|
301 |
-
public function testUnknownFunction()
|
302 |
-
{
|
303 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
304 |
-
$parser = new Twig_Parser($env);
|
305 |
-
|
306 |
-
$parser->parse($env->tokenize('{{ cycl() }}', 'index'));
|
307 |
-
}
|
308 |
-
|
309 |
-
/**
|
310 |
-
* @expectedException Twig_Error_Syntax
|
311 |
-
* @expectedExceptionMessage The filter "lowe" does not exist. Did you mean "lower" in "index" at line 1
|
312 |
-
*/
|
313 |
-
public function testUnknownFilter()
|
314 |
-
{
|
315 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
316 |
-
$parser = new Twig_Parser($env);
|
317 |
-
|
318 |
-
$parser->parse($env->tokenize('{{ 1|lowe }}', 'index'));
|
319 |
-
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
* @expectedException Twig_Error_Syntax
|
323 |
-
* @expectedExceptionMessage The test "nul" does not exist. Did you mean "null" in "index" at line 1
|
324 |
-
*/
|
325 |
-
public function testUnknownTest()
|
326 |
-
{
|
327 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
328 |
-
$parser = new Twig_Parser($env);
|
329 |
-
|
330 |
-
$parser->parse($env->tokenize('{{ 1 is nul }}', 'index'));
|
331 |
-
}
|
332 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Extension/CoreTest.php
DELETED
@@ -1,115 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @dataProvider getRandomFunctionTestData
|
16 |
-
*/
|
17 |
-
public function testRandomFunction($value, $expectedInArray)
|
18 |
-
{
|
19 |
-
for ($i = 0; $i < 100; $i++) {
|
20 |
-
$this->assertTrue(in_array(twig_random(new Twig_Environment(), $value), $expectedInArray, true)); // assertContains() would not consider the type
|
21 |
-
}
|
22 |
-
}
|
23 |
-
|
24 |
-
public function getRandomFunctionTestData()
|
25 |
-
{
|
26 |
-
return array(
|
27 |
-
array( // array
|
28 |
-
array('apple', 'orange', 'citrus'),
|
29 |
-
array('apple', 'orange', 'citrus'),
|
30 |
-
),
|
31 |
-
array( // Traversable
|
32 |
-
new ArrayObject(array('apple', 'orange', 'citrus')),
|
33 |
-
array('apple', 'orange', 'citrus'),
|
34 |
-
),
|
35 |
-
array( // unicode string
|
36 |
-
'Ä€é',
|
37 |
-
array('Ä', '€', 'é'),
|
38 |
-
),
|
39 |
-
array( // numeric but string
|
40 |
-
'123',
|
41 |
-
array('1', '2', '3'),
|
42 |
-
),
|
43 |
-
array( // integer
|
44 |
-
5,
|
45 |
-
range(0, 5, 1),
|
46 |
-
),
|
47 |
-
array( // float
|
48 |
-
5.9,
|
49 |
-
range(0, 5, 1),
|
50 |
-
),
|
51 |
-
array( // negative
|
52 |
-
-2,
|
53 |
-
array(0, -1, -2),
|
54 |
-
),
|
55 |
-
);
|
56 |
-
}
|
57 |
-
|
58 |
-
public function testRandomFunctionWithoutParameter()
|
59 |
-
{
|
60 |
-
$max = mt_getrandmax();
|
61 |
-
|
62 |
-
for ($i = 0; $i < 100; $i++) {
|
63 |
-
$val = twig_random(new Twig_Environment());
|
64 |
-
$this->assertTrue(is_int($val) && $val >= 0 && $val <= $max);
|
65 |
-
}
|
66 |
-
}
|
67 |
-
|
68 |
-
public function testRandomFunctionReturnsAsIs()
|
69 |
-
{
|
70 |
-
$this->assertSame('', twig_random(new Twig_Environment(), ''));
|
71 |
-
$this->assertSame('', twig_random(new Twig_Environment(null, array('charset' => null)), ''));
|
72 |
-
|
73 |
-
$instance = new stdClass();
|
74 |
-
$this->assertSame($instance, twig_random(new Twig_Environment(), $instance));
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* @expectedException Twig_Error_Runtime
|
79 |
-
*/
|
80 |
-
public function testRandomFunctionOfEmptyArrayThrowsException()
|
81 |
-
{
|
82 |
-
twig_random(new Twig_Environment(), array());
|
83 |
-
}
|
84 |
-
|
85 |
-
public function testRandomFunctionOnNonUTF8String()
|
86 |
-
{
|
87 |
-
if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
|
88 |
-
$this->markTestSkipped('needs iconv or mbstring');
|
89 |
-
}
|
90 |
-
|
91 |
-
$twig = new Twig_Environment();
|
92 |
-
$twig->setCharset('ISO-8859-1');
|
93 |
-
|
94 |
-
$text = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8');
|
95 |
-
for ($i = 0; $i < 30; $i++) {
|
96 |
-
$rand = twig_random($twig, $text);
|
97 |
-
$this->assertTrue(in_array(twig_convert_encoding($rand, 'UTF-8', 'ISO-8859-1'), array('Ä', 'é'), true));
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
public function testReverseFilterOnNonUTF8String()
|
102 |
-
{
|
103 |
-
if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
|
104 |
-
$this->markTestSkipped('needs iconv or mbstring');
|
105 |
-
}
|
106 |
-
|
107 |
-
$twig = new Twig_Environment();
|
108 |
-
$twig->setCharset('ISO-8859-1');
|
109 |
-
|
110 |
-
$input = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8');
|
111 |
-
$output = twig_convert_encoding(twig_reverse_filter($twig, $input), 'UTF-8', 'ISO-8859-1');
|
112 |
-
|
113 |
-
$this->assertEquals($output, 'éÄ');
|
114 |
-
}
|
115 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Extension/SandboxTest.php
DELETED
@@ -1,212 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
protected static $params, $templates;
|
15 |
-
|
16 |
-
public function setUp()
|
17 |
-
{
|
18 |
-
self::$params = array(
|
19 |
-
'name' => 'Fabien',
|
20 |
-
'obj' => new FooObject(),
|
21 |
-
'arr' => array('obj' => new FooObject()),
|
22 |
-
);
|
23 |
-
|
24 |
-
self::$templates = array(
|
25 |
-
'1_basic1' => '{{ obj.foo }}',
|
26 |
-
'1_basic2' => '{{ name|upper }}',
|
27 |
-
'1_basic3' => '{% if name %}foo{% endif %}',
|
28 |
-
'1_basic4' => '{{ obj.bar }}',
|
29 |
-
'1_basic5' => '{{ obj }}',
|
30 |
-
'1_basic6' => '{{ arr.obj }}',
|
31 |
-
'1_basic7' => '{{ cycle(["foo","bar"], 1) }}',
|
32 |
-
'1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}',
|
33 |
-
'1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
34 |
-
'1_layout' => '{% block content %}{% endblock %}',
|
35 |
-
'1_child' => '{% extends "1_layout" %}{% block content %}{{ "a"|json_encode }}{% endblock %}',
|
36 |
-
);
|
37 |
-
}
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @expectedException Twig_Sandbox_SecurityError
|
41 |
-
* @expectedExceptionMessage Filter "json_encode" is not allowed in "1_child".
|
42 |
-
*/
|
43 |
-
public function testSandboxWithInheritance()
|
44 |
-
{
|
45 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array('block'));
|
46 |
-
$twig->loadTemplate('1_child')->render(array());
|
47 |
-
}
|
48 |
-
|
49 |
-
public function testSandboxGloballySet()
|
50 |
-
{
|
51 |
-
$twig = $this->getEnvironment(false, array(), self::$templates);
|
52 |
-
$this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally');
|
53 |
-
|
54 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
55 |
-
try {
|
56 |
-
$twig->loadTemplate('1_basic1')->render(self::$params);
|
57 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed method is called');
|
58 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
59 |
-
}
|
60 |
-
|
61 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
62 |
-
try {
|
63 |
-
$twig->loadTemplate('1_basic2')->render(self::$params);
|
64 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
|
65 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
66 |
-
}
|
67 |
-
|
68 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
69 |
-
try {
|
70 |
-
$twig->loadTemplate('1_basic3')->render(self::$params);
|
71 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template');
|
72 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
73 |
-
}
|
74 |
-
|
75 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
76 |
-
try {
|
77 |
-
$twig->loadTemplate('1_basic4')->render(self::$params);
|
78 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template');
|
79 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
80 |
-
}
|
81 |
-
|
82 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
83 |
-
try {
|
84 |
-
$twig->loadTemplate('1_basic5')->render(self::$params);
|
85 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
|
86 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
87 |
-
}
|
88 |
-
|
89 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
90 |
-
try {
|
91 |
-
$twig->loadTemplate('1_basic6')->render(self::$params);
|
92 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
|
93 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
94 |
-
}
|
95 |
-
|
96 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
97 |
-
try {
|
98 |
-
$twig->loadTemplate('1_basic7')->render(self::$params);
|
99 |
-
$this->fail('Sandbox throws a SecurityError exception if an unallowed function is called in the template');
|
100 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
101 |
-
}
|
102 |
-
|
103 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => 'foo'));
|
104 |
-
FooObject::reset();
|
105 |
-
$this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods');
|
106 |
-
$this->assertEquals(1, FooObject::$called['foo'], 'Sandbox only calls method once');
|
107 |
-
|
108 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => '__toString'));
|
109 |
-
FooObject::reset();
|
110 |
-
$this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allow some methods');
|
111 |
-
$this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
|
112 |
-
|
113 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array('upper'));
|
114 |
-
$this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters');
|
115 |
-
|
116 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array('if'));
|
117 |
-
$this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags');
|
118 |
-
|
119 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array('FooObject' => 'bar'));
|
120 |
-
$this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties');
|
121 |
-
|
122 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array(), array('cycle'));
|
123 |
-
$this->assertEquals('bar', $twig->loadTemplate('1_basic7')->render(self::$params), 'Sandbox allow some functions');
|
124 |
-
|
125 |
-
foreach (array('getfoobar', 'getFoobar', 'getFooBar') as $name) {
|
126 |
-
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => $name));
|
127 |
-
FooObject::reset();
|
128 |
-
$this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic8')->render(self::$params), 'Sandbox allow methods in a case-insensitive way');
|
129 |
-
$this->assertEquals(2, FooObject::$called['getFooBar'], 'Sandbox only calls method once');
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
-
public function testSandboxLocallySetForAnInclude()
|
134 |
-
{
|
135 |
-
self::$templates = array(
|
136 |
-
'2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}',
|
137 |
-
'2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
138 |
-
);
|
139 |
-
|
140 |
-
$twig = $this->getEnvironment(false, array(), self::$templates);
|
141 |
-
$this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include');
|
142 |
-
|
143 |
-
self::$templates = array(
|
144 |
-
'3_basic' => '{{ obj.foo }}{% sandbox %}{% include "3_included" %}{% endsandbox %}{{ obj.foo }}',
|
145 |
-
'3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
146 |
-
);
|
147 |
-
|
148 |
-
$twig = $this->getEnvironment(true, array(), self::$templates);
|
149 |
-
try {
|
150 |
-
$twig->loadTemplate('3_basic')->render(self::$params);
|
151 |
-
$this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed');
|
152 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
public function testMacrosInASandbox()
|
157 |
-
{
|
158 |
-
$twig = $this->getEnvironment(true, array('autoescape' => true), array('index' => <<<EOF
|
159 |
-
{%- import _self as macros %}
|
160 |
-
|
161 |
-
{%- macro test(text) %}<p>{{ text }}</p>{% endmacro %}
|
162 |
-
|
163 |
-
{{- macros.test('username') }}
|
164 |
-
EOF
|
165 |
-
), array('macro', 'import'), array('escape'));
|
166 |
-
|
167 |
-
$this->assertEquals('<p>username</p>', $twig->loadTemplate('index')->render(array()));
|
168 |
-
}
|
169 |
-
|
170 |
-
protected function getEnvironment($sandboxed, $options, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array(), $functions = array())
|
171 |
-
{
|
172 |
-
$loader = new Twig_Loader_Array($templates);
|
173 |
-
$twig = new Twig_Environment($loader, array_merge(array('debug' => true, 'cache' => false, 'autoescape' => false), $options));
|
174 |
-
$policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions);
|
175 |
-
$twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed));
|
176 |
-
|
177 |
-
return $twig;
|
178 |
-
}
|
179 |
-
}
|
180 |
-
|
181 |
-
class FooObject
|
182 |
-
{
|
183 |
-
public static $called = array('__toString' => 0, 'foo' => 0, 'getFooBar' => 0);
|
184 |
-
|
185 |
-
public $bar = 'bar';
|
186 |
-
|
187 |
-
public static function reset()
|
188 |
-
{
|
189 |
-
self::$called = array('__toString' => 0, 'foo' => 0, 'getFooBar' => 0);
|
190 |
-
}
|
191 |
-
|
192 |
-
public function __toString()
|
193 |
-
{
|
194 |
-
++self::$called['__toString'];
|
195 |
-
|
196 |
-
return 'foo';
|
197 |
-
}
|
198 |
-
|
199 |
-
public function foo()
|
200 |
-
{
|
201 |
-
++self::$called['foo'];
|
202 |
-
|
203 |
-
return 'foo';
|
204 |
-
}
|
205 |
-
|
206 |
-
public function getFooBar()
|
207 |
-
{
|
208 |
-
++self::$called['getFooBar'];
|
209 |
-
|
210 |
-
return 'foobar';
|
211 |
-
}
|
212 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/FileCachingTest.php
DELETED
@@ -1,70 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class Twig_Tests_FileCachingTest extends PHPUnit_Framework_TestCase
|
4 |
-
{
|
5 |
-
protected $fileName;
|
6 |
-
protected $env;
|
7 |
-
protected $tmpDir;
|
8 |
-
|
9 |
-
public function setUp()
|
10 |
-
{
|
11 |
-
$this->tmpDir = sys_get_temp_dir().'/TwigTests';
|
12 |
-
if (!file_exists($this->tmpDir)) {
|
13 |
-
@mkdir($this->tmpDir, 0777, true);
|
14 |
-
}
|
15 |
-
|
16 |
-
if (!is_writable($this->tmpDir)) {
|
17 |
-
$this->markTestSkipped(sprintf('Unable to run the tests as "%s" is not writable.', $this->tmpDir));
|
18 |
-
}
|
19 |
-
|
20 |
-
$this->env = new Twig_Environment(new Twig_Loader_String(), array('cache' => $this->tmpDir));
|
21 |
-
}
|
22 |
-
|
23 |
-
public function tearDown()
|
24 |
-
{
|
25 |
-
if ($this->fileName) {
|
26 |
-
unlink($this->fileName);
|
27 |
-
}
|
28 |
-
|
29 |
-
$this->removeDir($this->tmpDir);
|
30 |
-
}
|
31 |
-
|
32 |
-
public function testWritingCacheFiles()
|
33 |
-
{
|
34 |
-
$name = 'This is just text.';
|
35 |
-
$template = $this->env->loadTemplate($name);
|
36 |
-
$cacheFileName = $this->env->getCacheFilename($name);
|
37 |
-
|
38 |
-
$this->assertTrue(file_exists($cacheFileName), 'Cache file does not exist.');
|
39 |
-
$this->fileName = $cacheFileName;
|
40 |
-
}
|
41 |
-
|
42 |
-
public function testClearingCacheFiles()
|
43 |
-
{
|
44 |
-
$name = 'I will be deleted.';
|
45 |
-
$template = $this->env->loadTemplate($name);
|
46 |
-
$cacheFileName = $this->env->getCacheFilename($name);
|
47 |
-
|
48 |
-
$this->assertTrue(file_exists($cacheFileName), 'Cache file does not exist.');
|
49 |
-
$this->env->clearCacheFiles();
|
50 |
-
$this->assertFalse(file_exists($cacheFileName), 'Cache file was not cleared.');
|
51 |
-
}
|
52 |
-
|
53 |
-
private function removeDir($target)
|
54 |
-
{
|
55 |
-
$fp = opendir($target);
|
56 |
-
while (false !== $file = readdir($fp)) {
|
57 |
-
if (in_array($file, array('.', '..'))) {
|
58 |
-
continue;
|
59 |
-
}
|
60 |
-
|
61 |
-
if (is_dir($target.'/'.$file)) {
|
62 |
-
self::removeDir($target.'/'.$file);
|
63 |
-
} else {
|
64 |
-
unlink($target.'/'.$file);
|
65 |
-
}
|
66 |
-
}
|
67 |
-
closedir($fp);
|
68 |
-
rmdir($target);
|
69 |
-
}
|
70 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/errors/base.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
{% block content %}{% endblock %}
|
|
Twig/test/Twig/Tests/Fixtures/errors/index.html
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
{% extends 'base.html' %}
|
2 |
-
{% block content %}
|
3 |
-
{{ foo.bar }}
|
4 |
-
{% endblock %}
|
5 |
-
{% block foo %}
|
6 |
-
{{ foo.bar }}
|
7 |
-
{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/exceptions/unclosed_tag.test
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Exception for an unclosed tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block foo %}
|
5 |
-
{% if foo %}
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
{% for i in fo %}
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
{% endfor %}
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
{% endblock %}
|
19 |
-
--EXCEPTION--
|
20 |
-
Twig_Error_Syntax: Unexpected tag name "endblock" (expecting closing tag for the "if" tag defined near line 4) in "index.twig" at line 16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/array.test
DELETED
@@ -1,61 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports array notation
|
3 |
-
--TEMPLATE--
|
4 |
-
{# empty array #}
|
5 |
-
{{ []|join(',') }}
|
6 |
-
|
7 |
-
{{ [1, 2]|join(',') }}
|
8 |
-
{{ ['foo', "bar"]|join(',') }}
|
9 |
-
{{ {0: 1, 'foo': 'bar'}|join(',') }}
|
10 |
-
{{ {0: 1, 'foo': 'bar'}|keys|join(',') }}
|
11 |
-
|
12 |
-
{{ {0: 1, foo: 'bar'}|join(',') }}
|
13 |
-
{{ {0: 1, foo: 'bar'}|keys|join(',') }}
|
14 |
-
|
15 |
-
{# nested arrays #}
|
16 |
-
{% set a = [1, 2, [1, 2], {'foo': {'foo': 'bar'}}] %}
|
17 |
-
{{ a[2]|join(',') }}
|
18 |
-
{{ a[3]["foo"]|join(',') }}
|
19 |
-
|
20 |
-
{# works even if [] is used inside the array #}
|
21 |
-
{{ [foo[bar]]|join(',') }}
|
22 |
-
|
23 |
-
{# elements can be any expression #}
|
24 |
-
{{ ['foo'|upper, bar|upper, bar == foo]|join(',') }}
|
25 |
-
|
26 |
-
{# arrays can have a trailing , like in PHP #}
|
27 |
-
{{
|
28 |
-
[
|
29 |
-
1,
|
30 |
-
2,
|
31 |
-
]|join(',')
|
32 |
-
}}
|
33 |
-
|
34 |
-
{# keys can be any expression #}
|
35 |
-
{% set a = 1 %}
|
36 |
-
{% set b = "foo" %}
|
37 |
-
{% set ary = { (a): 'a', (b): 'b', 'c': 'c', (a ~ b): 'd' } %}
|
38 |
-
{{ ary|keys|join(',') }}
|
39 |
-
{{ ary|join(',') }}
|
40 |
-
--DATA--
|
41 |
-
return array('bar' => 'bar', 'foo' => array('bar' => 'bar'))
|
42 |
-
--EXPECT--
|
43 |
-
1,2
|
44 |
-
foo,bar
|
45 |
-
1,bar
|
46 |
-
0,foo
|
47 |
-
|
48 |
-
1,bar
|
49 |
-
0,foo
|
50 |
-
|
51 |
-
1,2
|
52 |
-
bar
|
53 |
-
|
54 |
-
bar
|
55 |
-
|
56 |
-
FOO,BAR,
|
57 |
-
|
58 |
-
1,2
|
59 |
-
|
60 |
-
1,foo,c,1foo
|
61 |
-
a,b,c,d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/array_call.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports method calls
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ items.foo }}
|
5 |
-
{{ items['foo'] }}
|
6 |
-
{{ items[foo] }}
|
7 |
-
{{ items[items[foo]] }}
|
8 |
-
--DATA--
|
9 |
-
return array('foo' => 'bar', 'items' => array('foo' => 'bar', 'bar' => 'foo'))
|
10 |
-
--EXPECT--
|
11 |
-
bar
|
12 |
-
bar
|
13 |
-
foo
|
14 |
-
bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/binary.test
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports binary operations (+, -, *, /, ~, %, and, or)
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 + 1 }}
|
5 |
-
{{ 2 - 1 }}
|
6 |
-
{{ 2 * 2 }}
|
7 |
-
{{ 2 / 2 }}
|
8 |
-
{{ 3 % 2 }}
|
9 |
-
{{ 1 and 1 }}
|
10 |
-
{{ 1 and 0 }}
|
11 |
-
{{ 0 and 1 }}
|
12 |
-
{{ 0 and 0 }}
|
13 |
-
{{ 1 or 1 }}
|
14 |
-
{{ 1 or 0 }}
|
15 |
-
{{ 0 or 1 }}
|
16 |
-
{{ 0 or 0 }}
|
17 |
-
{{ 0 or 1 and 0 }}
|
18 |
-
{{ 1 or 0 and 1 }}
|
19 |
-
{{ "foo" ~ "bar" }}
|
20 |
-
{{ foo ~ "bar" }}
|
21 |
-
{{ "foo" ~ bar }}
|
22 |
-
{{ foo ~ bar }}
|
23 |
-
{{ 20 // 7 }}
|
24 |
-
--DATA--
|
25 |
-
return array('foo' => 'bar', 'bar' => 'foo')
|
26 |
-
--EXPECT--
|
27 |
-
2
|
28 |
-
1
|
29 |
-
4
|
30 |
-
1
|
31 |
-
1
|
32 |
-
1
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
1
|
37 |
-
1
|
38 |
-
1
|
39 |
-
|
40 |
-
|
41 |
-
1
|
42 |
-
foobar
|
43 |
-
barbar
|
44 |
-
foofoo
|
45 |
-
barfoo
|
46 |
-
2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/bitwise.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports bitwise operations
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 b-and 5 }}
|
5 |
-
{{ 1 b-or 5 }}
|
6 |
-
{{ 1 b-xor 5 }}
|
7 |
-
{{ (1 and 0 b-or 0) is sameas(1 and (0 b-or 0)) ? 'ok' : 'ko' }}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
1
|
12 |
-
5
|
13 |
-
4
|
14 |
-
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/comparison.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports comparison operators (==, !=, <, >, >=, <=)
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 > 2 }}/{{ 1 > 1 }}/{{ 1 >= 2 }}/{{ 1 >= 1 }}
|
5 |
-
{{ 1 < 2 }}/{{ 1 < 1 }}/{{ 1 <= 2 }}/{{ 1 <= 1 }}
|
6 |
-
{{ 1 == 1 }}/{{ 1 == 2 }}
|
7 |
-
{{ 1 != 1 }}/{{ 1 != 2 }}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
///1
|
12 |
-
1//1/1
|
13 |
-
1/
|
14 |
-
/1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/dotdot.test
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports the .. operator
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for i in 0..10 %}{{ i }} {% endfor %}
|
5 |
-
|
6 |
-
{% for letter in 'a'..'z' %}{{ letter }} {% endfor %}
|
7 |
-
|
8 |
-
{% for letter in 'a'|upper..'z'|upper %}{{ letter }} {% endfor %}
|
9 |
-
|
10 |
-
{% for i in foo[0]..foo[1] %}{{ i }} {% endfor %}
|
11 |
-
|
12 |
-
{% for i in 0 + 1 .. 10 - 1 %}{{ i }} {% endfor %}
|
13 |
-
--DATA--
|
14 |
-
return array('foo' => array(1, 10))
|
15 |
-
--EXPECT--
|
16 |
-
0 1 2 3 4 5 6 7 8 9 10
|
17 |
-
a b c d e f g h i j k l m n o p q r s t u v w x y z
|
18 |
-
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
|
19 |
-
1 2 3 4 5 6 7 8 9 10
|
20 |
-
1 2 3 4 5 6 7 8 9
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/grouping.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports grouping of expressions
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ (2 + 2) / 2 }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/literals.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports literals
|
3 |
-
--TEMPLATE--
|
4 |
-
1 {{ true }}
|
5 |
-
2 {{ TRUE }}
|
6 |
-
3 {{ false }}
|
7 |
-
4 {{ FALSE }}
|
8 |
-
5 {{ none }}
|
9 |
-
6 {{ NONE }}
|
10 |
-
7 {{ null }}
|
11 |
-
8 {{ NULL }}
|
12 |
-
--DATA--
|
13 |
-
return array()
|
14 |
-
--EXPECT--
|
15 |
-
1 1
|
16 |
-
2 1
|
17 |
-
3
|
18 |
-
4
|
19 |
-
5
|
20 |
-
6
|
21 |
-
7
|
22 |
-
8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/magic_call.test
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports __call() for attributes
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ foo.foo }}
|
5 |
-
{{ foo.bar }}
|
6 |
-
--DATA--
|
7 |
-
class TestClassForMagicCallAttributes
|
8 |
-
{
|
9 |
-
public function getBar()
|
10 |
-
{
|
11 |
-
return 'bar_from_getbar';
|
12 |
-
}
|
13 |
-
|
14 |
-
public function __call($method, $arguments)
|
15 |
-
{
|
16 |
-
if ('foo' === $method)
|
17 |
-
{
|
18 |
-
return 'foo_from_call';
|
19 |
-
}
|
20 |
-
|
21 |
-
return false;
|
22 |
-
}
|
23 |
-
}
|
24 |
-
return array('foo' => new TestClassForMagicCallAttributes())
|
25 |
-
--EXPECT--
|
26 |
-
foo_from_call
|
27 |
-
bar_from_getbar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/method_call.test
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports method calls
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ items.foo.foo }}
|
5 |
-
{{ items.foo.getFoo() }}
|
6 |
-
{{ items.foo.bar }}
|
7 |
-
{{ items.foo['bar'] }}
|
8 |
-
{{ items.foo.bar('a', 43) }}
|
9 |
-
{{ items.foo.bar(foo) }}
|
10 |
-
{{ items.foo.self.foo() }}
|
11 |
-
{{ items.foo.is }}
|
12 |
-
{{ items.foo.in }}
|
13 |
-
{{ items.foo.not }}
|
14 |
-
--DATA--
|
15 |
-
return array('foo' => 'bar', 'items' => array('foo' => new TwigTestFoo(), 'bar' => 'foo'))
|
16 |
-
--CONFIG--
|
17 |
-
return array('strict_variables' => false)
|
18 |
-
--EXPECT--
|
19 |
-
foo
|
20 |
-
foo
|
21 |
-
bar
|
22 |
-
|
23 |
-
bar_a-43
|
24 |
-
bar_bar
|
25 |
-
foo
|
26 |
-
is
|
27 |
-
in
|
28 |
-
not
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/postfix.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig parses postfix expressions
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as macros %}
|
5 |
-
|
6 |
-
{% macro foo() %}foo{% endmacro %}
|
7 |
-
|
8 |
-
{{ 'a' }}
|
9 |
-
{{ 'a'|upper }}
|
10 |
-
{{ ('a')|upper }}
|
11 |
-
{{ -1|upper }}
|
12 |
-
{{ macros.foo() }}
|
13 |
-
{{ (macros).foo() }}
|
14 |
-
--DATA--
|
15 |
-
return array();
|
16 |
-
--EXPECT--
|
17 |
-
a
|
18 |
-
A
|
19 |
-
A
|
20 |
-
-1
|
21 |
-
foo
|
22 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/strings.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports string interpolation
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "foo #{"foo #{bar} baz"} baz" }}
|
5 |
-
{{ "foo #{bar}#{bar} baz" }}
|
6 |
-
--DATA--
|
7 |
-
return array('bar' => 'BAR');
|
8 |
-
--EXPECT--
|
9 |
-
foo foo BAR baz baz
|
10 |
-
foo BARBAR baz
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/ternary_operator.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports the ternary operator
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 ? 'YES' : 'NO' }}
|
5 |
-
{{ 0 ? 'YES' : 'NO' }}
|
6 |
-
{{ 0 ? 'YES' : (1 ? 'YES1' : 'NO1') }}
|
7 |
-
{{ 0 ? 'YES' : (0 ? 'YES1' : 'NO1') }}
|
8 |
-
{{ 1 == 1 ? 'foo<br />':'' }}
|
9 |
-
{{ foo ~ (bar ? ('-' ~ bar) : '') }}
|
10 |
-
--DATA--
|
11 |
-
return array('foo' => 'foo', 'bar' => 'bar')
|
12 |
-
--EXPECT--
|
13 |
-
YES
|
14 |
-
NO
|
15 |
-
YES1
|
16 |
-
NO1
|
17 |
-
foo<br />
|
18 |
-
foo-bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_noelse.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports the ternary operator
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 ? 'YES' }}
|
5 |
-
{{ 0 ? 'YES' }}
|
6 |
-
--DATA--
|
7 |
-
return array()
|
8 |
-
--EXPECT--
|
9 |
-
YES
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_nothen.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports the ternary operator
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 'YES' ?: 'NO' }}
|
5 |
-
{{ 0 ?: 'NO' }}
|
6 |
-
--DATA--
|
7 |
-
return array()
|
8 |
-
--EXPECT--
|
9 |
-
YES
|
10 |
-
NO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/unary.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports unary operators (not, -, +)
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ not 1 }}/{{ not 0 }}
|
5 |
-
{{ +1 + 1 }}/{{ -1 - 1 }}
|
6 |
-
{{ not (false or true) }}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
/1
|
11 |
-
2/-2
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/expressions/unary_precedence.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig unary operators precedence
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ -1 - 1 }}
|
5 |
-
{{ -1 - -1 }}
|
6 |
-
{{ -1 * -1 }}
|
7 |
-
{{ 4 / -1 * 5 }}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
-2
|
12 |
-
0
|
13 |
-
1
|
14 |
-
-20
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/abs.test
DELETED
@@ -1,30 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"abs" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ (-5.5)|abs }}
|
5 |
-
{{ (-5)|abs }}
|
6 |
-
{{ (-0)|abs }}
|
7 |
-
{{ 0|abs }}
|
8 |
-
{{ 5|abs }}
|
9 |
-
{{ 5.5|abs }}
|
10 |
-
{{ number1|abs }}
|
11 |
-
{{ number2|abs }}
|
12 |
-
{{ number3|abs }}
|
13 |
-
{{ number4|abs }}
|
14 |
-
{{ number5|abs }}
|
15 |
-
{{ number6|abs }}
|
16 |
-
--DATA--
|
17 |
-
return array('number1' => -5.5, 'number2' => -5, 'number3' => -0, 'number4' => 0, 'number5' => 5, 'number6' => 5.5)
|
18 |
-
--EXPECT--
|
19 |
-
5.5
|
20 |
-
5
|
21 |
-
0
|
22 |
-
0
|
23 |
-
5
|
24 |
-
5.5
|
25 |
-
5.5
|
26 |
-
5
|
27 |
-
0
|
28 |
-
0
|
29 |
-
5
|
30 |
-
5.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/convert_encoding.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"convert_encoding" filter
|
3 |
-
--CONDITION--
|
4 |
-
function_exists('iconv') || function_exists('mb_convert_encoding')
|
5 |
-
--TEMPLATE--
|
6 |
-
{{ "愛していますか?"|convert_encoding('ISO-2022-JP', 'UTF-8')|convert_encoding('UTF-8', 'ISO-2022-JP') }}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
愛していますか?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/date.test
DELETED
@@ -1,61 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ date1|date }}
|
5 |
-
{{ date1|date('d/m/Y') }}
|
6 |
-
{{ date1|date('d/m/Y H:i:s', 'Europe/Paris') }}
|
7 |
-
{{ date1|date('d/m/Y H:i:s P', 'Europe/Paris') }}
|
8 |
-
{{ date1|date('d/m/Y H:i:s P', 'America/Chicago') }}
|
9 |
-
{{ date1|date('e') }}
|
10 |
-
{{ date1|date('d/m/Y H:i:s') }}
|
11 |
-
{{ date2|date }}
|
12 |
-
{{ date2|date('d/m/Y') }}
|
13 |
-
{{ date2|date('d/m/Y H:i:s', 'Europe/Paris') }}
|
14 |
-
{{ date2|date('d/m/Y H:i:s', timezone1) }}
|
15 |
-
{{ date2|date('d/m/Y H:i:s') }}
|
16 |
-
{{ date3|date }}
|
17 |
-
{{ date3|date('d/m/Y') }}
|
18 |
-
{{ date4|date }}
|
19 |
-
{{ date4|date('d/m/Y') }}
|
20 |
-
{{ date5|date }}
|
21 |
-
{{ date5|date('d/m/Y') }}
|
22 |
-
{{ date6|date('d/m/Y H:i:s P', 'Europe/Paris') }}
|
23 |
-
{{ date6|date('d/m/Y H:i:s P', 'Asia/Hong_Kong') }}
|
24 |
-
{{ date6|date('d/m/Y H:i:s P', false) }}
|
25 |
-
{{ date6|date('e', 'Europe/Paris') }}
|
26 |
-
{{ date6|date('e', false) }}
|
27 |
-
--DATA--
|
28 |
-
date_default_timezone_set('UTC');
|
29 |
-
return array(
|
30 |
-
'date1' => mktime(13, 45, 0, 10, 4, 2010),
|
31 |
-
'date2' => new DateTime('2010-10-04 13:45'),
|
32 |
-
'date3' => '2010-10-04 13:45',
|
33 |
-
'date4' => 1286199900,
|
34 |
-
'date5' => -86410,
|
35 |
-
'date6' => new DateTime('2010-10-04 13:45', new DateTimeZone('America/New_York')),
|
36 |
-
'timezone1' => new DateTimeZone('America/New_York'),
|
37 |
-
)
|
38 |
-
--EXPECT--
|
39 |
-
October 4, 2010 13:45
|
40 |
-
04/10/2010
|
41 |
-
04/10/2010 15:45:00
|
42 |
-
04/10/2010 15:45:00 +02:00
|
43 |
-
04/10/2010 08:45:00 -05:00
|
44 |
-
UTC
|
45 |
-
04/10/2010 13:45:00
|
46 |
-
October 4, 2010 13:45
|
47 |
-
04/10/2010
|
48 |
-
04/10/2010 15:45:00
|
49 |
-
04/10/2010 09:45:00
|
50 |
-
04/10/2010 13:45:00
|
51 |
-
October 4, 2010 13:45
|
52 |
-
04/10/2010
|
53 |
-
October 4, 2010 13:45
|
54 |
-
04/10/2010
|
55 |
-
December 30, 1969 23:59
|
56 |
-
30/12/1969
|
57 |
-
04/10/2010 19:45:00 +02:00
|
58 |
-
05/10/2010 01:45:00 +08:00
|
59 |
-
04/10/2010 13:45:00 -04:00
|
60 |
-
Europe/Paris
|
61 |
-
America/New_York
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/date_default_format.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ date1|date }}
|
5 |
-
{{ date1|date('d/m/Y') }}
|
6 |
-
--DATA--
|
7 |
-
date_default_timezone_set('UTC');
|
8 |
-
$twig->getExtension('core')->setDateFormat('Y-m-d', '%d days %h hours');
|
9 |
-
return array(
|
10 |
-
'date1' => mktime(13, 45, 0, 10, 4, 2010),
|
11 |
-
)
|
12 |
-
--EXPECT--
|
13 |
-
2010-10-04
|
14 |
-
04/10/2010
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" filter (interval support as of PHP 5.3)
|
3 |
-
--CONDITION--
|
4 |
-
version_compare(phpversion(), '5.3.0', '>=')
|
5 |
-
--TEMPLATE--
|
6 |
-
{{ date2|date }}
|
7 |
-
{{ date2|date('%d days') }}
|
8 |
-
--DATA--
|
9 |
-
date_default_timezone_set('UTC');
|
10 |
-
$twig->getExtension('core')->setDateFormat('Y-m-d', '%d days %h hours');
|
11 |
-
return array(
|
12 |
-
'date2' => new DateInterval('P2D'),
|
13 |
-
)
|
14 |
-
--EXPECT--
|
15 |
-
2 days 0 hours
|
16 |
-
2 days
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/date_interval.test
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" filter (interval support as of PHP 5.3)
|
3 |
-
--CONDITION--
|
4 |
-
version_compare(phpversion(), '5.3.0', '>=')
|
5 |
-
--TEMPLATE--
|
6 |
-
{{ date1|date }}
|
7 |
-
{{ date1|date('%d days %h hours') }}
|
8 |
-
{{ date1|date('%d days %h hours', timezone1) }}
|
9 |
-
--DATA--
|
10 |
-
date_default_timezone_set('UTC');
|
11 |
-
return array(
|
12 |
-
'date1' => new DateInterval('P2D'),
|
13 |
-
// This should have no effect on DateInterval formatting
|
14 |
-
'timezone1' => new DateTimeZone('America/New_York'),
|
15 |
-
)
|
16 |
-
--EXPECT--
|
17 |
-
2 days
|
18 |
-
2 days 0 hours
|
19 |
-
2 days 0 hours
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/date_modify.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date_modify" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ date1|date_modify('-1day')|date('Y-m-d H:i:s') }}
|
5 |
-
{{ date2|date_modify('-1day')|date('Y-m-d H:i:s') }}
|
6 |
-
--DATA--
|
7 |
-
date_default_timezone_set('UTC');
|
8 |
-
return array(
|
9 |
-
'date1' => '2010-10-04 13:45',
|
10 |
-
'date2' => new DateTime('2010-10-04 13:45'),
|
11 |
-
)
|
12 |
-
--EXPECT--
|
13 |
-
2010-10-03 13:45:00
|
14 |
-
2010-10-03 13:45:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ date|date(format='d/m/Y H:i:s P', timezone='America/Chicago') }}
|
5 |
-
{{ date|date(timezone='America/Chicago', format='d/m/Y H:i:s P') }}
|
6 |
-
{{ date|date(timezone='America/Chicago', 'd/m/Y H:i:s P') }}
|
7 |
-
{{ date|date('d/m/Y H:i:s P', timezone='America/Chicago') }}
|
8 |
-
--DATA--
|
9 |
-
date_default_timezone_set('UTC');
|
10 |
-
return array('date' => mktime(13, 45, 0, 10, 4, 2010))
|
11 |
-
--EXPECT--
|
12 |
-
04/10/2010 08:45:00 -05:00
|
13 |
-
04/10/2010 08:45:00 -05:00
|
14 |
-
04/10/2010 08:45:00 -05:00
|
15 |
-
04/10/2010 08:45:00 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/default.test
DELETED
@@ -1,150 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"default" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
Variable:
|
5 |
-
{{ definedVar |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
6 |
-
{{ zeroVar |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
7 |
-
{{ emptyVar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
8 |
-
{{ nullVar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
9 |
-
{{ undefinedVar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
10 |
-
Array access:
|
11 |
-
{{ nested.definedVar |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
12 |
-
{{ nested['definedVar'] |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
13 |
-
{{ nested.zeroVar |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
14 |
-
{{ nested.emptyVar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
15 |
-
{{ nested.nullVar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
16 |
-
{{ nested.undefinedVar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
17 |
-
{{ nested['undefinedVar'] |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
18 |
-
{{ undefinedVar.foo |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
19 |
-
Plain values:
|
20 |
-
{{ 'defined' |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
21 |
-
{{ 0 |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
22 |
-
{{ '' |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
23 |
-
{{ null |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
24 |
-
Precedence:
|
25 |
-
{{ 'o' ~ nullVar |default('k') }}
|
26 |
-
{{ 'o' ~ nested.nullVar |default('k') }}
|
27 |
-
Object methods:
|
28 |
-
{{ object.foo |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
29 |
-
{{ object.undefinedMethod |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
30 |
-
{{ object.getFoo() |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
31 |
-
{{ object.getFoo('a') |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
32 |
-
{{ object.undefinedMethod() |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
33 |
-
{{ object.undefinedMethod('a') |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
34 |
-
Deep nested:
|
35 |
-
{{ nested.undefinedVar.foo.bar |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
36 |
-
{{ nested.definedArray.0 |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
37 |
-
{{ nested['definedArray'][0] |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
38 |
-
{{ object.self.foo |default('default') is sameas('default') ? 'ko' : 'ok' }}
|
39 |
-
{{ object.self.undefinedMethod |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
40 |
-
{{ object.undefinedMethod.self |default('default') is sameas('default') ? 'ok' : 'ko' }}
|
41 |
-
--DATA--
|
42 |
-
return array(
|
43 |
-
'definedVar' => 'defined',
|
44 |
-
'zeroVar' => 0,
|
45 |
-
'emptyVar' => '',
|
46 |
-
'nullVar' => null,
|
47 |
-
'nested' => array(
|
48 |
-
'definedVar' => 'defined',
|
49 |
-
'zeroVar' => 0,
|
50 |
-
'emptyVar' => '',
|
51 |
-
'nullVar' => null,
|
52 |
-
'definedArray' => array(0),
|
53 |
-
),
|
54 |
-
'object' => new TwigTestFoo(),
|
55 |
-
)
|
56 |
-
--CONFIG--
|
57 |
-
return array('strict_variables' => false)
|
58 |
-
--EXPECT--
|
59 |
-
Variable:
|
60 |
-
ok
|
61 |
-
ok
|
62 |
-
ok
|
63 |
-
ok
|
64 |
-
ok
|
65 |
-
Array access:
|
66 |
-
ok
|
67 |
-
ok
|
68 |
-
ok
|
69 |
-
ok
|
70 |
-
ok
|
71 |
-
ok
|
72 |
-
ok
|
73 |
-
ok
|
74 |
-
Plain values:
|
75 |
-
ok
|
76 |
-
ok
|
77 |
-
ok
|
78 |
-
ok
|
79 |
-
Precedence:
|
80 |
-
ok
|
81 |
-
ok
|
82 |
-
Object methods:
|
83 |
-
ok
|
84 |
-
ok
|
85 |
-
ok
|
86 |
-
ok
|
87 |
-
ok
|
88 |
-
ok
|
89 |
-
Deep nested:
|
90 |
-
ok
|
91 |
-
ok
|
92 |
-
ok
|
93 |
-
ok
|
94 |
-
ok
|
95 |
-
ok
|
96 |
-
--DATA--
|
97 |
-
return array(
|
98 |
-
'definedVar' => 'defined',
|
99 |
-
'zeroVar' => 0,
|
100 |
-
'emptyVar' => '',
|
101 |
-
'nullVar' => null,
|
102 |
-
'nested' => array(
|
103 |
-
'definedVar' => 'defined',
|
104 |
-
'zeroVar' => 0,
|
105 |
-
'emptyVar' => '',
|
106 |
-
'nullVar' => null,
|
107 |
-
'definedArray' => array(0),
|
108 |
-
),
|
109 |
-
'object' => new TwigTestFoo(),
|
110 |
-
)
|
111 |
-
--CONFIG--
|
112 |
-
return array('strict_variables' => true)
|
113 |
-
--EXPECT--
|
114 |
-
Variable:
|
115 |
-
ok
|
116 |
-
ok
|
117 |
-
ok
|
118 |
-
ok
|
119 |
-
ok
|
120 |
-
Array access:
|
121 |
-
ok
|
122 |
-
ok
|
123 |
-
ok
|
124 |
-
ok
|
125 |
-
ok
|
126 |
-
ok
|
127 |
-
ok
|
128 |
-
ok
|
129 |
-
Plain values:
|
130 |
-
ok
|
131 |
-
ok
|
132 |
-
ok
|
133 |
-
ok
|
134 |
-
Precedence:
|
135 |
-
ok
|
136 |
-
ok
|
137 |
-
Object methods:
|
138 |
-
ok
|
139 |
-
ok
|
140 |
-
ok
|
141 |
-
ok
|
142 |
-
ok
|
143 |
-
ok
|
144 |
-
Deep nested:
|
145 |
-
ok
|
146 |
-
ok
|
147 |
-
ok
|
148 |
-
ok
|
149 |
-
ok
|
150 |
-
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/dynamic_filter.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
dynamic filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 'bar'|foo_path }}
|
5 |
-
{{ 'bar'|a_foo_b_bar }}
|
6 |
-
--DATA--
|
7 |
-
return array()
|
8 |
-
--EXPECT--
|
9 |
-
foo/bar
|
10 |
-
a/b/bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/escape.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"escape" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "foo <br />"|e }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
foo <br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/escape_non_supported_charset.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"escape" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "愛していますか? <br />"|e }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
愛していますか? <br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/force_escape.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"escape" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{% set foo %}
|
5 |
-
foo<br />
|
6 |
-
{% endset %}
|
7 |
-
|
8 |
-
{{ foo|e('html') -}}
|
9 |
-
{{ foo|e('js') }}
|
10 |
-
{% autoescape true %}
|
11 |
-
{{ foo }}
|
12 |
-
{% endautoescape %}
|
13 |
-
--DATA--
|
14 |
-
return array()
|
15 |
-
--EXPECT--
|
16 |
-
foo<br />
|
17 |
-
\x20\x20\x20\x20foo\x3Cbr\x20\x2F\x3E\x0A
|
18 |
-
foo<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/format.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"format" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ string|format(foo, 3) }}
|
5 |
-
--DATA--
|
6 |
-
return array('string' => '%s/%d', 'foo' => 'bar')
|
7 |
-
--EXPECT--
|
8 |
-
bar/3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/join.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"join" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ ["foo", "bar"]|join(', ') }}
|
5 |
-
{{ foo|join(', ') }}
|
6 |
-
{{ bar|join(', ') }}
|
7 |
-
--DATA--
|
8 |
-
return array('foo' => new TwigTestFoo(), 'bar' => new ArrayObject(array(3, 4)))
|
9 |
-
--EXPECT--
|
10 |
-
foo, bar
|
11 |
-
1, 2
|
12 |
-
3, 4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/json_encode.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"json_encode" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "foo"|json_encode|raw }}
|
5 |
-
{{ foo|json_encode|raw }}
|
6 |
-
{{ [foo, "foo"]|json_encode|raw }}
|
7 |
-
--DATA--
|
8 |
-
return array('foo' => new Twig_Markup('foo', 'UTF-8'))
|
9 |
-
--EXPECT--
|
10 |
-
"foo"
|
11 |
-
"foo"
|
12 |
-
["foo","foo"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/length.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"length" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ array|length }}
|
5 |
-
{{ string|length }}
|
6 |
-
{{ number|length }}
|
7 |
-
{{ markup|length }}
|
8 |
-
--DATA--
|
9 |
-
return array('array' => array(1, 4), 'string' => 'foo', 'number' => 1000, 'markup' => new Twig_Markup('foo', 'UTF-8'))
|
10 |
-
--EXPECT--
|
11 |
-
2
|
12 |
-
3
|
13 |
-
4
|
14 |
-
3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/length_utf8.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"length" filter
|
3 |
-
--CONDITION--
|
4 |
-
function_exists('mb_get_info')
|
5 |
-
--TEMPLATE--
|
6 |
-
{{ string|length }}
|
7 |
-
{{ markup|length }}
|
8 |
-
--DATA--
|
9 |
-
return array('string' => 'été', 'markup' => new Twig_Markup('foo', 'UTF-8'))
|
10 |
-
--EXPECT--
|
11 |
-
3
|
12 |
-
3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/merge.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"merge" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ items|merge({'bar': 'foo'})|join }}
|
5 |
-
{{ items|merge({'bar': 'foo'})|keys|join }}
|
6 |
-
{{ {'bar': 'foo'}|merge(items)|join }}
|
7 |
-
{{ {'bar': 'foo'}|merge(items)|keys|join }}
|
8 |
-
{{ numerics|merge([4, 5, 6])|join }}
|
9 |
-
--DATA--
|
10 |
-
return array('items' => array('foo' => 'bar'), 'numerics' => array(1, 2, 3))
|
11 |
-
--EXPECT--
|
12 |
-
barfoo
|
13 |
-
foobar
|
14 |
-
foobar
|
15 |
-
barfoo
|
16 |
-
123456
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/nl2br.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"nl2br" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "I like Twig.\nYou will like it too.\n\nEverybody like it!"|nl2br }}
|
5 |
-
{{ text|nl2br }}
|
6 |
-
--DATA--
|
7 |
-
return array('text' => "If you have some <strong>HTML</strong>\nit will be escaped.")
|
8 |
-
--EXPECT--
|
9 |
-
I like Twig.<br />
|
10 |
-
You will like it too.<br />
|
11 |
-
<br />
|
12 |
-
Everybody like it!
|
13 |
-
If you have some <strong>HTML</strong><br />
|
14 |
-
it will be escaped.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/number_format.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"number_format" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 20|number_format }}
|
5 |
-
{{ 20.25|number_format }}
|
6 |
-
{{ 20.25|number_format(2) }}
|
7 |
-
{{ 20.25|number_format(2, ',') }}
|
8 |
-
{{ 1020.25|number_format(2, ',') }}
|
9 |
-
{{ 1020.25|number_format(2, ',', '.') }}
|
10 |
-
--DATA--
|
11 |
-
return array();
|
12 |
-
--EXPECT--
|
13 |
-
20
|
14 |
-
20
|
15 |
-
20.25
|
16 |
-
20,25
|
17 |
-
1,020,25
|
18 |
-
1.020,25
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/number_format_default.test
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"number_format" filter with defaults.
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 20|number_format }}
|
5 |
-
{{ 20.25|number_format }}
|
6 |
-
{{ 20.25|number_format(1) }}
|
7 |
-
{{ 20.25|number_format(2, ',') }}
|
8 |
-
{{ 1020.25|number_format }}
|
9 |
-
{{ 1020.25|number_format(2, ',') }}
|
10 |
-
{{ 1020.25|number_format(2, ',', '.') }}
|
11 |
-
--DATA--
|
12 |
-
$twig->getExtension('core')->setNumberFormat(2, '!', '=');
|
13 |
-
return array();
|
14 |
-
--EXPECT--
|
15 |
-
20!00
|
16 |
-
20!25
|
17 |
-
20!3
|
18 |
-
20,25
|
19 |
-
1=020!25
|
20 |
-
1=020,25
|
21 |
-
1.020,25
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/replace.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"replace" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "I like %this% and %that%."|replace({'%this%': "foo", '%that%': "bar"}) }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
I like foo and bar.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/reverse.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"reverse" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ [1, 2, 3, 4]|reverse|join('') }}
|
5 |
-
{{ '1234évènement'|reverse }}
|
6 |
-
{{ arr|reverse|join('') }}
|
7 |
-
{{ {'a': 'c', 'b': 'a'}|reverse()|join(',') }}
|
8 |
-
{{ {'a': 'c', 'b': 'a'}|reverse(preserveKeys=true)|join(glue=',') }}
|
9 |
-
{{ {'a': 'c', 'b': 'a'}|reverse(preserve_keys=true)|join(glue=',') }}
|
10 |
-
--DATA--
|
11 |
-
return array('arr' => new ArrayObject(array(1, 2, 3, 4)))
|
12 |
-
--EXPECT--
|
13 |
-
4321
|
14 |
-
tnemenèvé4321
|
15 |
-
4321
|
16 |
-
a,c
|
17 |
-
a,c
|
18 |
-
a,c
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/slice.test
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"slice" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ [1, 2, 3, 4][1:2]|join('') }}
|
5 |
-
{{ {a: 1, b: 2, c: 3, d: 4}[1:2]|join('') }}
|
6 |
-
{{ [1, 2, 3, 4][start:length]|join('') }}
|
7 |
-
{{ [1, 2, 3, 4]|slice(1, 2)|join('') }}
|
8 |
-
{{ [1, 2, 3, 4]|slice(1, 2)|keys|join('') }}
|
9 |
-
{{ [1, 2, 3, 4]|slice(1, 2, true)|keys|join('') }}
|
10 |
-
{{ {a: 1, b: 2, c: 3, d: 4}|slice(1, 2)|join('') }}
|
11 |
-
{{ {a: 1, b: 2, c: 3, d: 4}|slice(1, 2)|keys|join('') }}
|
12 |
-
{{ '1234'|slice(1, 2) }}
|
13 |
-
{{ '1234'[1:2] }}
|
14 |
-
{{ arr|slice(1, 2)|join('') }}
|
15 |
-
{{ arr[1:2]|join('') }}
|
16 |
-
|
17 |
-
{{ [1, 2, 3, 4]|slice(1)|join('') }}
|
18 |
-
{{ [1, 2, 3, 4][1:]|join('') }}
|
19 |
-
{{ '1234'|slice(1) }}
|
20 |
-
{{ '1234'[1:] }}
|
21 |
-
{{ '1234'[:1] }}
|
22 |
-
--DATA--
|
23 |
-
return array('start' => 1, 'length' => 2, 'arr' => new ArrayObject(array(1, 2, 3, 4)))
|
24 |
-
--EXPECT--
|
25 |
-
23
|
26 |
-
23
|
27 |
-
23
|
28 |
-
23
|
29 |
-
01
|
30 |
-
12
|
31 |
-
23
|
32 |
-
bc
|
33 |
-
23
|
34 |
-
23
|
35 |
-
23
|
36 |
-
23
|
37 |
-
|
38 |
-
234
|
39 |
-
234
|
40 |
-
234
|
41 |
-
234
|
42 |
-
1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/sort.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"sort" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ array1|sort|join }}
|
5 |
-
{{ array2|sort|join }}
|
6 |
-
--DATA--
|
7 |
-
return array('array1' => array(4, 1), 'array2' => array('foo', 'bar'))
|
8 |
-
--EXPECT--
|
9 |
-
14
|
10 |
-
barfoo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/special_chars.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"☃" custom filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 'foo'|☃ }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
☃foo☃
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/split.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"split" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ "one,two,three,four,five"|split(',')|join('-') }}
|
5 |
-
{{ foo|split(',')|join('-') }}
|
6 |
-
{{ foo|split(',', 3)|join('-') }}
|
7 |
-
{{ baz|split('')|join('-') }}
|
8 |
-
{{ baz|split('', 2)|join('-') }}
|
9 |
-
{{ foo|split(',', -2)|join('-') }}
|
10 |
-
--DATA--
|
11 |
-
return array('foo' => "one,two,three,four,five", 'baz' => '12345',)
|
12 |
-
--EXPECT--
|
13 |
-
one-two-three-four-five
|
14 |
-
one-two-three-four-five
|
15 |
-
one-two-three,four,five
|
16 |
-
1-2-3-4-5
|
17 |
-
12-34-5
|
18 |
-
one-two-three
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/filters/trim.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"trim" filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ " I like Twig. "|trim }}
|
5 |
-
{{ text|trim }}
|
6 |
-
{{ " foo/"|trim("/") }}
|
7 |
-
--DATA--
|
8 |
-
return array('text' => " If you have some <strong>HTML</strong> it will be escaped. ")
|
9 |
-
--EXPECT--
|
10 |
-
I like Twig.
|
11 |
-
If you have some <strong>HTML</strong> it will be escaped.
|
12 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/attribute.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"attribute" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ attribute(obj, method) }}
|
5 |
-
{{ attribute(array, item) }}
|
6 |
-
{{ attribute(obj, "bar", ["a", "b"]) }}
|
7 |
-
--DATA--
|
8 |
-
return array('obj' => new TwigTestFoo(), 'method' => 'foo', 'array' => array('foo' => 'bar'), 'item' => 'foo')
|
9 |
-
--EXPECT--
|
10 |
-
foo
|
11 |
-
bar
|
12 |
-
bar_a-b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/block.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"block" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends 'base.twig' %}
|
5 |
-
{% block bar %}BAR{% endblock %}
|
6 |
-
--TEMPLATE(base.twig)--
|
7 |
-
{% block foo %}{{ block('bar') }}{% endblock %}
|
8 |
-
{% block bar %}BAR_BASE{% endblock %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
BARBAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/constant.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"constant" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ constant('DATE_W3C') == expect ? 'true' : 'false' }}
|
5 |
-
{{ constant('ARRAY_AS_PROPS', object) }}
|
6 |
-
--DATA--
|
7 |
-
return array('expect' => DATE_W3C, 'object' => new ArrayObject(array('hi')));
|
8 |
-
--EXPECT--
|
9 |
-
true
|
10 |
-
2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/cycle.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"cycle" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for i in 0..6 %}
|
5 |
-
{{ cycle(array1, i) }}-{{ cycle(array2, i) }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('array1' => array('odd', 'even'), 'array2' => array('apple', 'orange', 'citrus'))
|
9 |
-
--EXPECT--
|
10 |
-
odd-apple
|
11 |
-
even-orange
|
12 |
-
odd-citrus
|
13 |
-
even-apple
|
14 |
-
odd-orange
|
15 |
-
even-citrus
|
16 |
-
odd-apple
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/date.test
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ date() == date('now') ? 'OK' : 'KO' }}
|
5 |
-
{{ date() > date('-1day') ? 'OK' : 'KO' }}
|
6 |
-
{{ date(date1) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
7 |
-
{{ date(date2) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
8 |
-
{{ date(date3) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
9 |
-
{{ date(date4) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
10 |
-
--DATA--
|
11 |
-
date_default_timezone_set('UTC');
|
12 |
-
return array(
|
13 |
-
'date1' => mktime(13, 45, 0, 10, 4, 2010),
|
14 |
-
'date2' => new DateTime('2010-10-04 13:45'),
|
15 |
-
'date3' => '2010-10-04 13:45',
|
16 |
-
'date4' => 1286199900,
|
17 |
-
'date5' => -86410,
|
18 |
-
)
|
19 |
-
--EXPECT--
|
20 |
-
OK
|
21 |
-
OK
|
22 |
-
OK
|
23 |
-
OK
|
24 |
-
OK
|
25 |
-
OK
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/date_namedargs.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"date" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ date(date, "America/New_York")|date('d/m/Y H:i:s P', false) }}
|
5 |
-
{{ date(timezone="America/New_York", date=date)|date('d/m/Y H:i:s P', false) }}
|
6 |
-
--DATA--
|
7 |
-
date_default_timezone_set('UTC');
|
8 |
-
return array('date' => mktime(13, 45, 0, 10, 4, 2010))
|
9 |
-
--EXPECT--
|
10 |
-
04/10/2010 09:45:00 -04:00
|
11 |
-
04/10/2010 09:45:00 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/dump.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"dump" function
|
3 |
-
--CONDITION--
|
4 |
-
!extension_loaded('xdebug')
|
5 |
-
--TEMPLATE--
|
6 |
-
{{ dump('foo') }}
|
7 |
-
{{ dump('foo', 'bar') }}
|
8 |
-
--DATA--
|
9 |
-
return array('foo' => 'foo', 'bar' => 'bar')
|
10 |
-
--CONFIG--
|
11 |
-
return array('debug' => true, 'autoescape' => false);
|
12 |
-
--EXPECT--
|
13 |
-
string(3) "foo"
|
14 |
-
|
15 |
-
string(3) "foo"
|
16 |
-
string(3) "bar"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/dump_array.test
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"dump" function, xdebug is not loaded or xdebug <2.2-dev is loaded
|
3 |
-
--CONDITION--
|
4 |
-
!extension_loaded('xdebug') || (($r = new ReflectionExtension('xdebug')) && version_compare($r->getVersion(), '2.2-dev', '<'))
|
5 |
-
--TEMPLATE--
|
6 |
-
{{ dump() }}
|
7 |
-
--DATA--
|
8 |
-
return array('foo' => 'foo', 'bar' => 'bar')
|
9 |
-
--CONFIG--
|
10 |
-
return array('debug' => true, 'autoescape' => false);
|
11 |
-
--EXPECT--
|
12 |
-
array(3) {
|
13 |
-
["foo"]=>
|
14 |
-
string(3) "foo"
|
15 |
-
["bar"]=>
|
16 |
-
string(3) "bar"
|
17 |
-
["global"]=>
|
18 |
-
string(6) "global"
|
19 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/dynamic_function.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
dynamic function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ foo_path('bar') }}
|
5 |
-
{{ a_foo_b_bar('bar') }}
|
6 |
-
--DATA--
|
7 |
-
return array()
|
8 |
-
--EXPECT--
|
9 |
-
foo/bar
|
10 |
-
a/b/bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/basic.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function
|
3 |
-
--TEMPLATE--
|
4 |
-
FOO
|
5 |
-
{{ include("foo.twig") }}
|
6 |
-
|
7 |
-
BAR
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
FOOBAR
|
10 |
-
--DATA--
|
11 |
-
return array()
|
12 |
-
--EXPECT--
|
13 |
-
FOO
|
14 |
-
|
15 |
-
FOOBAR
|
16 |
-
|
17 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/expression.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function allows expressions for the template to include
|
3 |
-
--TEMPLATE--
|
4 |
-
FOO
|
5 |
-
{{ include(foo) }}
|
6 |
-
|
7 |
-
BAR
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
FOOBAR
|
10 |
-
--DATA--
|
11 |
-
return array('foo' => 'foo.twig')
|
12 |
-
--EXPECT--
|
13 |
-
FOO
|
14 |
-
|
15 |
-
FOOBAR
|
16 |
-
|
17 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/ignore_missing.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include(["foo.twig", "bar.twig"], ignore_missing = true) }}
|
5 |
-
{{ include("foo.twig", ignore_missing = true) }}
|
6 |
-
{{ include("foo.twig", ignore_missing = true, variables = {}) }}
|
7 |
-
{{ include("foo.twig", ignore_missing = true, variables = {}, with_context = true) }}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/missing.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include("foo.twig") }}
|
5 |
-
--DATA--
|
6 |
-
return array();
|
7 |
-
--EXCEPTION--
|
8 |
-
Twig_Error_Loader: Template "foo.twig" is not defined in "index.twig" at line 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/missing_nested.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "base.twig" %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
{{ parent() }}
|
8 |
-
{% endblock %}
|
9 |
-
--TEMPLATE(base.twig)--
|
10 |
-
{% block content %}
|
11 |
-
{{ include("foo.twig") }}
|
12 |
-
{% endblock %}
|
13 |
-
--DATA--
|
14 |
-
return array();
|
15 |
-
--EXCEPTION--
|
16 |
-
Twig_Error_Loader: Template "foo.twig" is not defined in "base.twig" at line 3.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag sandboxed
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include("foo.twig", sandboxed = true) }}
|
5 |
-
--TEMPLATE(foo.twig)--
|
6 |
-
{{ foo|e }}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXCEPTION--
|
10 |
-
Twig_Sandbox_SecurityError: Filter "e" is not allowed in "index.twig" at line 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/template_instance.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function accepts Twig_Template instance
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include(foo) }} FOO
|
5 |
-
--TEMPLATE(foo.twig)--
|
6 |
-
BAR
|
7 |
-
--DATA--
|
8 |
-
return array('foo' => $twig->loadTemplate('foo.twig'))
|
9 |
-
--EXPECT--
|
10 |
-
BAR FOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/templates_as_array.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include(["foo.twig", "bar.twig"]) }}
|
5 |
-
{{- include(["bar.twig", "foo.twig"]) }}
|
6 |
-
--TEMPLATE(foo.twig)--
|
7 |
-
foo
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
foo
|
12 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/with_context.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function accept variables and with_context
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include("foo.twig") }}
|
5 |
-
{{- include("foo.twig", with_context = false) }}
|
6 |
-
{{- include("foo.twig", {'foo1': 'bar'}) }}
|
7 |
-
{{- include("foo.twig", {'foo1': 'bar'}, with_context = false) }}
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
{% for k, v in _context %}{{ k }},{% endfor %}
|
10 |
-
--DATA--
|
11 |
-
return array('foo' => 'bar')
|
12 |
-
--EXPECT--
|
13 |
-
foo,global,_parent,
|
14 |
-
global,_parent,
|
15 |
-
foo,global,foo1,_parent,
|
16 |
-
foo1,global,_parent,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/include/with_variables.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" function accept variables
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ include("foo.twig", {'foo': 'bar'}) }}
|
5 |
-
{{- include("foo.twig", vars) }}
|
6 |
-
--TEMPLATE(foo.twig)--
|
7 |
-
{{ foo }}
|
8 |
-
--DATA--
|
9 |
-
return array('vars' => array('foo' => 'bar'))
|
10 |
-
--EXPECT--
|
11 |
-
bar
|
12 |
-
bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/range.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"range" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ range(low=0+1, high=10+0, step=2)|join(',') }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
1,3,5,7,9
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/special_chars.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"☃" custom function
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ ☃('foo') }}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
☃foo☃
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/functions/template_from_string.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"template_from_string" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include template_from_string(template) %}
|
5 |
-
|
6 |
-
{% include template_from_string("Hello {{ name }}") %}
|
7 |
-
--DATA--
|
8 |
-
return array('name' => 'Fabien', 'template' => "Hello {{ name }}")
|
9 |
-
--EXPECT--
|
10 |
-
Hello Fabien
|
11 |
-
Hello Fabien
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/macros/default_values.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
macro
|
3 |
-
--TEMPLATE--
|
4 |
-
{% from _self import test %}
|
5 |
-
|
6 |
-
{% macro test(a, b = 'bar') -%}
|
7 |
-
{{ a }}{{ b }}
|
8 |
-
{%- endmacro %}
|
9 |
-
|
10 |
-
{{ test('foo') }}
|
11 |
-
{{ test('bar', 'foo') }}
|
12 |
-
--DATA--
|
13 |
-
return array();
|
14 |
-
--EXPECT--
|
15 |
-
foobar
|
16 |
-
barfoo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/macros/nested_calls.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
macro
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as macros %}
|
5 |
-
|
6 |
-
{% macro foo(data) %}
|
7 |
-
{{ data }}
|
8 |
-
{% endmacro %}
|
9 |
-
|
10 |
-
{% macro bar() %}
|
11 |
-
<br />
|
12 |
-
{% endmacro %}
|
13 |
-
|
14 |
-
{{ macros.foo(macros.bar()) }}
|
15 |
-
--DATA--
|
16 |
-
return array();
|
17 |
-
--EXPECT--
|
18 |
-
<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/macros/reserved_variables.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
macro
|
3 |
-
--TEMPLATE--
|
4 |
-
{% from _self import test %}
|
5 |
-
|
6 |
-
{% macro test(this) -%}
|
7 |
-
{{ this }}
|
8 |
-
{%- endmacro %}
|
9 |
-
|
10 |
-
{{ test(this) }}
|
11 |
-
--DATA--
|
12 |
-
return array('this' => 'foo');
|
13 |
-
--EXPECT--
|
14 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/macros/simple.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
macro
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as test %}
|
5 |
-
{% from _self import test %}
|
6 |
-
|
7 |
-
{% macro test(a, b) -%}
|
8 |
-
{{ a|default('a') }}<br />
|
9 |
-
{{- b|default('b') }}<br />
|
10 |
-
{%- endmacro %}
|
11 |
-
|
12 |
-
{{ test.test() }}
|
13 |
-
{{ test() }}
|
14 |
-
{{ test.test(1, "c") }}
|
15 |
-
{{ test(1, "c") }}
|
16 |
-
--DATA--
|
17 |
-
return array();
|
18 |
-
--EXPECT--
|
19 |
-
a<br />b<br />
|
20 |
-
a<br />b<br />
|
21 |
-
1<br />c<br />
|
22 |
-
1<br />c<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/macros/with_filters.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
macro with a filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as test %}
|
5 |
-
|
6 |
-
{% macro test() %}
|
7 |
-
{% filter escape %}foo<br />{% endfilter %}
|
8 |
-
{% endmacro %}
|
9 |
-
|
10 |
-
{{ test.test() }}
|
11 |
-
--DATA--
|
12 |
-
return array();
|
13 |
-
--EXPECT--
|
14 |
-
foo<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/regression/empty_token.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig outputs 0 nodes correctly
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ foo }}0{{ foo }}
|
5 |
-
--DATA--
|
6 |
-
return array('foo' => 'foo')
|
7 |
-
--EXPECT--
|
8 |
-
foo0foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig is able to deal with SimpleXMLElement instances as variables
|
3 |
-
--CONDITION--
|
4 |
-
version_compare(phpversion(), '5.3.0', '>=')
|
5 |
-
--TEMPLATE--
|
6 |
-
Hello '{{ images.image.0.group }}'!
|
7 |
-
{{ images.children().count() }}
|
8 |
-
{% for image in images %}
|
9 |
-
- {{ image.group }}
|
10 |
-
{% endfor %}
|
11 |
-
--DATA--
|
12 |
-
return array('images' => new SimpleXMLElement('<images><image><group>foo</group></image><image><group>bar</group></image></images>'))
|
13 |
-
--EXPECT--
|
14 |
-
Hello 'foo'!
|
15 |
-
2
|
16 |
-
- foo
|
17 |
-
- bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/regression/strings_like_numbers.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig does not confuse strings with integers in getAttribute()
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ hash['2e2'] }}
|
5 |
-
--DATA--
|
6 |
-
return array('hash' => array('2e2' => 'works'))
|
7 |
-
--EXPECT--
|
8 |
-
works
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/basic.test
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag applies escaping on its children
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape %}
|
5 |
-
{{ var }}<br />
|
6 |
-
{% endautoescape %}
|
7 |
-
{% autoescape 'html' %}
|
8 |
-
{{ var }}<br />
|
9 |
-
{% endautoescape %}
|
10 |
-
{% autoescape false %}
|
11 |
-
{{ var }}<br />
|
12 |
-
{% endautoescape %}
|
13 |
-
{% autoescape true %}
|
14 |
-
{{ var }}<br />
|
15 |
-
{% endautoescape %}
|
16 |
-
{% autoescape false %}
|
17 |
-
{{ var }}<br />
|
18 |
-
{% endautoescape %}
|
19 |
-
--DATA--
|
20 |
-
return array('var' => '<br />')
|
21 |
-
--EXPECT--
|
22 |
-
<br /><br />
|
23 |
-
<br /><br />
|
24 |
-
<br /><br />
|
25 |
-
<br /><br />
|
26 |
-
<br /><br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/blocks.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag applies escaping on embedded blocks
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
{% block foo %}
|
6 |
-
{{ var }}
|
7 |
-
{% endblock %}
|
8 |
-
{% endautoescape %}
|
9 |
-
--DATA--
|
10 |
-
return array('var' => '<br />')
|
11 |
-
--EXPECT--
|
12 |
-
<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/double_escaping.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag does not double-escape
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
{{ var|escape }}
|
6 |
-
{% endautoescape %}
|
7 |
-
--DATA--
|
8 |
-
return array('var' => '<br />')
|
9 |
-
--EXPECT--
|
10 |
-
<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/functions.test
DELETED
@@ -1,83 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag applies escaping after calling functions
|
3 |
-
--TEMPLATE--
|
4 |
-
|
5 |
-
autoescape false
|
6 |
-
{% autoescape false %}
|
7 |
-
|
8 |
-
safe_br
|
9 |
-
{{ safe_br() }}
|
10 |
-
|
11 |
-
unsafe_br
|
12 |
-
{{ unsafe_br() }}
|
13 |
-
|
14 |
-
{% endautoescape %}
|
15 |
-
|
16 |
-
autoescape 'html'
|
17 |
-
{% autoescape 'html' %}
|
18 |
-
|
19 |
-
safe_br
|
20 |
-
{{ safe_br() }}
|
21 |
-
|
22 |
-
unsafe_br
|
23 |
-
{{ unsafe_br() }}
|
24 |
-
|
25 |
-
unsafe_br()|raw
|
26 |
-
{{ (unsafe_br())|raw }}
|
27 |
-
|
28 |
-
safe_br()|escape
|
29 |
-
{{ (safe_br())|escape }}
|
30 |
-
|
31 |
-
safe_br()|raw
|
32 |
-
{{ (safe_br())|raw }}
|
33 |
-
|
34 |
-
unsafe_br()|escape
|
35 |
-
{{ (unsafe_br())|escape }}
|
36 |
-
|
37 |
-
{% endautoescape %}
|
38 |
-
|
39 |
-
autoescape js
|
40 |
-
{% autoescape 'js' %}
|
41 |
-
|
42 |
-
safe_br
|
43 |
-
{{ safe_br() }}
|
44 |
-
|
45 |
-
{% endautoescape %}
|
46 |
-
--DATA--
|
47 |
-
return array()
|
48 |
-
--EXPECT--
|
49 |
-
|
50 |
-
autoescape false
|
51 |
-
|
52 |
-
safe_br
|
53 |
-
<br />
|
54 |
-
|
55 |
-
unsafe_br
|
56 |
-
<br />
|
57 |
-
|
58 |
-
|
59 |
-
autoescape 'html'
|
60 |
-
|
61 |
-
safe_br
|
62 |
-
<br />
|
63 |
-
|
64 |
-
unsafe_br
|
65 |
-
<br />
|
66 |
-
|
67 |
-
unsafe_br()|raw
|
68 |
-
<br />
|
69 |
-
|
70 |
-
safe_br()|escape
|
71 |
-
<br />
|
72 |
-
|
73 |
-
safe_br()|raw
|
74 |
-
<br />
|
75 |
-
|
76 |
-
unsafe_br()|escape
|
77 |
-
<br />
|
78 |
-
|
79 |
-
|
80 |
-
autoescape js
|
81 |
-
|
82 |
-
safe_br
|
83 |
-
\x3Cbr\x20\x2F\x3E
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/literal.test
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag does not apply escaping on literals
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
|
6 |
-
1. Simple literal
|
7 |
-
{{ "<br />" }}
|
8 |
-
|
9 |
-
2. Conditional expression with only literals
|
10 |
-
{{ true ? "<br />" : "<br>" }}
|
11 |
-
|
12 |
-
3. Conditonal expression with a variable
|
13 |
-
{{ true ? "<br />" : someVar }}
|
14 |
-
|
15 |
-
4. Nested conditionals with only literals
|
16 |
-
{{ true ? (true ? "<br />" : "<br>") : "\n" }}
|
17 |
-
|
18 |
-
5. Nested conditionals with a variable
|
19 |
-
{{ true ? (true ? "<br />" : someVar) : "\n" }}
|
20 |
-
|
21 |
-
6. Nested conditionals with a variable marked safe
|
22 |
-
{{ true ? (true ? "<br />" : someVar|raw) : "\n" }}
|
23 |
-
|
24 |
-
{% endautoescape %}
|
25 |
-
--DATA--
|
26 |
-
return array()
|
27 |
-
--EXPECT--
|
28 |
-
|
29 |
-
1. Simple literal
|
30 |
-
<br />
|
31 |
-
|
32 |
-
2. Conditional expression with only literals
|
33 |
-
<br />
|
34 |
-
|
35 |
-
3. Conditonal expression with a variable
|
36 |
-
<br />
|
37 |
-
|
38 |
-
4. Nested conditionals with only literals
|
39 |
-
<br />
|
40 |
-
|
41 |
-
5. Nested conditionals with a variable
|
42 |
-
<br />
|
43 |
-
|
44 |
-
6. Nested conditionals with a variable marked safe
|
45 |
-
<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/nested.test
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tags can be nested at will
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ var }}
|
5 |
-
{% autoescape 'html' %}
|
6 |
-
{{ var }}
|
7 |
-
{% autoescape false %}
|
8 |
-
{{ var }}
|
9 |
-
{% autoescape 'html' %}
|
10 |
-
{{ var }}
|
11 |
-
{% endautoescape %}
|
12 |
-
{{ var }}
|
13 |
-
{% endautoescape %}
|
14 |
-
{{ var }}
|
15 |
-
{% endautoescape %}
|
16 |
-
{{ var }}
|
17 |
-
--DATA--
|
18 |
-
return array('var' => '<br />')
|
19 |
-
--EXPECT--
|
20 |
-
<br />
|
21 |
-
<br />
|
22 |
-
<br />
|
23 |
-
<br />
|
24 |
-
<br />
|
25 |
-
<br />
|
26 |
-
<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/objects.test
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag applies escaping to object method calls
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
{{ user.name }}
|
6 |
-
{{ user.name|lower }}
|
7 |
-
{{ user }}
|
8 |
-
{% endautoescape %}
|
9 |
-
--DATA--
|
10 |
-
class UserForAutoEscapeTest
|
11 |
-
{
|
12 |
-
public function getName()
|
13 |
-
{
|
14 |
-
return 'Fabien<br />';
|
15 |
-
}
|
16 |
-
|
17 |
-
public function __toString()
|
18 |
-
{
|
19 |
-
return 'Fabien<br />';
|
20 |
-
}
|
21 |
-
}
|
22 |
-
return array('user' => new UserForAutoEscapeTest())
|
23 |
-
--EXPECT--
|
24 |
-
Fabien<br />
|
25 |
-
fabien<br />
|
26 |
-
Fabien<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/raw.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag does not escape when raw is used as a filter
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
{{ var|raw }}
|
6 |
-
{% endautoescape %}
|
7 |
-
--DATA--
|
8 |
-
return array('var' => '<br />')
|
9 |
-
--EXPECT--
|
10 |
-
<br />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag accepts an escaping strategy
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape true js %}{{ var }}{% endautoescape %}
|
5 |
-
|
6 |
-
{% autoescape true html %}{{ var }}{% endautoescape %}
|
7 |
-
|
8 |
-
{% autoescape 'js' %}{{ var }}{% endautoescape %}
|
9 |
-
|
10 |
-
{% autoescape 'html' %}{{ var }}{% endautoescape %}
|
11 |
-
--DATA--
|
12 |
-
return array('var' => '<br />"')
|
13 |
-
--EXPECT--
|
14 |
-
\x3Cbr\x20\x2F\x3E\x22
|
15 |
-
<br />"
|
16 |
-
\x3Cbr\x20\x2F\x3E\x22
|
17 |
-
<br />"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/type.test
DELETED
@@ -1,69 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
escape types
|
3 |
-
--TEMPLATE--
|
4 |
-
|
5 |
-
1. autoescape 'html' |escape('js')
|
6 |
-
|
7 |
-
{% autoescape 'html' %}
|
8 |
-
<a onclick="alert("{{ msg|escape('js') }}")"></a>
|
9 |
-
{% endautoescape %}
|
10 |
-
|
11 |
-
2. autoescape 'html' |escape('js')
|
12 |
-
|
13 |
-
{% autoescape 'html' %}
|
14 |
-
<a onclick="alert("{{ msg|escape('js') }}")"></a>
|
15 |
-
{% endautoescape %}
|
16 |
-
|
17 |
-
3. autoescape 'js' |escape('js')
|
18 |
-
|
19 |
-
{% autoescape 'js' %}
|
20 |
-
<a onclick="alert("{{ msg|escape('js') }}")"></a>
|
21 |
-
{% endautoescape %}
|
22 |
-
|
23 |
-
4. no escape
|
24 |
-
|
25 |
-
{% autoescape false %}
|
26 |
-
<a onclick="alert("{{ msg }}")"></a>
|
27 |
-
{% endautoescape %}
|
28 |
-
|
29 |
-
5. |escape('js')|escape('html')
|
30 |
-
|
31 |
-
{% autoescape false %}
|
32 |
-
<a onclick="alert("{{ msg|escape('js')|escape('html') }}")"></a>
|
33 |
-
{% endautoescape %}
|
34 |
-
|
35 |
-
6. autoescape 'html' |escape('js')|escape('html')
|
36 |
-
|
37 |
-
{% autoescape 'html' %}
|
38 |
-
<a onclick="alert("{{ msg|escape('js')|escape('html') }}")"></a>
|
39 |
-
{% endautoescape %}
|
40 |
-
|
41 |
-
--DATA--
|
42 |
-
return array('msg' => "<>\n'\"")
|
43 |
-
--EXPECT--
|
44 |
-
|
45 |
-
1. autoescape 'html' |escape('js')
|
46 |
-
|
47 |
-
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
48 |
-
|
49 |
-
2. autoescape 'html' |escape('js')
|
50 |
-
|
51 |
-
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
52 |
-
|
53 |
-
3. autoescape 'js' |escape('js')
|
54 |
-
|
55 |
-
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
56 |
-
|
57 |
-
4. no escape
|
58 |
-
|
59 |
-
<a onclick="alert("<>
|
60 |
-
'"")"></a>
|
61 |
-
|
62 |
-
5. |escape('js')|escape('html')
|
63 |
-
|
64 |
-
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
65 |
-
|
66 |
-
6. autoescape 'html' |escape('js')|escape('html')
|
67 |
-
|
68 |
-
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters.test
DELETED
@@ -1,131 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag applies escaping after calling filters
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
|
6 |
-
(escape_and_nl2br is an escaper filter)
|
7 |
-
|
8 |
-
1. Don't escape escaper filter output
|
9 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
10 |
-
the output is not escaped )
|
11 |
-
{{ var|escape_and_nl2br }}
|
12 |
-
|
13 |
-
2. Don't escape escaper filter output
|
14 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
15 |
-
the output is not escaped, |raw is redundant )
|
16 |
-
{{ var|escape_and_nl2br|raw }}
|
17 |
-
|
18 |
-
3. Explicit escape
|
19 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
20 |
-
the output is explicitly escaped by |escape )
|
21 |
-
{{ var|escape_and_nl2br|escape }}
|
22 |
-
|
23 |
-
4. Escape non-escaper filter output
|
24 |
-
( var is upper-cased by |upper,
|
25 |
-
the output is auto-escaped )
|
26 |
-
{{ var|upper }}
|
27 |
-
|
28 |
-
5. Escape if last filter is not an escaper
|
29 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
30 |
-
the output is upper-cased by |upper,
|
31 |
-
the output is auto-escaped as |upper is not an escaper )
|
32 |
-
{{ var|escape_and_nl2br|upper }}
|
33 |
-
|
34 |
-
6. Don't escape escaper filter output
|
35 |
-
( var is upper cased by upper,
|
36 |
-
the output is escaped by |escape_and_nl2br, line-breaks are added,
|
37 |
-
the output is not escaped as |escape_and_nl2br is an escaper )
|
38 |
-
{{ var|upper|escape_and_nl2br }}
|
39 |
-
|
40 |
-
7. Escape if last filter is not an escaper
|
41 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
42 |
-
the output is auto-escaped )
|
43 |
-
{{ "<b>%s</b>"|format(var) }}
|
44 |
-
|
45 |
-
8. Escape if last filter is not an escaper
|
46 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
47 |
-
|raw is redundant,
|
48 |
-
the output is auto-escaped )
|
49 |
-
{{ "<b>%s</b>"|raw|format(var) }}
|
50 |
-
|
51 |
-
9. Don't escape escaper filter output
|
52 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
53 |
-
the output is not escaped due to |raw filter at the end )
|
54 |
-
{{ "<b>%s</b>"|format(var)|raw }}
|
55 |
-
|
56 |
-
10. Don't escape escaper filter output
|
57 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
58 |
-
the output is not escaped due to |raw filter at the end,
|
59 |
-
the |raw filter on var is redundant )
|
60 |
-
{{ "<b>%s</b>"|format(var|raw)|raw }}
|
61 |
-
|
62 |
-
{% endautoescape %}
|
63 |
-
--DATA--
|
64 |
-
return array('var' => "<Fabien>\nTwig")
|
65 |
-
--EXPECT--
|
66 |
-
|
67 |
-
(escape_and_nl2br is an escaper filter)
|
68 |
-
|
69 |
-
1. Don't escape escaper filter output
|
70 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
71 |
-
the output is not escaped )
|
72 |
-
<Fabien><br />
|
73 |
-
Twig
|
74 |
-
|
75 |
-
2. Don't escape escaper filter output
|
76 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
77 |
-
the output is not escaped, |raw is redundant )
|
78 |
-
<Fabien><br />
|
79 |
-
Twig
|
80 |
-
|
81 |
-
3. Explicit escape
|
82 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
83 |
-
the output is explicitly escaped by |escape )
|
84 |
-
&lt;Fabien&gt;<br />
|
85 |
-
Twig
|
86 |
-
|
87 |
-
4. Escape non-escaper filter output
|
88 |
-
( var is upper-cased by |upper,
|
89 |
-
the output is auto-escaped )
|
90 |
-
<FABIEN>
|
91 |
-
TWIG
|
92 |
-
|
93 |
-
5. Escape if last filter is not an escaper
|
94 |
-
( var is escaped by |escape_and_nl2br, line-breaks are added,
|
95 |
-
the output is upper-cased by |upper,
|
96 |
-
the output is auto-escaped as |upper is not an escaper )
|
97 |
-
&LT;FABIEN&GT;<BR />
|
98 |
-
TWIG
|
99 |
-
|
100 |
-
6. Don't escape escaper filter output
|
101 |
-
( var is upper cased by upper,
|
102 |
-
the output is escaped by |escape_and_nl2br, line-breaks are added,
|
103 |
-
the output is not escaped as |escape_and_nl2br is an escaper )
|
104 |
-
<FABIEN><br />
|
105 |
-
TWIG
|
106 |
-
|
107 |
-
7. Escape if last filter is not an escaper
|
108 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
109 |
-
the output is auto-escaped )
|
110 |
-
<b><Fabien>
|
111 |
-
Twig</b>
|
112 |
-
|
113 |
-
8. Escape if last filter is not an escaper
|
114 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
115 |
-
|raw is redundant,
|
116 |
-
the output is auto-escaped )
|
117 |
-
<b><Fabien>
|
118 |
-
Twig</b>
|
119 |
-
|
120 |
-
9. Don't escape escaper filter output
|
121 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
122 |
-
the output is not escaped due to |raw filter at the end )
|
123 |
-
<b><Fabien>
|
124 |
-
Twig</b>
|
125 |
-
|
126 |
-
10. Don't escape escaper filter output
|
127 |
-
( the output of |format is "<b>" ~ var ~ "</b>",
|
128 |
-
the output is not escaped due to |raw filter at the end,
|
129 |
-
the |raw filter on var is redundant )
|
130 |
-
<b><Fabien>
|
131 |
-
Twig</b>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters_arguments.test
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag do not applies escaping on filter arguments
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
{{ var|nl2br("<br />") }}
|
6 |
-
{{ var|nl2br("<br />"|escape) }}
|
7 |
-
{{ var|nl2br(sep) }}
|
8 |
-
{{ var|nl2br(sep|raw) }}
|
9 |
-
{{ var|nl2br(sep|escape) }}
|
10 |
-
{% endautoescape %}
|
11 |
-
--DATA--
|
12 |
-
return array('var' => "<Fabien>\nTwig", 'sep' => '<br />')
|
13 |
-
--EXPECT--
|
14 |
-
<Fabien><br />
|
15 |
-
Twig
|
16 |
-
<Fabien><br />
|
17 |
-
Twig
|
18 |
-
<Fabien><br />
|
19 |
-
Twig
|
20 |
-
<Fabien><br />
|
21 |
-
Twig
|
22 |
-
<Fabien><br />
|
23 |
-
Twig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_pre_escape_filters.test
DELETED
@@ -1,68 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag applies escaping after calling filters, and before calling pre_escape filters
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
|
6 |
-
(nl2br is pre_escaped for "html" and declared safe for "html")
|
7 |
-
|
8 |
-
1. Pre-escape and don't post-escape
|
9 |
-
( var|escape|nl2br )
|
10 |
-
{{ var|nl2br }}
|
11 |
-
|
12 |
-
2. Don't double-pre-escape
|
13 |
-
( var|escape|nl2br )
|
14 |
-
{{ var|escape|nl2br }}
|
15 |
-
|
16 |
-
3. Don't escape safe values
|
17 |
-
( var|raw|nl2br )
|
18 |
-
{{ var|raw|nl2br }}
|
19 |
-
|
20 |
-
4. Don't escape safe values
|
21 |
-
( var|escape|nl2br|nl2br )
|
22 |
-
{{ var|nl2br|nl2br }}
|
23 |
-
|
24 |
-
5. Re-escape values that are escaped for an other contexts
|
25 |
-
( var|escape_something|escape|nl2br )
|
26 |
-
{{ var|escape_something|nl2br }}
|
27 |
-
|
28 |
-
6. Still escape when using filters not declared safe
|
29 |
-
( var|escape|nl2br|upper|escape )
|
30 |
-
{{ var|nl2br|upper }}
|
31 |
-
|
32 |
-
{% endautoescape %}
|
33 |
-
--DATA--
|
34 |
-
return array('var' => "<Fabien>\nTwig")
|
35 |
-
--EXPECT--
|
36 |
-
|
37 |
-
(nl2br is pre_escaped for "html" and declared safe for "html")
|
38 |
-
|
39 |
-
1. Pre-escape and don't post-escape
|
40 |
-
( var|escape|nl2br )
|
41 |
-
<Fabien><br />
|
42 |
-
Twig
|
43 |
-
|
44 |
-
2. Don't double-pre-escape
|
45 |
-
( var|escape|nl2br )
|
46 |
-
<Fabien><br />
|
47 |
-
Twig
|
48 |
-
|
49 |
-
3. Don't escape safe values
|
50 |
-
( var|raw|nl2br )
|
51 |
-
<Fabien><br />
|
52 |
-
Twig
|
53 |
-
|
54 |
-
4. Don't escape safe values
|
55 |
-
( var|escape|nl2br|nl2br )
|
56 |
-
<Fabien><br /><br />
|
57 |
-
Twig
|
58 |
-
|
59 |
-
5. Re-escape values that are escaped for an other contexts
|
60 |
-
( var|escape_something|escape|nl2br )
|
61 |
-
<FABIEN><br />
|
62 |
-
TWIG
|
63 |
-
|
64 |
-
6. Still escape when using filters not declared safe
|
65 |
-
( var|escape|nl2br|upper|escape )
|
66 |
-
&LT;FABIEN&GT;<BR />
|
67 |
-
TWIG
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"autoescape" tag handles filters preserving the safety
|
3 |
-
--TEMPLATE--
|
4 |
-
{% autoescape 'html' %}
|
5 |
-
|
6 |
-
(preserves_safety is preserving safety for "html")
|
7 |
-
|
8 |
-
1. Unsafe values are still unsafe
|
9 |
-
( var|preserves_safety|escape )
|
10 |
-
{{ var|preserves_safety }}
|
11 |
-
|
12 |
-
2. Safe values are still safe
|
13 |
-
( var|escape|preserves_safety )
|
14 |
-
{{ var|escape|preserves_safety }}
|
15 |
-
|
16 |
-
3. Re-escape values that are escaped for an other contexts
|
17 |
-
( var|escape_something|preserves_safety|escape )
|
18 |
-
{{ var|escape_something|preserves_safety }}
|
19 |
-
|
20 |
-
4. Still escape when using filters not declared safe
|
21 |
-
( var|escape|preserves_safety|replace({'FABIEN': 'FABPOT'})|escape )
|
22 |
-
{{ var|escape|preserves_safety|replace({'FABIEN': 'FABPOT'}) }}
|
23 |
-
|
24 |
-
{% endautoescape %}
|
25 |
-
--DATA--
|
26 |
-
return array('var' => "<Fabien>\nTwig")
|
27 |
-
--EXPECT--
|
28 |
-
|
29 |
-
(preserves_safety is preserving safety for "html")
|
30 |
-
|
31 |
-
1. Unsafe values are still unsafe
|
32 |
-
( var|preserves_safety|escape )
|
33 |
-
<FABIEN>
|
34 |
-
TWIG
|
35 |
-
|
36 |
-
2. Safe values are still safe
|
37 |
-
( var|escape|preserves_safety )
|
38 |
-
<FABIEN>
|
39 |
-
TWIG
|
40 |
-
|
41 |
-
3. Re-escape values that are escaped for an other contexts
|
42 |
-
( var|escape_something|preserves_safety|escape )
|
43 |
-
<FABIEN>
|
44 |
-
TWIG
|
45 |
-
|
46 |
-
4. Still escape when using filters not declared safe
|
47 |
-
( var|escape|preserves_safety|replace({'FABIEN': 'FABPOT'})|escape )
|
48 |
-
&LT;FABPOT&GT;
|
49 |
-
TWIG
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/block/basic.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"block" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block title1 %}FOO{% endblock %}
|
5 |
-
{% block title2 foo|lower %}
|
6 |
-
--TEMPLATE(foo.twig)--
|
7 |
-
{% block content %}{% endblock %}
|
8 |
-
--DATA--
|
9 |
-
return array('foo' => 'bar')
|
10 |
-
--EXPECT--
|
11 |
-
FOObar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/block/block_unique_name.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"block" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block content %}
|
5 |
-
{% block content %}
|
6 |
-
{% endblock %}
|
7 |
-
{% endblock %}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXCEPTION--
|
11 |
-
Twig_Error_Syntax: The block 'content' has already been defined line 2 in "index.twig" at line 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"☃" special chars in a block name
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block ☃ %}
|
5 |
-
☃
|
6 |
-
{% endblock ☃ %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
☃
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/embed/basic.test
DELETED
@@ -1,35 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"embed" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
FOO
|
5 |
-
{% embed "foo.twig" %}
|
6 |
-
{% block c1 %}
|
7 |
-
{{ parent() }}
|
8 |
-
block1extended
|
9 |
-
{% endblock %}
|
10 |
-
{% endembed %}
|
11 |
-
|
12 |
-
BAR
|
13 |
-
--TEMPLATE(foo.twig)--
|
14 |
-
A
|
15 |
-
{% block c1 %}
|
16 |
-
block1
|
17 |
-
{% endblock %}
|
18 |
-
B
|
19 |
-
{% block c2 %}
|
20 |
-
block2
|
21 |
-
{% endblock %}
|
22 |
-
C
|
23 |
-
--DATA--
|
24 |
-
return array()
|
25 |
-
--EXPECT--
|
26 |
-
FOO
|
27 |
-
|
28 |
-
A
|
29 |
-
block1
|
30 |
-
|
31 |
-
block1extended
|
32 |
-
B
|
33 |
-
block2
|
34 |
-
C
|
35 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/embed/multiple.test
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"embed" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
FOO
|
5 |
-
{% embed "foo.twig" %}
|
6 |
-
{% block c1 %}
|
7 |
-
{{ parent() }}
|
8 |
-
block1extended
|
9 |
-
{% endblock %}
|
10 |
-
{% endembed %}
|
11 |
-
|
12 |
-
{% embed "foo.twig" %}
|
13 |
-
{% block c1 %}
|
14 |
-
{{ parent() }}
|
15 |
-
block1extended
|
16 |
-
{% endblock %}
|
17 |
-
{% endembed %}
|
18 |
-
|
19 |
-
BAR
|
20 |
-
--TEMPLATE(foo.twig)--
|
21 |
-
A
|
22 |
-
{% block c1 %}
|
23 |
-
block1
|
24 |
-
{% endblock %}
|
25 |
-
B
|
26 |
-
{% block c2 %}
|
27 |
-
block2
|
28 |
-
{% endblock %}
|
29 |
-
C
|
30 |
-
--DATA--
|
31 |
-
return array()
|
32 |
-
--EXPECT--
|
33 |
-
FOO
|
34 |
-
|
35 |
-
A
|
36 |
-
block1
|
37 |
-
|
38 |
-
block1extended
|
39 |
-
B
|
40 |
-
block2
|
41 |
-
C
|
42 |
-
|
43 |
-
A
|
44 |
-
block1
|
45 |
-
|
46 |
-
block1extended
|
47 |
-
B
|
48 |
-
block2
|
49 |
-
C
|
50 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/embed/nested.test
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"embed" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% embed "foo.twig" %}
|
5 |
-
{% block c1 %}
|
6 |
-
{{ parent() }}
|
7 |
-
{% embed "foo.twig" %}
|
8 |
-
{% block c1 %}
|
9 |
-
{{ parent() }}
|
10 |
-
block1extended
|
11 |
-
{% endblock %}
|
12 |
-
{% endembed %}
|
13 |
-
|
14 |
-
{% endblock %}
|
15 |
-
{% endembed %}
|
16 |
-
--TEMPLATE(foo.twig)--
|
17 |
-
A
|
18 |
-
{% block c1 %}
|
19 |
-
block1
|
20 |
-
{% endblock %}
|
21 |
-
B
|
22 |
-
{% block c2 %}
|
23 |
-
block2
|
24 |
-
{% endblock %}
|
25 |
-
C
|
26 |
-
--DATA--
|
27 |
-
return array()
|
28 |
-
--EXPECT--
|
29 |
-
A
|
30 |
-
block1
|
31 |
-
|
32 |
-
|
33 |
-
A
|
34 |
-
block1
|
35 |
-
|
36 |
-
block1extended
|
37 |
-
B
|
38 |
-
block2
|
39 |
-
C
|
40 |
-
B
|
41 |
-
block2
|
42 |
-
C
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test
DELETED
@@ -1,57 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"embed" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "base.twig" %}
|
5 |
-
|
6 |
-
{% block c1 %}
|
7 |
-
{{ parent() }}
|
8 |
-
blockc1baseextended
|
9 |
-
{% endblock %}
|
10 |
-
|
11 |
-
{% block c2 %}
|
12 |
-
{{ parent() }}
|
13 |
-
|
14 |
-
{% embed "foo.twig" %}
|
15 |
-
{% block c1 %}
|
16 |
-
{{ parent() }}
|
17 |
-
block1extended
|
18 |
-
{% endblock %}
|
19 |
-
{% endembed %}
|
20 |
-
{% endblock %}
|
21 |
-
--TEMPLATE(base.twig)--
|
22 |
-
A
|
23 |
-
{% block c1 %}
|
24 |
-
blockc1base
|
25 |
-
{% endblock %}
|
26 |
-
{% block c2 %}
|
27 |
-
blockc2base
|
28 |
-
{% endblock %}
|
29 |
-
B
|
30 |
-
--TEMPLATE(foo.twig)--
|
31 |
-
A
|
32 |
-
{% block c1 %}
|
33 |
-
block1
|
34 |
-
{% endblock %}
|
35 |
-
B
|
36 |
-
{% block c2 %}
|
37 |
-
block2
|
38 |
-
{% endblock %}
|
39 |
-
C
|
40 |
-
--DATA--
|
41 |
-
return array()
|
42 |
-
--EXPECT--
|
43 |
-
A
|
44 |
-
blockc1base
|
45 |
-
|
46 |
-
blockc1baseextended
|
47 |
-
blockc2base
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
A
|
52 |
-
block1
|
53 |
-
|
54 |
-
block1extended
|
55 |
-
B
|
56 |
-
block2
|
57 |
-
CB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/filter/basic.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"filter" tag applies a filter on its children
|
3 |
-
--TEMPLATE--
|
4 |
-
{% filter upper %}
|
5 |
-
Some text with a {{ var }}
|
6 |
-
{% endfilter %}
|
7 |
-
--DATA--
|
8 |
-
return array('var' => 'var')
|
9 |
-
--EXPECT--
|
10 |
-
SOME TEXT WITH A VAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/filter/json_encode.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"filter" tag applies a filter on its children
|
3 |
-
--TEMPLATE--
|
4 |
-
{% filter json_encode|raw %}test{% endfilter %}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
"test"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/filter/multiple.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"filter" tags accept multiple chained filters
|
3 |
-
--TEMPLATE--
|
4 |
-
{% filter lower|title %}
|
5 |
-
{{ var }}
|
6 |
-
{% endfilter %}
|
7 |
-
--DATA--
|
8 |
-
return array('var' => 'VAR')
|
9 |
-
--EXPECT--
|
10 |
-
Var
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/filter/nested.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"filter" tags can be nested at will
|
3 |
-
--TEMPLATE--
|
4 |
-
{% filter lower|title %}
|
5 |
-
{{ var }}
|
6 |
-
{% filter upper %}
|
7 |
-
{{ var }}
|
8 |
-
{% endfilter %}
|
9 |
-
{{ var }}
|
10 |
-
{% endfilter %}
|
11 |
-
--DATA--
|
12 |
-
return array('var' => 'var')
|
13 |
-
--EXPECT--
|
14 |
-
Var
|
15 |
-
Var
|
16 |
-
Var
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/filter/with_for_tag.test
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"filter" tag applies the filter on "for" tags
|
3 |
-
--TEMPLATE--
|
4 |
-
{% filter upper %}
|
5 |
-
{% for item in items %}
|
6 |
-
{{ item }}
|
7 |
-
{% endfor %}
|
8 |
-
{% endfilter %}
|
9 |
-
--DATA--
|
10 |
-
return array('items' => array('a', 'b'))
|
11 |
-
--EXPECT--
|
12 |
-
A
|
13 |
-
B
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/filter/with_if_tag.test
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"filter" tag applies the filter on "if" tags
|
3 |
-
--TEMPLATE--
|
4 |
-
{% filter upper %}
|
5 |
-
{% if items %}
|
6 |
-
{{ items|join(', ') }}
|
7 |
-
{% endif %}
|
8 |
-
|
9 |
-
{% if items.3 is defined %}
|
10 |
-
FOO
|
11 |
-
{% else %}
|
12 |
-
{{ items.1 }}
|
13 |
-
{% endif %}
|
14 |
-
|
15 |
-
{% if items.3 is defined %}
|
16 |
-
FOO
|
17 |
-
{% elseif items.1 %}
|
18 |
-
{{ items.0 }}
|
19 |
-
{% endif %}
|
20 |
-
|
21 |
-
{% endfilter %}
|
22 |
-
--DATA--
|
23 |
-
return array('items' => array('a', 'b'))
|
24 |
-
--EXPECT--
|
25 |
-
A, B
|
26 |
-
|
27 |
-
B
|
28 |
-
|
29 |
-
A
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/condition.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag takes a condition
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for i in 1..5 if i is odd -%}
|
5 |
-
{{ loop.index }}.{{ i }}{{ foo.bar }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('foo' => array('bar' => 'X'))
|
9 |
-
--CONFIG--
|
10 |
-
return array('strict_variables' => false)
|
11 |
-
--EXPECT--
|
12 |
-
1.1X
|
13 |
-
2.3X
|
14 |
-
3.5X
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/context.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag keeps the context safe
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
{% for item in items %}
|
6 |
-
* {{ item }}
|
7 |
-
{% endfor %}
|
8 |
-
* {{ item }}
|
9 |
-
{% endfor %}
|
10 |
-
--DATA--
|
11 |
-
return array('items' => array('a', 'b'))
|
12 |
-
--EXPECT--
|
13 |
-
* a
|
14 |
-
* b
|
15 |
-
* a
|
16 |
-
* a
|
17 |
-
* b
|
18 |
-
* b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/else.test
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag can use an "else" clause
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
* {{ item }}
|
6 |
-
{% else %}
|
7 |
-
no item
|
8 |
-
{% endfor %}
|
9 |
-
--DATA--
|
10 |
-
return array('items' => array('a', 'b'))
|
11 |
-
--EXPECT--
|
12 |
-
* a
|
13 |
-
* b
|
14 |
-
--DATA--
|
15 |
-
return array('items' => array())
|
16 |
-
--EXPECT--
|
17 |
-
no item
|
18 |
-
--DATA--
|
19 |
-
return array()
|
20 |
-
--CONFIG--
|
21 |
-
return array('strict_variables' => false)
|
22 |
-
--EXPECT--
|
23 |
-
no item
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/inner_variables.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag does not reset inner variables
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for i in 1..2 %}
|
5 |
-
{% for j in 0..2 %}
|
6 |
-
{{k}}{% set k = k+1 %} {{ loop.parent.loop.index }}
|
7 |
-
{% endfor %}
|
8 |
-
{% endfor %}
|
9 |
-
--DATA--
|
10 |
-
return array('k' => 0)
|
11 |
-
--EXPECT--
|
12 |
-
0 1
|
13 |
-
1 1
|
14 |
-
2 1
|
15 |
-
3 2
|
16 |
-
4 2
|
17 |
-
5 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/keys.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag can iterate over keys
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for key in items|keys %}
|
5 |
-
* {{ key }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('items' => array('a', 'b'))
|
9 |
-
--EXPECT--
|
10 |
-
* 0
|
11 |
-
* 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/keys_and_values.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag can iterate over keys and values
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for key, item in items %}
|
5 |
-
* {{ key }}/{{ item }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('items' => array('a', 'b'))
|
9 |
-
--EXPECT--
|
10 |
-
* 0/a
|
11 |
-
* 1/b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/loop_context.test
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag adds a loop variable to the context
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
* {{ loop.index }}/{{ loop.index0 }}
|
6 |
-
* {{ loop.revindex }}/{{ loop.revindex0 }}
|
7 |
-
* {{ loop.first }}/{{ loop.last }}/{{ loop.length }}
|
8 |
-
|
9 |
-
{% endfor %}
|
10 |
-
--DATA--
|
11 |
-
return array('items' => array('a', 'b'))
|
12 |
-
--EXPECT--
|
13 |
-
* 1/0
|
14 |
-
* 2/1
|
15 |
-
* 1//2
|
16 |
-
|
17 |
-
* 2/1
|
18 |
-
* 1/0
|
19 |
-
* /1/2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/loop_context_local.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag adds a loop variable to the context locally
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
{% endfor %}
|
6 |
-
{% if loop is not defined %}WORKS{% endif %}
|
7 |
-
--DATA--
|
8 |
-
return array('items' => array())
|
9 |
-
--EXPECT--
|
10 |
-
WORKS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for i, item in items if i > 0 %}
|
5 |
-
{{ loop.last }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('items' => array('a', 'b'))
|
9 |
-
--EXCEPTION--
|
10 |
-
Twig_Error_Syntax: The "loop.last" variable is not defined when looping with a condition in "index.twig" at line 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined_cond.test
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for i, item in items if loop.last > 0 %}
|
5 |
-
{% endfor %}
|
6 |
-
--DATA--
|
7 |
-
return array('items' => array('a', 'b'))
|
8 |
-
--EXCEPTION--
|
9 |
-
Twig_Error_Syntax: The "loop" variable cannot be used in a looping condition in "index.twig" at line 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/nested_else.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag can use an "else" clause
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
{% for item in items1 %}
|
6 |
-
* {{ item }}
|
7 |
-
{% else %}
|
8 |
-
no {{ item }}
|
9 |
-
{% endfor %}
|
10 |
-
{% else %}
|
11 |
-
no item1
|
12 |
-
{% endfor %}
|
13 |
-
--DATA--
|
14 |
-
return array('items' => array('a', 'b'), 'items1' => array())
|
15 |
-
--EXPECT--
|
16 |
-
no a
|
17 |
-
no b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/objects.test
DELETED
@@ -1,43 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag iterates over iterable objects
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
* {{ item }}
|
6 |
-
* {{ loop.index }}/{{ loop.index0 }}
|
7 |
-
* {{ loop.first }}
|
8 |
-
|
9 |
-
{% endfor %}
|
10 |
-
|
11 |
-
{% for key, value in items %}
|
12 |
-
* {{ key }}/{{ value }}
|
13 |
-
{% endfor %}
|
14 |
-
|
15 |
-
{% for key in items|keys %}
|
16 |
-
* {{ key }}
|
17 |
-
{% endfor %}
|
18 |
-
--DATA--
|
19 |
-
class ItemsIterator implements Iterator
|
20 |
-
{
|
21 |
-
protected $values = array('foo' => 'bar', 'bar' => 'foo');
|
22 |
-
public function current() { return current($this->values); }
|
23 |
-
public function key() { return key($this->values); }
|
24 |
-
public function next() { return next($this->values); }
|
25 |
-
public function rewind() { return reset($this->values); }
|
26 |
-
public function valid() { return false !== current($this->values); }
|
27 |
-
}
|
28 |
-
return array('items' => new ItemsIterator())
|
29 |
-
--EXPECT--
|
30 |
-
* bar
|
31 |
-
* 1/0
|
32 |
-
* 1
|
33 |
-
|
34 |
-
* foo
|
35 |
-
* 2/1
|
36 |
-
*
|
37 |
-
|
38 |
-
|
39 |
-
* foo/bar
|
40 |
-
* bar/foo
|
41 |
-
|
42 |
-
* foo
|
43 |
-
* bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/objects_countable.test
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag iterates over iterable and countable objects
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
* {{ item }}
|
6 |
-
* {{ loop.index }}/{{ loop.index0 }}
|
7 |
-
* {{ loop.revindex }}/{{ loop.revindex0 }}
|
8 |
-
* {{ loop.first }}/{{ loop.last }}/{{ loop.length }}
|
9 |
-
|
10 |
-
{% endfor %}
|
11 |
-
|
12 |
-
{% for key, value in items %}
|
13 |
-
* {{ key }}/{{ value }}
|
14 |
-
{% endfor %}
|
15 |
-
|
16 |
-
{% for key in items|keys %}
|
17 |
-
* {{ key }}
|
18 |
-
{% endfor %}
|
19 |
-
--DATA--
|
20 |
-
class ItemsIteratorCountable implements Iterator, Countable
|
21 |
-
{
|
22 |
-
protected $values = array('foo' => 'bar', 'bar' => 'foo');
|
23 |
-
public function current() { return current($this->values); }
|
24 |
-
public function key() { return key($this->values); }
|
25 |
-
public function next() { return next($this->values); }
|
26 |
-
public function rewind() { return reset($this->values); }
|
27 |
-
public function valid() { return false !== current($this->values); }
|
28 |
-
public function count() { return count($this->values); }
|
29 |
-
}
|
30 |
-
return array('items' => new ItemsIteratorCountable())
|
31 |
-
--EXPECT--
|
32 |
-
* bar
|
33 |
-
* 1/0
|
34 |
-
* 2/1
|
35 |
-
* 1//2
|
36 |
-
|
37 |
-
* foo
|
38 |
-
* 2/1
|
39 |
-
* 1/0
|
40 |
-
* /1/2
|
41 |
-
|
42 |
-
|
43 |
-
* foo/bar
|
44 |
-
* bar/foo
|
45 |
-
|
46 |
-
* foo
|
47 |
-
* bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/recursive.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tags can be nested
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for key, item in items %}
|
5 |
-
* {{ key }} ({{ loop.length }}):
|
6 |
-
{% for value in item %}
|
7 |
-
* {{ value }} ({{ loop.length }})
|
8 |
-
{% endfor %}
|
9 |
-
{% endfor %}
|
10 |
-
--DATA--
|
11 |
-
return array('items' => array('a' => array('a1', 'a2', 'a3'), 'b' => array('b1')))
|
12 |
-
--EXPECT--
|
13 |
-
* a (2):
|
14 |
-
* a1 (3)
|
15 |
-
* a2 (3)
|
16 |
-
* a3 (3)
|
17 |
-
* b (2):
|
18 |
-
* b1 (1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/for/values.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"for" tag iterates over item values
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for item in items %}
|
5 |
-
* {{ item }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('items' => array('a', 'b'))
|
9 |
-
--EXPECT--
|
10 |
-
* a
|
11 |
-
* b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/from.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
global variables
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include "included.twig" %}
|
5 |
-
{% from "included.twig" import foobar %}
|
6 |
-
{{ foobar() }}
|
7 |
-
--TEMPLATE(included.twig)--
|
8 |
-
{% macro foobar() %}
|
9 |
-
called foobar
|
10 |
-
{% endmacro %}
|
11 |
-
--DATA--
|
12 |
-
return array();
|
13 |
-
--EXPECT--
|
14 |
-
called foobar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/if/basic.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"if" creates a condition
|
3 |
-
--TEMPLATE--
|
4 |
-
{% if a is defined %}
|
5 |
-
{{ a }}
|
6 |
-
{% elseif b is defined %}
|
7 |
-
{{ b }}
|
8 |
-
{% else %}
|
9 |
-
NOTHING
|
10 |
-
{% endif %}
|
11 |
-
--DATA--
|
12 |
-
return array('a' => 'a')
|
13 |
-
--EXPECT--
|
14 |
-
a
|
15 |
-
--DATA--
|
16 |
-
return array('b' => 'b')
|
17 |
-
--EXPECT--
|
18 |
-
b
|
19 |
-
--DATA--
|
20 |
-
return array()
|
21 |
-
--EXPECT--
|
22 |
-
NOTHING
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/if/expression.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"if" takes an expression as a test
|
3 |
-
--TEMPLATE--
|
4 |
-
{% if a < 2 %}
|
5 |
-
A1
|
6 |
-
{% elseif a > 10 %}
|
7 |
-
A2
|
8 |
-
{% else %}
|
9 |
-
A3
|
10 |
-
{% endif %}
|
11 |
-
--DATA--
|
12 |
-
return array('a' => 1)
|
13 |
-
--EXPECT--
|
14 |
-
A1
|
15 |
-
--DATA--
|
16 |
-
return array('a' => 12)
|
17 |
-
--EXPECT--
|
18 |
-
A2
|
19 |
-
--DATA--
|
20 |
-
return array('a' => 7)
|
21 |
-
--EXPECT--
|
22 |
-
A3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/basic.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
FOO
|
5 |
-
{% include "foo.twig" %}
|
6 |
-
|
7 |
-
BAR
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
FOOBAR
|
10 |
-
--DATA--
|
11 |
-
return array()
|
12 |
-
--EXPECT--
|
13 |
-
FOO
|
14 |
-
|
15 |
-
FOOBAR
|
16 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/expression.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag allows expressions for the template to include
|
3 |
-
--TEMPLATE--
|
4 |
-
FOO
|
5 |
-
{% include foo %}
|
6 |
-
|
7 |
-
BAR
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
FOOBAR
|
10 |
-
--DATA--
|
11 |
-
return array('foo' => 'foo.twig')
|
12 |
-
--EXPECT--
|
13 |
-
FOO
|
14 |
-
|
15 |
-
FOOBAR
|
16 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/ignore_missing.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include ["foo.twig", "bar.twig"] ignore missing %}
|
5 |
-
{% include "foo.twig" ignore missing %}
|
6 |
-
{% include "foo.twig" ignore missing with {} %}
|
7 |
-
{% include "foo.twig" ignore missing with {} only %}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/missing.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include "foo.twig" %}
|
5 |
-
--DATA--
|
6 |
-
return array();
|
7 |
-
--EXCEPTION--
|
8 |
-
Twig_Error_Loader: Template "foo.twig" is not defined in "index.twig" at line 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/missing_nested.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "base.twig" %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
{{ parent() }}
|
8 |
-
{% endblock %}
|
9 |
-
--TEMPLATE(base.twig)--
|
10 |
-
{% block content %}
|
11 |
-
{% include "foo.twig" %}
|
12 |
-
{% endblock %}
|
13 |
-
--DATA--
|
14 |
-
return array();
|
15 |
-
--EXCEPTION--
|
16 |
-
Twig_Error_Loader: Template "foo.twig" is not defined in "base.twig" at line 3.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/only.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag accept variables and only
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include "foo.twig" %}
|
5 |
-
{% include "foo.twig" only %}
|
6 |
-
{% include "foo.twig" with {'foo1': 'bar'} %}
|
7 |
-
{% include "foo.twig" with {'foo1': 'bar'} only %}
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
{% for k, v in _context %}{{ k }},{% endfor %}
|
10 |
-
--DATA--
|
11 |
-
return array('foo' => 'bar')
|
12 |
-
--EXPECT--
|
13 |
-
foo,global,_parent,
|
14 |
-
global,_parent,
|
15 |
-
foo,global,foo1,_parent,
|
16 |
-
foo1,global,_parent,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/template_instance.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag accepts Twig_Template instance
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include foo %} FOO
|
5 |
-
--TEMPLATE(foo.twig)--
|
6 |
-
BAR
|
7 |
-
--DATA--
|
8 |
-
return array('foo' => $twig->loadTemplate('foo.twig'))
|
9 |
-
--EXPECT--
|
10 |
-
BAR FOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/templates_as_array.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include ["foo.twig", "bar.twig"] %}
|
5 |
-
{% include ["bar.twig", "foo.twig"] %}
|
6 |
-
--TEMPLATE(foo.twig)--
|
7 |
-
foo
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
foo
|
12 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/include/with_variables.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"include" tag accept variables
|
3 |
-
--TEMPLATE--
|
4 |
-
{% include "foo.twig" with {'foo': 'bar'} %}
|
5 |
-
{% include "foo.twig" with vars %}
|
6 |
-
--TEMPLATE(foo.twig)--
|
7 |
-
{{ foo }}
|
8 |
-
--DATA--
|
9 |
-
return array('vars' => array('foo' => 'bar'))
|
10 |
-
--EXPECT--
|
11 |
-
bar
|
12 |
-
bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/basic.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "foo.twig" %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
FOO
|
8 |
-
{% endblock %}
|
9 |
-
--TEMPLATE(foo.twig)--
|
10 |
-
{% block content %}{% endblock %}
|
11 |
-
--DATA--
|
12 |
-
return array()
|
13 |
-
--EXPECT--
|
14 |
-
FOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/conditional.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends standalone ? foo : 'bar.twig' %}
|
5 |
-
|
6 |
-
{% block content %}{{ parent() }}FOO{% endblock %}
|
7 |
-
--TEMPLATE(foo.twig)--
|
8 |
-
{% block content %}FOO{% endblock %}
|
9 |
-
--TEMPLATE(bar.twig)--
|
10 |
-
{% block content %}BAR{% endblock %}
|
11 |
-
--DATA--
|
12 |
-
return array('foo' => 'foo.twig', 'standalone' => true)
|
13 |
-
--EXPECT--
|
14 |
-
FOOFOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/dynamic.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends foo %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
FOO
|
8 |
-
{% endblock %}
|
9 |
-
--TEMPLATE(foo.twig)--
|
10 |
-
{% block content %}{% endblock %}
|
11 |
-
--DATA--
|
12 |
-
return array('foo' => 'foo.twig')
|
13 |
-
--EXPECT--
|
14 |
-
FOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/empty.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "foo.twig" %}
|
5 |
-
--TEMPLATE(foo.twig)--
|
6 |
-
{% block content %}FOO{% endblock %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
FOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends ["foo.twig", "bar.twig"] %}
|
5 |
-
--TEMPLATE(bar.twig)--
|
6 |
-
{% block content %}
|
7 |
-
foo
|
8 |
-
{% endblock %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "layout.twig" %}{% block content %}{{ parent() }}index {% endblock %}
|
5 |
-
--TEMPLATE(layout.twig)--
|
6 |
-
{% extends "base.twig" %}{% block content %}{{ parent() }}layout {% endblock %}
|
7 |
-
--TEMPLATE(base.twig)--
|
8 |
-
{% block content %}base {% endblock %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
base layout index
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"block" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "foo.twig" %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
{% block subcontent %}
|
8 |
-
{% block subsubcontent %}
|
9 |
-
SUBSUBCONTENT
|
10 |
-
{% endblock %}
|
11 |
-
{% endblock %}
|
12 |
-
{% endblock %}
|
13 |
-
--TEMPLATE(foo.twig)--
|
14 |
-
{% block content %}
|
15 |
-
{% block subcontent %}
|
16 |
-
SUBCONTENT
|
17 |
-
{% endblock %}
|
18 |
-
{% endblock %}
|
19 |
-
--DATA--
|
20 |
-
return array()
|
21 |
-
--EXPECT--
|
22 |
-
SUBSUBCONTENT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"block" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block content %}
|
5 |
-
CONTENT
|
6 |
-
{%- block subcontent -%}
|
7 |
-
SUBCONTENT
|
8 |
-
{%- endblock -%}
|
9 |
-
ENDCONTENT
|
10 |
-
{% endblock %}
|
11 |
-
--TEMPLATE(foo.twig)--
|
12 |
-
--DATA--
|
13 |
-
return array()
|
14 |
-
--EXPECT--
|
15 |
-
CONTENTSUBCONTENTENDCONTENT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_inheritance.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "layout.twig" %}
|
5 |
-
{% block inside %}INSIDE{% endblock inside %}
|
6 |
-
--TEMPLATE(layout.twig)--
|
7 |
-
{% extends "base.twig" %}
|
8 |
-
{% block body %}
|
9 |
-
{% block inside '' %}
|
10 |
-
{% endblock body %}
|
11 |
-
--TEMPLATE(base.twig)--
|
12 |
-
{% block body '' %}
|
13 |
-
--DATA--
|
14 |
-
return array()
|
15 |
-
--EXPECT--
|
16 |
-
INSIDE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "foo.twig" %}
|
5 |
-
|
6 |
-
{% block content %}{{ parent() }}FOO{{ parent() }}{% endblock %}
|
7 |
-
--TEMPLATE(foo.twig)--
|
8 |
-
{% block content %}BAR{% endblock %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
BARFOOBAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_change.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends foo ? 'foo.twig' : 'bar.twig' %}
|
5 |
-
--TEMPLATE(foo.twig)--
|
6 |
-
FOO
|
7 |
-
--TEMPLATE(bar.twig)--
|
8 |
-
BAR
|
9 |
-
--DATA--
|
10 |
-
return array('foo' => true)
|
11 |
-
--EXPECT--
|
12 |
-
FOO
|
13 |
-
--DATA--
|
14 |
-
return array('foo' => false)
|
15 |
-
--EXPECT--
|
16 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_in_a_block.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block content %}
|
5 |
-
{% extends "foo.twig" %}
|
6 |
-
{% endblock %}
|
7 |
-
--EXCEPTION--
|
8 |
-
Twig_Error_Syntax: Cannot extend from a block in "index.twig" at line 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_isolation.test
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "base.twig" %}
|
5 |
-
{% block content %}{% include "included.twig" %}{% endblock %}
|
6 |
-
|
7 |
-
{% block footer %}Footer{% endblock %}
|
8 |
-
--TEMPLATE(included.twig)--
|
9 |
-
{% extends "base.twig" %}
|
10 |
-
{% block content %}Included Content{% endblock %}
|
11 |
-
--TEMPLATE(base.twig)--
|
12 |
-
{% block content %}Default Content{% endblock %}
|
13 |
-
|
14 |
-
{% block footer %}Default Footer{% endblock %}
|
15 |
-
--DATA--
|
16 |
-
return array()
|
17 |
-
--EXPECT--
|
18 |
-
Included Content
|
19 |
-
Default Footer
|
20 |
-
Footer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_nested.test
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "foo.twig" %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
{% block inside %}
|
8 |
-
INSIDE OVERRIDDEN
|
9 |
-
{% endblock %}
|
10 |
-
|
11 |
-
BEFORE
|
12 |
-
{{ parent() }}
|
13 |
-
AFTER
|
14 |
-
{% endblock %}
|
15 |
-
--TEMPLATE(foo.twig)--
|
16 |
-
{% block content %}
|
17 |
-
BAR
|
18 |
-
{% endblock %}
|
19 |
-
--DATA--
|
20 |
-
return array()
|
21 |
-
--EXPECT--
|
22 |
-
|
23 |
-
INSIDE OVERRIDDEN
|
24 |
-
|
25 |
-
BEFORE
|
26 |
-
BAR
|
27 |
-
|
28 |
-
AFTER
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"parent" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% block content %}
|
5 |
-
{{ parent() }}
|
6 |
-
{% endblock %}
|
7 |
-
--EXCEPTION--
|
8 |
-
Twig_Error_Syntax: Calling "parent" on a template that does not extend nor "use" another template is forbidden in "index.twig" at line 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"parent" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use 'foo.twig' %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
{{ parent() }}
|
8 |
-
{% endblock %}
|
9 |
-
--TEMPLATE(foo.twig)--
|
10 |
-
{% block content %}BAR{% endblock %}
|
11 |
-
--DATA--
|
12 |
-
return array()
|
13 |
-
--EXPECT--
|
14 |
-
BAR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/template_instance.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"extends" tag accepts Twig_Template instance
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends foo %}
|
5 |
-
|
6 |
-
{% block content %}
|
7 |
-
{{ parent() }}FOO
|
8 |
-
{% endblock %}
|
9 |
-
--TEMPLATE(foo.twig)--
|
10 |
-
{% block content %}BAR{% endblock %}
|
11 |
-
--DATA--
|
12 |
-
return array('foo' => $twig->loadTemplate('foo.twig'))
|
13 |
-
--EXPECT--
|
14 |
-
BARFOO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/inheritance/use.test
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"parent" function
|
3 |
-
--TEMPLATE--
|
4 |
-
{% extends "parent.twig" %}
|
5 |
-
|
6 |
-
{% use "use1.twig" %}
|
7 |
-
{% use "use2.twig" %}
|
8 |
-
|
9 |
-
{% block content_parent %}
|
10 |
-
{{ parent() }}
|
11 |
-
{% endblock %}
|
12 |
-
|
13 |
-
{% block content_use1 %}
|
14 |
-
{{ parent() }}
|
15 |
-
{% endblock %}
|
16 |
-
|
17 |
-
{% block content_use2 %}
|
18 |
-
{{ parent() }}
|
19 |
-
{% endblock %}
|
20 |
-
|
21 |
-
{% block content %}
|
22 |
-
{{ block('content_use1_only') }}
|
23 |
-
{{ block('content_use2_only') }}
|
24 |
-
{% endblock %}
|
25 |
-
--TEMPLATE(parent.twig)--
|
26 |
-
{% block content_parent 'content_parent' %}
|
27 |
-
{% block content_use1 'content_parent' %}
|
28 |
-
{% block content_use2 'content_parent' %}
|
29 |
-
{% block content '' %}
|
30 |
-
--TEMPLATE(use1.twig)--
|
31 |
-
{% block content_use1 'content_use1' %}
|
32 |
-
{% block content_use2 'content_use1' %}
|
33 |
-
{% block content_use1_only 'content_use1_only' %}
|
34 |
-
--TEMPLATE(use2.twig)--
|
35 |
-
{% block content_use2 'content_use2' %}
|
36 |
-
{% block content_use2_only 'content_use2_only' %}
|
37 |
-
--DATA--
|
38 |
-
return array()
|
39 |
-
--EXPECT--
|
40 |
-
content_parent
|
41 |
-
content_use1
|
42 |
-
content_use2
|
43 |
-
content_use1_only
|
44 |
-
content_use2_only
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/basic.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"macro" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as macros %}
|
5 |
-
|
6 |
-
{{ macros.input('username') }}
|
7 |
-
{{ macros.input('password', null, 'password', 1) }}
|
8 |
-
|
9 |
-
{% macro input(name, value, type, size) %}
|
10 |
-
<input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}">
|
11 |
-
{% endmacro %}
|
12 |
-
--DATA--
|
13 |
-
return array()
|
14 |
-
--EXPECT--
|
15 |
-
<input type="text" name="username" value="" size="20">
|
16 |
-
|
17 |
-
<input type="password" name="password" value="" size="1">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/endmacro_name.test
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"macro" tag supports name for endmacro
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as macros %}
|
5 |
-
|
6 |
-
{{ macros.foo() }}
|
7 |
-
{{ macros.bar() }}
|
8 |
-
|
9 |
-
{% macro foo() %}foo{% endmacro %}
|
10 |
-
{% macro bar() %}bar{% endmacro bar %}
|
11 |
-
--DATA--
|
12 |
-
return array()
|
13 |
-
--EXPECT--
|
14 |
-
foo
|
15 |
-
bar
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/external.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"macro" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import 'forms.twig' as forms %}
|
5 |
-
|
6 |
-
{{ forms.input('username') }}
|
7 |
-
{{ forms.input('password', null, 'password', 1) }}
|
8 |
-
--TEMPLATE(forms.twig)--
|
9 |
-
{% macro input(name, value, type, size) %}
|
10 |
-
<input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}">
|
11 |
-
{% endmacro %}
|
12 |
-
--DATA--
|
13 |
-
return array()
|
14 |
-
--EXPECT--
|
15 |
-
<input type="text" name="username" value="" size="20">
|
16 |
-
|
17 |
-
<input type="password" name="password" value="" size="1">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/from.test
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"macro" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% from 'forms.twig' import foo %}
|
5 |
-
{% from 'forms.twig' import foo as foobar, bar %}
|
6 |
-
|
7 |
-
{{ foo('foo') }}
|
8 |
-
{{ foobar('foo') }}
|
9 |
-
{{ bar('foo') }}
|
10 |
-
--TEMPLATE(forms.twig)--
|
11 |
-
{% macro foo(name) %}foo{{ name }}{% endmacro %}
|
12 |
-
{% macro bar(name) %}bar{{ name }}{% endmacro %}
|
13 |
-
--DATA--
|
14 |
-
return array()
|
15 |
-
--EXPECT--
|
16 |
-
foofoo
|
17 |
-
foofoo
|
18 |
-
barfoo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/global.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"macro" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% from 'forms.twig' import foo %}
|
5 |
-
|
6 |
-
{{ foo('foo') }}
|
7 |
-
{{ foo() }}
|
8 |
-
--TEMPLATE(forms.twig)--
|
9 |
-
{% macro foo(name) %}{{ name|default('foo') }}{{ global }}{% endmacro %}
|
10 |
-
--DATA--
|
11 |
-
return array()
|
12 |
-
--EXPECT--
|
13 |
-
fooglobal
|
14 |
-
fooglobal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/self_import.test
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"macro" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as forms %}
|
5 |
-
|
6 |
-
{{ forms.input('username') }}
|
7 |
-
{{ forms.input('password', null, 'password', 1) }}
|
8 |
-
|
9 |
-
{% macro input(name, value, type, size) %}
|
10 |
-
<input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}">
|
11 |
-
{% endmacro %}
|
12 |
-
--DATA--
|
13 |
-
return array()
|
14 |
-
--EXPECT--
|
15 |
-
<input type="text" name="username" value="" size="20">
|
16 |
-
|
17 |
-
<input type="password" name="password" value="" size="1">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"☃" as a macro name
|
3 |
-
--TEMPLATE--
|
4 |
-
{% import _self as macros %}
|
5 |
-
|
6 |
-
{{ macros.☃('foo') }}
|
7 |
-
|
8 |
-
{% macro ☃(foo) %}
|
9 |
-
☃{{ foo }}☃
|
10 |
-
{% endmacro %}
|
11 |
-
--DATA--
|
12 |
-
return array()
|
13 |
-
--EXPECT--
|
14 |
-
☃foo☃
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/raw/basic.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"raw" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% raw %}
|
5 |
-
{{ foo }}
|
6 |
-
{% endraw %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
{{ foo }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/raw/mixed_usage_with_raw.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"raw" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% raw %}
|
5 |
-
{{ foo }}
|
6 |
-
{% endverbatim %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXCEPTION--
|
10 |
-
Twig_Error_Syntax: Unexpected end of file: Unclosed "raw" block in "index.twig" at line 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/raw/whitespace_control.test
DELETED
@@ -1,56 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"raw" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
1***
|
5 |
-
|
6 |
-
{%- raw %}
|
7 |
-
{{ 'bla' }}
|
8 |
-
{% endraw %}
|
9 |
-
|
10 |
-
1***
|
11 |
-
2***
|
12 |
-
|
13 |
-
{%- raw -%}
|
14 |
-
{{ 'bla' }}
|
15 |
-
{% endraw %}
|
16 |
-
|
17 |
-
2***
|
18 |
-
3***
|
19 |
-
|
20 |
-
{%- raw -%}
|
21 |
-
{{ 'bla' }}
|
22 |
-
{% endraw -%}
|
23 |
-
|
24 |
-
3***
|
25 |
-
4***
|
26 |
-
|
27 |
-
{%- raw -%}
|
28 |
-
{{ 'bla' }}
|
29 |
-
{%- endraw %}
|
30 |
-
|
31 |
-
4***
|
32 |
-
5***
|
33 |
-
|
34 |
-
{%- raw -%}
|
35 |
-
{{ 'bla' }}
|
36 |
-
{%- endraw -%}
|
37 |
-
|
38 |
-
5***
|
39 |
-
--DATA--
|
40 |
-
return array()
|
41 |
-
--EXPECT--
|
42 |
-
1***
|
43 |
-
{{ 'bla' }}
|
44 |
-
|
45 |
-
|
46 |
-
1***
|
47 |
-
2***{{ 'bla' }}
|
48 |
-
|
49 |
-
|
50 |
-
2***
|
51 |
-
3***{{ 'bla' }}
|
52 |
-
3***
|
53 |
-
4***{{ 'bla' }}
|
54 |
-
|
55 |
-
4***
|
56 |
-
5***{{ 'bla' }}5***
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid1.test
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
sandbox tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{%- sandbox %}
|
5 |
-
{%- include "foo.twig" %}
|
6 |
-
a
|
7 |
-
{%- endsandbox %}
|
8 |
-
--TEMPLATE(foo.twig)--
|
9 |
-
foo
|
10 |
-
--EXCEPTION--
|
11 |
-
Twig_Error_Syntax: Only "include" tags are allowed within a "sandbox" section in "index.twig" at line 4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid2.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
sandbox tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{%- sandbox %}
|
5 |
-
{%- include "foo.twig" %}
|
6 |
-
|
7 |
-
{% if 1 %}
|
8 |
-
{%- include "foo.twig" %}
|
9 |
-
{% endif %}
|
10 |
-
{%- endsandbox %}
|
11 |
-
--TEMPLATE(foo.twig)--
|
12 |
-
foo
|
13 |
-
--EXCEPTION--
|
14 |
-
Twig_Error_Syntax: Only "include" tags are allowed within a "sandbox" section in "index.twig" at line 5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/sandbox/simple.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
sandbox tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{%- sandbox %}
|
5 |
-
{%- include "foo.twig" %}
|
6 |
-
{%- endsandbox %}
|
7 |
-
|
8 |
-
{%- sandbox %}
|
9 |
-
{%- include "foo.twig" %}
|
10 |
-
{%- include "foo.twig" %}
|
11 |
-
{%- endsandbox %}
|
12 |
-
|
13 |
-
{%- sandbox %}{% include "foo.twig" %}{% endsandbox %}
|
14 |
-
--TEMPLATE(foo.twig)--
|
15 |
-
foo
|
16 |
-
--DATA--
|
17 |
-
return array()
|
18 |
-
--EXPECT--
|
19 |
-
foo
|
20 |
-
foo
|
21 |
-
foo
|
22 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/set/basic.test
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"set" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% set foo = 'foo' %}
|
5 |
-
{% set bar = 'foo<br />' %}
|
6 |
-
|
7 |
-
{{ foo }}
|
8 |
-
{{ bar }}
|
9 |
-
|
10 |
-
{% set foo, bar = 'foo', 'bar' %}
|
11 |
-
|
12 |
-
{{ foo }}{{ bar }}
|
13 |
-
--DATA--
|
14 |
-
return array()
|
15 |
-
--EXPECT--
|
16 |
-
foo
|
17 |
-
foo<br />
|
18 |
-
|
19 |
-
|
20 |
-
foobar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/set/capture-empty.test
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"set" tag block empty capture
|
3 |
-
--TEMPLATE--
|
4 |
-
{% set foo %}{% endset %}
|
5 |
-
|
6 |
-
{% if foo %}FAIL{% endif %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/set/capture.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"set" tag block capture
|
3 |
-
--TEMPLATE--
|
4 |
-
{% set foo %}f<br />o<br />o{% endset %}
|
5 |
-
|
6 |
-
{{ foo }}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
f<br />o<br />o
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/set/expression.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"set" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% set foo, bar = 'foo' ~ 'bar', 'bar' ~ 'foo' %}
|
5 |
-
|
6 |
-
{{ foo }}
|
7 |
-
{{ bar }}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
foobar
|
12 |
-
barfoo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/spaceless/simple.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"spaceless" tag removes whites between HTML tags
|
3 |
-
--TEMPLATE--
|
4 |
-
{% spaceless %}
|
5 |
-
|
6 |
-
<div> <div> foo </div> </div>
|
7 |
-
|
8 |
-
{% endspaceless %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
<div><div> foo </div></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/special_chars.test
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"☃" custom tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% ☃ %}
|
5 |
-
--DATA--
|
6 |
-
return array()
|
7 |
-
--EXPECT--
|
8 |
-
☃
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/trim_block.test
DELETED
@@ -1,74 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Whitespace trimming on tags.
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 5 * '{#-'|length }}
|
5 |
-
{{ '{{-'|length * 5 + '{%-'|length }}
|
6 |
-
|
7 |
-
Trim on control tag:
|
8 |
-
{% for i in range(1, 9) -%}
|
9 |
-
{{ i }}
|
10 |
-
{%- endfor %}
|
11 |
-
|
12 |
-
|
13 |
-
Trim on output tag:
|
14 |
-
{% for i in range(1, 9) %}
|
15 |
-
{{- i -}}
|
16 |
-
{% endfor %}
|
17 |
-
|
18 |
-
|
19 |
-
Trim comments:
|
20 |
-
|
21 |
-
{#- Invisible -#}
|
22 |
-
|
23 |
-
After the comment.
|
24 |
-
|
25 |
-
Trim leading space:
|
26 |
-
{% if leading %}
|
27 |
-
|
28 |
-
{{- leading }}
|
29 |
-
{% endif %}
|
30 |
-
|
31 |
-
{%- if leading %}
|
32 |
-
{{- leading }}
|
33 |
-
|
34 |
-
{%- endif %}
|
35 |
-
|
36 |
-
|
37 |
-
Trim trailing space:
|
38 |
-
{% if trailing -%}
|
39 |
-
{{ trailing -}}
|
40 |
-
|
41 |
-
{% endif -%}
|
42 |
-
|
43 |
-
Combined:
|
44 |
-
|
45 |
-
{%- if both -%}
|
46 |
-
<ul>
|
47 |
-
<li> {{- both -}} </li>
|
48 |
-
</ul>
|
49 |
-
|
50 |
-
{%- endif -%}
|
51 |
-
|
52 |
-
end
|
53 |
-
--DATA--
|
54 |
-
return array('leading' => 'leading space', 'trailing' => 'trailing space', 'both' => 'both')
|
55 |
-
--EXPECT--
|
56 |
-
15
|
57 |
-
18
|
58 |
-
|
59 |
-
Trim on control tag:
|
60 |
-
123456789
|
61 |
-
|
62 |
-
Trim on output tag:
|
63 |
-
123456789
|
64 |
-
|
65 |
-
Trim comments:After the comment.
|
66 |
-
|
67 |
-
Trim leading space:
|
68 |
-
leading space
|
69 |
-
leading space
|
70 |
-
|
71 |
-
Trim trailing space:
|
72 |
-
trailing spaceCombined:<ul>
|
73 |
-
<li>both</li>
|
74 |
-
</ul>end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/use/aliases.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"use" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use "blocks.twig" with content as foo %}
|
5 |
-
|
6 |
-
{{ block('foo') }}
|
7 |
-
--TEMPLATE(blocks.twig)--
|
8 |
-
{% block content 'foo' %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/use/basic.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"use" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use "blocks.twig" %}
|
5 |
-
|
6 |
-
{{ block('content') }}
|
7 |
-
--TEMPLATE(blocks.twig)--
|
8 |
-
{% block content 'foo' %}
|
9 |
-
--DATA--
|
10 |
-
return array()
|
11 |
-
--EXPECT--
|
12 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/use/deep.test
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"use" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use "foo.twig" %}
|
5 |
-
|
6 |
-
{{ block('content') }}
|
7 |
-
{{ block('foo') }}
|
8 |
-
{{ block('bar') }}
|
9 |
-
--TEMPLATE(foo.twig)--
|
10 |
-
{% use "bar.twig" %}
|
11 |
-
|
12 |
-
{% block content 'foo' %}
|
13 |
-
{% block foo 'foo' %}
|
14 |
-
--TEMPLATE(bar.twig)--
|
15 |
-
{% block content 'bar' %}
|
16 |
-
{% block bar 'bar' %}
|
17 |
-
--DATA--
|
18 |
-
return array()
|
19 |
-
--EXPECT--
|
20 |
-
foo
|
21 |
-
foo
|
22 |
-
bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/use/deep_empty.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"use" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use "foo.twig" %}
|
5 |
-
--TEMPLATE(foo.twig)--
|
6 |
-
{% use "bar.twig" %}
|
7 |
-
--TEMPLATE(bar.twig)--
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/use/multiple.test
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"use" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use "foo.twig" %}
|
5 |
-
{% use "bar.twig" %}
|
6 |
-
|
7 |
-
{{ block('content') }}
|
8 |
-
{{ block('foo') }}
|
9 |
-
{{ block('bar') }}
|
10 |
-
--TEMPLATE(foo.twig)--
|
11 |
-
{% block content 'foo' %}
|
12 |
-
{% block foo 'foo' %}
|
13 |
-
--TEMPLATE(bar.twig)--
|
14 |
-
{% block content 'bar' %}
|
15 |
-
{% block bar 'bar' %}
|
16 |
-
--DATA--
|
17 |
-
return array()
|
18 |
-
--EXPECT--
|
19 |
-
bar
|
20 |
-
foo
|
21 |
-
bar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/use/multiple_aliases.test
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"use" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% use "foo.twig" with content as foo_content %}
|
5 |
-
{% use "bar.twig" %}
|
6 |
-
|
7 |
-
{{ block('content') }}
|
8 |
-
{{ block('foo') }}
|
9 |
-
{{ block('bar') }}
|
10 |
-
{{ block('foo_content') }}
|
11 |
-
--TEMPLATE(foo.twig)--
|
12 |
-
{% block content 'foo' %}
|
13 |
-
{% block foo 'foo' %}
|
14 |
-
--TEMPLATE(bar.twig)--
|
15 |
-
{% block content 'bar' %}
|
16 |
-
{% block bar 'bar' %}
|
17 |
-
--DATA--
|
18 |
-
return array()
|
19 |
-
--EXPECT--
|
20 |
-
bar
|
21 |
-
foo
|
22 |
-
bar
|
23 |
-
foo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/verbatim/basic.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"verbatim" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% verbatim %}
|
5 |
-
{{ foo }}
|
6 |
-
{% endverbatim %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXPECT--
|
10 |
-
{{ foo }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"verbatim" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
{% verbatim %}
|
5 |
-
{{ foo }}
|
6 |
-
{% endraw %}
|
7 |
-
--DATA--
|
8 |
-
return array()
|
9 |
-
--EXCEPTION--
|
10 |
-
Twig_Error_Syntax: Unexpected end of file: Unclosed "verbatim" block in "index.twig" at line 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tags/verbatim/whitespace_control.test
DELETED
@@ -1,56 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"verbatim" tag
|
3 |
-
--TEMPLATE--
|
4 |
-
1***
|
5 |
-
|
6 |
-
{%- verbatim %}
|
7 |
-
{{ 'bla' }}
|
8 |
-
{% endverbatim %}
|
9 |
-
|
10 |
-
1***
|
11 |
-
2***
|
12 |
-
|
13 |
-
{%- verbatim -%}
|
14 |
-
{{ 'bla' }}
|
15 |
-
{% endverbatim %}
|
16 |
-
|
17 |
-
2***
|
18 |
-
3***
|
19 |
-
|
20 |
-
{%- verbatim -%}
|
21 |
-
{{ 'bla' }}
|
22 |
-
{% endverbatim -%}
|
23 |
-
|
24 |
-
3***
|
25 |
-
4***
|
26 |
-
|
27 |
-
{%- verbatim -%}
|
28 |
-
{{ 'bla' }}
|
29 |
-
{%- endverbatim %}
|
30 |
-
|
31 |
-
4***
|
32 |
-
5***
|
33 |
-
|
34 |
-
{%- verbatim -%}
|
35 |
-
{{ 'bla' }}
|
36 |
-
{%- endverbatim -%}
|
37 |
-
|
38 |
-
5***
|
39 |
-
--DATA--
|
40 |
-
return array()
|
41 |
-
--EXPECT--
|
42 |
-
1***
|
43 |
-
{{ 'bla' }}
|
44 |
-
|
45 |
-
|
46 |
-
1***
|
47 |
-
2***{{ 'bla' }}
|
48 |
-
|
49 |
-
|
50 |
-
2***
|
51 |
-
3***{{ 'bla' }}
|
52 |
-
3***
|
53 |
-
4***{{ 'bla' }}
|
54 |
-
|
55 |
-
4***
|
56 |
-
5***{{ 'bla' }}5***
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/array.test
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
array index test
|
3 |
-
--TEMPLATE--
|
4 |
-
{% for key, value in days %}
|
5 |
-
{{ key }}
|
6 |
-
{% endfor %}
|
7 |
-
--DATA--
|
8 |
-
return array('days' => array(
|
9 |
-
1 => array('money' => 9),
|
10 |
-
2 => array('money' => 21),
|
11 |
-
3 => array('money' => 38),
|
12 |
-
4 => array('money' => 6),
|
13 |
-
18 => array('money' => 6),
|
14 |
-
19 => array('money' => 3),
|
15 |
-
31 => array('money' => 11),
|
16 |
-
));
|
17 |
-
--EXPECT--
|
18 |
-
1
|
19 |
-
2
|
20 |
-
3
|
21 |
-
4
|
22 |
-
18
|
23 |
-
19
|
24 |
-
31
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/constant.test
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"const" test
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 8 is constant('E_NOTICE') ? 'ok' : 'no' }}
|
5 |
-
{{ 'bar' is constant('TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }}
|
6 |
-
{{ value is constant('TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }}
|
7 |
-
--DATA--
|
8 |
-
return array('value' => 'bar');
|
9 |
-
--EXPECT--
|
10 |
-
ok
|
11 |
-
ok
|
12 |
-
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/defined.test
DELETED
@@ -1,108 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"defined" test
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ definedVar is defined ? 'ok' : 'ko' }}
|
5 |
-
{{ definedVar is not defined ? 'ko' : 'ok' }}
|
6 |
-
{{ undefinedVar is defined ? 'ko' : 'ok' }}
|
7 |
-
{{ undefinedVar is not defined ? 'ok' : 'ko' }}
|
8 |
-
{{ zeroVar is defined ? 'ok' : 'ko' }}
|
9 |
-
{{ nullVar is defined ? 'ok' : 'ko' }}
|
10 |
-
{{ nested.definedVar is defined ? 'ok' : 'ko' }}
|
11 |
-
{{ nested['definedVar'] is defined ? 'ok' : 'ko' }}
|
12 |
-
{{ nested.definedVar is not defined ? 'ko' : 'ok' }}
|
13 |
-
{{ nested.undefinedVar is defined ? 'ko' : 'ok' }}
|
14 |
-
{{ nested['undefinedVar'] is defined ? 'ko' : 'ok' }}
|
15 |
-
{{ nested.undefinedVar is not defined ? 'ok' : 'ko' }}
|
16 |
-
{{ nested.zeroVar is defined ? 'ok' : 'ko' }}
|
17 |
-
{{ nested.nullVar is defined ? 'ok' : 'ko' }}
|
18 |
-
{{ nested.definedArray.0 is defined ? 'ok' : 'ko' }}
|
19 |
-
{{ nested['definedArray'][0] is defined ? 'ok' : 'ko' }}
|
20 |
-
{{ object.foo is defined ? 'ok' : 'ko' }}
|
21 |
-
{{ object.undefinedMethod is defined ? 'ko' : 'ok' }}
|
22 |
-
{{ object.getFoo() is defined ? 'ok' : 'ko' }}
|
23 |
-
{{ object.getFoo('a') is defined ? 'ok' : 'ko' }}
|
24 |
-
{{ object.undefinedMethod() is defined ? 'ko' : 'ok' }}
|
25 |
-
{{ object.undefinedMethod('a') is defined ? 'ko' : 'ok' }}
|
26 |
-
{{ object.self.foo is defined ? 'ok' : 'ko' }}
|
27 |
-
{{ object.self.undefinedMethod is defined ? 'ko' : 'ok' }}
|
28 |
-
{{ object.undefinedMethod.self is defined ? 'ko' : 'ok' }}
|
29 |
-
--DATA--
|
30 |
-
return array(
|
31 |
-
'definedVar' => 'defined',
|
32 |
-
'zeroVar' => 0,
|
33 |
-
'nullVar' => null,
|
34 |
-
'nested' => array(
|
35 |
-
'definedVar' => 'defined',
|
36 |
-
'zeroVar' => 0,
|
37 |
-
'nullVar' => null,
|
38 |
-
'definedArray' => array(0),
|
39 |
-
),
|
40 |
-
'object' => new TwigTestFoo(),
|
41 |
-
);
|
42 |
-
--EXPECT--
|
43 |
-
ok
|
44 |
-
ok
|
45 |
-
ok
|
46 |
-
ok
|
47 |
-
ok
|
48 |
-
ok
|
49 |
-
ok
|
50 |
-
ok
|
51 |
-
ok
|
52 |
-
ok
|
53 |
-
ok
|
54 |
-
ok
|
55 |
-
ok
|
56 |
-
ok
|
57 |
-
ok
|
58 |
-
ok
|
59 |
-
ok
|
60 |
-
ok
|
61 |
-
ok
|
62 |
-
ok
|
63 |
-
ok
|
64 |
-
ok
|
65 |
-
ok
|
66 |
-
ok
|
67 |
-
ok
|
68 |
-
--DATA--
|
69 |
-
return array(
|
70 |
-
'definedVar' => 'defined',
|
71 |
-
'zeroVar' => 0,
|
72 |
-
'nullVar' => null,
|
73 |
-
'nested' => array(
|
74 |
-
'definedVar' => 'defined',
|
75 |
-
'zeroVar' => 0,
|
76 |
-
'nullVar' => null,
|
77 |
-
'definedArray' => array(0),
|
78 |
-
),
|
79 |
-
'object' => new TwigTestFoo(),
|
80 |
-
);
|
81 |
-
--CONFIG--
|
82 |
-
return array('strict_variables' => false)
|
83 |
-
--EXPECT--
|
84 |
-
ok
|
85 |
-
ok
|
86 |
-
ok
|
87 |
-
ok
|
88 |
-
ok
|
89 |
-
ok
|
90 |
-
ok
|
91 |
-
ok
|
92 |
-
ok
|
93 |
-
ok
|
94 |
-
ok
|
95 |
-
ok
|
96 |
-
ok
|
97 |
-
ok
|
98 |
-
ok
|
99 |
-
ok
|
100 |
-
ok
|
101 |
-
ok
|
102 |
-
ok
|
103 |
-
ok
|
104 |
-
ok
|
105 |
-
ok
|
106 |
-
ok
|
107 |
-
ok
|
108 |
-
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/empty.test
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"empty" test
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ foo is empty ? 'ok' : 'ko' }}
|
5 |
-
{{ bar is empty ? 'ok' : 'ko' }}
|
6 |
-
{{ foobar is empty ? 'ok' : 'ko' }}
|
7 |
-
{{ array is empty ? 'ok' : 'ko' }}
|
8 |
-
{{ zero is empty ? 'ok' : 'ko' }}
|
9 |
-
{{ string is empty ? 'ok' : 'ko' }}
|
10 |
-
{{ countable_empty is empty ? 'ok' : 'ko' }}
|
11 |
-
{{ countable_not_empty is empty ? 'ok' : 'ko' }}
|
12 |
-
{{ markup_empty is empty ? 'ok' : 'ko' }}
|
13 |
-
{{ markup_not_empty is empty ? 'ok' : 'ko' }}
|
14 |
-
--DATA--
|
15 |
-
|
16 |
-
class CountableStub implements Countable
|
17 |
-
{
|
18 |
-
private $items;
|
19 |
-
|
20 |
-
public function __construct(array $items)
|
21 |
-
{
|
22 |
-
$this->items = $items;
|
23 |
-
}
|
24 |
-
|
25 |
-
public function count()
|
26 |
-
{
|
27 |
-
return count($this->items);
|
28 |
-
}
|
29 |
-
}
|
30 |
-
return array(
|
31 |
-
'foo' => '', 'bar' => null, 'foobar' => false, 'array' => array(), 'zero' => 0, 'string' => '0',
|
32 |
-
'countable_empty' => new CountableStub(array()), 'countable_not_empty' => new CountableStub(array(1, 2)),
|
33 |
-
'markup_empty' => new Twig_Markup('', 'UTF-8'), 'markup_not_empty' => new Twig_Markup('test', 'UTF-8'),
|
34 |
-
);
|
35 |
-
--EXPECT--
|
36 |
-
ok
|
37 |
-
ok
|
38 |
-
ok
|
39 |
-
ok
|
40 |
-
ko
|
41 |
-
ko
|
42 |
-
ok
|
43 |
-
ko
|
44 |
-
ok
|
45 |
-
ko
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/even.test
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"even" test
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 is even ? 'ko' : 'ok' }}
|
5 |
-
{{ 2 is even ? 'ok' : 'ko' }}
|
6 |
-
{{ 1 is not even ? 'ok' : 'ko' }}
|
7 |
-
{{ 2 is not even ? 'ko' : 'ok' }}
|
8 |
-
--DATA--
|
9 |
-
return array()
|
10 |
-
--EXPECT--
|
11 |
-
ok
|
12 |
-
ok
|
13 |
-
ok
|
14 |
-
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/in.test
DELETED
@@ -1,48 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports the in operator
|
3 |
-
--TEMPLATE--
|
4 |
-
{% if bar in foo %}
|
5 |
-
TRUE
|
6 |
-
{% endif %}
|
7 |
-
{% if not (bar in foo) %}
|
8 |
-
{% else %}
|
9 |
-
TRUE
|
10 |
-
{% endif %}
|
11 |
-
{% if bar not in foo %}
|
12 |
-
{% else %}
|
13 |
-
TRUE
|
14 |
-
{% endif %}
|
15 |
-
{% if 'a' in bar %}
|
16 |
-
TRUE
|
17 |
-
{% endif %}
|
18 |
-
{% if 'c' not in bar %}
|
19 |
-
TRUE
|
20 |
-
{% endif %}
|
21 |
-
{% if '' not in bar %}
|
22 |
-
TRUE
|
23 |
-
{% endif %}
|
24 |
-
{% if '' in '' %}
|
25 |
-
TRUE
|
26 |
-
{% endif %}
|
27 |
-
{% if '0' not in '' %}
|
28 |
-
TRUE
|
29 |
-
{% endif %}
|
30 |
-
{% if 'a' not in '0' %}
|
31 |
-
TRUE
|
32 |
-
{% endif %}
|
33 |
-
{% if '0' in '0' %}
|
34 |
-
TRUE
|
35 |
-
{% endif %}
|
36 |
-
--DATA--
|
37 |
-
return array('bar' => 'bar', 'foo' => array('bar' => 'bar'))
|
38 |
-
--EXPECT--
|
39 |
-
TRUE
|
40 |
-
TRUE
|
41 |
-
TRUE
|
42 |
-
TRUE
|
43 |
-
TRUE
|
44 |
-
TRUE
|
45 |
-
TRUE
|
46 |
-
TRUE
|
47 |
-
TRUE
|
48 |
-
TRUE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/in_with_objects.test
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
Twig supports the in operator when using objects
|
3 |
-
--TEMPLATE--
|
4 |
-
{% if object in object_list %}
|
5 |
-
TRUE
|
6 |
-
{% endif %}
|
7 |
-
--DATA--
|
8 |
-
$foo = new TwigTestFoo();
|
9 |
-
$foo1 = new TwigTestFoo();
|
10 |
-
|
11 |
-
$foo->position = $foo1;
|
12 |
-
$foo1->position = $foo;
|
13 |
-
|
14 |
-
return array(
|
15 |
-
'object' => $foo,
|
16 |
-
'object_list' => array($foo1, $foo),
|
17 |
-
);
|
18 |
-
--EXPECT--
|
19 |
-
TRUE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/iterable.test
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"iterable" test
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ foo is iterable ? 'ok' : 'ko' }}
|
5 |
-
{{ traversable is iterable ? 'ok' : 'ko' }}
|
6 |
-
{{ obj is iterable ? 'ok' : 'ko' }}
|
7 |
-
{{ val is iterable ? 'ok' : 'ko' }}
|
8 |
-
--DATA--
|
9 |
-
return array(
|
10 |
-
'foo' => array(),
|
11 |
-
'traversable' => new ArrayIterator(array()),
|
12 |
-
'obj' => new stdClass(),
|
13 |
-
'val' => 'test',
|
14 |
-
);
|
15 |
-
--EXPECT--
|
16 |
-
ok
|
17 |
-
ok
|
18 |
-
ko
|
19 |
-
ko
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Fixtures/tests/odd.test
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
--TEST--
|
2 |
-
"odd" test
|
3 |
-
--TEMPLATE--
|
4 |
-
{{ 1 is odd ? 'ok' : 'ko' }}
|
5 |
-
{{ 2 is odd ? 'ko' : 'ok' }}
|
6 |
-
--DATA--
|
7 |
-
return array()
|
8 |
-
--EXPECT--
|
9 |
-
ok
|
10 |
-
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/IntegrationTest.php
DELETED
@@ -1,217 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
// This function is defined to check that escaping strategies
|
13 |
-
// like html works even if a function with the same name is defined.
|
14 |
-
function html()
|
15 |
-
{
|
16 |
-
return 'foo';
|
17 |
-
}
|
18 |
-
|
19 |
-
class Twig_Tests_IntegrationTest extends Twig_Test_IntegrationTestCase
|
20 |
-
{
|
21 |
-
public function getExtensions()
|
22 |
-
{
|
23 |
-
$policy = new Twig_Sandbox_SecurityPolicy(array(), array(), array(), array(), array());
|
24 |
-
|
25 |
-
return array(
|
26 |
-
new Twig_Extension_Debug(),
|
27 |
-
new Twig_Extension_Sandbox($policy, false),
|
28 |
-
new Twig_Extension_StringLoader(),
|
29 |
-
new TwigTestExtension(),
|
30 |
-
);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getFixturesDir()
|
34 |
-
{
|
35 |
-
return dirname(__FILE__).'/Fixtures/';
|
36 |
-
}
|
37 |
-
}
|
38 |
-
|
39 |
-
function test_foo($value = 'foo')
|
40 |
-
{
|
41 |
-
return $value;
|
42 |
-
}
|
43 |
-
|
44 |
-
class TwigTestFoo implements Iterator
|
45 |
-
{
|
46 |
-
const BAR_NAME = 'bar';
|
47 |
-
|
48 |
-
public $position = 0;
|
49 |
-
public $array = array(1, 2);
|
50 |
-
|
51 |
-
public function bar($param1 = null, $param2 = null)
|
52 |
-
{
|
53 |
-
return 'bar'.($param1 ? '_'.$param1 : '').($param2 ? '-'.$param2 : '');
|
54 |
-
}
|
55 |
-
|
56 |
-
public function getFoo()
|
57 |
-
{
|
58 |
-
return 'foo';
|
59 |
-
}
|
60 |
-
|
61 |
-
public function getSelf()
|
62 |
-
{
|
63 |
-
return $this;
|
64 |
-
}
|
65 |
-
|
66 |
-
public function is()
|
67 |
-
{
|
68 |
-
return 'is';
|
69 |
-
}
|
70 |
-
|
71 |
-
public function in()
|
72 |
-
{
|
73 |
-
return 'in';
|
74 |
-
}
|
75 |
-
|
76 |
-
public function not()
|
77 |
-
{
|
78 |
-
return 'not';
|
79 |
-
}
|
80 |
-
|
81 |
-
public function strToLower($value)
|
82 |
-
{
|
83 |
-
return strtolower($value);
|
84 |
-
}
|
85 |
-
|
86 |
-
public function rewind()
|
87 |
-
{
|
88 |
-
$this->position = 0;
|
89 |
-
}
|
90 |
-
|
91 |
-
public function current()
|
92 |
-
{
|
93 |
-
return $this->array[$this->position];
|
94 |
-
}
|
95 |
-
|
96 |
-
public function key()
|
97 |
-
{
|
98 |
-
return 'a';
|
99 |
-
}
|
100 |
-
|
101 |
-
public function next()
|
102 |
-
{
|
103 |
-
++$this->position;
|
104 |
-
}
|
105 |
-
|
106 |
-
public function valid()
|
107 |
-
{
|
108 |
-
return isset($this->array[$this->position]);
|
109 |
-
}
|
110 |
-
}
|
111 |
-
|
112 |
-
class TwigTestTokenParser_☃ extends Twig_TokenParser
|
113 |
-
{
|
114 |
-
public function parse(Twig_Token $token)
|
115 |
-
{
|
116 |
-
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
117 |
-
|
118 |
-
return new Twig_Node_Print(new Twig_Node_Expression_Constant('☃', -1), -1);
|
119 |
-
}
|
120 |
-
|
121 |
-
public function getTag()
|
122 |
-
{
|
123 |
-
return '☃';
|
124 |
-
}
|
125 |
-
}
|
126 |
-
|
127 |
-
class TwigTestExtension extends Twig_Extension
|
128 |
-
{
|
129 |
-
public function getTokenParsers()
|
130 |
-
{
|
131 |
-
return array(
|
132 |
-
new TwigTestTokenParser_☃(),
|
133 |
-
);
|
134 |
-
}
|
135 |
-
|
136 |
-
public function getFilters()
|
137 |
-
{
|
138 |
-
return array(
|
139 |
-
'☃' => new Twig_Filter_Method($this, '☃Filter'),
|
140 |
-
'escape_and_nl2br' => new Twig_Filter_Method($this, 'escape_and_nl2br', array('needs_environment' => true, 'is_safe' => array('html'))),
|
141 |
-
'nl2br' => new Twig_Filter_Method($this, 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
|
142 |
-
'escape_something' => new Twig_Filter_Method($this, 'escape_something', array('is_safe' => array('something'))),
|
143 |
-
'preserves_safety' => new Twig_Filter_Method($this, 'preserves_safety', array('preserves_safety' => array('html'))),
|
144 |
-
'*_path' => new Twig_Filter_Method($this, 'dynamic_path'),
|
145 |
-
'*_foo_*_bar' => new Twig_Filter_Method($this, 'dynamic_foo'),
|
146 |
-
);
|
147 |
-
}
|
148 |
-
|
149 |
-
public function getFunctions()
|
150 |
-
{
|
151 |
-
return array(
|
152 |
-
'☃' => new Twig_Function_Method($this, '☃Function'),
|
153 |
-
'safe_br' => new Twig_Function_Method($this, 'br', array('is_safe' => array('html'))),
|
154 |
-
'unsafe_br' => new Twig_Function_Method($this, 'br'),
|
155 |
-
'*_path' => new Twig_Function_Method($this, 'dynamic_path'),
|
156 |
-
'*_foo_*_bar' => new Twig_Function_Method($this, 'dynamic_foo'),
|
157 |
-
);
|
158 |
-
}
|
159 |
-
|
160 |
-
public function ☃Filter($value)
|
161 |
-
{
|
162 |
-
return "☃{$value}☃";
|
163 |
-
}
|
164 |
-
|
165 |
-
public function ☃Function($value)
|
166 |
-
{
|
167 |
-
return "☃{$value}☃";
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* nl2br which also escapes, for testing escaper filters
|
172 |
-
*/
|
173 |
-
public function escape_and_nl2br($env, $value, $sep = '<br />')
|
174 |
-
{
|
175 |
-
return $this->nl2br(twig_escape_filter($env, $value, 'html'), $sep);
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* nl2br only, for testing filters with pre_escape
|
180 |
-
*/
|
181 |
-
public function nl2br($value, $sep = '<br />')
|
182 |
-
{
|
183 |
-
// not secure if $value contains html tags (not only entities)
|
184 |
-
// don't use
|
185 |
-
return str_replace("\n", "$sep\n", $value);
|
186 |
-
}
|
187 |
-
|
188 |
-
public function dynamic_path($element, $item)
|
189 |
-
{
|
190 |
-
return $element.'/'.$item;
|
191 |
-
}
|
192 |
-
|
193 |
-
public function dynamic_foo($foo, $bar, $item)
|
194 |
-
{
|
195 |
-
return $foo.'/'.$bar.'/'.$item;
|
196 |
-
}
|
197 |
-
|
198 |
-
public function escape_something($value)
|
199 |
-
{
|
200 |
-
return strtoupper($value);
|
201 |
-
}
|
202 |
-
|
203 |
-
public function preserves_safety($value)
|
204 |
-
{
|
205 |
-
return strtoupper($value);
|
206 |
-
}
|
207 |
-
|
208 |
-
public function br()
|
209 |
-
{
|
210 |
-
return '<br />';
|
211 |
-
}
|
212 |
-
|
213 |
-
public function getName()
|
214 |
-
{
|
215 |
-
return 'test';
|
216 |
-
}
|
217 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/LexerTest.php
DELETED
@@ -1,249 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
12 |
-
{
|
13 |
-
public function testNameLabelForTag()
|
14 |
-
{
|
15 |
-
$template = '{% ☃ %}';
|
16 |
-
|
17 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
18 |
-
$stream = $lexer->tokenize($template);
|
19 |
-
|
20 |
-
$stream->expect(Twig_Token::BLOCK_START_TYPE);
|
21 |
-
$this->assertSame('☃', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
|
22 |
-
}
|
23 |
-
|
24 |
-
public function testNameLabelForFunction()
|
25 |
-
{
|
26 |
-
$template = '{{ ☃() }}';
|
27 |
-
|
28 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
29 |
-
$stream = $lexer->tokenize($template);
|
30 |
-
|
31 |
-
$stream->expect(Twig_Token::VAR_START_TYPE);
|
32 |
-
$this->assertSame('☃', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
|
33 |
-
}
|
34 |
-
|
35 |
-
public function testBracketsNesting()
|
36 |
-
{
|
37 |
-
$template = '{{ {"a":{"b":"c"}} }}';
|
38 |
-
|
39 |
-
$this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '{'));
|
40 |
-
$this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '}'));
|
41 |
-
}
|
42 |
-
|
43 |
-
protected function countToken($template, $type, $value = null)
|
44 |
-
{
|
45 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
46 |
-
$stream = $lexer->tokenize($template);
|
47 |
-
|
48 |
-
$count = 0;
|
49 |
-
$tokens = array();
|
50 |
-
while (!$stream->isEOF()) {
|
51 |
-
$token = $stream->next();
|
52 |
-
if ($type === $token->getType()) {
|
53 |
-
if (null === $value || $value === $token->getValue()) {
|
54 |
-
++$count;
|
55 |
-
}
|
56 |
-
}
|
57 |
-
}
|
58 |
-
|
59 |
-
return $count;
|
60 |
-
}
|
61 |
-
|
62 |
-
public function testLineDirective()
|
63 |
-
{
|
64 |
-
$template = "foo\n"
|
65 |
-
. "bar\n"
|
66 |
-
. "{% line 10 %}\n"
|
67 |
-
. "{{\n"
|
68 |
-
. "baz\n"
|
69 |
-
. "}}\n";
|
70 |
-
|
71 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
72 |
-
$stream = $lexer->tokenize($template);
|
73 |
-
|
74 |
-
// foo\nbar\n
|
75 |
-
$this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
76 |
-
// \n (after {% line %})
|
77 |
-
$this->assertSame(10, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
78 |
-
// {{
|
79 |
-
$this->assertSame(11, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine());
|
80 |
-
// baz
|
81 |
-
$this->assertSame(12, $stream->expect(Twig_Token::NAME_TYPE)->getLine());
|
82 |
-
}
|
83 |
-
|
84 |
-
public function testLineDirectiveInline()
|
85 |
-
{
|
86 |
-
$template = "foo\n"
|
87 |
-
. "bar{% line 10 %}{{\n"
|
88 |
-
. "baz\n"
|
89 |
-
. "}}\n";
|
90 |
-
|
91 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
92 |
-
$stream = $lexer->tokenize($template);
|
93 |
-
|
94 |
-
// foo\nbar
|
95 |
-
$this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
96 |
-
// {{
|
97 |
-
$this->assertSame(10, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine());
|
98 |
-
// baz
|
99 |
-
$this->assertSame(11, $stream->expect(Twig_Token::NAME_TYPE)->getLine());
|
100 |
-
}
|
101 |
-
|
102 |
-
public function testLongComments()
|
103 |
-
{
|
104 |
-
$template = '{# '.str_repeat('*', 100000).' #}';
|
105 |
-
|
106 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
107 |
-
$lexer->tokenize($template);
|
108 |
-
|
109 |
-
// should not throw an exception
|
110 |
-
}
|
111 |
-
|
112 |
-
public function testLongRaw()
|
113 |
-
{
|
114 |
-
$template = '{% raw %}'.str_repeat('*', 100000).'{% endraw %}';
|
115 |
-
|
116 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
117 |
-
$stream = $lexer->tokenize($template);
|
118 |
-
|
119 |
-
// should not throw an exception
|
120 |
-
}
|
121 |
-
|
122 |
-
public function testLongVar()
|
123 |
-
{
|
124 |
-
$template = '{{ '.str_repeat('x', 100000).' }}';
|
125 |
-
|
126 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
127 |
-
$stream = $lexer->tokenize($template);
|
128 |
-
|
129 |
-
// should not throw an exception
|
130 |
-
}
|
131 |
-
|
132 |
-
public function testLongBlock()
|
133 |
-
{
|
134 |
-
$template = '{% '.str_repeat('x', 100000).' %}';
|
135 |
-
|
136 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
137 |
-
$stream = $lexer->tokenize($template);
|
138 |
-
|
139 |
-
// should not throw an exception
|
140 |
-
}
|
141 |
-
|
142 |
-
public function testBigNumbers()
|
143 |
-
{
|
144 |
-
$template = '{{ 922337203685477580700 }}';
|
145 |
-
|
146 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
147 |
-
$stream = $lexer->tokenize($template);
|
148 |
-
$node = $stream->next();
|
149 |
-
$node = $stream->next();
|
150 |
-
$this->assertEquals(922337203685477580700, $node->getValue());
|
151 |
-
}
|
152 |
-
|
153 |
-
public function testString()
|
154 |
-
{
|
155 |
-
$template = 'foo {{ "bar #{ baz + 1 }" }}';
|
156 |
-
|
157 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
158 |
-
$stream = $lexer->tokenize($template);
|
159 |
-
$stream->expect(Twig_Token::TEXT_TYPE, 'foo ');
|
160 |
-
$stream->expect(Twig_Token::VAR_START_TYPE);
|
161 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
162 |
-
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
163 |
-
$stream->expect(Twig_Token::NAME_TYPE, 'baz');
|
164 |
-
$stream->expect(Twig_Token::OPERATOR_TYPE, '+');
|
165 |
-
$stream->expect(Twig_Token::NUMBER_TYPE, '1');
|
166 |
-
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
167 |
-
$stream->expect(Twig_Token::VAR_END_TYPE);
|
168 |
-
}
|
169 |
-
|
170 |
-
public function testStringWithEscapedInterpolation()
|
171 |
-
{
|
172 |
-
$template = '{{ "bar \#{baz+1}" }}';
|
173 |
-
|
174 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
175 |
-
$stream = $lexer->tokenize($template);
|
176 |
-
$stream->expect(Twig_Token::VAR_START_TYPE);
|
177 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'bar #{baz+1}');
|
178 |
-
$stream->expect(Twig_Token::VAR_END_TYPE);
|
179 |
-
}
|
180 |
-
|
181 |
-
public function testStringWithHash()
|
182 |
-
{
|
183 |
-
$template = '{{ "bar # baz" }}';
|
184 |
-
|
185 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
186 |
-
$stream = $lexer->tokenize($template);
|
187 |
-
$stream->expect(Twig_Token::VAR_START_TYPE);
|
188 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'bar # baz');
|
189 |
-
$stream->expect(Twig_Token::VAR_END_TYPE);
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* @expectedException Twig_Error_Syntax
|
194 |
-
* @expectedExceptionMessage Unclosed """
|
195 |
-
*/
|
196 |
-
public function testStringWithUnterminatedInterpolation()
|
197 |
-
{
|
198 |
-
$template = '{{ "bar #{x" }}';
|
199 |
-
|
200 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
201 |
-
$stream = $lexer->tokenize($template);
|
202 |
-
}
|
203 |
-
|
204 |
-
public function testStringWithNestedInterpolations()
|
205 |
-
{
|
206 |
-
$template = '{{ "bar #{ "foo#{bar}" }" }}';
|
207 |
-
|
208 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
209 |
-
$stream = $lexer->tokenize($template);
|
210 |
-
$stream->expect(Twig_Token::VAR_START_TYPE);
|
211 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
212 |
-
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
213 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'foo');
|
214 |
-
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
215 |
-
$stream->expect(Twig_Token::NAME_TYPE, 'bar');
|
216 |
-
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
217 |
-
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
218 |
-
$stream->expect(Twig_Token::VAR_END_TYPE);
|
219 |
-
}
|
220 |
-
|
221 |
-
public function testStringWithNestedInterpolationsInBlock()
|
222 |
-
{
|
223 |
-
$template = '{% foo "bar #{ "foo#{bar}" }" %}';
|
224 |
-
|
225 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
226 |
-
$stream = $lexer->tokenize($template);
|
227 |
-
$stream->expect(Twig_Token::BLOCK_START_TYPE);
|
228 |
-
$stream->expect(Twig_Token::NAME_TYPE, 'foo');
|
229 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
230 |
-
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
231 |
-
$stream->expect(Twig_Token::STRING_TYPE, 'foo');
|
232 |
-
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
233 |
-
$stream->expect(Twig_Token::NAME_TYPE, 'bar');
|
234 |
-
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
235 |
-
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
236 |
-
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
237 |
-
}
|
238 |
-
|
239 |
-
public function testOperatorEndingWithALetterAtTheEndOfALine()
|
240 |
-
{
|
241 |
-
$template = "{{ 1 and\n0}}";
|
242 |
-
|
243 |
-
$lexer = new Twig_Lexer(new Twig_Environment());
|
244 |
-
$stream = $lexer->tokenize($template);
|
245 |
-
$stream->expect(Twig_Token::VAR_START_TYPE);
|
246 |
-
$stream->expect(Twig_Token::NUMBER_TYPE, 1);
|
247 |
-
$stream->expect(Twig_Token::OPERATOR_TYPE, 'and');
|
248 |
-
}
|
249 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Loader/ArrayTest.php
DELETED
@@ -1,97 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testGetSource()
|
15 |
-
{
|
16 |
-
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
17 |
-
|
18 |
-
$this->assertEquals('bar', $loader->getSource('foo'));
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @expectedException Twig_Error_Loader
|
23 |
-
*/
|
24 |
-
public function testGetSourceWhenTemplateDoesNotExist()
|
25 |
-
{
|
26 |
-
$loader = new Twig_Loader_Array(array());
|
27 |
-
|
28 |
-
$loader->getSource('foo');
|
29 |
-
}
|
30 |
-
|
31 |
-
public function testGetCacheKey()
|
32 |
-
{
|
33 |
-
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
34 |
-
|
35 |
-
$this->assertEquals('bar', $loader->getCacheKey('foo'));
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @expectedException Twig_Error_Loader
|
40 |
-
*/
|
41 |
-
public function testGetCacheKeyWhenTemplateDoesNotExist()
|
42 |
-
{
|
43 |
-
$loader = new Twig_Loader_Array(array());
|
44 |
-
|
45 |
-
$loader->getCacheKey('foo');
|
46 |
-
}
|
47 |
-
|
48 |
-
public function testSetTemplate()
|
49 |
-
{
|
50 |
-
$loader = new Twig_Loader_Array(array());
|
51 |
-
$loader->setTemplate('foo', 'bar');
|
52 |
-
|
53 |
-
$this->assertEquals('bar', $loader->getSource('foo'));
|
54 |
-
}
|
55 |
-
|
56 |
-
public function testIsFresh()
|
57 |
-
{
|
58 |
-
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
59 |
-
$this->assertTrue($loader->isFresh('foo', time()));
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* @expectedException Twig_Error_Loader
|
64 |
-
*/
|
65 |
-
public function testIsFreshWhenTemplateDoesNotExist()
|
66 |
-
{
|
67 |
-
$loader = new Twig_Loader_Array(array());
|
68 |
-
|
69 |
-
$loader->isFresh('foo', time());
|
70 |
-
}
|
71 |
-
|
72 |
-
public function testTemplateReference()
|
73 |
-
{
|
74 |
-
$name = new Twig_Test_Loader_TemplateReference('foo');
|
75 |
-
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
76 |
-
|
77 |
-
$loader->getCacheKey($name);
|
78 |
-
$loader->getSource($name);
|
79 |
-
$loader->isFresh($name, time());
|
80 |
-
$loader->setTemplate($name, 'foobar');
|
81 |
-
}
|
82 |
-
}
|
83 |
-
|
84 |
-
class Twig_Test_Loader_TemplateReference
|
85 |
-
{
|
86 |
-
private $name;
|
87 |
-
|
88 |
-
public function __construct($name)
|
89 |
-
{
|
90 |
-
$this->name = $name;
|
91 |
-
}
|
92 |
-
|
93 |
-
public function __toString()
|
94 |
-
{
|
95 |
-
return $this->name;
|
96 |
-
}
|
97 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Loader/ChainTest.php
DELETED
@@ -1,63 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testGetSource()
|
15 |
-
{
|
16 |
-
$loader = new Twig_Loader_Chain(array(
|
17 |
-
new Twig_Loader_Array(array('foo' => 'bar')),
|
18 |
-
new Twig_Loader_Array(array('foo' => 'foobar', 'bar' => 'foo')),
|
19 |
-
));
|
20 |
-
|
21 |
-
$this->assertEquals('bar', $loader->getSource('foo'));
|
22 |
-
$this->assertEquals('foo', $loader->getSource('bar'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @expectedException Twig_Error_Loader
|
27 |
-
*/
|
28 |
-
public function testGetSourceWhenTemplateDoesNotExist()
|
29 |
-
{
|
30 |
-
$loader = new Twig_Loader_Chain(array());
|
31 |
-
|
32 |
-
$loader->getSource('foo');
|
33 |
-
}
|
34 |
-
|
35 |
-
public function testGetCacheKey()
|
36 |
-
{
|
37 |
-
$loader = new Twig_Loader_Chain(array(
|
38 |
-
new Twig_Loader_Array(array('foo' => 'bar')),
|
39 |
-
new Twig_Loader_Array(array('foo' => 'foobar', 'bar' => 'foo')),
|
40 |
-
));
|
41 |
-
|
42 |
-
$this->assertEquals('bar', $loader->getCacheKey('foo'));
|
43 |
-
$this->assertEquals('foo', $loader->getCacheKey('bar'));
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* @expectedException Twig_Error_Loader
|
48 |
-
*/
|
49 |
-
public function testGetCacheKeyWhenTemplateDoesNotExist()
|
50 |
-
{
|
51 |
-
$loader = new Twig_Loader_Chain(array());
|
52 |
-
|
53 |
-
$loader->getCacheKey('foo');
|
54 |
-
}
|
55 |
-
|
56 |
-
public function testAddLoader()
|
57 |
-
{
|
58 |
-
$loader = new Twig_Loader_Chain();
|
59 |
-
$loader->addLoader(new Twig_Loader_Array(array('foo' => 'bar')));
|
60 |
-
|
61 |
-
$this->assertEquals('bar', $loader->getSource('foo'));
|
62 |
-
}
|
63 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Loader/FilesystemTest.php
DELETED
@@ -1,90 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @dataProvider getSecurityTests
|
16 |
-
*/
|
17 |
-
public function testSecurity($template)
|
18 |
-
{
|
19 |
-
$loader = new Twig_Loader_Filesystem(array(dirname(__FILE__).'/../Fixtures'));
|
20 |
-
|
21 |
-
try {
|
22 |
-
$loader->getCacheKey($template);
|
23 |
-
$this->fail();
|
24 |
-
} catch (Twig_Error_Loader $e) {
|
25 |
-
$this->assertNotContains('Unable to find template', $e->getMessage());
|
26 |
-
}
|
27 |
-
}
|
28 |
-
|
29 |
-
public function getSecurityTests()
|
30 |
-
{
|
31 |
-
return array(
|
32 |
-
array("AutoloaderTest\0.php"),
|
33 |
-
array('..\\AutoloaderTest.php'),
|
34 |
-
array('..\\\\\\AutoloaderTest.php'),
|
35 |
-
array('../AutoloaderTest.php'),
|
36 |
-
array('..////AutoloaderTest.php'),
|
37 |
-
array('./../AutoloaderTest.php'),
|
38 |
-
array('.\\..\\AutoloaderTest.php'),
|
39 |
-
array('././././././../AutoloaderTest.php'),
|
40 |
-
array('.\\./.\\./.\\./../AutoloaderTest.php'),
|
41 |
-
array('foo/../../AutoloaderTest.php'),
|
42 |
-
array('foo\\..\\..\\AutoloaderTest.php'),
|
43 |
-
array('foo/../bar/../../AutoloaderTest.php'),
|
44 |
-
array('foo/bar/../../../AutoloaderTest.php'),
|
45 |
-
array('filters/../../AutoloaderTest.php'),
|
46 |
-
array('filters//..//..//AutoloaderTest.php'),
|
47 |
-
array('filters\\..\\..\\AutoloaderTest.php'),
|
48 |
-
array('filters\\\\..\\\\..\\\\AutoloaderTest.php'),
|
49 |
-
array('filters\\//../\\/\\..\\AutoloaderTest.php'),
|
50 |
-
);
|
51 |
-
}
|
52 |
-
|
53 |
-
public function testPaths()
|
54 |
-
{
|
55 |
-
$basePath = dirname(__FILE__).'/Fixtures';
|
56 |
-
|
57 |
-
$loader = new Twig_Loader_Filesystem(array($basePath.'/normal', $basePath.'/normal_bis'));
|
58 |
-
$loader->setPaths(array($basePath.'/named', $basePath.'/named_bis'), 'named');
|
59 |
-
$loader->addPath($basePath.'/named_ter', 'named');
|
60 |
-
$loader->addPath($basePath.'/normal_ter');
|
61 |
-
$loader->prependPath($basePath.'/normal_final');
|
62 |
-
$loader->prependPath($basePath.'/named_final', 'named');
|
63 |
-
|
64 |
-
$this->assertEquals(array(
|
65 |
-
$basePath.'/normal_final',
|
66 |
-
$basePath.'/normal',
|
67 |
-
$basePath.'/normal_bis',
|
68 |
-
$basePath.'/normal_ter',
|
69 |
-
), $loader->getPaths());
|
70 |
-
$this->assertEquals(array(
|
71 |
-
$basePath.'/named_final',
|
72 |
-
$basePath.'/named',
|
73 |
-
$basePath.'/named_bis',
|
74 |
-
$basePath.'/named_ter',
|
75 |
-
), $loader->getPaths('named'));
|
76 |
-
|
77 |
-
$this->assertEquals("path (final)\n", $loader->getSource('index.html'));
|
78 |
-
$this->assertEquals("path (final)\n", $loader->getSource('@__main__/index.html'));
|
79 |
-
$this->assertEquals("named path (final)\n", $loader->getSource('@named/index.html'));
|
80 |
-
}
|
81 |
-
|
82 |
-
public function testGetNamespaces()
|
83 |
-
{
|
84 |
-
$loader = new Twig_Loader_Filesystem(sys_get_temp_dir());
|
85 |
-
$this->assertEquals(array('__main__'), $loader->getNamespaces());
|
86 |
-
|
87 |
-
$loader->addPath(sys_get_temp_dir(), 'named');
|
88 |
-
$this->assertEquals(array('__main__', 'named'), $loader->getNamespaces());
|
89 |
-
}
|
90 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Loader/Fixtures/named/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
named path
|
|
Twig/test/Twig/Tests/Loader/Fixtures/named_bis/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
named path (bis)
|
|
Twig/test/Twig/Tests/Loader/Fixtures/named_final/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
named path (final)
|
|
Twig/test/Twig/Tests/Loader/Fixtures/named_ter/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
named path (ter)
|
|
Twig/test/Twig/Tests/Loader/Fixtures/normal/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
path
|
|
Twig/test/Twig/Tests/Loader/Fixtures/normal_bis/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
path (bis)
|
|
Twig/test/Twig/Tests/Loader/Fixtures/normal_final/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
path (final)
|
|
Twig/test/Twig/Tests/Loader/Fixtures/normal_ter/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
path (ter)
|
|
Twig/test/Twig/Tests/NativeExtensionTest.php
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_NativeExtensionTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
public function testGetProperties()
|
15 |
-
{
|
16 |
-
$twig = new Twig_Environment(new Twig_Loader_String(), array(
|
17 |
-
'debug' => true,
|
18 |
-
'cache' => false,
|
19 |
-
'autoescape' => false
|
20 |
-
));
|
21 |
-
|
22 |
-
$d1 = new DateTime();
|
23 |
-
$d2 = new DateTime();
|
24 |
-
$output = $twig->render('{{ d1.date }}{{ d2.date }}', compact('d1', 'd2'));
|
25 |
-
|
26 |
-
// If it fails, PHP will crash.
|
27 |
-
$this->assertEquals($output, $d1->date . $d2->date);
|
28 |
-
}
|
29 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/AutoEscapeTest.php
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_AutoEscapeTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_AutoEscape::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node(array(new Twig_Node_Text('foo', 1)));
|
20 |
-
$node = new Twig_Node_AutoEscape(true, $body, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($body, $node->getNode('body'));
|
23 |
-
$this->assertEquals(true, $node->getAttribute('value'));
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @covers Twig_Node_AutoEscape::compile
|
28 |
-
* @dataProvider getTests
|
29 |
-
*/
|
30 |
-
public function testCompile($node, $source, $environment = null)
|
31 |
-
{
|
32 |
-
parent::testCompile($node, $source, $environment);
|
33 |
-
}
|
34 |
-
|
35 |
-
public function getTests()
|
36 |
-
{
|
37 |
-
$body = new Twig_Node(array(new Twig_Node_Text('foo', 1)));
|
38 |
-
$node = new Twig_Node_AutoEscape(true, $body, 1);
|
39 |
-
|
40 |
-
return array(
|
41 |
-
array($node, "// line 1\necho \"foo\";"),
|
42 |
-
);
|
43 |
-
}
|
44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/BlockReferenceTest.php
DELETED
@@ -1,43 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_BlockReferenceTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_BlockReference::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_BlockReference('foo', 1);
|
20 |
-
|
21 |
-
$this->assertEquals('foo', $node->getAttribute('name'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_BlockReference::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
return array(
|
36 |
-
array(new Twig_Node_BlockReference('foo', 1), <<<EOF
|
37 |
-
// line 1
|
38 |
-
\$this->displayBlock('foo', \$context, \$blocks);
|
39 |
-
EOF
|
40 |
-
),
|
41 |
-
);
|
42 |
-
}
|
43 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/BlockTest.php
DELETED
@@ -1,51 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_BlockTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Block::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node_Text('foo', 1);
|
20 |
-
$node = new Twig_Node_Block('foo', $body, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($body, $node->getNode('body'));
|
23 |
-
$this->assertEquals('foo', $node->getAttribute('name'));
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @covers Twig_Node_Block::compile
|
28 |
-
* @dataProvider getTests
|
29 |
-
*/
|
30 |
-
public function testCompile($node, $source, $environment = null)
|
31 |
-
{
|
32 |
-
parent::testCompile($node, $source, $environment);
|
33 |
-
}
|
34 |
-
|
35 |
-
public function getTests()
|
36 |
-
{
|
37 |
-
$body = new Twig_Node_Text('foo', 1);
|
38 |
-
$node = new Twig_Node_Block('foo', $body, 1);
|
39 |
-
|
40 |
-
return array(
|
41 |
-
array($node, <<<EOF
|
42 |
-
// line 1
|
43 |
-
public function block_foo(\$context, array \$blocks = array())
|
44 |
-
{
|
45 |
-
echo "foo";
|
46 |
-
}
|
47 |
-
EOF
|
48 |
-
),
|
49 |
-
);
|
50 |
-
}
|
51 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/DoTest.php
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_DoTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Do::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
20 |
-
$node = new Twig_Node_Do($expr, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($expr, $node->getNode('expr'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Do::compile
|
27 |
-
* @dataProvider getTests
|
28 |
-
*/
|
29 |
-
public function testCompile($node, $source, $environment = null)
|
30 |
-
{
|
31 |
-
parent::testCompile($node, $source, $environment);
|
32 |
-
}
|
33 |
-
|
34 |
-
public function getTests()
|
35 |
-
{
|
36 |
-
$tests = array();
|
37 |
-
|
38 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
39 |
-
$node = new Twig_Node_Do($expr, 1);
|
40 |
-
$tests[] = array($node, "// line 1\n\"foo\";");
|
41 |
-
|
42 |
-
return $tests;
|
43 |
-
}
|
44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/ArrayTest.php
DELETED
@@ -1,49 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_ArrayTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Array::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$elements = array(new Twig_Node_Expression_Constant('foo', 1), $foo = new Twig_Node_Expression_Constant('bar', 1));
|
20 |
-
$node = new Twig_Node_Expression_Array($elements, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($foo, $node->getNode(1));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Expression_Array::compile
|
27 |
-
* @dataProvider getTests
|
28 |
-
*/
|
29 |
-
public function testCompile($node, $source, $environment = null)
|
30 |
-
{
|
31 |
-
parent::testCompile($node, $source, $environment);
|
32 |
-
}
|
33 |
-
|
34 |
-
public function getTests()
|
35 |
-
{
|
36 |
-
$elements = array(
|
37 |
-
new Twig_Node_Expression_Constant('foo', 1),
|
38 |
-
new Twig_Node_Expression_Constant('bar', 1),
|
39 |
-
|
40 |
-
new Twig_Node_Expression_Constant('bar', 1),
|
41 |
-
new Twig_Node_Expression_Constant('foo', 1),
|
42 |
-
);
|
43 |
-
$node = new Twig_Node_Expression_Array($elements, 1);
|
44 |
-
|
45 |
-
return array(
|
46 |
-
array($node, 'array("foo" => "bar", "bar" => "foo")'),
|
47 |
-
);
|
48 |
-
}
|
49 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/AssignNameTest.php
DELETED
@@ -1,41 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_AssignNameTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_AssignName::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_Expression_AssignName('foo', 1);
|
20 |
-
|
21 |
-
$this->assertEquals('foo', $node->getAttribute('name'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_Expression_AssignName::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
$node = new Twig_Node_Expression_AssignName('foo', 1);
|
36 |
-
|
37 |
-
return array(
|
38 |
-
array($node, '$context["foo"]'),
|
39 |
-
);
|
40 |
-
}
|
41 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/AddTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_AddTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Add::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Add($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Add::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Add::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Add($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 + 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/AndTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_AndTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_And::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_And($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_And::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_And::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_And($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 && 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/ConcatTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_ConcatTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Concat::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Concat($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Concat::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Concat::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Concat($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 . 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/DivTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_DivTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Div::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Div($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Div::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Div::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Div($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 / 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/FloorDivTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_FloorDivTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_FloorDiv::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_FloorDiv($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_FloorDiv::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_FloorDiv::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_FloorDiv($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, 'intval(floor((1 / 2)))'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/ModTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_ModTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Mod::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Mod($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Mod::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Mod::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Mod($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 % 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/MulTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_MulTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Mul::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Mul($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Mul::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Mul::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Mul($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 * 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/OrTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_OrTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Or::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Or($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Or::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Or::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Or($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 || 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Binary/SubTest.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Binary_SubTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Binary_Sub::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$node = new Twig_Node_Expression_Binary_Sub($left, $right, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($left, $node->getNode('left'));
|
24 |
-
$this->assertEquals($right, $node->getNode('right'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Binary_Sub::compile
|
29 |
-
* @covers Twig_Node_Expression_Binary_Sub::operator
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$left = new Twig_Node_Expression_Constant(1, 1);
|
40 |
-
$right = new Twig_Node_Expression_Constant(2, 1);
|
41 |
-
$node = new Twig_Node_Expression_Binary_Sub($left, $right, 1);
|
42 |
-
|
43 |
-
return array(
|
44 |
-
array($node, '(1 - 2)'),
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/ConditionalTest.php
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_ConditionalTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Conditional::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr1 = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$expr2 = new Twig_Node_Expression_Constant(2, 1);
|
21 |
-
$expr3 = new Twig_Node_Expression_Constant(3, 1);
|
22 |
-
$node = new Twig_Node_Expression_Conditional($expr1, $expr2, $expr3, 1);
|
23 |
-
|
24 |
-
$this->assertEquals($expr1, $node->getNode('expr1'));
|
25 |
-
$this->assertEquals($expr2, $node->getNode('expr2'));
|
26 |
-
$this->assertEquals($expr3, $node->getNode('expr3'));
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @covers Twig_Node_Expression_Conditional::compile
|
31 |
-
* @dataProvider getTests
|
32 |
-
*/
|
33 |
-
public function testCompile($node, $source, $environment = null)
|
34 |
-
{
|
35 |
-
parent::testCompile($node, $source, $environment);
|
36 |
-
}
|
37 |
-
|
38 |
-
public function getTests()
|
39 |
-
{
|
40 |
-
$tests = array();
|
41 |
-
|
42 |
-
$expr1 = new Twig_Node_Expression_Constant(1, 1);
|
43 |
-
$expr2 = new Twig_Node_Expression_Constant(2, 1);
|
44 |
-
$expr3 = new Twig_Node_Expression_Constant(3, 1);
|
45 |
-
$node = new Twig_Node_Expression_Conditional($expr1, $expr2, $expr3, 1);
|
46 |
-
$tests[] = array($node, '((1) ? (2) : (3))');
|
47 |
-
|
48 |
-
return $tests;
|
49 |
-
}
|
50 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/ConstantTest.php
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_ConstantTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Constant::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_Expression_Constant('foo', 1);
|
20 |
-
|
21 |
-
$this->assertEquals('foo', $node->getAttribute('value'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_Expression_Constant::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
$tests = array();
|
36 |
-
|
37 |
-
$node = new Twig_Node_Expression_Constant('foo', 1);
|
38 |
-
$tests[] = array($node, '"foo"');
|
39 |
-
|
40 |
-
return $tests;
|
41 |
-
}
|
42 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/FilterTest.php
DELETED
@@ -1,133 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_FilterTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Filter::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
20 |
-
$name = new Twig_Node_Expression_Constant('upper', 1);
|
21 |
-
$args = new Twig_Node();
|
22 |
-
$node = new Twig_Node_Expression_Filter($expr, $name, $args, 1);
|
23 |
-
|
24 |
-
$this->assertEquals($expr, $node->getNode('node'));
|
25 |
-
$this->assertEquals($name, $node->getNode('filter'));
|
26 |
-
$this->assertEquals($args, $node->getNode('arguments'));
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @covers Twig_Node_Expression_Filter::compile
|
31 |
-
* @dataProvider getTests
|
32 |
-
*/
|
33 |
-
public function testCompile($node, $source, $environment = null)
|
34 |
-
{
|
35 |
-
parent::testCompile($node, $source, $environment);
|
36 |
-
}
|
37 |
-
|
38 |
-
public function getTests()
|
39 |
-
{
|
40 |
-
$tests = array();
|
41 |
-
|
42 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
43 |
-
$node = $this->createFilter($expr, 'upper');
|
44 |
-
$node = $this->createFilter($node, 'number_format', array(new Twig_Node_Expression_Constant(2, 1), new Twig_Node_Expression_Constant('.', 1), new Twig_Node_Expression_Constant(',', 1)));
|
45 |
-
|
46 |
-
if (function_exists('mb_get_info')) {
|
47 |
-
$tests[] = array($node, 'twig_number_format_filter($this->env, twig_upper_filter($this->env, "foo"), 2, ".", ",")');
|
48 |
-
} else {
|
49 |
-
$tests[] = array($node, 'twig_number_format_filter($this->env, strtoupper("foo"), 2, ".", ",")');
|
50 |
-
}
|
51 |
-
|
52 |
-
// named arguments
|
53 |
-
$date = new Twig_Node_Expression_Constant(0, 1);
|
54 |
-
$node = $this->createFilter($date, 'date', array(
|
55 |
-
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
56 |
-
'format' => new Twig_Node_Expression_Constant('d/m/Y H:i:s P', 1),
|
57 |
-
));
|
58 |
-
$tests[] = array($node, 'twig_date_format_filter($this->env, 0, "d/m/Y H:i:s P", "America/Chicago")');
|
59 |
-
|
60 |
-
// skip an optional argument
|
61 |
-
$date = new Twig_Node_Expression_Constant(0, 1);
|
62 |
-
$node = $this->createFilter($date, 'date', array(
|
63 |
-
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
64 |
-
));
|
65 |
-
$tests[] = array($node, 'twig_date_format_filter($this->env, 0, null, "America/Chicago")');
|
66 |
-
|
67 |
-
// underscores vs camelCase for named arguments
|
68 |
-
$string = new Twig_Node_Expression_Constant('abc', 1);
|
69 |
-
$node = $this->createFilter($string, 'reverse', array(
|
70 |
-
'preserve_keys' => new Twig_Node_Expression_Constant(true, 1),
|
71 |
-
));
|
72 |
-
$tests[] = array($node, 'twig_reverse_filter($this->env, "abc", true)');
|
73 |
-
$node = $this->createFilter($string, 'reverse', array(
|
74 |
-
'preserveKeys' => new Twig_Node_Expression_Constant(true, 1),
|
75 |
-
));
|
76 |
-
$tests[] = array($node, 'twig_reverse_filter($this->env, "abc", true)');
|
77 |
-
|
78 |
-
// filter as an anonymous function
|
79 |
-
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
80 |
-
$node = $this->createFilter(new Twig_Node_Expression_Constant('foo', 1), 'anonymous');
|
81 |
-
$tests[] = array($node, 'call_user_func_array($this->env->getFilter(\'anonymous\')->getCallable(), array("foo"))');
|
82 |
-
}
|
83 |
-
|
84 |
-
return $tests;
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* @expectedException Twig_Error_Syntax
|
89 |
-
* @expectedExceptionMessage Unknown argument "foobar" for filter "date".
|
90 |
-
*/
|
91 |
-
public function testCompileWithWrongNamedArgumentName()
|
92 |
-
{
|
93 |
-
$date = new Twig_Node_Expression_Constant(0, 1);
|
94 |
-
$node = $this->createFilter($date, 'date', array(
|
95 |
-
'foobar' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
96 |
-
));
|
97 |
-
|
98 |
-
$compiler = $this->getCompiler();
|
99 |
-
$compiler->compile($node);
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* @expectedException Twig_Error_Syntax
|
104 |
-
* @expectedExceptionMessage Value for argument "from" is required for filter "replace".
|
105 |
-
*/
|
106 |
-
public function testCompileWithMissingNamedArgument()
|
107 |
-
{
|
108 |
-
$value = new Twig_Node_Expression_Constant(0, 1);
|
109 |
-
$node = $this->createFilter($value, 'replace', array(
|
110 |
-
'to' => new Twig_Node_Expression_Constant('foo', 1),
|
111 |
-
));
|
112 |
-
|
113 |
-
$compiler = $this->getCompiler();
|
114 |
-
$compiler->compile($node);
|
115 |
-
}
|
116 |
-
|
117 |
-
protected function createFilter($node, $name, array $arguments = array())
|
118 |
-
{
|
119 |
-
$name = new Twig_Node_Expression_Constant($name, 1);
|
120 |
-
$arguments = new Twig_Node($arguments);
|
121 |
-
|
122 |
-
return new Twig_Node_Expression_Filter($node, $name, $arguments, 1);
|
123 |
-
}
|
124 |
-
|
125 |
-
protected function getEnvironment()
|
126 |
-
{
|
127 |
-
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
128 |
-
return include 'PHP53/FilterInclude.php';
|
129 |
-
}
|
130 |
-
|
131 |
-
return parent::getEnvironment();
|
132 |
-
}
|
133 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/FunctionTest.php
DELETED
@@ -1,99 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_FunctionTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Function::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$name = 'function';
|
20 |
-
$args = new Twig_Node();
|
21 |
-
$node = new Twig_Node_Expression_Function($name, $args, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($name, $node->getAttribute('name'));
|
24 |
-
$this->assertEquals($args, $node->getNode('arguments'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Expression_Function::compile
|
29 |
-
* @dataProvider getTests
|
30 |
-
*/
|
31 |
-
public function testCompile($node, $source, $environment = null)
|
32 |
-
{
|
33 |
-
parent::testCompile($node, $source, $environment);
|
34 |
-
}
|
35 |
-
|
36 |
-
public function getTests()
|
37 |
-
{
|
38 |
-
$environment = new Twig_Environment();
|
39 |
-
$environment->addFunction('foo', new Twig_Function_Function('foo', array()));
|
40 |
-
$environment->addFunction('bar', new Twig_Function_Function('bar', array('needs_environment' => true)));
|
41 |
-
$environment->addFunction('foofoo', new Twig_Function_Function('foofoo', array('needs_context' => true)));
|
42 |
-
$environment->addFunction('foobar', new Twig_Function_Function('foobar', array('needs_environment' => true, 'needs_context' => true)));
|
43 |
-
|
44 |
-
$tests = array();
|
45 |
-
|
46 |
-
$node = $this->createFunction('foo');
|
47 |
-
$tests[] = array($node, 'foo()', $environment);
|
48 |
-
|
49 |
-
$node = $this->createFunction('foo', array(new Twig_Node_Expression_Constant('bar', 1), new Twig_Node_Expression_Constant('foobar', 1)));
|
50 |
-
$tests[] = array($node, 'foo("bar", "foobar")', $environment);
|
51 |
-
|
52 |
-
$node = $this->createFunction('bar');
|
53 |
-
$tests[] = array($node, 'bar($this->env)', $environment);
|
54 |
-
|
55 |
-
$node = $this->createFunction('bar', array(new Twig_Node_Expression_Constant('bar', 1)));
|
56 |
-
$tests[] = array($node, 'bar($this->env, "bar")', $environment);
|
57 |
-
|
58 |
-
$node = $this->createFunction('foofoo');
|
59 |
-
$tests[] = array($node, 'foofoo($context)', $environment);
|
60 |
-
|
61 |
-
$node = $this->createFunction('foofoo', array(new Twig_Node_Expression_Constant('bar', 1)));
|
62 |
-
$tests[] = array($node, 'foofoo($context, "bar")', $environment);
|
63 |
-
|
64 |
-
$node = $this->createFunction('foobar');
|
65 |
-
$tests[] = array($node, 'foobar($this->env, $context)', $environment);
|
66 |
-
|
67 |
-
$node = $this->createFunction('foobar', array(new Twig_Node_Expression_Constant('bar', 1)));
|
68 |
-
$tests[] = array($node, 'foobar($this->env, $context, "bar")', $environment);
|
69 |
-
|
70 |
-
// named arguments
|
71 |
-
$node = $this->createFunction('date', array(
|
72 |
-
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
73 |
-
'date' => new Twig_Node_Expression_Constant(0, 1),
|
74 |
-
));
|
75 |
-
$tests[] = array($node, 'twig_date_converter($this->env, 0, "America/Chicago")');
|
76 |
-
|
77 |
-
// function as an anonymous function
|
78 |
-
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
79 |
-
$node = $this->createFunction('anonymous', array(new Twig_Node_Expression_Constant('foo', 1)));
|
80 |
-
$tests[] = array($node, 'call_user_func_array($this->env->getFunction(\'anonymous\')->getCallable(), array("foo"))');
|
81 |
-
}
|
82 |
-
|
83 |
-
return $tests;
|
84 |
-
}
|
85 |
-
|
86 |
-
protected function createFunction($name, array $arguments = array())
|
87 |
-
{
|
88 |
-
return new Twig_Node_Expression_Function($name, new Twig_Node($arguments), 1);
|
89 |
-
}
|
90 |
-
|
91 |
-
protected function getEnvironment()
|
92 |
-
{
|
93 |
-
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
94 |
-
return include 'PHP53/FunctionInclude.php';
|
95 |
-
}
|
96 |
-
|
97 |
-
return parent::getEnvironment();
|
98 |
-
}
|
99 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
DELETED
@@ -1,62 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_GetAttr::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Name('foo', 1);
|
20 |
-
$attr = new Twig_Node_Expression_Constant('bar', 1);
|
21 |
-
$args = new Twig_Node_Expression_Array(array(), 1);
|
22 |
-
$args->addElement(new Twig_Node_Expression_Name('foo', 1));
|
23 |
-
$args->addElement(new Twig_Node_Expression_Constant('bar', 1));
|
24 |
-
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 1);
|
25 |
-
|
26 |
-
$this->assertEquals($expr, $node->getNode('node'));
|
27 |
-
$this->assertEquals($attr, $node->getNode('attribute'));
|
28 |
-
$this->assertEquals($args, $node->getNode('arguments'));
|
29 |
-
$this->assertEquals(Twig_TemplateInterface::ARRAY_CALL, $node->getAttribute('type'));
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* @covers Twig_Node_Expression_GetAttr::compile
|
34 |
-
* @dataProvider getTests
|
35 |
-
*/
|
36 |
-
public function testCompile($node, $source, $environment = null)
|
37 |
-
{
|
38 |
-
parent::testCompile($node, $source, $environment);
|
39 |
-
}
|
40 |
-
|
41 |
-
public function getTests()
|
42 |
-
{
|
43 |
-
$tests = array();
|
44 |
-
|
45 |
-
$expr = new Twig_Node_Expression_Name('foo', 1);
|
46 |
-
$attr = new Twig_Node_Expression_Constant('bar', 1);
|
47 |
-
$args = new Twig_Node_Expression_Array(array(), 1);
|
48 |
-
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ANY_CALL, 1);
|
49 |
-
$tests[] = array($node, sprintf('%s%s, "bar")', $this->getAttributeGetter(), $this->getVariableGetter('foo')));
|
50 |
-
|
51 |
-
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 1);
|
52 |
-
$tests[] = array($node, sprintf('%s%s, "bar", array(), "array")', $this->getAttributeGetter(), $this->getVariableGetter('foo')));
|
53 |
-
|
54 |
-
$args = new Twig_Node_Expression_Array(array(), 1);
|
55 |
-
$args->addElement(new Twig_Node_Expression_Name('foo', 1));
|
56 |
-
$args->addElement(new Twig_Node_Expression_Constant('bar', 1));
|
57 |
-
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::METHOD_CALL, 1);
|
58 |
-
$tests[] = array($node, sprintf('%s%s, "bar", array(0 => %s, 1 => "bar"), "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo'), $this->getVariableGetter('foo')));
|
59 |
-
|
60 |
-
return $tests;
|
61 |
-
}
|
62 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/NameTest.php
DELETED
@@ -1,49 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_NameTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Name::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_Expression_Name('foo', 1);
|
20 |
-
|
21 |
-
$this->assertEquals('foo', $node->getAttribute('name'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_Expression_Name::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
$node = new Twig_Node_Expression_Name('foo', 1);
|
36 |
-
$self = new Twig_Node_Expression_Name('_self', 1);
|
37 |
-
$context = new Twig_Node_Expression_Name('_context', 1);
|
38 |
-
|
39 |
-
$env = new Twig_Environment(null, array('strict_variables' => true));
|
40 |
-
$env1 = new Twig_Environment(null, array('strict_variables' => false));
|
41 |
-
|
42 |
-
return array(
|
43 |
-
version_compare(PHP_VERSION, '5.4.0') >= 0 ? array($node, '(isset($context["foo"]) ? $context["foo"] : $this->getContext($context, "foo"))', $env) : array($node, '$this->getContext($context, "foo")', $env),
|
44 |
-
array($node, $this->getVariableGetter('foo'), $env1),
|
45 |
-
array($self, '$this'),
|
46 |
-
array($context, '$context'),
|
47 |
-
);
|
48 |
-
}
|
49 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/PHP53/FilterInclude.php
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
$env = new Twig_Environment();
|
4 |
-
$env->addFilter(new Twig_SimpleFilter('anonymous', function () {}));
|
5 |
-
|
6 |
-
return $env;
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/PHP53/FunctionInclude.php
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
$env = new Twig_Environment();
|
4 |
-
$env->addFunction(new Twig_SimpleFunction('anonymous', function () {}));
|
5 |
-
|
6 |
-
return $env;
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/PHP53/TestInclude.php
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
$env = new Twig_Environment();
|
4 |
-
$env->addTest(new Twig_SimpleTest('anonymous', function () {}));
|
5 |
-
|
6 |
-
return $env;
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/ParentTest.php
DELETED
@@ -1,40 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_ParentTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Parent::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_Expression_Parent('foo', 1);
|
20 |
-
|
21 |
-
$this->assertEquals('foo', $node->getAttribute('name'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_Expression_Parent::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
$tests = array();
|
36 |
-
$tests[] = array(new Twig_Node_Expression_Parent('foo', 1), '$this->renderParentBlock("foo", $context, $blocks)');
|
37 |
-
|
38 |
-
return $tests;
|
39 |
-
}
|
40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/TestTest.php
DELETED
@@ -1,68 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_TestTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Test::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
20 |
-
$name = new Twig_Node_Expression_Constant('null', 1);
|
21 |
-
$args = new Twig_Node();
|
22 |
-
$node = new Twig_Node_Expression_Test($expr, $name, $args, 1);
|
23 |
-
|
24 |
-
$this->assertEquals($expr, $node->getNode('node'));
|
25 |
-
$this->assertEquals($args, $node->getNode('arguments'));
|
26 |
-
$this->assertEquals($name, $node->getAttribute('name'));
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @covers Twig_Node_Expression_Test::compile
|
31 |
-
* @dataProvider getTests
|
32 |
-
*/
|
33 |
-
public function testCompile($node, $source, $environment = null)
|
34 |
-
{
|
35 |
-
parent::testCompile($node, $source, $environment);
|
36 |
-
}
|
37 |
-
|
38 |
-
public function getTests()
|
39 |
-
{
|
40 |
-
$tests = array();
|
41 |
-
|
42 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
43 |
-
$node = new Twig_Node_Expression_Test_Null($expr, 'null', new Twig_Node(array()), 1);
|
44 |
-
$tests[] = array($node, '(null === "foo")');
|
45 |
-
|
46 |
-
// test as an anonymous function
|
47 |
-
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
48 |
-
$node = $this->createTest(new Twig_Node_Expression_Constant('foo', 1), 'anonymous', array(new Twig_Node_Expression_Constant('foo', 1)));
|
49 |
-
$tests[] = array($node, 'call_user_func_array($this->env->getTest(\'anonymous\')->getCallable(), array("foo", "foo"))');
|
50 |
-
}
|
51 |
-
|
52 |
-
return $tests;
|
53 |
-
}
|
54 |
-
|
55 |
-
protected function createTest($node, $name, array $arguments = array())
|
56 |
-
{
|
57 |
-
return new Twig_Node_Expression_Test($node, $name, new Twig_Node($arguments), 1);
|
58 |
-
}
|
59 |
-
|
60 |
-
protected function getEnvironment()
|
61 |
-
{
|
62 |
-
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
63 |
-
return include 'PHP53/TestInclude.php';
|
64 |
-
}
|
65 |
-
|
66 |
-
return parent::getEnvironment();
|
67 |
-
}
|
68 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Unary/NegTest.php
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Unary_NegTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Unary_Neg::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$node = new Twig_Node_Expression_Unary_Neg($expr, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($expr, $node->getNode('node'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Expression_Unary_Neg::compile
|
27 |
-
* @covers Twig_Node_Expression_Unary_Neg::operator
|
28 |
-
* @dataProvider getTests
|
29 |
-
*/
|
30 |
-
public function testCompile($node, $source, $environment = null)
|
31 |
-
{
|
32 |
-
parent::testCompile($node, $source, $environment);
|
33 |
-
}
|
34 |
-
|
35 |
-
public function getTests()
|
36 |
-
{
|
37 |
-
$node = new Twig_Node_Expression_Constant(1, 1);
|
38 |
-
$node = new Twig_Node_Expression_Unary_Neg($node, 1);
|
39 |
-
|
40 |
-
return array(
|
41 |
-
array($node, '(-1)'),
|
42 |
-
);
|
43 |
-
}
|
44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Unary/NotTest.php
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Unary_NotTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Unary_Not::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$node = new Twig_Node_Expression_Unary_Not($expr, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($expr, $node->getNode('node'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Expression_Unary_Not::compile
|
27 |
-
* @covers Twig_Node_Expression_Unary_Not::operator
|
28 |
-
* @dataProvider getTests
|
29 |
-
*/
|
30 |
-
public function testCompile($node, $source, $environment = null)
|
31 |
-
{
|
32 |
-
parent::testCompile($node, $source, $environment);
|
33 |
-
}
|
34 |
-
|
35 |
-
public function getTests()
|
36 |
-
{
|
37 |
-
$node = new Twig_Node_Expression_Constant(1, 1);
|
38 |
-
$node = new Twig_Node_Expression_Unary_Not($node, 1);
|
39 |
-
|
40 |
-
return array(
|
41 |
-
array($node, '(!1)'),
|
42 |
-
);
|
43 |
-
}
|
44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/Expression/Unary/PosTest.php
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_Expression_Unary_PosTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Expression_Unary_Pos::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant(1, 1);
|
20 |
-
$node = new Twig_Node_Expression_Unary_Pos($expr, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($expr, $node->getNode('node'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Expression_Unary_Pos::compile
|
27 |
-
* @covers Twig_Node_Expression_Unary_Pos::operator
|
28 |
-
* @dataProvider getTests
|
29 |
-
*/
|
30 |
-
public function testCompile($node, $source, $environment = null)
|
31 |
-
{
|
32 |
-
parent::testCompile($node, $source, $environment);
|
33 |
-
}
|
34 |
-
|
35 |
-
public function getTests()
|
36 |
-
{
|
37 |
-
$node = new Twig_Node_Expression_Constant(1, 1);
|
38 |
-
$node = new Twig_Node_Expression_Unary_Pos($node, 1);
|
39 |
-
|
40 |
-
return array(
|
41 |
-
array($node, '(+1)'),
|
42 |
-
);
|
43 |
-
}
|
44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/ForTest.php
DELETED
@@ -1,203 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_ForTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_For::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$keyTarget = new Twig_Node_Expression_AssignName('key', 1);
|
20 |
-
$valueTarget = new Twig_Node_Expression_AssignName('item', 1);
|
21 |
-
$seq = new Twig_Node_Expression_Name('items', 1);
|
22 |
-
$ifexpr = new Twig_Node_Expression_Constant(true, 1);
|
23 |
-
$body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1);
|
24 |
-
$else = null;
|
25 |
-
$node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1);
|
26 |
-
$node->setAttribute('with_loop', false);
|
27 |
-
|
28 |
-
$this->assertEquals($keyTarget, $node->getNode('key_target'));
|
29 |
-
$this->assertEquals($valueTarget, $node->getNode('value_target'));
|
30 |
-
$this->assertEquals($seq, $node->getNode('seq'));
|
31 |
-
$this->assertTrue($node->getAttribute('ifexpr'));
|
32 |
-
$this->assertEquals('Twig_Node_If', get_class($node->getNode('body')));
|
33 |
-
$this->assertEquals($body, $node->getNode('body')->getNode('tests')->getNode(1)->getNode(0));
|
34 |
-
$this->assertEquals(null, $node->getNode('else'));
|
35 |
-
|
36 |
-
$else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1);
|
37 |
-
$node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1);
|
38 |
-
$node->setAttribute('with_loop', false);
|
39 |
-
$this->assertEquals($else, $node->getNode('else'));
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* @covers Twig_Node_For::compile
|
44 |
-
* @dataProvider getTests
|
45 |
-
*/
|
46 |
-
public function testCompile($node, $source, $environment = null)
|
47 |
-
{
|
48 |
-
parent::testCompile($node, $source, $environment);
|
49 |
-
}
|
50 |
-
|
51 |
-
public function getTests()
|
52 |
-
{
|
53 |
-
$tests = array();
|
54 |
-
|
55 |
-
$keyTarget = new Twig_Node_Expression_AssignName('key', 1);
|
56 |
-
$valueTarget = new Twig_Node_Expression_AssignName('item', 1);
|
57 |
-
$seq = new Twig_Node_Expression_Name('items', 1);
|
58 |
-
$ifexpr = null;
|
59 |
-
$body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1);
|
60 |
-
$else = null;
|
61 |
-
$node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1);
|
62 |
-
$node->setAttribute('with_loop', false);
|
63 |
-
|
64 |
-
$tests[] = array($node, <<<EOF
|
65 |
-
// line 1
|
66 |
-
\$context['_parent'] = (array) \$context;
|
67 |
-
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('items')});
|
68 |
-
foreach (\$context['_seq'] as \$context["key"] => \$context["item"]) {
|
69 |
-
echo {$this->getVariableGetter('foo')};
|
70 |
-
}
|
71 |
-
\$_parent = \$context['_parent'];
|
72 |
-
unset(\$context['_seq'], \$context['_iterated'], \$context['key'], \$context['item'], \$context['_parent'], \$context['loop']);
|
73 |
-
\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
|
74 |
-
EOF
|
75 |
-
);
|
76 |
-
|
77 |
-
$keyTarget = new Twig_Node_Expression_AssignName('k', 1);
|
78 |
-
$valueTarget = new Twig_Node_Expression_AssignName('v', 1);
|
79 |
-
$seq = new Twig_Node_Expression_Name('values', 1);
|
80 |
-
$ifexpr = null;
|
81 |
-
$body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1);
|
82 |
-
$else = null;
|
83 |
-
$node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1);
|
84 |
-
$node->setAttribute('with_loop', true);
|
85 |
-
|
86 |
-
$tests[] = array($node, <<<EOF
|
87 |
-
// line 1
|
88 |
-
\$context['_parent'] = (array) \$context;
|
89 |
-
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')});
|
90 |
-
\$context['loop'] = array(
|
91 |
-
'parent' => \$context['_parent'],
|
92 |
-
'index0' => 0,
|
93 |
-
'index' => 1,
|
94 |
-
'first' => true,
|
95 |
-
);
|
96 |
-
if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {
|
97 |
-
\$length = count(\$context['_seq']);
|
98 |
-
\$context['loop']['revindex0'] = \$length - 1;
|
99 |
-
\$context['loop']['revindex'] = \$length;
|
100 |
-
\$context['loop']['length'] = \$length;
|
101 |
-
\$context['loop']['last'] = 1 === \$length;
|
102 |
-
}
|
103 |
-
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
104 |
-
echo {$this->getVariableGetter('foo')};
|
105 |
-
++\$context['loop']['index0'];
|
106 |
-
++\$context['loop']['index'];
|
107 |
-
\$context['loop']['first'] = false;
|
108 |
-
if (isset(\$context['loop']['length'])) {
|
109 |
-
--\$context['loop']['revindex0'];
|
110 |
-
--\$context['loop']['revindex'];
|
111 |
-
\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];
|
112 |
-
}
|
113 |
-
}
|
114 |
-
\$_parent = \$context['_parent'];
|
115 |
-
unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
|
116 |
-
\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
|
117 |
-
EOF
|
118 |
-
);
|
119 |
-
|
120 |
-
$keyTarget = new Twig_Node_Expression_AssignName('k', 1);
|
121 |
-
$valueTarget = new Twig_Node_Expression_AssignName('v', 1);
|
122 |
-
$seq = new Twig_Node_Expression_Name('values', 1);
|
123 |
-
$ifexpr = new Twig_Node_Expression_Constant(true, 1);
|
124 |
-
$body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1);
|
125 |
-
$else = null;
|
126 |
-
$node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1);
|
127 |
-
$node->setAttribute('with_loop', true);
|
128 |
-
|
129 |
-
$tests[] = array($node, <<<EOF
|
130 |
-
// line 1
|
131 |
-
\$context['_parent'] = (array) \$context;
|
132 |
-
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')});
|
133 |
-
\$context['loop'] = array(
|
134 |
-
'parent' => \$context['_parent'],
|
135 |
-
'index0' => 0,
|
136 |
-
'index' => 1,
|
137 |
-
'first' => true,
|
138 |
-
);
|
139 |
-
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
140 |
-
if (true) {
|
141 |
-
echo {$this->getVariableGetter('foo')};
|
142 |
-
++\$context['loop']['index0'];
|
143 |
-
++\$context['loop']['index'];
|
144 |
-
\$context['loop']['first'] = false;
|
145 |
-
}
|
146 |
-
}
|
147 |
-
\$_parent = \$context['_parent'];
|
148 |
-
unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
|
149 |
-
\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
|
150 |
-
EOF
|
151 |
-
);
|
152 |
-
|
153 |
-
$keyTarget = new Twig_Node_Expression_AssignName('k', 1);
|
154 |
-
$valueTarget = new Twig_Node_Expression_AssignName('v', 1);
|
155 |
-
$seq = new Twig_Node_Expression_Name('values', 1);
|
156 |
-
$ifexpr = null;
|
157 |
-
$body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1);
|
158 |
-
$else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1);
|
159 |
-
$node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1);
|
160 |
-
$node->setAttribute('with_loop', true);
|
161 |
-
|
162 |
-
$tests[] = array($node, <<<EOF
|
163 |
-
// line 1
|
164 |
-
\$context['_parent'] = (array) \$context;
|
165 |
-
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')});
|
166 |
-
\$context['_iterated'] = false;
|
167 |
-
\$context['loop'] = array(
|
168 |
-
'parent' => \$context['_parent'],
|
169 |
-
'index0' => 0,
|
170 |
-
'index' => 1,
|
171 |
-
'first' => true,
|
172 |
-
);
|
173 |
-
if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {
|
174 |
-
\$length = count(\$context['_seq']);
|
175 |
-
\$context['loop']['revindex0'] = \$length - 1;
|
176 |
-
\$context['loop']['revindex'] = \$length;
|
177 |
-
\$context['loop']['length'] = \$length;
|
178 |
-
\$context['loop']['last'] = 1 === \$length;
|
179 |
-
}
|
180 |
-
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
181 |
-
echo {$this->getVariableGetter('foo')};
|
182 |
-
\$context['_iterated'] = true;
|
183 |
-
++\$context['loop']['index0'];
|
184 |
-
++\$context['loop']['index'];
|
185 |
-
\$context['loop']['first'] = false;
|
186 |
-
if (isset(\$context['loop']['length'])) {
|
187 |
-
--\$context['loop']['revindex0'];
|
188 |
-
--\$context['loop']['revindex'];
|
189 |
-
\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];
|
190 |
-
}
|
191 |
-
}
|
192 |
-
if (!\$context['_iterated']) {
|
193 |
-
echo {$this->getVariableGetter('foo')};
|
194 |
-
}
|
195 |
-
\$_parent = \$context['_parent'];
|
196 |
-
unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
|
197 |
-
\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
|
198 |
-
EOF
|
199 |
-
);
|
200 |
-
|
201 |
-
return $tests;
|
202 |
-
}
|
203 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/IfTest.php
DELETED
@@ -1,100 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_IfTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_If::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$t = new Twig_Node(array(
|
20 |
-
new Twig_Node_Expression_Constant(true, 1),
|
21 |
-
new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1),
|
22 |
-
), array(), 1);
|
23 |
-
$else = null;
|
24 |
-
$node = new Twig_Node_If($t, $else, 1);
|
25 |
-
|
26 |
-
$this->assertEquals($t, $node->getNode('tests'));
|
27 |
-
$this->assertEquals(null, $node->getNode('else'));
|
28 |
-
|
29 |
-
$else = new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1);
|
30 |
-
$node = new Twig_Node_If($t, $else, 1);
|
31 |
-
$this->assertEquals($else, $node->getNode('else'));
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @covers Twig_Node_If::compile
|
36 |
-
* @dataProvider getTests
|
37 |
-
*/
|
38 |
-
public function testCompile($node, $source, $environment = null)
|
39 |
-
{
|
40 |
-
parent::testCompile($node, $source, $environment);
|
41 |
-
}
|
42 |
-
|
43 |
-
public function getTests()
|
44 |
-
{
|
45 |
-
$tests = array();
|
46 |
-
|
47 |
-
$t = new Twig_Node(array(
|
48 |
-
new Twig_Node_Expression_Constant(true, 1),
|
49 |
-
new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1),
|
50 |
-
), array(), 1);
|
51 |
-
$else = null;
|
52 |
-
$node = new Twig_Node_If($t, $else, 1);
|
53 |
-
|
54 |
-
$tests[] = array($node, <<<EOF
|
55 |
-
// line 1
|
56 |
-
if (true) {
|
57 |
-
echo {$this->getVariableGetter('foo')};
|
58 |
-
}
|
59 |
-
EOF
|
60 |
-
);
|
61 |
-
|
62 |
-
$t = new Twig_Node(array(
|
63 |
-
new Twig_Node_Expression_Constant(true, 1),
|
64 |
-
new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1),
|
65 |
-
new Twig_Node_Expression_Constant(false, 1),
|
66 |
-
new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1),
|
67 |
-
), array(), 1);
|
68 |
-
$else = null;
|
69 |
-
$node = new Twig_Node_If($t, $else, 1);
|
70 |
-
|
71 |
-
$tests[] = array($node, <<<EOF
|
72 |
-
// line 1
|
73 |
-
if (true) {
|
74 |
-
echo {$this->getVariableGetter('foo')};
|
75 |
-
} elseif (false) {
|
76 |
-
echo {$this->getVariableGetter('bar')};
|
77 |
-
}
|
78 |
-
EOF
|
79 |
-
);
|
80 |
-
|
81 |
-
$t = new Twig_Node(array(
|
82 |
-
new Twig_Node_Expression_Constant(true, 1),
|
83 |
-
new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1),
|
84 |
-
), array(), 1);
|
85 |
-
$else = new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1);
|
86 |
-
$node = new Twig_Node_If($t, $else, 1);
|
87 |
-
|
88 |
-
$tests[] = array($node, <<<EOF
|
89 |
-
// line 1
|
90 |
-
if (true) {
|
91 |
-
echo {$this->getVariableGetter('foo')};
|
92 |
-
} else {
|
93 |
-
echo {$this->getVariableGetter('bar')};
|
94 |
-
}
|
95 |
-
EOF
|
96 |
-
);
|
97 |
-
|
98 |
-
return $tests;
|
99 |
-
}
|
100 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/ImportTest.php
DELETED
@@ -1,52 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_ImportTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Import::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$macro = new Twig_Node_Expression_Constant('foo.twig', 1);
|
20 |
-
$var = new Twig_Node_Expression_AssignName('macro', 1);
|
21 |
-
$node = new Twig_Node_Import($macro, $var, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($macro, $node->getNode('expr'));
|
24 |
-
$this->assertEquals($var, $node->getNode('var'));
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @covers Twig_Node_Import::compile
|
29 |
-
* @dataProvider getTests
|
30 |
-
*/
|
31 |
-
public function testCompile($node, $source, $environment = null)
|
32 |
-
{
|
33 |
-
parent::testCompile($node, $source, $environment);
|
34 |
-
}
|
35 |
-
|
36 |
-
public function getTests()
|
37 |
-
{
|
38 |
-
$tests = array();
|
39 |
-
|
40 |
-
$macro = new Twig_Node_Expression_Constant('foo.twig', 1);
|
41 |
-
$var = new Twig_Node_Expression_AssignName('macro', 1);
|
42 |
-
$node = new Twig_Node_Import($macro, $var, 1);
|
43 |
-
|
44 |
-
$tests[] = array($node, <<<EOF
|
45 |
-
// line 1
|
46 |
-
\$context["macro"] = \$this->env->loadTemplate("foo.twig");
|
47 |
-
EOF
|
48 |
-
);
|
49 |
-
|
50 |
-
return $tests;
|
51 |
-
}
|
52 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/IncludeTest.php
DELETED
@@ -1,96 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_IncludeTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Include::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant('foo.twig', 1);
|
20 |
-
$node = new Twig_Node_Include($expr, null, false, false, 1);
|
21 |
-
|
22 |
-
$this->assertEquals(null, $node->getNode('variables'));
|
23 |
-
$this->assertEquals($expr, $node->getNode('expr'));
|
24 |
-
$this->assertFalse($node->getAttribute('only'));
|
25 |
-
|
26 |
-
$vars = new Twig_Node_Expression_Array(array(new Twig_Node_Expression_Constant('foo', 1), new Twig_Node_Expression_Constant(true, 1)), 1);
|
27 |
-
$node = new Twig_Node_Include($expr, $vars, true, false, 1);
|
28 |
-
$this->assertEquals($vars, $node->getNode('variables'));
|
29 |
-
$this->assertTrue($node->getAttribute('only'));
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* @covers Twig_Node_Include::compile
|
34 |
-
* @dataProvider getTests
|
35 |
-
*/
|
36 |
-
public function testCompile($node, $source, $environment = null)
|
37 |
-
{
|
38 |
-
parent::testCompile($node, $source, $environment);
|
39 |
-
}
|
40 |
-
|
41 |
-
public function getTests()
|
42 |
-
{
|
43 |
-
$tests = array();
|
44 |
-
|
45 |
-
$expr = new Twig_Node_Expression_Constant('foo.twig', 1);
|
46 |
-
$node = new Twig_Node_Include($expr, null, false, false, 1);
|
47 |
-
$tests[] = array($node, <<<EOF
|
48 |
-
// line 1
|
49 |
-
\$this->env->loadTemplate("foo.twig")->display(\$context);
|
50 |
-
EOF
|
51 |
-
);
|
52 |
-
|
53 |
-
$expr = new Twig_Node_Expression_Conditional(
|
54 |
-
new Twig_Node_Expression_Constant(true, 1),
|
55 |
-
new Twig_Node_Expression_Constant('foo', 1),
|
56 |
-
new Twig_Node_Expression_Constant('foo', 1),
|
57 |
-
0
|
58 |
-
);
|
59 |
-
$node = new Twig_Node_Include($expr, null, false, false, 1);
|
60 |
-
$tests[] = array($node, <<<EOF
|
61 |
-
// line 1
|
62 |
-
\$template = \$this->env->resolveTemplate(((true) ? ("foo") : ("foo")));
|
63 |
-
\$template->display(\$context);
|
64 |
-
EOF
|
65 |
-
);
|
66 |
-
|
67 |
-
$expr = new Twig_Node_Expression_Constant('foo.twig', 1);
|
68 |
-
$vars = new Twig_Node_Expression_Array(array(new Twig_Node_Expression_Constant('foo', 1), new Twig_Node_Expression_Constant(true, 1)), 1);
|
69 |
-
$node = new Twig_Node_Include($expr, $vars, false, false, 1);
|
70 |
-
$tests[] = array($node, <<<EOF
|
71 |
-
// line 1
|
72 |
-
\$this->env->loadTemplate("foo.twig")->display(array_merge(\$context, array("foo" => true)));
|
73 |
-
EOF
|
74 |
-
);
|
75 |
-
|
76 |
-
$node = new Twig_Node_Include($expr, $vars, true, false, 1);
|
77 |
-
$tests[] = array($node, <<<EOF
|
78 |
-
// line 1
|
79 |
-
\$this->env->loadTemplate("foo.twig")->display(array("foo" => true));
|
80 |
-
EOF
|
81 |
-
);
|
82 |
-
|
83 |
-
$node = new Twig_Node_Include($expr, $vars, true, true, 1);
|
84 |
-
$tests[] = array($node, <<<EOF
|
85 |
-
// line 1
|
86 |
-
try {
|
87 |
-
\$this->env->loadTemplate("foo.twig")->display(array("foo" => true));
|
88 |
-
} catch (Twig_Error_Loader \$e) {
|
89 |
-
// ignore missing template
|
90 |
-
}
|
91 |
-
EOF
|
92 |
-
);
|
93 |
-
|
94 |
-
return $tests;
|
95 |
-
}
|
96 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/MacroTest.php
DELETED
@@ -1,73 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_MacroTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Macro::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node_Text('foo', 1);
|
20 |
-
$arguments = new Twig_Node(array(new Twig_Node_Expression_Name('foo', 1)), array(), 1);
|
21 |
-
$node = new Twig_Node_Macro('foo', $body, $arguments, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($body, $node->getNode('body'));
|
24 |
-
$this->assertEquals($arguments, $node->getNode('arguments'));
|
25 |
-
$this->assertEquals('foo', $node->getAttribute('name'));
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @covers Twig_Node_Macro::compile
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$body = new Twig_Node_Text('foo', 1);
|
40 |
-
$arguments = new Twig_Node(array(
|
41 |
-
'foo' => new Twig_Node_Expression_Constant(null, 1),
|
42 |
-
'bar' => new Twig_Node_Expression_Constant('Foo', 1),
|
43 |
-
), array(), 1);
|
44 |
-
$node = new Twig_Node_Macro('foo', $body, $arguments, 1);
|
45 |
-
|
46 |
-
return array(
|
47 |
-
array($node, <<<EOF
|
48 |
-
// line 1
|
49 |
-
public function getfoo(\$_foo = null, \$_bar = "Foo")
|
50 |
-
{
|
51 |
-
\$context = \$this->env->mergeGlobals(array(
|
52 |
-
"foo" => \$_foo,
|
53 |
-
"bar" => \$_bar,
|
54 |
-
));
|
55 |
-
|
56 |
-
\$blocks = array();
|
57 |
-
|
58 |
-
ob_start();
|
59 |
-
try {
|
60 |
-
echo "foo";
|
61 |
-
} catch (Exception \$e) {
|
62 |
-
ob_end_clean();
|
63 |
-
|
64 |
-
throw \$e;
|
65 |
-
}
|
66 |
-
|
67 |
-
return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());
|
68 |
-
}
|
69 |
-
EOF
|
70 |
-
),
|
71 |
-
);
|
72 |
-
}
|
73 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/ModuleTest.php
DELETED
@@ -1,196 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_ModuleTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Module::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node_Text('foo', 1);
|
20 |
-
$parent = new Twig_Node_Expression_Constant('layout.twig', 1);
|
21 |
-
$blocks = new Twig_Node();
|
22 |
-
$macros = new Twig_Node();
|
23 |
-
$traits = new Twig_Node();
|
24 |
-
$filename = 'foo.twig';
|
25 |
-
$node = new Twig_Node_Module($body, $parent, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
26 |
-
|
27 |
-
$this->assertEquals($body, $node->getNode('body'));
|
28 |
-
$this->assertEquals($blocks, $node->getNode('blocks'));
|
29 |
-
$this->assertEquals($macros, $node->getNode('macros'));
|
30 |
-
$this->assertEquals($parent, $node->getNode('parent'));
|
31 |
-
$this->assertEquals($filename, $node->getAttribute('filename'));
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @covers Twig_Node_Module::compile
|
36 |
-
* @covers Twig_Node_Module::compileTemplate
|
37 |
-
* @covers Twig_Node_Module::compileMacros
|
38 |
-
* @covers Twig_Node_Module::compileClassHeader
|
39 |
-
* @covers Twig_Node_Module::compileDisplayHeader
|
40 |
-
* @covers Twig_Node_Module::compileDisplayBody
|
41 |
-
* @covers Twig_Node_Module::compileDisplayFooter
|
42 |
-
* @covers Twig_Node_Module::compileClassFooter
|
43 |
-
* @dataProvider getTests
|
44 |
-
*/
|
45 |
-
public function testCompile($node, $source, $environment = null)
|
46 |
-
{
|
47 |
-
parent::testCompile($node, $source, $environment);
|
48 |
-
}
|
49 |
-
|
50 |
-
public function getTests()
|
51 |
-
{
|
52 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
53 |
-
|
54 |
-
$tests = array();
|
55 |
-
|
56 |
-
$body = new Twig_Node_Text('foo', 1);
|
57 |
-
$extends = null;
|
58 |
-
$blocks = new Twig_Node();
|
59 |
-
$macros = new Twig_Node();
|
60 |
-
$traits = new Twig_Node();
|
61 |
-
$filename = 'foo.twig';
|
62 |
-
|
63 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
64 |
-
$tests[] = array($node, <<<EOF
|
65 |
-
<?php
|
66 |
-
|
67 |
-
/* foo.twig */
|
68 |
-
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
69 |
-
{
|
70 |
-
public function __construct(Twig_Environment \$env)
|
71 |
-
{
|
72 |
-
parent::__construct(\$env);
|
73 |
-
|
74 |
-
\$this->parent = false;
|
75 |
-
|
76 |
-
\$this->blocks = array(
|
77 |
-
);
|
78 |
-
}
|
79 |
-
|
80 |
-
protected function doDisplay(array \$context, array \$blocks = array())
|
81 |
-
{
|
82 |
-
// line 1
|
83 |
-
echo "foo";
|
84 |
-
}
|
85 |
-
|
86 |
-
public function getTemplateName()
|
87 |
-
{
|
88 |
-
return "foo.twig";
|
89 |
-
}
|
90 |
-
|
91 |
-
public function getDebugInfo()
|
92 |
-
{
|
93 |
-
return array ( 19 => 1,);
|
94 |
-
}
|
95 |
-
}
|
96 |
-
EOF
|
97 |
-
, $twig);
|
98 |
-
|
99 |
-
$import = new Twig_Node_Import(new Twig_Node_Expression_Constant('foo.twig', 1), new Twig_Node_Expression_AssignName('macro', 1), 1);
|
100 |
-
|
101 |
-
$body = new Twig_Node(array($import));
|
102 |
-
$extends = new Twig_Node_Expression_Constant('layout.twig', 1);
|
103 |
-
|
104 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
105 |
-
$tests[] = array($node, <<<EOF
|
106 |
-
<?php
|
107 |
-
|
108 |
-
/* foo.twig */
|
109 |
-
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
110 |
-
{
|
111 |
-
public function __construct(Twig_Environment \$env)
|
112 |
-
{
|
113 |
-
parent::__construct(\$env);
|
114 |
-
|
115 |
-
\$this->parent = \$this->env->loadTemplate("layout.twig");
|
116 |
-
|
117 |
-
\$this->blocks = array(
|
118 |
-
);
|
119 |
-
}
|
120 |
-
|
121 |
-
protected function doGetParent(array \$context)
|
122 |
-
{
|
123 |
-
return "layout.twig";
|
124 |
-
}
|
125 |
-
|
126 |
-
protected function doDisplay(array \$context, array \$blocks = array())
|
127 |
-
{
|
128 |
-
// line 1
|
129 |
-
\$context["macro"] = \$this->env->loadTemplate("foo.twig");
|
130 |
-
\$this->parent->display(\$context, array_merge(\$this->blocks, \$blocks));
|
131 |
-
}
|
132 |
-
|
133 |
-
public function getTemplateName()
|
134 |
-
{
|
135 |
-
return "foo.twig";
|
136 |
-
}
|
137 |
-
|
138 |
-
public function isTraitable()
|
139 |
-
{
|
140 |
-
return false;
|
141 |
-
}
|
142 |
-
|
143 |
-
public function getDebugInfo()
|
144 |
-
{
|
145 |
-
return array ( 24 => 1,);
|
146 |
-
}
|
147 |
-
}
|
148 |
-
EOF
|
149 |
-
, $twig);
|
150 |
-
|
151 |
-
$body = new Twig_Node();
|
152 |
-
$extends = new Twig_Node_Expression_Conditional(
|
153 |
-
new Twig_Node_Expression_Constant(true, 1),
|
154 |
-
new Twig_Node_Expression_Constant('foo', 1),
|
155 |
-
new Twig_Node_Expression_Constant('foo', 1),
|
156 |
-
0
|
157 |
-
);
|
158 |
-
|
159 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
160 |
-
$tests[] = array($node, <<<EOF
|
161 |
-
<?php
|
162 |
-
|
163 |
-
/* foo.twig */
|
164 |
-
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
165 |
-
{
|
166 |
-
protected function doGetParent(array \$context)
|
167 |
-
{
|
168 |
-
return \$this->env->resolveTemplate(((true) ? ("foo") : ("foo")));
|
169 |
-
}
|
170 |
-
|
171 |
-
protected function doDisplay(array \$context, array \$blocks = array())
|
172 |
-
{
|
173 |
-
\$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));
|
174 |
-
}
|
175 |
-
|
176 |
-
public function getTemplateName()
|
177 |
-
{
|
178 |
-
return "foo.twig";
|
179 |
-
}
|
180 |
-
|
181 |
-
public function isTraitable()
|
182 |
-
{
|
183 |
-
return false;
|
184 |
-
}
|
185 |
-
|
186 |
-
public function getDebugInfo()
|
187 |
-
{
|
188 |
-
return array ();
|
189 |
-
}
|
190 |
-
}
|
191 |
-
EOF
|
192 |
-
, $twig);
|
193 |
-
|
194 |
-
return $tests;
|
195 |
-
}
|
196 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/PrintTest.php
DELETED
@@ -1,41 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_PrintTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Print::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
20 |
-
$node = new Twig_Node_Print($expr, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($expr, $node->getNode('expr'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Print::compile
|
27 |
-
* @dataProvider getTests
|
28 |
-
*/
|
29 |
-
public function testCompile($node, $source, $environment = null)
|
30 |
-
{
|
31 |
-
parent::testCompile($node, $source, $environment);
|
32 |
-
}
|
33 |
-
|
34 |
-
public function getTests()
|
35 |
-
{
|
36 |
-
$tests = array();
|
37 |
-
$tests[] = array(new Twig_Node_Print(new Twig_Node_Expression_Constant('foo', 1), 1), "// line 1\necho \"foo\";");
|
38 |
-
|
39 |
-
return $tests;
|
40 |
-
}
|
41 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/SandboxTest.php
DELETED
@@ -1,56 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_SandboxTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Sandbox::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node_Text('foo', 1);
|
20 |
-
$node = new Twig_Node_Sandbox($body, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($body, $node->getNode('body'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Sandbox::compile
|
27 |
-
* @dataProvider getTests
|
28 |
-
*/
|
29 |
-
public function testCompile($node, $source, $environment = null)
|
30 |
-
{
|
31 |
-
parent::testCompile($node, $source, $environment);
|
32 |
-
}
|
33 |
-
|
34 |
-
public function getTests()
|
35 |
-
{
|
36 |
-
$tests = array();
|
37 |
-
|
38 |
-
$body = new Twig_Node_Text('foo', 1);
|
39 |
-
$node = new Twig_Node_Sandbox($body, 1);
|
40 |
-
|
41 |
-
$tests[] = array($node, <<<EOF
|
42 |
-
// line 1
|
43 |
-
\$sandbox = \$this->env->getExtension('sandbox');
|
44 |
-
if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {
|
45 |
-
\$sandbox->enableSandbox();
|
46 |
-
}
|
47 |
-
echo "foo";
|
48 |
-
if (!\$alreadySandboxed) {
|
49 |
-
\$sandbox->disableSandbox();
|
50 |
-
}
|
51 |
-
EOF
|
52 |
-
);
|
53 |
-
|
54 |
-
return $tests;
|
55 |
-
}
|
56 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/SandboxedModuleTest.php
DELETED
@@ -1,173 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_SandboxedModuleTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_SandboxedModule::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node_Text('foo', 1);
|
20 |
-
$parent = new Twig_Node_Expression_Constant('layout.twig', 1);
|
21 |
-
$blocks = new Twig_Node();
|
22 |
-
$macros = new Twig_Node();
|
23 |
-
$traits = new Twig_Node();
|
24 |
-
$filename = 'foo.twig';
|
25 |
-
$node = new Twig_Node_Module($body, $parent, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
26 |
-
$node = new Twig_Node_SandboxedModule($node, array('for'), array('upper'), array('cycle'));
|
27 |
-
|
28 |
-
$this->assertEquals($body, $node->getNode('body'));
|
29 |
-
$this->assertEquals($blocks, $node->getNode('blocks'));
|
30 |
-
$this->assertEquals($macros, $node->getNode('macros'));
|
31 |
-
$this->assertEquals($parent, $node->getNode('parent'));
|
32 |
-
$this->assertEquals($filename, $node->getAttribute('filename'));
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @covers Twig_Node_SandboxedModule::compile
|
37 |
-
* @covers Twig_Node_SandboxedModule::compileDisplayBody
|
38 |
-
* @covers Twig_Node_SandboxedModule::compileDisplayFooter
|
39 |
-
* @dataProvider getTests
|
40 |
-
*/
|
41 |
-
public function testCompile($node, $source, $environment = null)
|
42 |
-
{
|
43 |
-
parent::testCompile($node, $source, $environment);
|
44 |
-
}
|
45 |
-
|
46 |
-
public function getTests()
|
47 |
-
{
|
48 |
-
$twig = new Twig_Environment(new Twig_Loader_String());
|
49 |
-
|
50 |
-
$tests = array();
|
51 |
-
|
52 |
-
$body = new Twig_Node_Text('foo', 1);
|
53 |
-
$extends = null;
|
54 |
-
$blocks = new Twig_Node();
|
55 |
-
$macros = new Twig_Node();
|
56 |
-
$traits = new Twig_Node();
|
57 |
-
$filename = 'foo.twig';
|
58 |
-
|
59 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
60 |
-
$node = new Twig_Node_SandboxedModule($node, array('for'), array('upper'), array('cycle'));
|
61 |
-
|
62 |
-
$tests[] = array($node, <<<EOF
|
63 |
-
<?php
|
64 |
-
|
65 |
-
/* foo.twig */
|
66 |
-
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
67 |
-
{
|
68 |
-
public function __construct(Twig_Environment \$env)
|
69 |
-
{
|
70 |
-
parent::__construct(\$env);
|
71 |
-
|
72 |
-
\$this->parent = false;
|
73 |
-
|
74 |
-
\$this->blocks = array(
|
75 |
-
);
|
76 |
-
}
|
77 |
-
|
78 |
-
protected function doDisplay(array \$context, array \$blocks = array())
|
79 |
-
{
|
80 |
-
\$this->checkSecurity();
|
81 |
-
// line 1
|
82 |
-
echo "foo";
|
83 |
-
}
|
84 |
-
|
85 |
-
protected function checkSecurity()
|
86 |
-
{
|
87 |
-
\$this->env->getExtension('sandbox')->checkSecurity(
|
88 |
-
array('upper'),
|
89 |
-
array('for'),
|
90 |
-
array('cycle')
|
91 |
-
);
|
92 |
-
}
|
93 |
-
|
94 |
-
public function getTemplateName()
|
95 |
-
{
|
96 |
-
return "foo.twig";
|
97 |
-
}
|
98 |
-
|
99 |
-
public function getDebugInfo()
|
100 |
-
{
|
101 |
-
return array ( 20 => 1,);
|
102 |
-
}
|
103 |
-
}
|
104 |
-
EOF
|
105 |
-
, $twig);
|
106 |
-
|
107 |
-
$body = new Twig_Node();
|
108 |
-
$extends = new Twig_Node_Expression_Constant('layout.twig', 1);
|
109 |
-
$blocks = new Twig_Node();
|
110 |
-
$macros = new Twig_Node();
|
111 |
-
$traits = new Twig_Node();
|
112 |
-
$filename = 'foo.twig';
|
113 |
-
|
114 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $filename);
|
115 |
-
$node = new Twig_Node_SandboxedModule($node, array('for'), array('upper'), array('cycle'));
|
116 |
-
|
117 |
-
$tests[] = array($node, <<<EOF
|
118 |
-
<?php
|
119 |
-
|
120 |
-
/* foo.twig */
|
121 |
-
class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
122 |
-
{
|
123 |
-
public function __construct(Twig_Environment \$env)
|
124 |
-
{
|
125 |
-
parent::__construct(\$env);
|
126 |
-
|
127 |
-
\$this->parent = \$this->env->loadTemplate("layout.twig");
|
128 |
-
|
129 |
-
\$this->blocks = array(
|
130 |
-
);
|
131 |
-
}
|
132 |
-
|
133 |
-
protected function doGetParent(array \$context)
|
134 |
-
{
|
135 |
-
return "layout.twig";
|
136 |
-
}
|
137 |
-
|
138 |
-
protected function doDisplay(array \$context, array \$blocks = array())
|
139 |
-
{
|
140 |
-
\$this->checkSecurity();
|
141 |
-
\$this->parent->display(\$context, array_merge(\$this->blocks, \$blocks));
|
142 |
-
}
|
143 |
-
|
144 |
-
protected function checkSecurity()
|
145 |
-
{
|
146 |
-
\$this->env->getExtension('sandbox')->checkSecurity(
|
147 |
-
array('upper'),
|
148 |
-
array('for'),
|
149 |
-
array('cycle')
|
150 |
-
);
|
151 |
-
}
|
152 |
-
|
153 |
-
public function getTemplateName()
|
154 |
-
{
|
155 |
-
return "foo.twig";
|
156 |
-
}
|
157 |
-
|
158 |
-
public function isTraitable()
|
159 |
-
{
|
160 |
-
return false;
|
161 |
-
}
|
162 |
-
|
163 |
-
public function getDebugInfo()
|
164 |
-
{
|
165 |
-
return array ();
|
166 |
-
}
|
167 |
-
}
|
168 |
-
EOF
|
169 |
-
, $twig);
|
170 |
-
|
171 |
-
return $tests;
|
172 |
-
}
|
173 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/SandboxedPrintTest.php
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_SandboxedPrintTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_SandboxedPrint::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_SandboxedPrint($expr = new Twig_Node_Expression_Constant('foo', 1), 1);
|
20 |
-
|
21 |
-
$this->assertEquals($expr, $node->getNode('expr'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_SandboxedPrint::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
$tests = array();
|
36 |
-
|
37 |
-
$tests[] = array(new Twig_Node_SandboxedPrint(new Twig_Node_Expression_Constant('foo', 1), 1), <<<EOF
|
38 |
-
// line 1
|
39 |
-
echo \$this->env->getExtension('sandbox')->ensureToStringAllowed("foo");
|
40 |
-
EOF
|
41 |
-
);
|
42 |
-
|
43 |
-
return $tests;
|
44 |
-
}
|
45 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/SetTest.php
DELETED
@@ -1,81 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_SetTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Set::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1);
|
20 |
-
$values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 1)), array(), 1);
|
21 |
-
$node = new Twig_Node_Set(false, $names, $values, 1);
|
22 |
-
|
23 |
-
$this->assertEquals($names, $node->getNode('names'));
|
24 |
-
$this->assertEquals($values, $node->getNode('values'));
|
25 |
-
$this->assertEquals(false, $node->getAttribute('capture'));
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @covers Twig_Node_Set::compile
|
30 |
-
* @dataProvider getTests
|
31 |
-
*/
|
32 |
-
public function testCompile($node, $source, $environment = null)
|
33 |
-
{
|
34 |
-
parent::testCompile($node, $source, $environment);
|
35 |
-
}
|
36 |
-
|
37 |
-
public function getTests()
|
38 |
-
{
|
39 |
-
$tests = array();
|
40 |
-
|
41 |
-
$names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1);
|
42 |
-
$values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 1)), array(), 1);
|
43 |
-
$node = new Twig_Node_Set(false, $names, $values, 1);
|
44 |
-
$tests[] = array($node, <<<EOF
|
45 |
-
// line 1
|
46 |
-
\$context["foo"] = "foo";
|
47 |
-
EOF
|
48 |
-
);
|
49 |
-
|
50 |
-
$names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1);
|
51 |
-
$values = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Constant('foo', 1), 1)), array(), 1);
|
52 |
-
$node = new Twig_Node_Set(true, $names, $values, 1);
|
53 |
-
$tests[] = array($node, <<<EOF
|
54 |
-
// line 1
|
55 |
-
ob_start();
|
56 |
-
echo "foo";
|
57 |
-
\$context["foo"] = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());
|
58 |
-
EOF
|
59 |
-
);
|
60 |
-
|
61 |
-
$names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1);
|
62 |
-
$values = new Twig_Node_Text('foo', 1);
|
63 |
-
$node = new Twig_Node_Set(true, $names, $values, 1);
|
64 |
-
$tests[] = array($node, <<<EOF
|
65 |
-
// line 1
|
66 |
-
\$context["foo"] = ('' === \$tmp = "foo") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());
|
67 |
-
EOF
|
68 |
-
);
|
69 |
-
|
70 |
-
$names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1), new Twig_Node_Expression_AssignName('bar', 1)), array(), 1);
|
71 |
-
$values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 1), new Twig_Node_Expression_Name('bar', 1)), array(), 1);
|
72 |
-
$node = new Twig_Node_Set(false, $names, $values, 1);
|
73 |
-
$tests[] = array($node, <<<EOF
|
74 |
-
// line 1
|
75 |
-
list(\$context["foo"], \$context["bar"]) = array("foo", {$this->getVariableGetter('bar')});
|
76 |
-
EOF
|
77 |
-
);
|
78 |
-
|
79 |
-
return $tests;
|
80 |
-
}
|
81 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/SpacelessTest.php
DELETED
@@ -1,49 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_SpacelessTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Spaceless::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$body = new Twig_Node(array(new Twig_Node_Text('<div> <div> foo </div> </div>', 1)));
|
20 |
-
$node = new Twig_Node_Spaceless($body, 1);
|
21 |
-
|
22 |
-
$this->assertEquals($body, $node->getNode('body'));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @covers Twig_Node_Spaceless::compile
|
27 |
-
* @dataProvider getTests
|
28 |
-
*/
|
29 |
-
public function testCompile($node, $source, $environment = null)
|
30 |
-
{
|
31 |
-
parent::testCompile($node, $source, $environment);
|
32 |
-
}
|
33 |
-
|
34 |
-
public function getTests()
|
35 |
-
{
|
36 |
-
$body = new Twig_Node(array(new Twig_Node_Text('<div> <div> foo </div> </div>', 1)));
|
37 |
-
$node = new Twig_Node_Spaceless($body, 1);
|
38 |
-
|
39 |
-
return array(
|
40 |
-
array($node, <<<EOF
|
41 |
-
// line 1
|
42 |
-
ob_start();
|
43 |
-
echo "<div> <div> foo </div> </div>";
|
44 |
-
echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));
|
45 |
-
EOF
|
46 |
-
),
|
47 |
-
);
|
48 |
-
}
|
49 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/Node/TextTest.php
DELETED
@@ -1,40 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_Node_TextTest extends Twig_Test_NodeTestCase
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @covers Twig_Node_Text::__construct
|
16 |
-
*/
|
17 |
-
public function testConstructor()
|
18 |
-
{
|
19 |
-
$node = new Twig_Node_Text('foo', 1);
|
20 |
-
|
21 |
-
$this->assertEquals('foo', $node->getAttribute('data'));
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @covers Twig_Node_Text::compile
|
26 |
-
* @dataProvider getTests
|
27 |
-
*/
|
28 |
-
public function testCompile($node, $source, $environment = null)
|
29 |
-
{
|
30 |
-
parent::testCompile($node, $source, $environment);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getTests()
|
34 |
-
{
|
35 |
-
$tests = array();
|
36 |
-
$tests[] = array(new Twig_Node_Text('foo', 1), "// line 1\necho \"foo\";");
|
37 |
-
|
38 |
-
return $tests;
|
39 |
-
}
|
40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php
DELETED
@@ -1,114 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
|
12 |
-
{
|
13 |
-
public function testRenderBlockOptimizer()
|
14 |
-
{
|
15 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
16 |
-
|
17 |
-
$stream = $env->parse($env->tokenize('{{ block("foo") }}', 'index'));
|
18 |
-
|
19 |
-
$node = $stream->getNode('body')->getNode(0);
|
20 |
-
|
21 |
-
$this->assertEquals('Twig_Node_Expression_BlockReference', get_class($node));
|
22 |
-
$this->assertTrue($node->getAttribute('output'));
|
23 |
-
}
|
24 |
-
|
25 |
-
public function testRenderParentBlockOptimizer()
|
26 |
-
{
|
27 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
28 |
-
|
29 |
-
$stream = $env->parse($env->tokenize('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}', 'index'));
|
30 |
-
|
31 |
-
$node = $stream->getNode('blocks')->getNode('content')->getNode(0)->getNode('body');
|
32 |
-
|
33 |
-
$this->assertEquals('Twig_Node_Expression_Parent', get_class($node));
|
34 |
-
$this->assertTrue($node->getAttribute('output'));
|
35 |
-
}
|
36 |
-
|
37 |
-
public function testRenderVariableBlockOptimizer()
|
38 |
-
{
|
39 |
-
if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
|
40 |
-
return;
|
41 |
-
}
|
42 |
-
|
43 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
44 |
-
$stream = $env->parse($env->tokenize('{{ block(name|lower) }}', 'index'));
|
45 |
-
|
46 |
-
$node = $stream->getNode('body')->getNode(0)->getNode(1);
|
47 |
-
|
48 |
-
$this->assertEquals('Twig_Node_Expression_BlockReference', get_class($node));
|
49 |
-
$this->assertTrue($node->getAttribute('output'));
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* @dataProvider getTestsForForOptimizer
|
54 |
-
*/
|
55 |
-
public function testForOptimizer($template, $expected)
|
56 |
-
{
|
57 |
-
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false));
|
58 |
-
|
59 |
-
$stream = $env->parse($env->tokenize($template, 'index'));
|
60 |
-
|
61 |
-
foreach ($expected as $target => $withLoop) {
|
62 |
-
$this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : ''));
|
63 |
-
}
|
64 |
-
}
|
65 |
-
|
66 |
-
public function getTestsForForOptimizer()
|
67 |
-
{
|
68 |
-
return array(
|
69 |
-
array('{% for i in foo %}{% endfor %}', array('i' => false)),
|
70 |
-
|
71 |
-
array('{% for i in foo %}{{ loop.index }}{% endfor %}', array('i' => true)),
|
72 |
-
|
73 |
-
array('{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)),
|
74 |
-
|
75 |
-
array('{% for i in foo %}{% include "foo" %}{% endfor %}', array('i' => true)),
|
76 |
-
|
77 |
-
array('{% for i in foo %}{% include "foo" only %}{% endfor %}', array('i' => false)),
|
78 |
-
|
79 |
-
array('{% for i in foo %}{% include "foo" with { "foo": "bar" } only %}{% endfor %}', array('i' => false)),
|
80 |
-
|
81 |
-
array('{% for i in foo %}{% include "foo" with { "foo": loop.index } only %}{% endfor %}', array('i' => true)),
|
82 |
-
|
83 |
-
array('{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => true)),
|
84 |
-
|
85 |
-
array('{% for i in foo %}{% for j in foo %}{{ loop.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
|
86 |
-
|
87 |
-
array('{% for i in foo %}{% set l = loop %}{% for j in foo %}{{ l.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => false)),
|
88 |
-
|
89 |
-
array('{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)),
|
90 |
-
|
91 |
-
array('{% for i in foo %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
|
92 |
-
);
|
93 |
-
}
|
94 |
-
|
95 |
-
public function checkForConfiguration(Twig_NodeInterface $node = null, $target, $withLoop)
|
96 |
-
{
|
97 |
-
if (null === $node) {
|
98 |
-
return;
|
99 |
-
}
|
100 |
-
|
101 |
-
foreach ($node as $n) {
|
102 |
-
if ($n instanceof Twig_Node_For) {
|
103 |
-
if ($target === $n->getNode('value_target')->getAttribute('name')) {
|
104 |
-
return $withLoop == $n->getAttribute('with_loop');
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
$ret = $this->checkForConfiguration($n, $target, $withLoop);
|
109 |
-
if (null !== $ret) {
|
110 |
-
return $ret;
|
111 |
-
}
|
112 |
-
}
|
113 |
-
}
|
114 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/ParserTest.php
DELETED
@@ -1,180 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
class Twig_Tests_ParserTest extends PHPUnit_Framework_TestCase
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* @expectedException Twig_Error_Syntax
|
15 |
-
*/
|
16 |
-
public function testSetMacroThrowsExceptionOnReservedMethods()
|
17 |
-
{
|
18 |
-
$parser = $this->getParser();
|
19 |
-
$parser->setMacro('display', $this->getMock('Twig_Node_Macro', array(), array(), '', null));
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @expectedException Twig_Error_Syntax
|
24 |
-
* @expectedExceptionMessage Unknown tag name "foo". Did you mean "for" at line 1
|
25 |
-
*/
|
26 |
-
public function testUnkownTag()
|
27 |
-
{
|
28 |
-
$stream = new Twig_TokenStream(array(
|
29 |
-
new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1),
|
30 |
-
new Twig_Token(Twig_Token::NAME_TYPE, 'foo', 1),
|
31 |
-
new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1),
|
32 |
-
new Twig_Token(Twig_Token::EOF_TYPE, '', 1),
|
33 |
-
));
|
34 |
-
$parser = new Twig_Parser(new Twig_Environment());
|
35 |
-
$parser->parse($stream);
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @dataProvider getFilterBodyNodesData
|
40 |
-
*/
|
41 |
-
public function testFilterBodyNodes($input, $expected)
|
42 |
-
{
|
43 |
-
$parser = $this->getParser();
|
44 |
-
|
45 |
-
$this->assertEquals($expected, $parser->filterBodyNodes($input));
|
46 |
-
}
|
47 |
-
|
48 |
-
public function getFilterBodyNodesData()
|
49 |
-
{
|
50 |
-
return array(
|
51 |
-
array(
|
52 |
-
new Twig_Node(array(new Twig_Node_Text(' ', 1))),
|
53 |
-
new Twig_Node(array()),
|
54 |
-
),
|
55 |
-
array(
|
56 |
-
$input = new Twig_Node(array(new Twig_Node_Set(false, new Twig_Node(), new Twig_Node(), 1))),
|
57 |
-
$input,
|
58 |
-
),
|
59 |
-
array(
|
60 |
-
$input = new Twig_Node(array(new Twig_Node_Set(true, new Twig_Node(), new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 1))))), 1))),
|
61 |
-
$input,
|
62 |
-
),
|
63 |
-
);
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* @dataProvider getFilterBodyNodesDataThrowsException
|
68 |
-
* @expectedException Twig_Error_Syntax
|
69 |
-
*/
|
70 |
-
public function testFilterBodyNodesThrowsException($input)
|
71 |
-
{
|
72 |
-
$parser = $this->getParser();
|
73 |
-
|
74 |
-
$parser->filterBodyNodes($input);
|
75 |
-
}
|
76 |
-
|
77 |
-
public function getFilterBodyNodesDataThrowsException()
|
78 |
-
{
|
79 |
-
return array(
|
80 |
-
array(new Twig_Node_Text('foo', 1)),
|
81 |
-
array(new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 1)))))),
|
82 |
-
);
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* @expectedException Twig_Error_Syntax
|
87 |
-
* @expectedExceptionMessage A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed at line 1.
|
88 |
-
*/
|
89 |
-
public function testFilterBodyNodesWithBOM()
|
90 |
-
{
|
91 |
-
$parser = $this->getParser();
|
92 |
-
$parser->filterBodyNodes(new Twig_Node_Text(chr(0xEF).chr(0xBB).chr(0xBF), 1));
|
93 |
-
}
|
94 |
-
|
95 |
-
public function testParseIsReentrant()
|
96 |
-
{
|
97 |
-
$twig = new Twig_Environment(null, array(
|
98 |
-
'autoescape' => false,
|
99 |
-
'optimizations' => 0,
|
100 |
-
));
|
101 |
-
$twig->addTokenParser(new TestTokenParser());
|
102 |
-
|
103 |
-
$parser = new Twig_Parser($twig);
|
104 |
-
|
105 |
-
$parser->parse(new Twig_TokenStream(array(
|
106 |
-
new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1),
|
107 |
-
new Twig_Token(Twig_Token::NAME_TYPE, 'test', 1),
|
108 |
-
new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1),
|
109 |
-
new Twig_Token(Twig_Token::VAR_START_TYPE, '', 1),
|
110 |
-
new Twig_Token(Twig_Token::NAME_TYPE, 'foo', 1),
|
111 |
-
new Twig_Token(Twig_Token::VAR_END_TYPE, '', 1),
|
112 |
-
new Twig_Token(Twig_Token::EOF_TYPE, '', 1),
|
113 |
-
)));
|
114 |
-
|
115 |
-
$this->assertEquals(null, $parser->getParent());
|
116 |
-
}
|
117 |
-
|
118 |
-
// The getVarName() must not depend on the template loaders,
|
119 |
-
// If this test does not throw any exception, that's good.
|
120 |
-
// see https://github.com/symfony/symfony/issues/4218
|
121 |
-
public function testGetVarName()
|
122 |
-
{
|
123 |
-
$twig = new Twig_Environment(null, array(
|
124 |
-
'autoescape' => false,
|
125 |
-
'optimizations' => 0,
|
126 |
-
));
|
127 |
-
|
128 |
-
$twig->parse($twig->tokenize(<<<EOF
|
129 |
-
{% from _self import foo %}
|
130 |
-
|
131 |
-
{% macro foo() %}
|
132 |
-
{{ foo }}
|
133 |
-
{% endmacro %}
|
134 |
-
EOF
|
135 |
-
));
|
136 |
-
}
|
137 |
-
|
138 |
-
protected function getParser()
|
139 |
-
{
|
140 |
-
$parser = new TestParser(new Twig_Environment());
|
141 |
-
$parser->setParent(new Twig_Node());
|
142 |
-
$parser->stream = $this->getMockBuilder('Twig_TokenStream')->disableOriginalConstructor()->getMock();
|
143 |
-
|
144 |
-
return $parser;
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
class TestParser extends Twig_Parser
|
149 |
-
{
|
150 |
-
public $stream;
|
151 |
-
|
152 |
-
public function filterBodyNodes(Twig_NodeInterface $node)
|
153 |
-
{
|
154 |
-
return parent::filterBodyNodes($node);
|
155 |
-
}
|
156 |
-
}
|
157 |
-
|
158 |
-
class TestTokenParser extends Twig_TokenParser
|
159 |
-
{
|
160 |
-
public function parse(Twig_Token $token)
|
161 |
-
{
|
162 |
-
// simulate the parsing of another template right in the middle of the parsing of the current template
|
163 |
-
$this->parser->parse(new Twig_TokenStream(array(
|
164 |
-
new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1),
|
165 |
-
new Twig_Token(Twig_Token::NAME_TYPE, 'extends', 1),
|
166 |
-
new Twig_Token(Twig_Token::STRING_TYPE, 'base', 1),
|
167 |
-
new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1),
|
168 |
-
new Twig_Token(Twig_Token::EOF_TYPE, '', 1),
|
169 |
-
)));
|
170 |
-
|
171 |
-
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
172 |
-
|
173 |
-
return new Twig_Node(array());
|
174 |
-
}
|
175 |
-
|
176 |
-
public function getTag()
|
177 |
-
{
|
178 |
-
return 'test';
|
179 |
-
}
|
180 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/TemplateTest.php
DELETED
@@ -1,556 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* @dataProvider getAttributeExceptions
|
15 |
-
*/
|
16 |
-
public function testGetAttributeExceptions($template, $message, $useExt)
|
17 |
-
{
|
18 |
-
$name = 'index_'.($useExt ? 1 : 0);
|
19 |
-
$templates = array(
|
20 |
-
$name => $template.$useExt, // appending $useExt makes the template content unique
|
21 |
-
);
|
22 |
-
|
23 |
-
$env = new Twig_Environment(new Twig_Loader_Array($templates), array('strict_variables' => true));
|
24 |
-
if (!$useExt) {
|
25 |
-
$env->addNodeVisitor(new CExtDisablingNodeVisitor());
|
26 |
-
}
|
27 |
-
$template = $env->loadTemplate($name);
|
28 |
-
|
29 |
-
$context = array(
|
30 |
-
'string' => 'foo',
|
31 |
-
'array' => array('foo' => 'foo'),
|
32 |
-
'array_access' => new Twig_TemplateArrayAccessObject(),
|
33 |
-
);
|
34 |
-
|
35 |
-
try {
|
36 |
-
$template->render($context);
|
37 |
-
} catch (Twig_Error_Runtime $e) {
|
38 |
-
$this->assertEquals(sprintf($message, $name), $e->getMessage());
|
39 |
-
}
|
40 |
-
}
|
41 |
-
|
42 |
-
public function getAttributeExceptions()
|
43 |
-
{
|
44 |
-
$tests = array(
|
45 |
-
array('{{ string["a"] }}', 'Impossible to access a key ("a") on a "string" variable in "%s" at line 1', false),
|
46 |
-
array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
|
47 |
-
array('{{ array_access["a"] }}', 'Key "a" in object (with ArrayAccess) of type "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
48 |
-
array('{{ string.a }}', 'Item "a" for "foo" does not exist in "%s" at line 1', false),
|
49 |
-
array('{{ array.a }}', 'Item "a" for "Array" does not exist in "%s" at line 1', false),
|
50 |
-
array('{{ array_access.a }}', 'Method "a" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
51 |
-
array('{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ _self.foo(array_access) }}', 'Method "missing_method" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
52 |
-
);
|
53 |
-
|
54 |
-
if (function_exists('twig_template_get_attributes')) {
|
55 |
-
foreach (array_slice($tests, 0) as $test) {
|
56 |
-
$test[2] = true;
|
57 |
-
$tests[] = $test;
|
58 |
-
}
|
59 |
-
}
|
60 |
-
|
61 |
-
return $tests;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* @dataProvider getGetAttributeWithSandbox
|
66 |
-
*/
|
67 |
-
public function testGetAttributeWithSandbox($object, $item, $allowed, $useExt)
|
68 |
-
{
|
69 |
-
$twig = new Twig_Environment();
|
70 |
-
$policy = new Twig_Sandbox_SecurityPolicy(array(), array(), array(/*methid*/), array(/*peop*/), array());
|
71 |
-
$twig->addExtension(new Twig_Extension_Sandbox($policy, !$allowed));
|
72 |
-
$template = new Twig_TemplateTest($twig, $useExt);
|
73 |
-
|
74 |
-
try {
|
75 |
-
$template->getAttribute($object, $item, array(), 'any');
|
76 |
-
|
77 |
-
if (!$allowed) {
|
78 |
-
$this->fail();
|
79 |
-
}
|
80 |
-
} catch (Twig_Sandbox_SecurityError $e) {
|
81 |
-
if ($allowed) {
|
82 |
-
$this->fail();
|
83 |
-
}
|
84 |
-
|
85 |
-
$this->assertContains('is not allowed', $e->getMessage());
|
86 |
-
}
|
87 |
-
}
|
88 |
-
|
89 |
-
public function getGetAttributeWithSandbox()
|
90 |
-
{
|
91 |
-
$tests = array(
|
92 |
-
array(new Twig_TemplatePropertyObject(), 'defined', false, false),
|
93 |
-
array(new Twig_TemplatePropertyObject(), 'defined', true, false),
|
94 |
-
array(new Twig_TemplateMethodObject(), 'defined', false, false),
|
95 |
-
array(new Twig_TemplateMethodObject(), 'defined', true, false),
|
96 |
-
);
|
97 |
-
|
98 |
-
if (function_exists('twig_template_get_attributes')) {
|
99 |
-
foreach (array_slice($tests, 0) as $test) {
|
100 |
-
$test[3] = true;
|
101 |
-
$tests[] = $test;
|
102 |
-
}
|
103 |
-
}
|
104 |
-
|
105 |
-
return $tests;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* @dataProvider getGetAttributeWithTemplateAsObject
|
110 |
-
*/
|
111 |
-
public function testGetAttributeWithTemplateAsObject($useExt)
|
112 |
-
{
|
113 |
-
$template = new Twig_TemplateTest(new Twig_Environment(), $useExt);
|
114 |
-
$template1 = new Twig_TemplateTest(new Twig_Environment(), false);
|
115 |
-
|
116 |
-
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string'));
|
117 |
-
$this->assertEquals('some_string', $template->getAttribute($template1, 'string'));
|
118 |
-
|
119 |
-
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'true'));
|
120 |
-
$this->assertEquals('1', $template->getAttribute($template1, 'true'));
|
121 |
-
|
122 |
-
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'zero'));
|
123 |
-
$this->assertEquals('0', $template->getAttribute($template1, 'zero'));
|
124 |
-
|
125 |
-
$this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty'));
|
126 |
-
$this->assertSame('', $template->getAttribute($template1, 'empty'));
|
127 |
-
}
|
128 |
-
|
129 |
-
public function getGetAttributeWithTemplateAsObject()
|
130 |
-
{
|
131 |
-
$bools = array(
|
132 |
-
array(false),
|
133 |
-
);
|
134 |
-
|
135 |
-
if (function_exists('twig_template_get_attributes')) {
|
136 |
-
$bools[] = array(true);
|
137 |
-
}
|
138 |
-
|
139 |
-
return $bools;
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* @dataProvider getGetAttributeTests
|
144 |
-
*/
|
145 |
-
public function testGetAttribute($defined, $value, $object, $item, $arguments, $type, $useExt = false)
|
146 |
-
{
|
147 |
-
$template = new Twig_TemplateTest(new Twig_Environment(), $useExt);
|
148 |
-
|
149 |
-
$this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
|
150 |
-
}
|
151 |
-
|
152 |
-
/**
|
153 |
-
* @dataProvider getGetAttributeTests
|
154 |
-
*/
|
155 |
-
public function testGetAttributeStrict($defined, $value, $object, $item, $arguments, $type, $useExt = false, $exceptionMessage = null)
|
156 |
-
{
|
157 |
-
$template = new Twig_TemplateTest(new Twig_Environment(null, array('strict_variables' => true)), $useExt);
|
158 |
-
|
159 |
-
if ($defined) {
|
160 |
-
$this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
|
161 |
-
} else {
|
162 |
-
try {
|
163 |
-
$this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
|
164 |
-
|
165 |
-
throw new Exception('Expected Twig_Error_Runtime exception.');
|
166 |
-
} catch (Twig_Error_Runtime $e) {
|
167 |
-
if (null !== $exceptionMessage) {
|
168 |
-
$this->assertSame($exceptionMessage, $e->getMessage());
|
169 |
-
}
|
170 |
-
}
|
171 |
-
}
|
172 |
-
}
|
173 |
-
|
174 |
-
/**
|
175 |
-
* @dataProvider getGetAttributeTests
|
176 |
-
*/
|
177 |
-
public function testGetAttributeDefined($defined, $value, $object, $item, $arguments, $type, $useExt = false)
|
178 |
-
{
|
179 |
-
$template = new Twig_TemplateTest(new Twig_Environment(), $useExt);
|
180 |
-
|
181 |
-
$this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* @dataProvider getGetAttributeTests
|
186 |
-
*/
|
187 |
-
public function testGetAttributeDefinedStrict($defined, $value, $object, $item, $arguments, $type, $useExt = false)
|
188 |
-
{
|
189 |
-
$template = new Twig_TemplateTest(new Twig_Environment(null, array('strict_variables' => true)), $useExt);
|
190 |
-
|
191 |
-
$this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
|
192 |
-
}
|
193 |
-
|
194 |
-
public function getGetAttributeTests()
|
195 |
-
{
|
196 |
-
$array = array(
|
197 |
-
'defined' => 'defined',
|
198 |
-
'zero' => 0,
|
199 |
-
'null' => null,
|
200 |
-
'1' => 1,
|
201 |
-
'bar' => true,
|
202 |
-
);
|
203 |
-
|
204 |
-
$objectArray = new Twig_TemplateArrayAccessObject();
|
205 |
-
$stdObject = (object) $array;
|
206 |
-
$magicPropertyObject = new Twig_TemplateMagicPropertyObject();
|
207 |
-
$propertyObject = new Twig_TemplatePropertyObject();
|
208 |
-
$propertyObject1 = new Twig_TemplatePropertyObjectAndIterator();
|
209 |
-
$propertyObject2 = new Twig_TemplatePropertyObjectAndArrayAccess();
|
210 |
-
$methodObject = new Twig_TemplateMethodObject();
|
211 |
-
$magicMethodObject = new Twig_TemplateMagicMethodObject();
|
212 |
-
|
213 |
-
$anyType = Twig_TemplateInterface::ANY_CALL;
|
214 |
-
$methodType = Twig_TemplateInterface::METHOD_CALL;
|
215 |
-
$arrayType = Twig_TemplateInterface::ARRAY_CALL;
|
216 |
-
|
217 |
-
$basicTests = array(
|
218 |
-
// array(defined, value, property to fetch)
|
219 |
-
array(true, 'defined', 'defined'),
|
220 |
-
array(false, null, 'undefined'),
|
221 |
-
array(false, null, 'protected'),
|
222 |
-
array(true, 0, 'zero'),
|
223 |
-
array(true, 1, 1),
|
224 |
-
array(true, 1, 1.0),
|
225 |
-
array(true, null, 'null'),
|
226 |
-
array(true, true, 'bar'),
|
227 |
-
);
|
228 |
-
$testObjects = array(
|
229 |
-
// array(object, type of fetch)
|
230 |
-
array($array, $arrayType),
|
231 |
-
array($objectArray, $arrayType),
|
232 |
-
array($stdObject, $anyType),
|
233 |
-
array($magicPropertyObject, $anyType),
|
234 |
-
array($methodObject, $methodType),
|
235 |
-
array($methodObject, $anyType),
|
236 |
-
array($propertyObject, $anyType),
|
237 |
-
array($propertyObject1, $anyType),
|
238 |
-
array($propertyObject2, $anyType),
|
239 |
-
);
|
240 |
-
|
241 |
-
$tests = array();
|
242 |
-
foreach ($testObjects as $testObject) {
|
243 |
-
foreach ($basicTests as $test) {
|
244 |
-
// properties cannot be numbers
|
245 |
-
if (($testObject[0] instanceof stdClass || $testObject[0] instanceof Twig_TemplatePropertyObject) && is_numeric($test[2])) {
|
246 |
-
continue;
|
247 |
-
}
|
248 |
-
|
249 |
-
$tests[] = array($test[0], $test[1], $testObject[0], $test[2], array(), $testObject[1]);
|
250 |
-
}
|
251 |
-
}
|
252 |
-
|
253 |
-
// additional method tests
|
254 |
-
$tests = array_merge($tests, array(
|
255 |
-
array(true, 'defined', $methodObject, 'defined', array(), $methodType),
|
256 |
-
array(true, 'defined', $methodObject, 'DEFINED', array(), $methodType),
|
257 |
-
array(true, 'defined', $methodObject, 'getDefined', array(), $methodType),
|
258 |
-
array(true, 'defined', $methodObject, 'GETDEFINED', array(), $methodType),
|
259 |
-
array(true, 'static', $methodObject, 'static', array(), $methodType),
|
260 |
-
array(true, 'static', $methodObject, 'getStatic', array(), $methodType),
|
261 |
-
|
262 |
-
array(true, '__call_undefined', $magicMethodObject, 'undefined', array(), $methodType),
|
263 |
-
array(true, '__call_UNDEFINED', $magicMethodObject, 'UNDEFINED', array(), $methodType),
|
264 |
-
));
|
265 |
-
|
266 |
-
// add the same tests for the any type
|
267 |
-
foreach ($tests as $test) {
|
268 |
-
if ($anyType !== $test[5]) {
|
269 |
-
$test[5] = $anyType;
|
270 |
-
$tests[] = $test;
|
271 |
-
}
|
272 |
-
}
|
273 |
-
|
274 |
-
$methodAndPropObject = new Twig_TemplateMethodAndPropObject;
|
275 |
-
|
276 |
-
// additional method tests
|
277 |
-
$tests = array_merge($tests, array(
|
278 |
-
array(true, 'a', $methodAndPropObject, 'a', array(), $anyType),
|
279 |
-
array(true, 'a', $methodAndPropObject, 'a', array(), $methodType),
|
280 |
-
array(false, null, $methodAndPropObject, 'a', array(), $arrayType),
|
281 |
-
|
282 |
-
array(true, 'b_prop', $methodAndPropObject, 'b', array(), $anyType),
|
283 |
-
array(true, 'b', $methodAndPropObject, 'B', array(), $anyType),
|
284 |
-
array(true, 'b', $methodAndPropObject, 'b', array(), $methodType),
|
285 |
-
array(true, 'b', $methodAndPropObject, 'B', array(), $methodType),
|
286 |
-
array(false, null, $methodAndPropObject, 'b', array(), $arrayType),
|
287 |
-
|
288 |
-
array(false, null, $methodAndPropObject, 'c', array(), $anyType),
|
289 |
-
array(false, null, $methodAndPropObject, 'c', array(), $methodType),
|
290 |
-
array(false, null, $methodAndPropObject, 'c', array(), $arrayType),
|
291 |
-
|
292 |
-
));
|
293 |
-
|
294 |
-
// tests when input is not an array or object
|
295 |
-
$tests = array_merge($tests, array(
|
296 |
-
array(false, null, 42, 'a', array(), $anyType, false, 'Item "a" for "42" does not exist'),
|
297 |
-
array(false, null, "string", 'a', array(), $anyType, false, 'Item "a" for "string" does not exist'),
|
298 |
-
array(false, null, array(), 'a', array(), $anyType, false, 'Item "a" for "Array" does not exist'),
|
299 |
-
));
|
300 |
-
|
301 |
-
// add twig_template_get_attributes tests
|
302 |
-
|
303 |
-
if (function_exists('twig_template_get_attributes')) {
|
304 |
-
foreach (array_slice($tests, 0) as $test) {
|
305 |
-
$test = array_pad($test, 7, null);
|
306 |
-
$test[6] = true;
|
307 |
-
$tests[] = $test;
|
308 |
-
}
|
309 |
-
}
|
310 |
-
|
311 |
-
return $tests;
|
312 |
-
}
|
313 |
-
}
|
314 |
-
|
315 |
-
class Twig_TemplateTest extends Twig_Template
|
316 |
-
{
|
317 |
-
protected $useExtGetAttribute = false;
|
318 |
-
|
319 |
-
public function __construct(Twig_Environment $env, $useExtGetAttribute = false)
|
320 |
-
{
|
321 |
-
parent::__construct($env);
|
322 |
-
$this->useExtGetAttribute = $useExtGetAttribute;
|
323 |
-
Twig_Template::clearCache();
|
324 |
-
}
|
325 |
-
|
326 |
-
public function getZero()
|
327 |
-
{
|
328 |
-
return 0;
|
329 |
-
}
|
330 |
-
|
331 |
-
public function getEmpty()
|
332 |
-
{
|
333 |
-
return '';
|
334 |
-
}
|
335 |
-
|
336 |
-
public function getString()
|
337 |
-
{
|
338 |
-
return 'some_string';
|
339 |
-
}
|
340 |
-
|
341 |
-
public function getTrue()
|
342 |
-
{
|
343 |
-
return true;
|
344 |
-
}
|
345 |
-
|
346 |
-
public function getTemplateName()
|
347 |
-
{
|
348 |
-
}
|
349 |
-
|
350 |
-
public function getDebugInfo()
|
351 |
-
{
|
352 |
-
return array();
|
353 |
-
}
|
354 |
-
|
355 |
-
protected function doGetParent(array $context)
|
356 |
-
{
|
357 |
-
}
|
358 |
-
|
359 |
-
protected function doDisplay(array $context, array $blocks = array())
|
360 |
-
{
|
361 |
-
}
|
362 |
-
|
363 |
-
public function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
364 |
-
{
|
365 |
-
if ($this->useExtGetAttribute) {
|
366 |
-
return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
|
367 |
-
} else {
|
368 |
-
return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
|
369 |
-
}
|
370 |
-
}
|
371 |
-
}
|
372 |
-
|
373 |
-
class Twig_TemplateArrayAccessObject implements ArrayAccess
|
374 |
-
{
|
375 |
-
protected $protected = 'protected';
|
376 |
-
|
377 |
-
public $attributes = array(
|
378 |
-
'defined' => 'defined',
|
379 |
-
'zero' => 0,
|
380 |
-
'null' => null,
|
381 |
-
'1' => 1,
|
382 |
-
'bar' => true,
|
383 |
-
);
|
384 |
-
|
385 |
-
public function offsetExists($name)
|
386 |
-
{
|
387 |
-
return array_key_exists($name, $this->attributes);
|
388 |
-
}
|
389 |
-
|
390 |
-
public function offsetGet($name)
|
391 |
-
{
|
392 |
-
return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null;
|
393 |
-
}
|
394 |
-
|
395 |
-
public function offsetSet($name, $value)
|
396 |
-
{
|
397 |
-
}
|
398 |
-
|
399 |
-
public function offsetUnset($name)
|
400 |
-
{
|
401 |
-
}
|
402 |
-
}
|
403 |
-
|
404 |
-
class Twig_TemplateMagicPropertyObject
|
405 |
-
{
|
406 |
-
public $defined = 'defined';
|
407 |
-
|
408 |
-
public $attributes = array(
|
409 |
-
'zero' => 0,
|
410 |
-
'null' => null,
|
411 |
-
'1' => 1,
|
412 |
-
'bar' => true,
|
413 |
-
);
|
414 |
-
|
415 |
-
protected $protected = 'protected';
|
416 |
-
|
417 |
-
public function __isset($name)
|
418 |
-
{
|
419 |
-
return array_key_exists($name, $this->attributes);
|
420 |
-
}
|
421 |
-
|
422 |
-
public function __get($name)
|
423 |
-
{
|
424 |
-
return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null;
|
425 |
-
}
|
426 |
-
}
|
427 |
-
|
428 |
-
class Twig_TemplatePropertyObject
|
429 |
-
{
|
430 |
-
public $defined = 'defined';
|
431 |
-
public $zero = 0;
|
432 |
-
public $null = null;
|
433 |
-
public $bar = true;
|
434 |
-
|
435 |
-
protected $protected = 'protected';
|
436 |
-
}
|
437 |
-
|
438 |
-
class Twig_TemplatePropertyObjectAndIterator extends Twig_TemplatePropertyObject implements IteratorAggregate
|
439 |
-
{
|
440 |
-
public function getIterator()
|
441 |
-
{
|
442 |
-
return new ArrayIterator(array('foo', 'bar'));
|
443 |
-
}
|
444 |
-
}
|
445 |
-
|
446 |
-
class Twig_TemplatePropertyObjectAndArrayAccess extends Twig_TemplatePropertyObject implements ArrayAccess
|
447 |
-
{
|
448 |
-
private $data = array();
|
449 |
-
|
450 |
-
public function offsetExists($offset)
|
451 |
-
{
|
452 |
-
return array_key_exists($offset, $this->data);
|
453 |
-
}
|
454 |
-
|
455 |
-
public function offsetGet($offset)
|
456 |
-
{
|
457 |
-
return $this->offsetExists($offset) ? $this->data[$offset] : 'n/a';
|
458 |
-
}
|
459 |
-
|
460 |
-
public function offsetSet($offset, $value)
|
461 |
-
{
|
462 |
-
}
|
463 |
-
|
464 |
-
public function offsetUnset($offset)
|
465 |
-
{
|
466 |
-
}
|
467 |
-
}
|
468 |
-
|
469 |
-
class Twig_TemplateMethodObject
|
470 |
-
{
|
471 |
-
public function getDefined()
|
472 |
-
{
|
473 |
-
return 'defined';
|
474 |
-
}
|
475 |
-
|
476 |
-
public function get1()
|
477 |
-
{
|
478 |
-
return 1;
|
479 |
-
}
|
480 |
-
|
481 |
-
public function getZero()
|
482 |
-
{
|
483 |
-
return 0;
|
484 |
-
}
|
485 |
-
|
486 |
-
public function getNull()
|
487 |
-
{
|
488 |
-
return null;
|
489 |
-
}
|
490 |
-
|
491 |
-
public function isBar()
|
492 |
-
{
|
493 |
-
return true;
|
494 |
-
}
|
495 |
-
|
496 |
-
protected function getProtected()
|
497 |
-
{
|
498 |
-
return 'protected';
|
499 |
-
}
|
500 |
-
|
501 |
-
public static function getStatic()
|
502 |
-
{
|
503 |
-
return 'static';
|
504 |
-
}
|
505 |
-
}
|
506 |
-
|
507 |
-
class Twig_TemplateMethodAndPropObject
|
508 |
-
{
|
509 |
-
private $a = 'a_prop';
|
510 |
-
public function getA()
|
511 |
-
{
|
512 |
-
return 'a';
|
513 |
-
}
|
514 |
-
|
515 |
-
public $b = 'b_prop';
|
516 |
-
public function getB()
|
517 |
-
{
|
518 |
-
return 'b';
|
519 |
-
}
|
520 |
-
|
521 |
-
private $c = 'c_prop';
|
522 |
-
private function getC()
|
523 |
-
{
|
524 |
-
return 'c';
|
525 |
-
}
|
526 |
-
}
|
527 |
-
|
528 |
-
class Twig_TemplateMagicMethodObject
|
529 |
-
{
|
530 |
-
public function __call($method, $arguments)
|
531 |
-
{
|
532 |
-
return '__call_'.$method;
|
533 |
-
}
|
534 |
-
}
|
535 |
-
|
536 |
-
class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface
|
537 |
-
{
|
538 |
-
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
539 |
-
{
|
540 |
-
if ($node instanceof Twig_Node_Expression_GetAttr) {
|
541 |
-
$node->setAttribute('disable_c_ext', true);
|
542 |
-
}
|
543 |
-
|
544 |
-
return $node;
|
545 |
-
}
|
546 |
-
|
547 |
-
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
548 |
-
{
|
549 |
-
return $node;
|
550 |
-
}
|
551 |
-
|
552 |
-
public function getPriority()
|
553 |
-
{
|
554 |
-
return 0;
|
555 |
-
}
|
556 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/TokenStreamTest.php
DELETED
@@ -1,70 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
class Twig_Tests_TokenStreamTest extends PHPUnit_Framework_TestCase
|
13 |
-
{
|
14 |
-
protected static $tokens;
|
15 |
-
|
16 |
-
public function setUp()
|
17 |
-
{
|
18 |
-
self::$tokens = array(
|
19 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 1, 1),
|
20 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 2, 1),
|
21 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 3, 1),
|
22 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 4, 1),
|
23 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 5, 1),
|
24 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 6, 1),
|
25 |
-
new Twig_Token(Twig_Token::TEXT_TYPE, 7, 1),
|
26 |
-
new Twig_Token(Twig_Token::EOF_TYPE, 0, 1),
|
27 |
-
);
|
28 |
-
}
|
29 |
-
|
30 |
-
public function testNext()
|
31 |
-
{
|
32 |
-
$stream = new Twig_TokenStream(self::$tokens);
|
33 |
-
$repr = array();
|
34 |
-
while (!$stream->isEOF()) {
|
35 |
-
$token = $stream->next();
|
36 |
-
|
37 |
-
$repr[] = $token->getValue();
|
38 |
-
}
|
39 |
-
$this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() advances the pointer and returns the current token');
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* @expectedException Twig_Error_Syntax
|
44 |
-
* @expectedMessage Unexpected end of template
|
45 |
-
*/
|
46 |
-
public function testEndOfTemplateNext()
|
47 |
-
{
|
48 |
-
$stream = new Twig_TokenStream(array(
|
49 |
-
new Twig_Token(Twig_Token::BLOCK_START_TYPE, 1, 1),
|
50 |
-
));
|
51 |
-
while (!$stream->isEOF()) {
|
52 |
-
$stream->next();
|
53 |
-
}
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* @expectedException Twig_Error_Syntax
|
58 |
-
* @expectedMessage Unexpected end of template
|
59 |
-
*/
|
60 |
-
public function testEndOfTemplateLook()
|
61 |
-
{
|
62 |
-
$stream = new Twig_TokenStream(array(
|
63 |
-
new Twig_Token(Twig_Token::BLOCK_START_TYPE, 1, 1),
|
64 |
-
));
|
65 |
-
while (!$stream->isEOF()) {
|
66 |
-
$stream->look();
|
67 |
-
$stream->next();
|
68 |
-
}
|
69 |
-
}
|
70 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/Twig/Tests/escapingTest.php
DELETED
@@ -1,320 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* This class is adapted from code coming from Zend Framework.
|
5 |
-
*
|
6 |
-
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
|
7 |
-
* @license http://framework.zend.com/license/new-bsd New BSD License
|
8 |
-
*/
|
9 |
-
|
10 |
-
class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* All character encodings supported by htmlspecialchars()
|
14 |
-
*/
|
15 |
-
protected $htmlSpecialChars = array(
|
16 |
-
'\'' => ''',
|
17 |
-
'"' => '"',
|
18 |
-
'<' => '<',
|
19 |
-
'>' => '>',
|
20 |
-
'&' => '&'
|
21 |
-
);
|
22 |
-
|
23 |
-
protected $htmlAttrSpecialChars = array(
|
24 |
-
'\'' => ''',
|
25 |
-
/* Characters beyond ASCII value 255 to unicode escape */
|
26 |
-
'Ā' => 'Ā',
|
27 |
-
/* Immune chars excluded */
|
28 |
-
',' => ',',
|
29 |
-
'.' => '.',
|
30 |
-
'-' => '-',
|
31 |
-
'_' => '_',
|
32 |
-
/* Basic alnums exluded */
|
33 |
-
'a' => 'a',
|
34 |
-
'A' => 'A',
|
35 |
-
'z' => 'z',
|
36 |
-
'Z' => 'Z',
|
37 |
-
'0' => '0',
|
38 |
-
'9' => '9',
|
39 |
-
/* Basic control characters and null */
|
40 |
-
"\r" => '
',
|
41 |
-
"\n" => '
',
|
42 |
-
"\t" => '	',
|
43 |
-
"\0" => '�', // should use Unicode replacement char
|
44 |
-
/* Encode chars as named entities where possible */
|
45 |
-
'<' => '<',
|
46 |
-
'>' => '>',
|
47 |
-
'&' => '&',
|
48 |
-
'"' => '"',
|
49 |
-
/* Encode spaces for quoteless attribute protection */
|
50 |
-
' ' => ' ',
|
51 |
-
);
|
52 |
-
|
53 |
-
protected $jsSpecialChars = array(
|
54 |
-
/* HTML special chars - escape without exception to hex */
|
55 |
-
'<' => '\\x3C',
|
56 |
-
'>' => '\\x3E',
|
57 |
-
'\'' => '\\x27',
|
58 |
-
'"' => '\\x22',
|
59 |
-
'&' => '\\x26',
|
60 |
-
/* Characters beyond ASCII value 255 to unicode escape */
|
61 |
-
'Ā' => '\\u0100',
|
62 |
-
/* Immune chars excluded */
|
63 |
-
',' => ',',
|
64 |
-
'.' => '.',
|
65 |
-
'_' => '_',
|
66 |
-
/* Basic alnums exluded */
|
67 |
-
'a' => 'a',
|
68 |
-
'A' => 'A',
|
69 |
-
'z' => 'z',
|
70 |
-
'Z' => 'Z',
|
71 |
-
'0' => '0',
|
72 |
-
'9' => '9',
|
73 |
-
/* Basic control characters and null */
|
74 |
-
"\r" => '\\x0D',
|
75 |
-
"\n" => '\\x0A',
|
76 |
-
"\t" => '\\x09',
|
77 |
-
"\0" => '\\x00',
|
78 |
-
/* Encode spaces for quoteless attribute protection */
|
79 |
-
' ' => '\\x20',
|
80 |
-
);
|
81 |
-
|
82 |
-
protected $urlSpecialChars = array(
|
83 |
-
/* HTML special chars - escape without exception to percent encoding */
|
84 |
-
'<' => '%3C',
|
85 |
-
'>' => '%3E',
|
86 |
-
'\'' => '%27',
|
87 |
-
'"' => '%22',
|
88 |
-
'&' => '%26',
|
89 |
-
/* Characters beyond ASCII value 255 to hex sequence */
|
90 |
-
'Ā' => '%C4%80',
|
91 |
-
/* Punctuation and unreserved check */
|
92 |
-
',' => '%2C',
|
93 |
-
'.' => '.',
|
94 |
-
'_' => '_',
|
95 |
-
'-' => '-',
|
96 |
-
':' => '%3A',
|
97 |
-
';' => '%3B',
|
98 |
-
'!' => '%21',
|
99 |
-
/* Basic alnums excluded */
|
100 |
-
'a' => 'a',
|
101 |
-
'A' => 'A',
|
102 |
-
'z' => 'z',
|
103 |
-
'Z' => 'Z',
|
104 |
-
'0' => '0',
|
105 |
-
'9' => '9',
|
106 |
-
/* Basic control characters and null */
|
107 |
-
"\r" => '%0D',
|
108 |
-
"\n" => '%0A',
|
109 |
-
"\t" => '%09',
|
110 |
-
"\0" => '%00',
|
111 |
-
/* PHP quirks from the past */
|
112 |
-
' ' => '%20',
|
113 |
-
'~' => '~',
|
114 |
-
'+' => '%2B',
|
115 |
-
);
|
116 |
-
|
117 |
-
protected $cssSpecialChars = array(
|
118 |
-
/* HTML special chars - escape without exception to hex */
|
119 |
-
'<' => '\\3C ',
|
120 |
-
'>' => '\\3E ',
|
121 |
-
'\'' => '\\27 ',
|
122 |
-
'"' => '\\22 ',
|
123 |
-
'&' => '\\26 ',
|
124 |
-
/* Characters beyond ASCII value 255 to unicode escape */
|
125 |
-
'Ā' => '\\100 ',
|
126 |
-
/* Immune chars excluded */
|
127 |
-
',' => '\\2C ',
|
128 |
-
'.' => '\\2E ',
|
129 |
-
'_' => '\\5F ',
|
130 |
-
/* Basic alnums exluded */
|
131 |
-
'a' => 'a',
|
132 |
-
'A' => 'A',
|
133 |
-
'z' => 'z',
|
134 |
-
'Z' => 'Z',
|
135 |
-
'0' => '0',
|
136 |
-
'9' => '9',
|
137 |
-
/* Basic control characters and null */
|
138 |
-
"\r" => '\\D ',
|
139 |
-
"\n" => '\\A ',
|
140 |
-
"\t" => '\\9 ',
|
141 |
-
"\0" => '\\0 ',
|
142 |
-
/* Encode spaces for quoteless attribute protection */
|
143 |
-
' ' => '\\20 ',
|
144 |
-
);
|
145 |
-
|
146 |
-
protected $env;
|
147 |
-
|
148 |
-
public function setUp()
|
149 |
-
{
|
150 |
-
$this->env = new Twig_Environment();
|
151 |
-
}
|
152 |
-
|
153 |
-
public function testHtmlEscapingConvertsSpecialChars()
|
154 |
-
{
|
155 |
-
foreach ($this->htmlSpecialChars as $key => $value) {
|
156 |
-
$this->assertEquals($value, twig_escape_filter($this->env, $key, 'html'), 'Failed to escape: '.$key);
|
157 |
-
}
|
158 |
-
}
|
159 |
-
|
160 |
-
public function testHtmlAttributeEscapingConvertsSpecialChars()
|
161 |
-
{
|
162 |
-
foreach ($this->htmlAttrSpecialChars as $key => $value) {
|
163 |
-
$this->assertEquals($value, twig_escape_filter($this->env, $key, 'html_attr'), 'Failed to escape: '.$key);
|
164 |
-
}
|
165 |
-
}
|
166 |
-
|
167 |
-
public function testJavascriptEscapingConvertsSpecialChars()
|
168 |
-
{
|
169 |
-
foreach ($this->jsSpecialChars as $key => $value) {
|
170 |
-
$this->assertEquals($value, twig_escape_filter($this->env, $key, 'js'), 'Failed to escape: '.$key);
|
171 |
-
}
|
172 |
-
}
|
173 |
-
|
174 |
-
public function testJavascriptEscapingReturnsStringIfZeroLength()
|
175 |
-
{
|
176 |
-
$this->assertEquals('', twig_escape_filter($this->env, '', 'js'));
|
177 |
-
}
|
178 |
-
|
179 |
-
public function testJavascriptEscapingReturnsStringIfContainsOnlyDigits()
|
180 |
-
{
|
181 |
-
$this->assertEquals('123', twig_escape_filter($this->env, '123', 'js'));
|
182 |
-
}
|
183 |
-
|
184 |
-
public function testCssEscapingConvertsSpecialChars()
|
185 |
-
{
|
186 |
-
foreach ($this->cssSpecialChars as $key => $value) {
|
187 |
-
$this->assertEquals($value, twig_escape_filter($this->env, $key, 'css'), 'Failed to escape: '.$key);
|
188 |
-
}
|
189 |
-
}
|
190 |
-
|
191 |
-
public function testCssEscapingReturnsStringIfZeroLength()
|
192 |
-
{
|
193 |
-
$this->assertEquals('', twig_escape_filter($this->env, '', 'css'));
|
194 |
-
}
|
195 |
-
|
196 |
-
public function testCssEscapingReturnsStringIfContainsOnlyDigits()
|
197 |
-
{
|
198 |
-
$this->assertEquals('123', twig_escape_filter($this->env, '123', 'css'));
|
199 |
-
}
|
200 |
-
|
201 |
-
public function testUrlEscapingConvertsSpecialChars()
|
202 |
-
{
|
203 |
-
foreach ($this->urlSpecialChars as $key => $value) {
|
204 |
-
$this->assertEquals($value, twig_escape_filter($this->env, $key, 'url'), 'Failed to escape: '.$key);
|
205 |
-
}
|
206 |
-
}
|
207 |
-
|
208 |
-
/**
|
209 |
-
* Range tests to confirm escaped range of characters is within OWASP recommendation
|
210 |
-
*/
|
211 |
-
|
212 |
-
/**
|
213 |
-
* Only testing the first few 2 ranges on this prot. function as that's all these
|
214 |
-
* other range tests require
|
215 |
-
*/
|
216 |
-
public function testUnicodeCodepointConversionToUtf8()
|
217 |
-
{
|
218 |
-
$expected = " ~ޙ";
|
219 |
-
$codepoints = array(0x20, 0x7e, 0x799);
|
220 |
-
$result = '';
|
221 |
-
foreach ($codepoints as $value) {
|
222 |
-
$result .= $this->codepointToUtf8($value);
|
223 |
-
}
|
224 |
-
$this->assertEquals($expected, $result);
|
225 |
-
}
|
226 |
-
|
227 |
-
/**
|
228 |
-
* Convert a Unicode Codepoint to a literal UTF-8 character.
|
229 |
-
*
|
230 |
-
* @param int Unicode codepoint in hex notation
|
231 |
-
* @return string UTF-8 literal string
|
232 |
-
*/
|
233 |
-
protected function codepointToUtf8($codepoint)
|
234 |
-
{
|
235 |
-
if ($codepoint < 0x80) {
|
236 |
-
return chr($codepoint);
|
237 |
-
}
|
238 |
-
if ($codepoint < 0x800) {
|
239 |
-
return chr($codepoint >> 6 & 0x3f | 0xc0)
|
240 |
-
. chr($codepoint & 0x3f | 0x80);
|
241 |
-
}
|
242 |
-
if ($codepoint < 0x10000) {
|
243 |
-
return chr($codepoint >> 12 & 0x0f | 0xe0)
|
244 |
-
. chr($codepoint >> 6 & 0x3f | 0x80)
|
245 |
-
. chr($codepoint & 0x3f | 0x80);
|
246 |
-
}
|
247 |
-
if ($codepoint < 0x110000) {
|
248 |
-
return chr($codepoint >> 18 & 0x07 | 0xf0)
|
249 |
-
. chr($codepoint >> 12 & 0x3f | 0x80)
|
250 |
-
. chr($codepoint >> 6 & 0x3f | 0x80)
|
251 |
-
. chr($codepoint & 0x3f | 0x80);
|
252 |
-
}
|
253 |
-
throw new Exception('Codepoint requested outside of Unicode range');
|
254 |
-
}
|
255 |
-
|
256 |
-
public function testJavascriptEscapingEscapesOwaspRecommendedRanges()
|
257 |
-
{
|
258 |
-
$immune = array(',', '.', '_'); // Exceptions to escaping ranges
|
259 |
-
for ($chr=0; $chr < 0xFF; $chr++) {
|
260 |
-
if ($chr >= 0x30 && $chr <= 0x39
|
261 |
-
|| $chr >= 0x41 && $chr <= 0x5A
|
262 |
-
|| $chr >= 0x61 && $chr <= 0x7A) {
|
263 |
-
$literal = $this->codepointToUtf8($chr);
|
264 |
-
$this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'js'));
|
265 |
-
} else {
|
266 |
-
$literal = $this->codepointToUtf8($chr);
|
267 |
-
if (in_array($literal, $immune)) {
|
268 |
-
$this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'js'));
|
269 |
-
} else {
|
270 |
-
$this->assertNotEquals(
|
271 |
-
$literal,
|
272 |
-
twig_escape_filter($this->env, $literal, 'js'),
|
273 |
-
"$literal should be escaped!");
|
274 |
-
}
|
275 |
-
}
|
276 |
-
}
|
277 |
-
}
|
278 |
-
|
279 |
-
public function testHtmlAttributeEscapingEscapesOwaspRecommendedRanges()
|
280 |
-
{
|
281 |
-
$immune = array(',', '.', '-', '_'); // Exceptions to escaping ranges
|
282 |
-
for ($chr=0; $chr < 0xFF; $chr++) {
|
283 |
-
if ($chr >= 0x30 && $chr <= 0x39
|
284 |
-
|| $chr >= 0x41 && $chr <= 0x5A
|
285 |
-
|| $chr >= 0x61 && $chr <= 0x7A) {
|
286 |
-
$literal = $this->codepointToUtf8($chr);
|
287 |
-
$this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'html_attr'));
|
288 |
-
} else {
|
289 |
-
$literal = $this->codepointToUtf8($chr);
|
290 |
-
if (in_array($literal, $immune)) {
|
291 |
-
$this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'html_attr'));
|
292 |
-
} else {
|
293 |
-
$this->assertNotEquals(
|
294 |
-
$literal,
|
295 |
-
twig_escape_filter($this->env, $literal, 'html_attr'),
|
296 |
-
"$literal should be escaped!");
|
297 |
-
}
|
298 |
-
}
|
299 |
-
}
|
300 |
-
}
|
301 |
-
|
302 |
-
public function testCssEscapingEscapesOwaspRecommendedRanges()
|
303 |
-
{
|
304 |
-
$immune = array(); // CSS has no exceptions to escaping ranges
|
305 |
-
for ($chr=0; $chr < 0xFF; $chr++) {
|
306 |
-
if ($chr >= 0x30 && $chr <= 0x39
|
307 |
-
|| $chr >= 0x41 && $chr <= 0x5A
|
308 |
-
|| $chr >= 0x61 && $chr <= 0x7A) {
|
309 |
-
$literal = $this->codepointToUtf8($chr);
|
310 |
-
$this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'css'));
|
311 |
-
} else {
|
312 |
-
$literal = $this->codepointToUtf8($chr);
|
313 |
-
$this->assertNotEquals(
|
314 |
-
$literal,
|
315 |
-
twig_escape_filter($this->env, $literal, 'css'),
|
316 |
-
"$literal should be escaped!");
|
317 |
-
}
|
318 |
-
}
|
319 |
-
}
|
320 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Twig/test/bootstrap.php
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of Twig.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php';
|
13 |
-
Twig_Autoloader::register();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
admin/timber-admin.css
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
li[class*="timber"] .wp-menu-image {
|
2 |
-
overflow:hidden;
|
3 |
-
}
|
4 |
-
|
5 |
-
li[class*="timber"] .wp-menu-image img {
|
6 |
-
position:relative;
|
7 |
-
left:-8px;
|
8 |
-
top:-36px;
|
9 |
-
}
|
10 |
-
li[class*="timber"]:hover .wp-menu-image img,
|
11 |
-
li[class*="timber"].current .wp-menu-image img {
|
12 |
-
top:-3px;
|
13 |
-
}
|
14 |
-
|
15 |
-
.timber-logo {
|
16 |
-
max-width:600px;
|
17 |
-
}
|
18 |
-
|
19 |
-
.timber-logo-img {
|
20 |
-
width:100%;
|
21 |
-
display:block;
|
22 |
-
max-width:100%;
|
23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
admin/timber-admin.php
DELETED
@@ -1,33 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class TimberAdmin {
|
4 |
-
|
5 |
-
function __construct(){
|
6 |
-
if (!is_admin() || true){
|
7 |
-
return;
|
8 |
-
}
|
9 |
-
add_action( 'admin_menu', array(&$this, 'create_menu'));
|
10 |
-
add_action( 'admin_enqueue_scripts', array(&$this, 'load_styles'));
|
11 |
-
}
|
12 |
-
|
13 |
-
function create_menu(){
|
14 |
-
add_menu_page('Timber', 'Timber', 'administrator', __FILE__, array(&$this, 'create_admin_page'), TIMBER_URL_PATH.'admin/timber-menu.png');
|
15 |
-
}
|
16 |
-
|
17 |
-
function create_admin_page(){
|
18 |
-
$data = array();
|
19 |
-
$data['theme_dir'] = get_stylesheet_directory();
|
20 |
-
$data['home_file']['name'] = 'index.php';
|
21 |
-
$data['timber_base'] = TIMBER_URL_PATH;
|
22 |
-
$data['home_file']['path'] = trailingslashit(get_stylesheet_directory()).$data['home_file']['name'];
|
23 |
-
$data['home_file']['contents'] = htmlentities(file_get_contents(realpath($data['home_file']['path'])));
|
24 |
-
Timber::render('timber-admin.twig', $data);
|
25 |
-
}
|
26 |
-
|
27 |
-
function load_styles(){
|
28 |
-
wp_enqueue_style('timber-admin-css', TIMBER_URL_PATH.'admin/timber-admin.css');
|
29 |
-
}
|
30 |
-
|
31 |
-
}
|
32 |
-
|
33 |
-
new TimberAdmin();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
admin/timber-admin.twig
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
<div class="wrap">
|
2 |
-
<h2 class="timber-logo"><img src="{{timber_base}}images/logo/timber-badge-large.jpg" class="timber-logo-img" /></h2>
|
3 |
-
|
4 |
-
<h3>Getting Started</h3>
|
5 |
-
<p>This is a quick getting-started guide to using Timber in your theme. It requires a solid knowledge of HTML and a basic understanding of PHP.</p>
|
6 |
-
|
7 |
-
<ol class="steps">
|
8 |
-
<li>
|
9 |
-
<h4>Open your {{home_file}}</h4>
|
10 |
-
<p>Using your favorite text editor, open up {{home_file.name}} inside of {{theme_dir}}. If you're working off your server, you'll need to use an FTP program like Cyberduck or Transmit.</p>
|
11 |
-
</li>
|
12 |
-
<li>
|
13 |
-
<h4>You should see this:</h4>
|
14 |
-
<pre><code>
|
15 |
-
{{home_file.contents}}
|
16 |
-
</code></pre>
|
17 |
-
</ol>
|
18 |
-
|
19 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
admin/timber-menu.png
DELETED
Binary file
|
admin/timber-menu.psd
DELETED
Binary file
|
functions/functions-wp-helper.php
CHANGED
@@ -9,6 +9,15 @@
|
|
9 |
return (bool)count(array_filter(array_keys($arr), 'is_string'));
|
10 |
}
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
function is_url($url){
|
13 |
$url = strtolower($url);
|
14 |
if (strstr('://', $url)){
|
9 |
return (bool)count(array_filter(array_keys($arr), 'is_string'));
|
10 |
}
|
11 |
|
12 |
+
function ob_function($function, $args = array(null)){
|
13 |
+
ob_start();
|
14 |
+
call_user_func_array($function, $args);
|
15 |
+
//call_user_func($function);
|
16 |
+
$data = ob_get_contents();
|
17 |
+
ob_end_clean();
|
18 |
+
return $data;
|
19 |
+
}
|
20 |
+
|
21 |
function is_url($url){
|
22 |
$url = strtolower($url);
|
23 |
if (strstr('://', $url)){
|
readme.txt
CHANGED
@@ -2,12 +2,12 @@
|
|
2 |
Contributors: jarednova
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.5
|
5 |
-
Stable tag: 0.10.
|
6 |
-
Tested up to: 3.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
10 |
-
Helps you create themes faster with
|
11 |
|
12 |
== Description ==
|
13 |
Timber cleans-up your theme code so, for example, your php file can focus on being the data, while your twig/html file can focus 100% on the HTML and display.
|
@@ -17,7 +17,8 @@ Once Timber is installed and activated in your plugin directory, it gives any Wo
|
|
17 |
### Looking for docs?
|
18 |
* **[Project Page](http://timber.upstatement.com)**
|
19 |
* [Timber Documentation](https://github.com/jarednova/timber/wiki/)
|
20 |
-
* [Twig Reference](http://twig.sensiolabs.org/documentation)
|
|
|
21 |
* **[Video Tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)**
|
22 |
* [Overview / Getting Started Guide](https://github.com/jarednova/timber/wiki/getting-started)
|
23 |
|
@@ -31,6 +32,11 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
31 |
|
32 |
== Changelog ==
|
33 |
|
|
|
|
|
|
|
|
|
|
|
34 |
= 0.10.2 =
|
35 |
* added more aliases for easier coding (post.thumbnail instead of post.get_thumbnail, etc.)
|
36 |
* Garbage removal
|
2 |
Contributors: jarednova
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.5
|
5 |
+
Stable tag: 0.10.3
|
6 |
+
Tested up to: 3.6
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
10 |
+
Helps you create themes faster with sustainable code. With Timber, you write HTML using Mustache-like Templates http://timber.upstatement.com
|
11 |
|
12 |
== Description ==
|
13 |
Timber cleans-up your theme code so, for example, your php file can focus on being the data, while your twig/html file can focus 100% on the HTML and display.
|
17 |
### Looking for docs?
|
18 |
* **[Project Page](http://timber.upstatement.com)**
|
19 |
* [Timber Documentation](https://github.com/jarednova/timber/wiki/)
|
20 |
+
* [Twig Reference (from SensioLabs)](http://twig.sensiolabs.org/documentation)
|
21 |
+
_Twig is the template language powering Timber; if you need a little background on what a template language is, check out this article_
|
22 |
* **[Video Tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)**
|
23 |
* [Overview / Getting Started Guide](https://github.com/jarednova/timber/wiki/getting-started)
|
24 |
|
32 |
|
33 |
== Changelog ==
|
34 |
|
35 |
+
= 0.10.3 =
|
36 |
+
* Corrected error with sidebar retrieval
|
37 |
+
* language_attributes are now avaiable as part of Timber::get_context(); payload.
|
38 |
+
* Upgraded to Twig 1.13.1
|
39 |
+
|
40 |
= 0.10.2 =
|
41 |
* added more aliases for easier coding (post.thumbnail instead of post.get_thumbnail, etc.)
|
42 |
* Garbage removal
|
timber-starter-theme/views/html-header.twig
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<!--[if lt IE 7]><html class="no-js ie ie6 lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
|
3 |
<!--[if IE 7]><html class="no-js ie ie7 lt-ie9 lt-ie8" lang="en"> <![endif]-->
|
4 |
<!--[if IE 8]><html class="no-js ie ie8 lt-ie9" lang="en"> <![endif]-->
|
5 |
-
<!--[if gt IE 8]><!--><html class="no-js"
|
6 |
<head>
|
7 |
<title>{{wp_title}}</title>
|
8 |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
2 |
<!--[if lt IE 7]><html class="no-js ie ie6 lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
|
3 |
<!--[if IE 7]><html class="no-js ie ie7 lt-ie9 lt-ie8" lang="en"> <![endif]-->
|
4 |
<!--[if IE 8]><html class="no-js ie ie8 lt-ie9" lang="en"> <![endif]-->
|
5 |
+
<!--[if gt IE 8]><!--><html class="no-js" {{language_attributes}}> <!--<![endif]-->
|
6 |
<head>
|
7 |
<title>{{wp_title}}</title>
|
8 |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
timber.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Timber
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power Twig templates
|
5 |
Author: Jared Novack + Upstatement
|
6 |
-
Version: 0.10.
|
7 |
Author URI: http://timber.upstatement.com/
|
8 |
*/
|
9 |
|
@@ -209,7 +209,9 @@ class Timber {
|
|
209 |
|
210 |
function get_sidebar_from_php($sidebar = '', $data){
|
211 |
$context = $data;
|
212 |
-
$
|
|
|
|
|
213 |
ob_start();
|
214 |
$found = false;
|
215 |
foreach($uris as $uri){
|
@@ -315,17 +317,17 @@ class Timber {
|
|
315 |
$data['wp_head'] = self::get_wp_head();
|
316 |
$data['wp_footer'] = self::get_wp_footer();
|
317 |
$data['body_class'] = implode(' ', get_body_class());
|
318 |
-
$
|
319 |
-
$
|
320 |
-
$
|
321 |
-
$
|
322 |
if (function_exists('wp_nav_menu')){
|
323 |
$data['wp_nav_menu'] = wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary' , 'echo' => false) );
|
324 |
}
|
|
|
325 |
return $data;
|
326 |
}
|
327 |
|
328 |
-
|
329 |
function is_post_class_or_class_map($arg){
|
330 |
if (is_string($arg) && class_exists($arg)){
|
331 |
return true;
|
3 |
Plugin Name: Timber
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power Twig templates
|
5 |
Author: Jared Novack + Upstatement
|
6 |
+
Version: 0.10.3
|
7 |
Author URI: http://timber.upstatement.com/
|
8 |
*/
|
9 |
|
209 |
|
210 |
function get_sidebar_from_php($sidebar = '', $data){
|
211 |
$context = $data;
|
212 |
+
$caller = self::get_calling_script_dir();
|
213 |
+
$loader = new TimberLoader();
|
214 |
+
$uris = $loader->get_locations($caller);
|
215 |
ob_start();
|
216 |
$found = false;
|
217 |
foreach($uris as $uri){
|
317 |
$data['wp_head'] = self::get_wp_head();
|
318 |
$data['wp_footer'] = self::get_wp_footer();
|
319 |
$data['body_class'] = implode(' ', get_body_class());
|
320 |
+
$data['bloginfo'] = array();
|
321 |
+
$data['bloginfo']['name'] = get_bloginfo('name');
|
322 |
+
$data['bloginfo']['description'] = get_bloginfo('description');
|
323 |
+
$data['bloginfo']['admin_email'] = get_bloginfo('admin_email');
|
324 |
if (function_exists('wp_nav_menu')){
|
325 |
$data['wp_nav_menu'] = wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary' , 'echo' => false) );
|
326 |
}
|
327 |
+
$data['language_attributes'] = WPHelper::ob_function('language_attributes');
|
328 |
return $data;
|
329 |
}
|
330 |
|
|
|
331 |
function is_post_class_or_class_map($arg){
|
332 |
if (is_string($arg) && class_exists($arg)){
|
333 |
return true;
|