Инициализация
This commit is contained in:
18
vendor/twig/twig/.editorconfig
vendored
Normal file
18
vendor/twig/twig/.editorconfig
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
; top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
; Unix-style newlines
|
||||
[*]
|
||||
end_of_line = LF
|
||||
|
||||
[*.php]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.test]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.rst]
|
||||
indent_style = space
|
||||
indent_size = 4
|
3
vendor/twig/twig/.gitattributes
vendored
Normal file
3
vendor/twig/twig/.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/extra/** export-ignore
|
||||
/tests export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
173
vendor/twig/twig/.github/workflows/ci.yml
vendored
Normal file
173
vendor/twig/twig/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
name: "CI"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- '3.x'
|
||||
|
||||
env:
|
||||
SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: 1
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: "PHP ${{ matrix.php-version }}"
|
||||
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- '7.2.5'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
composer-options: ['']
|
||||
experimental: [false]
|
||||
include:
|
||||
- { php-version: '8.1', experimental: true, composer-options: '--ignore-platform-req=php' }
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2.3.3
|
||||
|
||||
- name: "Install PHP with extensions"
|
||||
uses: shivammathur/setup-php@2.7.0
|
||||
with:
|
||||
coverage: "none"
|
||||
php-version: ${{ matrix.php-version }}
|
||||
ini-values: memory_limit=-1
|
||||
tools: composer:v2
|
||||
|
||||
- name: "Add PHPUnit matcher"
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: "Set composer cache directory"
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: "Cache composer"
|
||||
uses: actions/cache@v2.1.2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-${{ matrix.php-version }}-composer-
|
||||
|
||||
- run: composer install ${{ matrix.composer-options }}
|
||||
|
||||
- name: "Install PHPUnit"
|
||||
run: vendor/bin/simple-phpunit install
|
||||
|
||||
- name: "PHPUnit version"
|
||||
run: vendor/bin/simple-phpunit --version
|
||||
|
||||
- name: "Run tests"
|
||||
run: vendor/bin/simple-phpunit
|
||||
|
||||
extension-tests:
|
||||
needs:
|
||||
- 'tests'
|
||||
|
||||
name: "${{ matrix.extension }} with PHP ${{ matrix.php-version }}"
|
||||
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
continue-on-error: true
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- '7.2.5'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
extension:
|
||||
- 'extra/cache-extra'
|
||||
- 'extra/cssinliner-extra'
|
||||
- 'extra/html-extra'
|
||||
- 'extra/inky-extra'
|
||||
- 'extra/intl-extra'
|
||||
- 'extra/markdown-extra'
|
||||
- 'extra/string-extra'
|
||||
- 'extra/twig-extra-bundle'
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2.3.3
|
||||
|
||||
- name: "Install PHP with extensions"
|
||||
uses: shivammathur/setup-php@2.7.0
|
||||
with:
|
||||
coverage: "none"
|
||||
php-version: ${{ matrix.php-version }}
|
||||
ini-values: memory_limit=-1
|
||||
tools: composer:v2
|
||||
|
||||
- name: "Add PHPUnit matcher"
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: "Set composer cache directory"
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: "Cache composer"
|
||||
uses: actions/cache@v2.1.2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.extension }}-${{ hashFiles('composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.extension }}-
|
||||
|
||||
- run: composer install
|
||||
|
||||
- name: "Install PHPUnit"
|
||||
run: vendor/bin/simple-phpunit install
|
||||
|
||||
- name: "PHPUnit version"
|
||||
run: vendor/bin/simple-phpunit --version
|
||||
|
||||
- if: matrix.extension == 'extra/markdown-extra' && matrix.php-version == '8.0'
|
||||
working-directory: ${{ matrix.extension}}
|
||||
run: composer config platform.php 7.4.99
|
||||
|
||||
- name: "Composer install"
|
||||
working-directory: ${{ matrix.extension}}
|
||||
run: composer install
|
||||
|
||||
- name: "Run tests"
|
||||
working-directory: ${{ matrix.extension}}
|
||||
run: ../../vendor/bin/simple-phpunit
|
||||
#
|
||||
# Drupal does not support Twig 3 now!
|
||||
#
|
||||
# integration-tests:
|
||||
# needs:
|
||||
# - 'tests'
|
||||
#
|
||||
# name: "Integration tests with PHP ${{ matrix.php-version }}"
|
||||
#
|
||||
# runs-on: 'ubuntu-20.04'
|
||||
#
|
||||
# continue-on-error: true
|
||||
#
|
||||
# strategy:
|
||||
# matrix:
|
||||
# php-version:
|
||||
# - '7.3'
|
||||
#
|
||||
# steps:
|
||||
# - name: "Checkout code"
|
||||
# uses: actions/checkout@v2.3.3
|
||||
#
|
||||
# - name: "Install PHP with extensions"
|
||||
# uses: shivammathur/setup-php@2.7.0
|
||||
# with:
|
||||
# coverage: "none"
|
||||
# extensions: "gd, pdo_sqlite"
|
||||
# php-version: ${{ matrix.php-version }}
|
||||
# ini-values: memory_limit=-1
|
||||
# tools: composer:v2
|
||||
#
|
||||
# - run: bash ./tests/drupal_test.sh
|
||||
# shell: "bash"
|
60
vendor/twig/twig/.github/workflows/documentation.yml
vendored
Normal file
60
vendor/twig/twig/.github/workflows/documentation.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
name: "Documentation"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- '3.x'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build"
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Set up Python 3.7"
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: '3.7' # Semantic version range syntax or exact version of a Python version
|
||||
|
||||
- name: "Display Python version"
|
||||
run: python -c "import sys; print(sys.version)"
|
||||
|
||||
- name: "Install Sphinx dependencies"
|
||||
run: sudo apt-get install python-dev build-essential
|
||||
|
||||
- name: "Cache pip"
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('_build/.requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: "Install Sphinx + requirements via pip"
|
||||
working-directory: "doc"
|
||||
run: pip install -r _build/.requirements.txt
|
||||
|
||||
- name: "Build documentation"
|
||||
working-directory: "doc"
|
||||
run: make -C _build SPHINXOPTS="-nqW -j auto" html
|
||||
|
||||
doctor-rst:
|
||||
name: "DOCtor-RST"
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Run DOCtor-RST"
|
||||
uses: docker://oskarstark/doctor-rst
|
||||
with:
|
||||
args: --short
|
||||
env:
|
||||
DOCS_DIR: 'doc/'
|
4
vendor/twig/twig/.gitignore
vendored
Normal file
4
vendor/twig/twig/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/composer.lock
|
||||
/phpunit.xml
|
||||
/vendor
|
||||
.phpunit.result.cache
|
20
vendor/twig/twig/.php-cs-fixer.dist.php
vendored
Normal file
20
vendor/twig/twig/.php-cs-fixer.dist.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
'@Symfony:risky' => true,
|
||||
'@PHPUnit75Migration:risky' => true,
|
||||
'php_unit_dedicate_assert' => ['target' => '5.6'],
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'php_unit_fqcn_annotation' => true,
|
||||
'no_unreachable_default_argument_value' => false,
|
||||
'braces' => ['allow_single_line_closure' => true],
|
||||
'heredoc_to_nowdoc' => false,
|
||||
'ordered_imports' => true,
|
||||
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
|
||||
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'],
|
||||
])
|
||||
->setRiskyAllowed(true)
|
||||
->setFinder((new PhpCsFixer\Finder())->in(__DIR__))
|
||||
;
|
1646
vendor/twig/twig/CHANGELOG
vendored
Normal file
1646
vendor/twig/twig/CHANGELOG
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
vendor/twig/twig/LICENSE
vendored
Normal file
27
vendor/twig/twig/LICENSE
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009-2021 by the Twig Team.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of Twig nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
vendor/twig/twig/README.rst
vendored
Normal file
24
vendor/twig/twig/README.rst
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Twig, the flexible, fast, and secure template language for PHP
|
||||
==============================================================
|
||||
|
||||
Twig is a template language for PHP, released under the new BSD license (code
|
||||
and documentation).
|
||||
|
||||
Twig uses a syntax similar to the Django and Jinja template languages which
|
||||
inspired the Twig runtime environment.
|
||||
|
||||
Sponsors
|
||||
--------
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<a href="https://blackfire.io/docs/introduction?utm_source=twig&utm_medium=github_readme&utm_campaign=logo">
|
||||
<img src="https://static.blackfire.io/assets/intemporals/logo/png/blackfire-io_secondary_horizontal_transparent.png?1" width="255px" alt="Blackfire.io">
|
||||
</a>
|
||||
|
||||
More Information
|
||||
----------------
|
||||
|
||||
Read the `documentation`_ for more information.
|
||||
|
||||
.. _documentation: https://twig.symfony.com/documentation
|
50
vendor/twig/twig/composer.json
vendored
Normal file
50
vendor/twig/twig/composer.json
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"type": "library",
|
||||
"description": "Twig, the flexible, fast, and secure template language for PHP",
|
||||
"keywords": ["templating"],
|
||||
"homepage": "https://twig.symfony.com",
|
||||
"license": "BSD-3-Clause",
|
||||
"minimum-stability": "dev",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com",
|
||||
"homepage": "http://fabien.potencier.org",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Twig Team",
|
||||
"role": "Contributors"
|
||||
},
|
||||
{
|
||||
"name": "Armin Ronacher",
|
||||
"email": "armin.ronacher@active-4.com",
|
||||
"role": "Project Founder"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/polyfill-mbstring": "^1.3",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4" : {
|
||||
"Twig\\" : "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4" : {
|
||||
"Twig\\Tests\\" : "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
54
vendor/twig/twig/doc/.doctor-rst.yaml
vendored
Normal file
54
vendor/twig/twig/doc/.doctor-rst.yaml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
rules:
|
||||
american_english: ~
|
||||
avoid_repetetive_words: ~
|
||||
blank_line_after_directive: ~
|
||||
blank_line_before_directive: ~
|
||||
composer_dev_option_not_at_the_end: ~
|
||||
correct_code_block_directive_based_on_the_content: ~
|
||||
deprecated_directive_should_have_version: ~
|
||||
ensure_order_of_code_blocks_in_configuration_block: ~
|
||||
extension_xlf_instead_of_xliff: ~
|
||||
indention: ~
|
||||
lowercase_as_in_use_statements: ~
|
||||
max_blank_lines:
|
||||
max: 2
|
||||
no_blank_line_after_filepath_in_php_code_block: ~
|
||||
no_blank_line_after_filepath_in_twig_code_block: ~
|
||||
no_blank_line_after_filepath_in_xml_code_block: ~
|
||||
no_blank_line_after_filepath_in_yaml_code_block: ~
|
||||
no_composer_req: ~
|
||||
no_explicit_use_of_code_block_php: ~
|
||||
no_inheritdoc: ~
|
||||
no_namespace_after_use_statements: ~
|
||||
no_php_open_tag_in_code_block_php_directive: ~
|
||||
no_space_before_self_xml_closing_tag: ~
|
||||
ordered_use_statements: ~
|
||||
php_prefix_before_bin_console: ~
|
||||
replace_code_block_types: ~
|
||||
replacement: ~
|
||||
short_array_syntax: ~
|
||||
typo: ~
|
||||
unused_links: ~
|
||||
use_deprecated_directive_instead_of_versionadded: ~
|
||||
use_https_xsd_urls: ~
|
||||
valid_inline_highlighted_namespaces: ~
|
||||
valid_use_statements: ~
|
||||
versionadded_directive_should_have_version: ~
|
||||
yaml_instead_of_yml_suffix: ~
|
||||
yarn_dev_option_at_the_end: ~
|
||||
|
||||
versionadded_directive_major_version:
|
||||
major_version: 3
|
||||
|
||||
versionadded_directive_min_version:
|
||||
min_version: '3.0'
|
||||
|
||||
deprecated_directive_major_version:
|
||||
major_version: 3
|
||||
|
||||
deprecated_directive_min_version:
|
||||
min_version: '3.0'
|
||||
|
||||
whitelist:
|
||||
lines:
|
||||
- 'I like Twig.<br />'
|
6
vendor/twig/twig/doc/_build/.requirements.txt
vendored
Normal file
6
vendor/twig/twig/doc/_build/.requirements.txt
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
docutils==0.13.1
|
||||
Pygments==2.2.0
|
||||
sphinx==1.8.5
|
||||
git+https://github.com/fabpot/sphinx-php.git@v2.0.0#egg_name=sphinx-php
|
||||
jsx-lexer===0.0.8
|
||||
sphinx_rtd_theme==0.5.0
|
153
vendor/twig/twig/doc/_build/Makefile
vendored
Normal file
153
vendor/twig/twig/doc/_build/Makefile
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = .
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -c $(BUILDDIR) -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ../
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Symfony.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Symfony.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Symfony"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Symfony"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
271
vendor/twig/twig/doc/_build/conf.py
vendored
Normal file
271
vendor/twig/twig/doc/_build/conf.py
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Symfony documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Jul 28 21:58:57 2012.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.append(os.path.abspath('_exts'))
|
||||
|
||||
# adding PhpLexer
|
||||
from sphinx.highlighting import lexers
|
||||
from pygments.lexers.special import TextLexer
|
||||
from pygments.lexers.text import RstLexer
|
||||
from pygments.lexers.web import PhpLexer
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
needs_sphinx = '1.8.5'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc', 'sphinx.ext.doctest',
|
||||
'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.viewcode', 'sphinx.ext.extlinks',
|
||||
'sensio.sphinx.codeblock', 'sensio.sphinx.configurationblock', 'sensio.sphinx.phpcode', 'sensio.sphinx.bestpractice'
|
||||
]
|
||||
|
||||
#spelling_show_sugestions=True
|
||||
#spelling_lang='en_US'
|
||||
#spelling_word_list_filename='_build/spelling_word_list.txt'
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
# templates_path = ['_theme/_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'Twig'
|
||||
copyright = ''
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
# version = '2.2'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
# release = '2.2.13'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
#pygments_style = 'symfonycom.sphinx.SensioStyle'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# -- Settings for symfony doc extension ---------------------------------------------------
|
||||
|
||||
# enable highlighting for PHP code not between ``<?php ... ?>`` by default
|
||||
lexers['php'] = PhpLexer(startinline=True)
|
||||
lexers['rst'] = RstLexer()
|
||||
|
||||
config_block = {
|
||||
'rst': 'reStructuredText',
|
||||
}
|
||||
|
||||
# don't enable Sphinx Domains
|
||||
primary_domain = None
|
||||
|
||||
# set url for API links
|
||||
#api_url = 'https://github.com/symfony/symfony/blob/master/src/%s.php'
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
html_theme_options = {
|
||||
'logo_only': True,
|
||||
'prev_next_buttons_location': None,
|
||||
'style_nav_header_background': '#f0f0f0'
|
||||
}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = '_static/symfony-logo.svg'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
#html_static_path = ['_static']
|
||||
#html_css_files = ['rtd_custom.css']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Twig'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
#latex_documents = []
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
#man_pages = []
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
#texinfo_documents = []
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
# Use PHP syntax highlighting in code examples by default
|
||||
highlight_language='php'
|
911
vendor/twig/twig/doc/advanced.rst
vendored
Normal file
911
vendor/twig/twig/doc/advanced.rst
vendored
Normal file
@@ -0,0 +1,911 @@
|
||||
Extending Twig
|
||||
==============
|
||||
|
||||
Twig can be extended in many ways; you can add extra tags, filters, tests,
|
||||
operators, global variables, and functions. You can even extend the parser
|
||||
itself with node visitors.
|
||||
|
||||
.. note::
|
||||
|
||||
The first section of this chapter describes how to extend Twig. If you want
|
||||
to reuse your changes in different projects or if you want to share them
|
||||
with others, you should then create an extension as described in the
|
||||
following section.
|
||||
|
||||
.. caution::
|
||||
|
||||
When extending Twig without creating an extension, Twig won't be able to
|
||||
recompile your templates when the PHP code is updated. To see your changes
|
||||
in real-time, either disable template caching or package your code into an
|
||||
extension (see the next section of this chapter).
|
||||
|
||||
Before extending Twig, you must understand the differences between all the
|
||||
different possible extension points and when to use them.
|
||||
|
||||
First, remember that Twig has two main language constructs:
|
||||
|
||||
* ``{{ }}``: used to print the result of an expression evaluation;
|
||||
|
||||
* ``{% %}``: used to execute statements.
|
||||
|
||||
To understand why Twig exposes so many extension points, let's see how to
|
||||
implement a *Lorem ipsum* generator (it needs to know the number of words to
|
||||
generate).
|
||||
|
||||
You can use a ``lipsum`` *tag*:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% lipsum 40 %}
|
||||
|
||||
That works, but using a tag for ``lipsum`` is not a good idea for at least
|
||||
three main reasons:
|
||||
|
||||
* ``lipsum`` is not a language construct;
|
||||
* The tag outputs something;
|
||||
* The tag is not flexible as you cannot use it in an expression:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'some text' ~ {% lipsum 40 %} ~ 'some more text' }}
|
||||
|
||||
In fact, you rarely need to create tags; and that's good news because tags are
|
||||
the most complex extension point.
|
||||
|
||||
Now, let's use a ``lipsum`` *filter*:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 40|lipsum }}
|
||||
|
||||
Again, it works. But a filter should transform the passed value to something
|
||||
else. Here, we use the value to indicate the number of words to generate (so,
|
||||
``40`` is an argument of the filter, not the value we want to transform).
|
||||
|
||||
Next, let's use a ``lipsum`` *function*:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ lipsum(40) }}
|
||||
|
||||
Here we go. For this specific example, the creation of a function is the
|
||||
extension point to use. And you can use it anywhere an expression is accepted:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'some text' ~ lipsum(40) ~ 'some more text' }}
|
||||
|
||||
{% set lipsum = lipsum(40) %}
|
||||
|
||||
Lastly, you can also use a *global* object with a method able to generate lorem
|
||||
ipsum text:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ text.lipsum(40) }}
|
||||
|
||||
As a rule of thumb, use functions for frequently used features and global
|
||||
objects for everything else.
|
||||
|
||||
Keep in mind the following when you want to extend Twig:
|
||||
|
||||
========== ========================== ========== =========================
|
||||
What? Implementation difficulty? How often? When?
|
||||
========== ========================== ========== =========================
|
||||
*macro* simple frequent Content generation
|
||||
*global* simple frequent Helper object
|
||||
*function* simple frequent Content generation
|
||||
*filter* simple frequent Value transformation
|
||||
*tag* complex rare DSL language construct
|
||||
*test* simple rare Boolean decision
|
||||
*operator* simple rare Values transformation
|
||||
========== ========================== ========== =========================
|
||||
|
||||
Globals
|
||||
-------
|
||||
|
||||
A global variable is like any other template variable, except that it's
|
||||
available in all templates and macros::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->addGlobal('text', new Text());
|
||||
|
||||
You can then use the ``text`` variable anywhere in a template:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ text.lipsum(40) }}
|
||||
|
||||
Filters
|
||||
-------
|
||||
|
||||
Creating a filter consists of associating a name with a PHP callable::
|
||||
|
||||
// an anonymous function
|
||||
$filter = new \Twig\TwigFilter('rot13', function ($string) {
|
||||
return str_rot13($string);
|
||||
});
|
||||
|
||||
// or a simple PHP function
|
||||
$filter = new \Twig\TwigFilter('rot13', 'str_rot13');
|
||||
|
||||
// or a class static method
|
||||
$filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']);
|
||||
$filter = new \Twig\TwigFilter('rot13', 'SomeClass::rot13Filter');
|
||||
|
||||
// or a class method
|
||||
$filter = new \Twig\TwigFilter('rot13', [$this, 'rot13Filter']);
|
||||
// the one below needs a runtime implementation (see below for more information)
|
||||
$filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']);
|
||||
|
||||
The first argument passed to the ``\Twig\TwigFilter`` constructor is the name of the
|
||||
filter you will use in templates and the second one is the PHP callable to
|
||||
associate with it.
|
||||
|
||||
Then, add the filter to the Twig environment::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->addFilter($filter);
|
||||
|
||||
And here is how to use it in a template:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Twig'|rot13 }}
|
||||
|
||||
{# will output Gjvt #}
|
||||
|
||||
When called by Twig, the PHP callable receives the left side of the filter
|
||||
(before the pipe ``|``) as the first argument and the extra arguments passed
|
||||
to the filter (within parentheses ``()``) as extra arguments.
|
||||
|
||||
For instance, the following code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'TWIG'|lower }}
|
||||
{{ now|date('d/m/Y') }}
|
||||
|
||||
is compiled to something like the following::
|
||||
|
||||
<?php echo strtolower('TWIG') ?>
|
||||
<?php echo twig_date_format_filter($now, 'd/m/Y') ?>
|
||||
|
||||
The ``\Twig\TwigFilter`` class takes an array of options as its last argument::
|
||||
|
||||
$filter = new \Twig\TwigFilter('rot13', 'str_rot13', $options);
|
||||
|
||||
Environment-aware Filters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to access the current environment instance in your filter, set the
|
||||
``needs_environment`` option to ``true``; Twig will pass the current
|
||||
environment as the first argument to the filter call::
|
||||
|
||||
$filter = new \Twig\TwigFilter('rot13', function (\Twig\Environment $env, $string) {
|
||||
// get the current charset for instance
|
||||
$charset = $env->getCharset();
|
||||
|
||||
return str_rot13($string);
|
||||
}, ['needs_environment' => true]);
|
||||
|
||||
Context-aware Filters
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to access the current context in your filter, set the
|
||||
``needs_context`` option to ``true``; Twig will pass the current context as
|
||||
the first argument to the filter call (or the second one if
|
||||
``needs_environment`` is also set to ``true``)::
|
||||
|
||||
$filter = new \Twig\TwigFilter('rot13', function ($context, $string) {
|
||||
// ...
|
||||
}, ['needs_context' => true]);
|
||||
|
||||
$filter = new \Twig\TwigFilter('rot13', function (\Twig\Environment $env, $context, $string) {
|
||||
// ...
|
||||
}, ['needs_context' => true, 'needs_environment' => true]);
|
||||
|
||||
Automatic Escaping
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If automatic escaping is enabled, the output of the filter may be escaped
|
||||
before printing. If your filter acts as an escaper (or explicitly outputs HTML
|
||||
or JavaScript code), you will want the raw output to be printed. In such a
|
||||
case, set the ``is_safe`` option::
|
||||
|
||||
$filter = new \Twig\TwigFilter('nl2br', 'nl2br', ['is_safe' => ['html']]);
|
||||
|
||||
Some filters may need to work on input that is already escaped or safe, for
|
||||
example when adding (safe) HTML tags to originally unsafe output. In such a
|
||||
case, set the ``pre_escape`` option to escape the input data before it is run
|
||||
through your filter::
|
||||
|
||||
$filter = new \Twig\TwigFilter('somefilter', 'somefilter', ['pre_escape' => 'html', 'is_safe' => ['html']]);
|
||||
|
||||
Variadic Filters
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
When a filter should accept an arbitrary number of arguments, set the
|
||||
``is_variadic`` option to ``true``; Twig will pass the extra arguments as the
|
||||
last argument to the filter call as an array::
|
||||
|
||||
$filter = new \Twig\TwigFilter('thumbnail', function ($file, array $options = []) {
|
||||
// ...
|
||||
}, ['is_variadic' => true]);
|
||||
|
||||
Be warned that :ref:`named arguments <named-arguments>` passed to a variadic
|
||||
filter cannot be checked for validity as they will automatically end up in the
|
||||
option array.
|
||||
|
||||
Dynamic Filters
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
A filter name containing the special ``*`` character is a dynamic filter and
|
||||
the ``*`` part will match any string::
|
||||
|
||||
$filter = new \Twig\TwigFilter('*_path', function ($name, $arguments) {
|
||||
// ...
|
||||
});
|
||||
|
||||
The following filters are matched by the above defined dynamic filter:
|
||||
|
||||
* ``product_path``
|
||||
* ``category_path``
|
||||
|
||||
A dynamic filter can define more than one dynamic parts::
|
||||
|
||||
$filter = new \Twig\TwigFilter('*_path_*', function ($name, $suffix, $arguments) {
|
||||
// ...
|
||||
});
|
||||
|
||||
The filter receives all dynamic part values before the normal filter arguments,
|
||||
but after the environment and the context. For instance, a call to
|
||||
``'foo'|a_path_b()`` will result in the following arguments to be passed to the
|
||||
filter: ``('a', 'b', 'foo')``.
|
||||
|
||||
Deprecated Filters
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can mark a filter as being deprecated by setting the ``deprecated`` option
|
||||
to ``true``. You can also give an alternative filter that replaces the
|
||||
deprecated one when that makes sense::
|
||||
|
||||
$filter = new \Twig\TwigFilter('obsolete', function () {
|
||||
// ...
|
||||
}, ['deprecated' => true, 'alternative' => 'new_one']);
|
||||
|
||||
When a filter is deprecated, Twig emits a deprecation notice when compiling a
|
||||
template using it. See :ref:`deprecation-notices` for more information.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
Functions are defined in the exact same way as filters, but you need to create
|
||||
an instance of ``\Twig\TwigFunction``::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$function = new \Twig\TwigFunction('function_name', function () {
|
||||
// ...
|
||||
});
|
||||
$twig->addFunction($function);
|
||||
|
||||
Functions support the same features as filters, except for the ``pre_escape``
|
||||
and ``preserves_safety`` options.
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
Tests are defined in the exact same way as filters and functions, but you need
|
||||
to create an instance of ``\Twig\TwigTest``::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$test = new \Twig\TwigTest('test_name', function () {
|
||||
// ...
|
||||
});
|
||||
$twig->addTest($test);
|
||||
|
||||
Tests allow you to create custom application specific logic for evaluating
|
||||
boolean conditions. As a simple example, let's create a Twig test that checks if
|
||||
objects are 'red'::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$test = new \Twig\TwigTest('red', function ($value) {
|
||||
if (isset($value->color) && $value->color == 'red') {
|
||||
return true;
|
||||
}
|
||||
if (isset($value->paint) && $value->paint == 'red') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$twig->addTest($test);
|
||||
|
||||
Test functions must always return ``true``/``false``.
|
||||
|
||||
When creating tests you can use the ``node_class`` option to provide custom test
|
||||
compilation. This is useful if your test can be compiled into PHP primitives.
|
||||
This is used by many of the tests built into Twig::
|
||||
|
||||
namespace App;
|
||||
|
||||
use Twig\Environment;
|
||||
use Twig\Node\Expression\TestExpression;
|
||||
use Twig\TwigTest;
|
||||
|
||||
$twig = new Environment($loader);
|
||||
$test = new TwigTest(
|
||||
'odd',
|
||||
null,
|
||||
['node_class' => OddTestExpression::class]);
|
||||
$twig->addTest($test);
|
||||
|
||||
class OddTestExpression extends TestExpression
|
||||
{
|
||||
public function compile(\Twig\Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->raw('(')
|
||||
->subcompile($this->getNode('node'))
|
||||
->raw(' % 2 != 0')
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
The above example shows how you can create tests that use a node class. The node
|
||||
class has access to one sub-node called ``node``. This sub-node contains the
|
||||
value that is being tested. When the ``odd`` filter is used in code such as:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% if my_value is odd %}
|
||||
|
||||
The ``node`` sub-node will contain an expression of ``my_value``. Node-based
|
||||
tests also have access to the ``arguments`` node. This node will contain the
|
||||
various other arguments that have been provided to your test.
|
||||
|
||||
If you want to pass a variable number of positional or named arguments to the
|
||||
test, set the ``is_variadic`` option to ``true``. Tests support dynamic
|
||||
names (see dynamic filters for the syntax).
|
||||
|
||||
Tags
|
||||
----
|
||||
|
||||
One of the most exciting features of a template engine like Twig is the
|
||||
possibility to define new **language constructs**. This is also the most complex
|
||||
feature as you need to understand how Twig's internals work.
|
||||
|
||||
Most of the time though, a tag is not needed:
|
||||
|
||||
* If your tag generates some output, use a **function** instead.
|
||||
|
||||
* If your tag modifies some content and returns it, use a **filter** instead.
|
||||
|
||||
For instance, if you want to create a tag that converts a Markdown formatted
|
||||
text to HTML, create a ``markdown`` filter instead:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ '**markdown** text'|markdown }}
|
||||
|
||||
If you want use this filter on large amounts of text, wrap it with the
|
||||
:doc:`apply <tags/apply>` tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply markdown %}
|
||||
Title
|
||||
=====
|
||||
|
||||
Much better than creating a tag as you can **compose** filters.
|
||||
{% endapply %}
|
||||
|
||||
* If your tag does not output anything, but only exists because of a side
|
||||
effect, create a **function** that returns nothing and call it via the
|
||||
:doc:`filter <tags/do>` tag.
|
||||
|
||||
For instance, if you want to create a tag that logs text, create a ``log``
|
||||
function instead and call it via the :doc:`do <tags/do>` tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% do log('Log some things') %}
|
||||
|
||||
If you still want to create a tag for a new language construct, great!
|
||||
|
||||
Let's create a ``set`` tag that allows the definition of simple variables from
|
||||
within a template. The tag can be used like follows:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set name = "value" %}
|
||||
|
||||
{{ name }}
|
||||
|
||||
{# should output value #}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``set`` tag is part of the Core extension and as such is always
|
||||
available. The built-in version is slightly more powerful and supports
|
||||
multiple assignments by default.
|
||||
|
||||
Three steps are needed to define a new tag:
|
||||
|
||||
* Defining a Token Parser class (responsible for parsing the template code);
|
||||
|
||||
* Defining a Node class (responsible for converting the parsed code to PHP);
|
||||
|
||||
* Registering the tag.
|
||||
|
||||
Registering a new tag
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Add a tag by calling the ``addTokenParser`` method on the ``\Twig\Environment``
|
||||
instance::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->addTokenParser(new Project_Set_TokenParser());
|
||||
|
||||
Defining a Token Parser
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now, let's see the actual code of this class::
|
||||
|
||||
class Project_Set_TokenParser extends \Twig\TokenParser\AbstractTokenParser
|
||||
{
|
||||
public function parse(\Twig\Token $token)
|
||||
{
|
||||
$parser = $this->parser;
|
||||
$stream = $parser->getStream();
|
||||
|
||||
$name = $stream->expect(\Twig\Token::NAME_TYPE)->getValue();
|
||||
$stream->expect(\Twig\Token::OPERATOR_TYPE, '=');
|
||||
$value = $parser->getExpressionParser()->parseExpression();
|
||||
$stream->expect(\Twig\Token::BLOCK_END_TYPE);
|
||||
|
||||
return new Project_Set_Node($name, $value, $token->getLine(), $this->getTag());
|
||||
}
|
||||
|
||||
public function getTag()
|
||||
{
|
||||
return 'set';
|
||||
}
|
||||
}
|
||||
|
||||
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
||||
|
||||
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
||||
tag. It should return a ``\Twig\Node\Node`` instance that represents the node (the
|
||||
``Project_Set_Node`` calls creating is explained in the next section).
|
||||
|
||||
The parsing process is simplified thanks to a bunch of methods you can call
|
||||
from the token stream (``$this->parser->getStream()``):
|
||||
|
||||
* ``getCurrent()``: Gets the current token in the stream.
|
||||
|
||||
* ``next()``: Moves to the next token in the stream, *but returns the old one*.
|
||||
|
||||
* ``test($type)``, ``test($value)`` or ``test($type, $value)``: Determines whether
|
||||
the current token is of a particular type or value (or both). The value may be an
|
||||
array of several possible values.
|
||||
|
||||
* ``expect($type[, $value[, $message]])``: If the current token isn't of the given
|
||||
type/value a syntax error is thrown. Otherwise, if the type and value are correct,
|
||||
the token is returned and the stream moves to the next token.
|
||||
|
||||
* ``look()``: Looks at the next token without consuming it.
|
||||
|
||||
Parsing expressions is done by calling the ``parseExpression()`` like we did for
|
||||
the ``set`` tag.
|
||||
|
||||
.. tip::
|
||||
|
||||
Reading the existing ``TokenParser`` classes is the best way to learn all
|
||||
the nitty-gritty details of the parsing process.
|
||||
|
||||
Defining a Node
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The ``Project_Set_Node`` class itself is quite short::
|
||||
|
||||
class Project_Set_Node extends \Twig\Node\Node
|
||||
{
|
||||
public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $line, $tag = null)
|
||||
{
|
||||
parent::__construct(['value' => $value], ['name' => $name], $line, $tag);
|
||||
}
|
||||
|
||||
public function compile(\Twig\Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write('$context[\''.$this->getAttribute('name').'\'] = ')
|
||||
->subcompile($this->getNode('value'))
|
||||
->raw(";\n")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
The compiler implements a fluid interface and provides methods that helps the
|
||||
developer generate beautiful and readable PHP code:
|
||||
|
||||
* ``subcompile()``: Compiles a node.
|
||||
|
||||
* ``raw()``: Writes the given string as is.
|
||||
|
||||
* ``write()``: Writes the given string by adding indentation at the beginning
|
||||
of each line.
|
||||
|
||||
* ``string()``: Writes a quoted string.
|
||||
|
||||
* ``repr()``: Writes a PHP representation of a given value (see
|
||||
``\Twig\Node\ForNode`` for a usage example).
|
||||
|
||||
* ``addDebugInfo()``: Adds the line of the original template file related to
|
||||
the current node as a comment.
|
||||
|
||||
* ``indent()``: Indents the generated code (see ``\Twig\Node\BlockNode`` for a
|
||||
usage example).
|
||||
|
||||
* ``outdent()``: Outdents the generated code (see ``\Twig\Node\BlockNode`` for a
|
||||
usage example).
|
||||
|
||||
.. _creating_extensions:
|
||||
|
||||
Creating an Extension
|
||||
---------------------
|
||||
|
||||
The main motivation for writing an extension is to move often used code into a
|
||||
reusable class like adding support for internationalization. An extension can
|
||||
define tags, filters, tests, operators, functions, and node visitors.
|
||||
|
||||
Most of the time, it is useful to create a single extension for your project,
|
||||
to host all the specific tags and filters you want to add to Twig.
|
||||
|
||||
.. tip::
|
||||
|
||||
When packaging your code into an extension, Twig is smart enough to
|
||||
recompile your templates whenever you make a change to it (when
|
||||
``auto_reload`` is enabled).
|
||||
|
||||
An extension is a class that implements the following interface::
|
||||
|
||||
interface \Twig\Extension\ExtensionInterface
|
||||
{
|
||||
/**
|
||||
* Returns the token parser instances to add to the existing list.
|
||||
*
|
||||
* @return \Twig\TokenParser\TokenParserInterface[]
|
||||
*/
|
||||
public function getTokenParsers();
|
||||
|
||||
/**
|
||||
* Returns the node visitor instances to add to the existing list.
|
||||
*
|
||||
* @return \Twig\NodeVisitor\NodeVisitorInterface[]
|
||||
*/
|
||||
public function getNodeVisitors();
|
||||
|
||||
/**
|
||||
* Returns a list of filters to add to the existing list.
|
||||
*
|
||||
* @return \Twig\TwigFilter[]
|
||||
*/
|
||||
public function getFilters();
|
||||
|
||||
/**
|
||||
* Returns a list of tests to add to the existing list.
|
||||
*
|
||||
* @return \Twig\TwigTest[]
|
||||
*/
|
||||
public function getTests();
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return \Twig\TwigFunction[]
|
||||
*/
|
||||
public function getFunctions();
|
||||
|
||||
/**
|
||||
* Returns a list of operators to add to the existing list.
|
||||
*
|
||||
* @return array<array> First array of unary operators, second array of binary operators
|
||||
*/
|
||||
public function getOperators();
|
||||
}
|
||||
|
||||
To keep your extension class clean and lean, inherit from the built-in
|
||||
``\Twig\Extension\AbstractExtension`` class instead of implementing the interface as it provides
|
||||
empty implementations for all methods::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
}
|
||||
|
||||
This extension does nothing for now. We will customize it in the next sections.
|
||||
|
||||
You can save your extension anywhere on the filesystem, as all extensions must
|
||||
be registered explicitly to be available in your templates.
|
||||
|
||||
You can register an extension by using the ``addExtension()`` method on your
|
||||
main ``Environment`` object::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->addExtension(new Project_Twig_Extension());
|
||||
|
||||
.. tip::
|
||||
|
||||
The Twig core extensions are great examples of how extensions work.
|
||||
|
||||
Globals
|
||||
~~~~~~~
|
||||
|
||||
Global variables can be registered in an extension via the ``getGlobals()``
|
||||
method::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension implements \Twig\Extension\GlobalsInterface
|
||||
{
|
||||
public function getGlobals(): array
|
||||
{
|
||||
return [
|
||||
'text' => new Text(),
|
||||
];
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
Functions
|
||||
~~~~~~~~~
|
||||
|
||||
Functions can be registered in an extension via the ``getFunctions()``
|
||||
method::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig\TwigFunction('lipsum', 'generate_lipsum'),
|
||||
];
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
Filters
|
||||
~~~~~~~
|
||||
|
||||
To add a filter to an extension, you need to override the ``getFilters()``
|
||||
method. This method must return an array of filters to add to the Twig
|
||||
environment::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig\TwigFilter('rot13', 'str_rot13'),
|
||||
];
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
Tags
|
||||
~~~~
|
||||
|
||||
Adding a tag in an extension can be done by overriding the
|
||||
``getTokenParsers()`` method. This method must return an array of tags to add
|
||||
to the Twig environment::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return [new Project_Set_TokenParser()];
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
In the above code, we have added a single new tag, defined by the
|
||||
``Project_Set_TokenParser`` class. The ``Project_Set_TokenParser`` class is
|
||||
responsible for parsing the tag and compiling it to PHP.
|
||||
|
||||
Operators
|
||||
~~~~~~~~~
|
||||
|
||||
The ``getOperators()`` methods lets you add new operators. Here is how to add
|
||||
the ``!``, ``||``, and ``&&`` operators::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
public function getOperators()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'!' => ['precedence' => 50, 'class' => \Twig\Node\Expression\Unary\NotUnary::class],
|
||||
],
|
||||
[
|
||||
'||' => ['precedence' => 10, 'class' => \Twig\Node\Expression\Binary\OrBinary::class, 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
|
||||
'&&' => ['precedence' => 15, 'class' => \Twig\Node\Expression\Binary\AndBinary::class, 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
Tests
|
||||
~~~~~
|
||||
|
||||
The ``getTests()`` method lets you add new test functions::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
public function getTests()
|
||||
{
|
||||
return [
|
||||
new \Twig\TwigTest('even', 'twig_test_even'),
|
||||
];
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
Definition vs Runtime
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Twig filters, functions, and tests runtime implementations can be defined as
|
||||
any valid PHP callable:
|
||||
|
||||
* **functions/static methods**: Simple to implement and fast (used by all Twig
|
||||
core extensions); but it is hard for the runtime to depend on external
|
||||
objects;
|
||||
|
||||
* **closures**: Simple to implement;
|
||||
|
||||
* **object methods**: More flexible and required if your runtime code depends
|
||||
on external objects.
|
||||
|
||||
The simplest way to use methods is to define them on the extension itself::
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
private $rot13Provider;
|
||||
|
||||
public function __construct($rot13Provider)
|
||||
{
|
||||
$this->rot13Provider = $rot13Provider;
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig\TwigFunction('rot13', [$this, 'rot13']),
|
||||
];
|
||||
}
|
||||
|
||||
public function rot13($value)
|
||||
{
|
||||
return $this->rot13Provider->rot13($value);
|
||||
}
|
||||
}
|
||||
|
||||
This is very convenient but not recommended as it makes template compilation
|
||||
depend on runtime dependencies even if they are not needed (think for instance
|
||||
as a dependency that connects to a database engine).
|
||||
|
||||
You can decouple the extension definitions from their runtime implementations by
|
||||
registering a ``\Twig\RuntimeLoader\RuntimeLoaderInterface`` instance on the
|
||||
environment that knows how to instantiate such runtime classes (runtime classes
|
||||
must be autoload-able)::
|
||||
|
||||
class RuntimeLoader implements \Twig\RuntimeLoader\RuntimeLoaderInterface
|
||||
{
|
||||
public function load($class)
|
||||
{
|
||||
// implement the logic to create an instance of $class
|
||||
// and inject its dependencies
|
||||
// most of the time, it means using your dependency injection container
|
||||
if ('Project_Twig_RuntimeExtension' === $class) {
|
||||
return new $class(new Rot13Provider());
|
||||
} else {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$twig->addRuntimeLoader(new RuntimeLoader());
|
||||
|
||||
.. note::
|
||||
|
||||
Twig comes with a PSR-11 compatible runtime loader
|
||||
(``\Twig\RuntimeLoader\ContainerRuntimeLoader``).
|
||||
|
||||
It is now possible to move the runtime logic to a new
|
||||
``Project_Twig_RuntimeExtension`` class and use it directly in the extension::
|
||||
|
||||
class Project_Twig_RuntimeExtension
|
||||
{
|
||||
private $rot13Provider;
|
||||
|
||||
public function __construct($rot13Provider)
|
||||
{
|
||||
$this->rot13Provider = $rot13Provider;
|
||||
}
|
||||
|
||||
public function rot13($value)
|
||||
{
|
||||
return $this->rot13Provider->rot13($value);
|
||||
}
|
||||
}
|
||||
|
||||
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig\TwigFunction('rot13', ['Project_Twig_RuntimeExtension', 'rot13']),
|
||||
// or
|
||||
new \Twig\TwigFunction('rot13', 'Project_Twig_RuntimeExtension::rot13'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Testing an Extension
|
||||
--------------------
|
||||
|
||||
Functional Tests
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
You can create functional tests for extensions by creating the following file
|
||||
structure in your test directory::
|
||||
|
||||
Fixtures/
|
||||
filters/
|
||||
foo.test
|
||||
bar.test
|
||||
functions/
|
||||
foo.test
|
||||
bar.test
|
||||
tags/
|
||||
foo.test
|
||||
bar.test
|
||||
IntegrationTest.php
|
||||
|
||||
The ``IntegrationTest.php`` file should look like this::
|
||||
|
||||
use Twig\Test\IntegrationTestCase;
|
||||
|
||||
class Project_Tests_IntegrationTest extends IntegrationTestCase
|
||||
{
|
||||
public function getExtensions()
|
||||
{
|
||||
return [
|
||||
new Project_Twig_Extension1(),
|
||||
new Project_Twig_Extension2(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getFixturesDir()
|
||||
{
|
||||
return __DIR__.'/Fixtures/';
|
||||
}
|
||||
}
|
||||
|
||||
Fixtures examples can be found within the Twig repository
|
||||
`tests/Twig/Fixtures`_ directory.
|
||||
|
||||
Node Tests
|
||||
~~~~~~~~~~
|
||||
|
||||
Testing the node visitors can be complex, so extend your test cases from
|
||||
``\Twig\Test\NodeTestCase``. Examples can be found in the Twig repository
|
||||
`tests/Twig/Node`_ directory.
|
||||
|
||||
.. _`tests/Twig/Fixtures`: https://github.com/twigphp/Twig/tree/3.x/tests/Fixtures
|
||||
.. _`tests/Twig/Node`: https://github.com/twigphp/Twig/tree/3.x/tests/Node
|
583
vendor/twig/twig/doc/api.rst
vendored
Normal file
583
vendor/twig/twig/doc/api.rst
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
Twig for Developers
|
||||
===================
|
||||
|
||||
This chapter describes the API to Twig and not the template language. It will
|
||||
be most useful as reference to those implementing the template interface to
|
||||
the application and not those who are creating Twig templates.
|
||||
|
||||
Basics
|
||||
------
|
||||
|
||||
Twig uses a central object called the **environment** (of class
|
||||
``\Twig\Environment``). Instances of this class are used to store the
|
||||
configuration and extensions, and are used to load templates.
|
||||
|
||||
Most applications create one ``\Twig\Environment`` object on application
|
||||
initialization and use that to load templates. In some cases, it might be useful
|
||||
to have multiple environments side by side, with different configurations.
|
||||
|
||||
The typical way to configure Twig to load templates for an application looks
|
||||
roughly like this::
|
||||
|
||||
require_once '/path/to/vendor/autoload.php';
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
|
||||
$twig = new \Twig\Environment($loader, [
|
||||
'cache' => '/path/to/compilation_cache',
|
||||
]);
|
||||
|
||||
This creates a template environment with a default configuration and a loader
|
||||
that looks up templates in the ``/path/to/templates/`` directory. Different
|
||||
loaders are available and you can also write your own if you want to load
|
||||
templates from a database or other resources.
|
||||
|
||||
.. note::
|
||||
|
||||
Notice that the second argument of the environment is an array of options.
|
||||
The ``cache`` option is a compilation cache directory, where Twig caches
|
||||
the compiled templates to avoid the parsing phase for sub-sequent
|
||||
requests. It is very different from the cache you might want to add for
|
||||
the evaluated templates. For such a need, you can use any available PHP
|
||||
cache library.
|
||||
|
||||
Rendering Templates
|
||||
-------------------
|
||||
|
||||
To load a template from a Twig environment, call the ``load()`` method which
|
||||
returns a ``\Twig\TemplateWrapper`` instance::
|
||||
|
||||
$template = $twig->load('index.html');
|
||||
|
||||
To render the template with some variables, call the ``render()`` method::
|
||||
|
||||
echo $template->render(['the' => 'variables', 'go' => 'here']);
|
||||
|
||||
.. note::
|
||||
|
||||
The ``display()`` method is a shortcut to output the rendered template.
|
||||
|
||||
You can also load and render the template in one fell swoop::
|
||||
|
||||
echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']);
|
||||
|
||||
If a template defines blocks, they can be rendered individually via the
|
||||
``renderBlock()`` call::
|
||||
|
||||
echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
|
||||
|
||||
.. _environment_options:
|
||||
|
||||
Environment Options
|
||||
-------------------
|
||||
|
||||
When creating a new ``\Twig\Environment`` instance, you can pass an array of
|
||||
options as the constructor second argument::
|
||||
|
||||
$twig = new \Twig\Environment($loader, ['debug' => true]);
|
||||
|
||||
The following options are available:
|
||||
|
||||
* ``debug`` *boolean*
|
||||
|
||||
When set to ``true``, the generated templates have a
|
||||
``__toString()`` method that you can use to display the generated nodes
|
||||
(default to ``false``).
|
||||
|
||||
* ``charset`` *string* (defaults to ``utf-8``)
|
||||
|
||||
The charset used by the templates.
|
||||
|
||||
* ``cache`` *string* or ``false``
|
||||
|
||||
An absolute path where to store the compiled templates, or
|
||||
``false`` to disable caching (which is the default).
|
||||
|
||||
* ``auto_reload`` *boolean*
|
||||
|
||||
When developing with Twig, it's useful to recompile the
|
||||
template whenever the source code changes. If you don't provide a value for
|
||||
the ``auto_reload`` option, it will be determined automatically based on the
|
||||
``debug`` value.
|
||||
|
||||
* ``strict_variables`` *boolean*
|
||||
|
||||
If set to ``false``, Twig will silently ignore invalid
|
||||
variables (variables and or attributes/methods that do not exist) and
|
||||
replace them with a ``null`` value. When set to ``true``, Twig throws an
|
||||
exception instead (default to ``false``).
|
||||
|
||||
* ``autoescape`` *string*
|
||||
|
||||
Sets the default auto-escaping strategy (``name``, ``html``, ``js``, ``css``,
|
||||
``url``, ``html_attr``, or a PHP callback that takes the template "filename"
|
||||
and returns the escaping strategy to use -- the callback cannot be a function
|
||||
name to avoid collision with built-in escaping strategies); set it to
|
||||
``false`` to disable auto-escaping. The ``name`` escaping strategy determines
|
||||
the escaping strategy to use for a template based on the template filename
|
||||
extension (this strategy does not incur any overhead at runtime as
|
||||
auto-escaping is done at compilation time.)
|
||||
|
||||
* ``optimizations`` *integer*
|
||||
|
||||
A flag that indicates which optimizations to apply
|
||||
(default to ``-1`` -- all optimizations are enabled; set it to ``0`` to
|
||||
disable).
|
||||
|
||||
Loaders
|
||||
-------
|
||||
|
||||
Loaders are responsible for loading templates from a resource such as the file
|
||||
system.
|
||||
|
||||
Compilation Cache
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
All template loaders can cache the compiled templates on the filesystem for
|
||||
future reuse. It speeds up Twig a lot as templates are only compiled once.
|
||||
|
||||
Built-in Loaders
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Here is a list of the built-in loaders:
|
||||
|
||||
``\Twig\Loader\FilesystemLoader``
|
||||
.................................
|
||||
|
||||
``\Twig\Loader\FilesystemLoader`` loads templates from the file system. This loader
|
||||
can find templates in folders on the file system and is the preferred way to
|
||||
load them::
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader($templateDir);
|
||||
|
||||
It can also look for templates in an array of directories::
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
|
||||
|
||||
With such a configuration, Twig will first look for templates in
|
||||
``$templateDir1`` and if they do not exist, it will fallback to look for them
|
||||
in the ``$templateDir2``.
|
||||
|
||||
You can add or prepend paths via the ``addPath()`` and ``prependPath()``
|
||||
methods::
|
||||
|
||||
$loader->addPath($templateDir3);
|
||||
$loader->prependPath($templateDir4);
|
||||
|
||||
The filesystem loader also supports namespaced templates. This allows to group
|
||||
your templates under different namespaces which have their own template paths.
|
||||
|
||||
When using the ``setPaths()``, ``addPath()``, and ``prependPath()`` methods,
|
||||
specify the namespace as the second argument (when not specified, these
|
||||
methods act on the "main" namespace)::
|
||||
|
||||
$loader->addPath($templateDir, 'admin');
|
||||
|
||||
Namespaced templates can be accessed via the special
|
||||
``@namespace_name/template_path`` notation::
|
||||
|
||||
$twig->render('@admin/index.html', []);
|
||||
|
||||
``\Twig\Loader\FilesystemLoader`` support absolute and relative paths. Using relative
|
||||
paths is preferred as it makes the cache keys independent of the project root
|
||||
directory (for instance, it allows warming the cache from a build server where
|
||||
the directory might be different from the one used on production servers)::
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');
|
||||
|
||||
.. note::
|
||||
|
||||
When not passing the root path as a second argument, Twig uses ``getcwd()``
|
||||
for relative paths.
|
||||
|
||||
``\Twig\Loader\ArrayLoader``
|
||||
............................
|
||||
|
||||
``\Twig\Loader\ArrayLoader`` loads a template from a PHP array. It is passed an
|
||||
array of strings bound to template names::
|
||||
|
||||
$loader = new \Twig\Loader\ArrayLoader([
|
||||
'index.html' => 'Hello {{ name }}!',
|
||||
]);
|
||||
$twig = new \Twig\Environment($loader);
|
||||
|
||||
echo $twig->render('index.html', ['name' => 'Fabien']);
|
||||
|
||||
This loader is very useful for unit testing. It can also be used for small
|
||||
projects where storing all templates in a single PHP file might make sense.
|
||||
|
||||
.. tip::
|
||||
|
||||
When using the ``Array`` loader with a cache mechanism, you should know that
|
||||
a new cache key is generated each time a template content "changes" (the
|
||||
cache key being the source code of the template). If you don't want to see
|
||||
your cache grows out of control, you need to take care of clearing the old
|
||||
cache file by yourself.
|
||||
|
||||
``\Twig\Loader\ChainLoader``
|
||||
............................
|
||||
|
||||
``\Twig\Loader\ChainLoader`` delegates the loading of templates to other loaders::
|
||||
|
||||
$loader1 = new \Twig\Loader\ArrayLoader([
|
||||
'base.html' => '{% block content %}{% endblock %}',
|
||||
]);
|
||||
$loader2 = new \Twig\Loader\ArrayLoader([
|
||||
'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
|
||||
'base.html' => 'Will never be loaded',
|
||||
]);
|
||||
|
||||
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
|
||||
When looking for a template, Twig tries each loader in turn and returns as soon
|
||||
as the template is found. When rendering the ``index.html`` template from the
|
||||
above example, Twig will load it with ``$loader2`` but the ``base.html``
|
||||
template will be loaded from ``$loader1``.
|
||||
|
||||
.. note::
|
||||
|
||||
You can also add loaders via the ``addLoader()`` method.
|
||||
|
||||
Create your own Loader
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All loaders implement the ``\Twig\Loader\LoaderInterface``::
|
||||
|
||||
interface \Twig\Loader\LoaderInterface
|
||||
{
|
||||
/**
|
||||
* Returns the source context for a given template logical name.
|
||||
*
|
||||
* @param string $name The template logical name
|
||||
*
|
||||
* @return \Twig\Source
|
||||
*
|
||||
* @throws \Twig\Error\LoaderError When $name is not found
|
||||
*/
|
||||
public function getSourceContext($name);
|
||||
|
||||
/**
|
||||
* Gets the cache key to use for the cache for a given template name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The cache key
|
||||
*
|
||||
* @throws \Twig\Error\LoaderError When $name is not found
|
||||
*/
|
||||
public function getCacheKey($name);
|
||||
|
||||
/**
|
||||
* Returns true if the template is still fresh.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param timestamp $time The last modification time of the cached template
|
||||
*
|
||||
* @return bool true if the template is fresh, false otherwise
|
||||
*
|
||||
* @throws \Twig\Error\LoaderError When $name is not found
|
||||
*/
|
||||
public function isFresh($name, $time);
|
||||
|
||||
/**
|
||||
* Check if we have the source code of a template, given its name.
|
||||
*
|
||||
* @param string $name The name of the template to check if we can load
|
||||
*
|
||||
* @return bool If the template source code is handled by this loader or not
|
||||
*/
|
||||
public function exists($name);
|
||||
}
|
||||
|
||||
The ``isFresh()`` method must return ``true`` if the current cached template
|
||||
is still fresh, given the last modification time, or ``false`` otherwise.
|
||||
|
||||
The ``getSourceContext()`` method must return an instance of ``\Twig\Source``.
|
||||
|
||||
Using Extensions
|
||||
----------------
|
||||
|
||||
Twig extensions are packages that add new features to Twig. Register an
|
||||
extension via the ``addExtension()`` method::
|
||||
|
||||
$twig->addExtension(new \Twig\Extension\SandboxExtension());
|
||||
|
||||
Twig comes bundled with the following extensions:
|
||||
|
||||
* *Twig\Extension\CoreExtension*: Defines all the core features of Twig.
|
||||
|
||||
* *Twig\Extension\DebugExtension*: Defines the ``dump`` function to help debug
|
||||
template variables.
|
||||
|
||||
* *Twig\Extension\EscaperExtension*: Adds automatic output-escaping and the
|
||||
possibility to escape/unescape blocks of code.
|
||||
|
||||
* *Twig\Extension\SandboxExtension*: Adds a sandbox mode to the default Twig
|
||||
environment, making it safe to evaluate untrusted code.
|
||||
|
||||
* *Twig\Extension\ProfilerExtension*: Enables the built-in Twig profiler.
|
||||
|
||||
* *Twig\Extension\OptimizerExtension*: Optimizes the node tree before
|
||||
compilation.
|
||||
|
||||
* *Twig\Extension\StringLoaderExtension*: Defines the ``template_from_string``
|
||||
function to allow loading templates from string in a template.
|
||||
|
||||
The Core, Escaper, and Optimizer extensions are registered by default.
|
||||
|
||||
Built-in Extensions
|
||||
-------------------
|
||||
|
||||
This section describes the features added by the built-in extensions.
|
||||
|
||||
.. tip::
|
||||
|
||||
Read the chapter about :doc:`extending Twig <advanced>` to learn how to
|
||||
create your own extensions.
|
||||
|
||||
Core Extension
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The ``core`` extension defines all the core features of Twig:
|
||||
|
||||
* :doc:`Tags <tags/index>`;
|
||||
* :doc:`Filters <filters/index>`;
|
||||
* :doc:`Functions <functions/index>`;
|
||||
* :doc:`Tests <tests/index>`.
|
||||
|
||||
Escaper Extension
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``escaper`` extension adds automatic output escaping to Twig. It defines a
|
||||
tag, ``autoescape``, and a filter, ``raw``.
|
||||
|
||||
When creating the escaper extension, you can switch on or off the global
|
||||
output escaping strategy::
|
||||
|
||||
$escaper = new \Twig\Extension\EscaperExtension('html');
|
||||
$twig->addExtension($escaper);
|
||||
|
||||
If set to ``html``, all variables in templates are escaped (using the ``html``
|
||||
escaping strategy), except those using the ``raw`` filter:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ article.to_html|raw }}
|
||||
|
||||
You can also change the escaping mode locally by using the ``autoescape`` tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% autoescape 'html' %}
|
||||
{{ var }}
|
||||
{{ var|raw }} {# var won't be escaped #}
|
||||
{{ var|escape }} {# var won't be double-escaped #}
|
||||
{% endautoescape %}
|
||||
|
||||
.. warning::
|
||||
|
||||
The ``autoescape`` tag has no effect on included files.
|
||||
|
||||
The escaping rules are implemented as follows:
|
||||
|
||||
* Literals (integers, booleans, arrays, ...) used in the template directly as
|
||||
variables or filter arguments are never automatically escaped:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{{ "Twig<br/>" }} {# won't be escaped #}
|
||||
|
||||
{% set text = "Twig<br/>" %}
|
||||
{{ text }} {# will be escaped #}
|
||||
|
||||
* Expressions which the result is a literal or a variable marked safe
|
||||
are never automatically escaped:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{{ foo ? "Twig<br/>" : "<br/>Twig" }} {# won't be escaped #}
|
||||
|
||||
{% set text = "Twig<br/>" %}
|
||||
{{ true ? text : "<br/>Twig" }} {# will be escaped #}
|
||||
{{ false ? text : "<br/>Twig" }} {# won't be escaped #}
|
||||
|
||||
{% set text = "Twig<br/>" %}
|
||||
{{ foo ? text|raw : "<br/>Twig" }} {# won't be escaped #}
|
||||
|
||||
* Objects with a ``__toString`` method are converted to strings and
|
||||
escaped. You can mark some classes and/or interfaces as being safe for some
|
||||
strategies via ``EscaperExtension::addSafeClass()``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
// mark object of class Foo as safe for the HTML strategy
|
||||
$escaper->addSafeClass('Foo', ['html']);
|
||||
|
||||
// mark object of interface Foo as safe for the HTML strategy
|
||||
$escaper->addSafeClass('FooInterface', ['html']);
|
||||
|
||||
// mark object of class Foo as safe for the HTML and JS strategies
|
||||
$escaper->addSafeClass('Foo', ['html', 'js']);
|
||||
|
||||
// mark object of class Foo as safe for all strategies
|
||||
$escaper->addSafeClass('Foo', ['all']);
|
||||
|
||||
* Escaping is applied before printing, after any other filter is applied:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ var|upper }} {# is equivalent to {{ var|upper|escape }} #}
|
||||
|
||||
* The `raw` filter should only be used at the end of the filter chain:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ var|raw|upper }} {# will be escaped #}
|
||||
|
||||
{{ var|upper|raw }} {# won't be escaped #}
|
||||
|
||||
* Automatic escaping is not applied if the last filter in the chain is marked
|
||||
safe for the current context (e.g. ``html`` or ``js``). ``escape`` and
|
||||
``escape('html')`` are marked safe for HTML, ``escape('js')`` is marked
|
||||
safe for JavaScript, ``raw`` is marked safe for everything.
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% autoescape 'js' %}
|
||||
{{ var|escape('html') }} {# will be escaped for HTML and JavaScript #}
|
||||
{{ var }} {# will be escaped for JavaScript #}
|
||||
{{ var|escape('js') }} {# won't be double-escaped #}
|
||||
{% endautoescape %}
|
||||
|
||||
.. note::
|
||||
|
||||
Note that autoescaping has some limitations as escaping is applied on
|
||||
expressions after evaluation. For instance, when working with
|
||||
concatenation, ``{{ foo|raw ~ bar }}`` won't give the expected result as
|
||||
escaping is applied on the result of the concatenation, not on the
|
||||
individual variables (so, the ``raw`` filter won't have any effect here).
|
||||
|
||||
Sandbox Extension
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``sandbox`` extension can be used to evaluate untrusted code. Access to
|
||||
unsafe attributes and methods is prohibited. The sandbox security is managed
|
||||
by a policy instance. By default, Twig comes with one policy class:
|
||||
``\Twig\Sandbox\SecurityPolicy``. This class allows you to white-list some
|
||||
tags, filters, properties, and methods::
|
||||
|
||||
$tags = ['if'];
|
||||
$filters = ['upper'];
|
||||
$methods = [
|
||||
'Article' => ['getTitle', 'getBody'],
|
||||
];
|
||||
$properties = [
|
||||
'Article' => ['title', 'body'],
|
||||
];
|
||||
$functions = ['range'];
|
||||
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
|
||||
|
||||
With the previous configuration, the security policy will only allow usage of
|
||||
the ``if`` tag, and the ``upper`` filter. Moreover, the templates will only be
|
||||
able to call the ``getTitle()`` and ``getBody()`` methods on ``Article``
|
||||
objects, and the ``title`` and ``body`` public properties. Everything else
|
||||
won't be allowed and will generate a ``\Twig\Sandbox\SecurityError`` exception.
|
||||
|
||||
The policy object is the first argument of the sandbox constructor::
|
||||
|
||||
$sandbox = new \Twig\Extension\SandboxExtension($policy);
|
||||
$twig->addExtension($sandbox);
|
||||
|
||||
By default, the sandbox mode is disabled and should be enabled when including
|
||||
untrusted template code by using the ``sandbox`` tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% sandbox %}
|
||||
{% include 'user.html' %}
|
||||
{% endsandbox %}
|
||||
|
||||
You can sandbox all templates by passing ``true`` as the second argument of
|
||||
the extension constructor::
|
||||
|
||||
$sandbox = new \Twig\Extension\SandboxExtension($policy, true);
|
||||
|
||||
Profiler Extension
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``profiler`` extension enables a profiler for Twig templates; it should
|
||||
only be used on your development machines as it adds some overhead::
|
||||
|
||||
$profile = new \Twig\Profiler\Profile();
|
||||
$twig->addExtension(new \Twig\Extension\ProfilerExtension($profile));
|
||||
|
||||
$dumper = new \Twig\Profiler\Dumper\TextDumper();
|
||||
echo $dumper->dump($profile);
|
||||
|
||||
A profile contains information about time and memory consumption for template,
|
||||
block, and macro executions.
|
||||
|
||||
You can also dump the data in a `Blackfire.io <https://blackfire.io/>`_
|
||||
compatible format::
|
||||
|
||||
$dumper = new \Twig\Profiler\Dumper\BlackfireDumper();
|
||||
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
|
||||
|
||||
Upload the profile to visualize it (create a `free account
|
||||
<https://blackfire.io/signup?utm_source=twig&utm_medium=doc&utm_campaign=profiler>`_
|
||||
first):
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
blackfire --slot=7 upload /path/to/profile.prof
|
||||
|
||||
Optimizer Extension
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``optimizer`` extension optimizes the node tree before compilation::
|
||||
|
||||
$twig->addExtension(new \Twig\Extension\OptimizerExtension());
|
||||
|
||||
By default, all optimizations are turned on. You can select the ones you want
|
||||
to enable by passing them to the constructor::
|
||||
|
||||
$optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR);
|
||||
|
||||
$twig->addExtension($optimizer);
|
||||
|
||||
Twig supports the following optimizations:
|
||||
|
||||
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL``, enables all optimizations
|
||||
(this is the default value).
|
||||
|
||||
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE``, disables all optimizations.
|
||||
This reduces the compilation time, but it can increase the execution time
|
||||
and the consumed memory.
|
||||
|
||||
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR``, optimizes the ``for`` tag by
|
||||
removing the ``loop`` variable creation whenever possible.
|
||||
|
||||
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER``, removes the ``raw``
|
||||
filter whenever possible.
|
||||
|
||||
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS``, simplifies the creation
|
||||
and access of variables in the compiled templates whenever possible.
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
Twig can throw exceptions:
|
||||
|
||||
* ``\Twig\Error\Error``: The base exception for all errors.
|
||||
|
||||
* ``\Twig\Error\SyntaxError``: Thrown to tell the user that there is a problem with
|
||||
the template syntax.
|
||||
|
||||
* ``\Twig\Error\RuntimeError``: Thrown when an error occurs at runtime (when a filter
|
||||
does not exist for instance).
|
||||
|
||||
* ``\Twig\Error\LoaderError``: Thrown when an error occurs during template loading.
|
||||
|
||||
* ``\Twig\Sandbox\SecurityError``: Thrown when an unallowed tag, filter, or
|
||||
method is called in a sandboxed template.
|
101
vendor/twig/twig/doc/coding_standards.rst
vendored
Normal file
101
vendor/twig/twig/doc/coding_standards.rst
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
Coding Standards
|
||||
================
|
||||
|
||||
When writing Twig templates, we recommend you to follow these official coding
|
||||
standards:
|
||||
|
||||
* Put one (and only one) space after the start of a delimiter (``{{``, ``{%``,
|
||||
and ``{#``) and before the end of a delimiter (``}}``, ``%}``, and ``#}``):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ foo }}
|
||||
{# comment #}
|
||||
{% if foo %}{% endif %}
|
||||
|
||||
When using the whitespace control character, do not put any spaces between
|
||||
it and the delimiter:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{- foo -}}
|
||||
{#- comment -#}
|
||||
{%- if foo -%}{%- endif -%}
|
||||
|
||||
* Put one (and only one) space before and after the following operators:
|
||||
comparison operators (``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``), math
|
||||
operators (``+``, ``-``, ``/``, ``*``, ``%``, ``//``, ``**``), logic
|
||||
operators (``not``, ``and``, ``or``), ``~``, ``is``, ``in``, and the ternary
|
||||
operator (``?:``):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 1 + 2 }}
|
||||
{{ foo ~ bar }}
|
||||
{{ true ? true : false }}
|
||||
|
||||
* Put one (and only one) space after the ``:`` sign in hashes and ``,`` in
|
||||
arrays and hashes:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3] }}
|
||||
{{ {'foo': 'bar'} }}
|
||||
|
||||
* Do not put any spaces after an opening parenthesis and before a closing
|
||||
parenthesis in expressions:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 1 + (2 * 3) }}
|
||||
|
||||
* Do not put any spaces before and after string delimiters:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'foo' }}
|
||||
{{ "foo" }}
|
||||
|
||||
* Do not put any spaces before and after the following operators: ``|``,
|
||||
``.``, ``..``, ``[]``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ foo|upper|lower }}
|
||||
{{ user.name }}
|
||||
{{ user[name] }}
|
||||
{% for i in 1..12 %}{% endfor %}
|
||||
|
||||
* Do not put any spaces before and after the parenthesis used for filter and
|
||||
function calls:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ foo|default('foo') }}
|
||||
{{ range(1..10) }}
|
||||
|
||||
* Do not put any spaces before and after the opening and the closing of arrays
|
||||
and hashes:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3] }}
|
||||
{{ {'foo': 'bar'} }}
|
||||
|
||||
* Use lower cased and underscored variable names:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set foo = 'foo' %}
|
||||
{% set foo_bar = 'foo' %}
|
||||
|
||||
* Indent your code inside tags (use the same indentation as the one used for
|
||||
the target language of the rendered template):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% block foo %}
|
||||
{% if true %}
|
||||
true
|
||||
{% endif %}
|
||||
{% endblock %}
|
6
vendor/twig/twig/doc/deprecated.rst
vendored
Normal file
6
vendor/twig/twig/doc/deprecated.rst
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
Deprecated Features
|
||||
===================
|
||||
|
||||
This document lists deprecated features in Twig 3.x. Deprecated features are
|
||||
kept for backward compatibility and removed in the next major release (a
|
||||
feature that was deprecated in Twig 3.x is removed in Twig 4.0).
|
18
vendor/twig/twig/doc/filters/abs.rst
vendored
Normal file
18
vendor/twig/twig/doc/filters/abs.rst
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
``abs``
|
||||
=======
|
||||
|
||||
The ``abs`` filter returns the absolute value.
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# number = -5 #}
|
||||
|
||||
{{ number|abs }}
|
||||
|
||||
{# outputs 5 #}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `abs`_ function.
|
||||
|
||||
.. _`abs`: https://www.php.net/abs
|
44
vendor/twig/twig/doc/filters/batch.rst
vendored
Normal file
44
vendor/twig/twig/doc/filters/batch.rst
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
``batch``
|
||||
=========
|
||||
|
||||
The ``batch`` filter "batches" items by returning a list of lists with the
|
||||
given number of items. A second parameter can be provided and used to fill in
|
||||
missing items:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% set items = ['a', 'b', 'c', 'd'] %}
|
||||
|
||||
<table>
|
||||
{% for row in items|batch(3, 'No item') %}
|
||||
<tr>
|
||||
{% for column in row %}
|
||||
<td>{{ column }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
The above example will be rendered as:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>a</td>
|
||||
<td>b</td>
|
||||
<td>c</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>d</td>
|
||||
<td>No item</td>
|
||||
<td>No item</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``size``: The size of the batch; fractional numbers will be rounded up
|
||||
* ``fill``: Used to fill in missing items
|
||||
* ``preserve_keys``: Whether to preserve keys or not
|
11
vendor/twig/twig/doc/filters/capitalize.rst
vendored
Normal file
11
vendor/twig/twig/doc/filters/capitalize.rst
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
``capitalize``
|
||||
==============
|
||||
|
||||
The ``capitalize`` filter capitalizes a value. The first character will be
|
||||
uppercase, all others lowercase:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'my first car'|capitalize }}
|
||||
|
||||
{# outputs 'My first car' #}
|
24
vendor/twig/twig/doc/filters/column.rst
vendored
Normal file
24
vendor/twig/twig/doc/filters/column.rst
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
``column``
|
||||
==========
|
||||
|
||||
The ``column`` filter returns the values from a single column in the input
|
||||
array.
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set items = [{ 'fruit' : 'apple'}, {'fruit' : 'orange' }] %}
|
||||
|
||||
{% set fruits = items|column('fruit') %}
|
||||
|
||||
{# fruits now contains ['apple', 'orange'] #}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `array_column`_ function.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``name``: The column name to extract
|
||||
|
||||
.. _`array_column`: https://www.php.net/array_column
|
22
vendor/twig/twig/doc/filters/convert_encoding.rst
vendored
Normal file
22
vendor/twig/twig/doc/filters/convert_encoding.rst
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
``convert_encoding``
|
||||
====================
|
||||
|
||||
The ``convert_encoding`` filter converts a string from one encoding to
|
||||
another. The first argument is the expected output charset and the second one
|
||||
is the input charset:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
|
||||
|
||||
.. note::
|
||||
|
||||
This filter relies on the `iconv`_ extension.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``to``: The output charset
|
||||
* ``from``: The input charset
|
||||
|
||||
.. _`iconv`: https://www.php.net/iconv
|
44
vendor/twig/twig/doc/filters/country_name.rst
vendored
Normal file
44
vendor/twig/twig/doc/filters/country_name.rst
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
``country_name``
|
||||
================
|
||||
|
||||
The ``country_name`` filter returns the country name given its ISO-3166
|
||||
two-letter code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# France #}
|
||||
{{ 'FR'|country_name }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# États-Unis #}
|
||||
{{ 'US'|country_name('fr') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``country_name`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
47
vendor/twig/twig/doc/filters/currency_name.rst
vendored
Normal file
47
vendor/twig/twig/doc/filters/currency_name.rst
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
``currency_name``
|
||||
=================
|
||||
|
||||
The ``currency_name`` filter returns the currency name given its three-letter
|
||||
code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# Euro #}
|
||||
{{ 'EUR'|currency_name }}
|
||||
|
||||
{# Japanese Yen #}
|
||||
{{ 'JPY'|currency_name }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# yen japonais #}
|
||||
{{ 'JPY'|currency_name('fr_FR') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``currency_name`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
47
vendor/twig/twig/doc/filters/currency_symbol.rst
vendored
Normal file
47
vendor/twig/twig/doc/filters/currency_symbol.rst
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
``currency_symbol``
|
||||
===================
|
||||
|
||||
The ``currency_symbol`` filter returns the currency symbol given its three-letter
|
||||
code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# € #}
|
||||
{{ 'EUR'|currency_symbol }}
|
||||
|
||||
{# ¥ #}
|
||||
{{ 'JPY'|currency_symbol }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# ¥ #}
|
||||
{{ 'JPY'|currency_symbol('fr') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``currency_symbol`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
55
vendor/twig/twig/doc/filters/data_uri.rst
vendored
Normal file
55
vendor/twig/twig/doc/filters/data_uri.rst
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
``data_uri``
|
||||
============
|
||||
|
||||
The ``data_uri`` filter generates a URL using the data scheme as defined in
|
||||
`RFC 2397`_:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{{ image_data|data_uri }}
|
||||
|
||||
{{ source('path_to_image')|data_uri }}
|
||||
|
||||
{# force the mime type, disable the guessing of the mime type #}
|
||||
{{ image_data|data_uri(mime="image/svg") }}
|
||||
|
||||
{# also works with plain text #}
|
||||
{{ '<b>foobar</b>'|data_uri(mime="text/html") }}
|
||||
|
||||
{# add some extra parameters #}
|
||||
{{ '<b>foobar</b>'|data_uri(mime="text/html", parameters={charset: "ascii"}) }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``data_uri`` filter is part of the ``HtmlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/html-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Html\HtmlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new HtmlExtension());
|
||||
|
||||
.. note::
|
||||
|
||||
The filter does not perform any length validation on purpose (limit depends
|
||||
on the usage context), validation should be done before calling this filter.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``mime``: The mime type
|
||||
* ``parameters``: An array of parameters
|
||||
|
||||
.. _RFC 2397: https://tools.ietf.org/html/rfc2397
|
78
vendor/twig/twig/doc/filters/date.rst
vendored
Normal file
78
vendor/twig/twig/doc/filters/date.rst
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
``date``
|
||||
========
|
||||
|
||||
The ``date`` filter formats a date to a given format:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ post.published_at|date("m/d/Y") }}
|
||||
|
||||
The format specifier is the same as supported by `date`_,
|
||||
except when the filtered data is of type `DateInterval`_, when the format must conform to
|
||||
`DateInterval::format`_ instead.
|
||||
|
||||
The ``date`` filter accepts strings (it must be in a format supported by the
|
||||
`strtotime`_ function), `DateTime`_ instances, or `DateInterval`_ instances. For
|
||||
instance, to display the current date, filter the word "now":
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ "now"|date("m/d/Y") }}
|
||||
|
||||
To escape words and characters in the date format use ``\\`` in front of each
|
||||
character:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ post.published_at|date("F jS \\a\\t g:ia") }}
|
||||
|
||||
If the value passed to the ``date`` filter is ``null``, it will return the
|
||||
current date by default. If an empty string is desired instead of the current
|
||||
date, use a ternary operator:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ post.published_at is empty ? "" : post.published_at|date("m/d/Y") }}
|
||||
|
||||
If no format is provided, Twig will use the default one: ``F j, Y H:i``. This
|
||||
default can be changed by calling the ``setDateFormat()`` method on the
|
||||
``core`` extension instance. The first argument is the default format for
|
||||
dates and the second one is the default format for date intervals::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setDateFormat('d/m/Y', '%d days');
|
||||
|
||||
Timezone
|
||||
--------
|
||||
|
||||
By default, the date is displayed by applying the default timezone (the one
|
||||
specified in php.ini or declared in Twig -- see below), but you can override
|
||||
it by explicitly specifying a timezone:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ post.published_at|date("m/d/Y", "Europe/Paris") }}
|
||||
|
||||
If the date is already a DateTime object, and if you want to keep its current
|
||||
timezone, pass ``false`` as the timezone value:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ post.published_at|date("m/d/Y", false) }}
|
||||
|
||||
The default timezone can also be set globally by calling ``setTimezone()``::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setTimezone('Europe/Paris');
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``format``: The date format
|
||||
* ``timezone``: The date timezone
|
||||
|
||||
.. _`strtotime`: https://www.php.net/strtotime
|
||||
.. _`DateTime`: https://www.php.net/DateTime
|
||||
.. _`DateInterval`: https://www.php.net/DateInterval
|
||||
.. _`date`: https://www.php.net/date
|
||||
.. _`DateInterval::format`: https://www.php.net/DateInterval.format
|
20
vendor/twig/twig/doc/filters/date_modify.rst
vendored
Normal file
20
vendor/twig/twig/doc/filters/date_modify.rst
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
``date_modify``
|
||||
===============
|
||||
|
||||
The ``date_modify`` filter modifies a date with a given modifier string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ post.published_at|date_modify("+1 day")|date("m/d/Y") }}
|
||||
|
||||
The ``date_modify`` filter accepts strings (it must be in a format supported
|
||||
by the `strtotime`_ function) or `DateTime`_ instances. You can combine
|
||||
it with the :doc:`date<date>` filter for formatting.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``modifier``: The modifier
|
||||
|
||||
.. _`strtotime`: https://www.php.net/strtotime
|
||||
.. _`DateTime`: https://www.php.net/DateTime
|
42
vendor/twig/twig/doc/filters/default.rst
vendored
Normal file
42
vendor/twig/twig/doc/filters/default.rst
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
``default``
|
||||
===========
|
||||
|
||||
The ``default`` filter returns the passed default value if the value is
|
||||
undefined or empty, otherwise the value of the variable:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ var|default('var is not defined') }}
|
||||
|
||||
{{ var.foo|default('foo item on var is not defined') }}
|
||||
|
||||
{{ var['foo']|default('foo item on var is not defined') }}
|
||||
|
||||
{{ ''|default('passed var is empty') }}
|
||||
|
||||
When using the ``default`` filter on an expression that uses variables in some
|
||||
method calls, be sure to use the ``default`` filter whenever a variable can be
|
||||
undefined:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ var.method(foo|default('foo'))|default('foo') }}
|
||||
|
||||
Using the ``default`` filter on a boolean variable might trigger unexpected behavior, as
|
||||
``false`` is treated as an empty value. Consider using ``??`` instead:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set foo = false %}
|
||||
{{ foo|default(true) }} {# true #}
|
||||
{{ foo ?? true }} {# false #}
|
||||
|
||||
.. note::
|
||||
|
||||
Read the documentation for the :doc:`defined<../tests/defined>` and
|
||||
:doc:`empty<../tests/empty>` tests to learn more about their semantics.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``default``: The default value
|
117
vendor/twig/twig/doc/filters/escape.rst
vendored
Normal file
117
vendor/twig/twig/doc/filters/escape.rst
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
``escape``
|
||||
==========
|
||||
|
||||
The ``escape`` filter escapes a string using strategies that depend on the
|
||||
context.
|
||||
|
||||
By default, it uses the HTML escaping strategy:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
<p>
|
||||
{{ user.username|escape }}
|
||||
</p>
|
||||
|
||||
For convenience, the ``e`` filter is defined as an alias:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
<p>
|
||||
{{ user.username|e }}
|
||||
</p>
|
||||
|
||||
The ``escape`` filter can also be used in other contexts than HTML thanks to
|
||||
an optional argument which defines the escaping strategy to use:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ user.username|e }}
|
||||
{# is equivalent to #}
|
||||
{{ user.username|e('html') }}
|
||||
|
||||
And here is how to escape variables included in JavaScript code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ user.username|escape('js') }}
|
||||
{{ user.username|e('js') }}
|
||||
|
||||
The ``escape`` filter supports the following escaping strategies for HTML
|
||||
documents:
|
||||
|
||||
* ``html``: escapes a string for the **HTML body** context.
|
||||
|
||||
* ``js``: escapes a string for the **JavaScript** context.
|
||||
|
||||
* ``css``: escapes a string for the **CSS** context. CSS escaping can be
|
||||
applied to any string being inserted into CSS and escapes everything except
|
||||
alphanumerics.
|
||||
|
||||
* ``url``: escapes a string for the **URI or parameter** contexts. This should
|
||||
not be used to escape an entire URI; only a subcomponent being inserted.
|
||||
|
||||
* ``html_attr``: escapes a string for the **HTML attribute** context.
|
||||
|
||||
Note that doing contextual escaping in HTML documents is hard and choosing the
|
||||
right escaping strategy depends on a lot of factors. Please, read related
|
||||
documentation like `the OWASP prevention cheat sheet
|
||||
<https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md>`_
|
||||
to learn more about this topic.
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, ``escape`` uses the PHP native `htmlspecialchars`_ function
|
||||
for the HTML escaping strategy.
|
||||
|
||||
.. caution::
|
||||
|
||||
When using automatic escaping, Twig tries to not double-escape a variable
|
||||
when the automatic escaping strategy is the same as the one applied by the
|
||||
escape filter; but that does not work when using a variable as the
|
||||
escaping strategy:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set strategy = 'html' %}
|
||||
|
||||
{% autoescape 'html' %}
|
||||
{{ var|escape('html') }} {# won't be double-escaped #}
|
||||
{{ var|escape(strategy) }} {# will be double-escaped #}
|
||||
{% endautoescape %}
|
||||
|
||||
When using a variable as the escaping strategy, you should disable
|
||||
automatic escaping:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set strategy = 'html' %}
|
||||
|
||||
{% autoescape 'html' %}
|
||||
{{ var|escape(strategy)|raw }} {# won't be double-escaped #}
|
||||
{% endautoescape %}
|
||||
|
||||
Custom Escapers
|
||||
---------------
|
||||
|
||||
You can define custom escapers by calling the ``setEscaper()`` method on the
|
||||
escaper extension instance. The first argument is the escaper name (to be
|
||||
used in the ``escape`` call) and the second one must be a valid PHP callable::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->getExtension(\Twig\Extension\EscaperExtension::class)->setEscaper('csv', 'csv_escaper');
|
||||
|
||||
When called by Twig, the callable receives the Twig environment instance, the
|
||||
string to escape, and the charset.
|
||||
|
||||
.. note::
|
||||
|
||||
Built-in escapers cannot be overridden mainly because they should be
|
||||
considered as the final implementation and also for better performance.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``strategy``: The escaping strategy
|
||||
* ``charset``: The string charset
|
||||
|
||||
.. _`htmlspecialchars`: https://www.php.net/htmlspecialchars
|
55
vendor/twig/twig/doc/filters/filter.rst
vendored
Normal file
55
vendor/twig/twig/doc/filters/filter.rst
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
``filter``
|
||||
==========
|
||||
|
||||
The ``filter`` filter filters elements of a sequence or a mapping using an arrow
|
||||
function. The arrow function receives the value of the sequence or mapping:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set sizes = [34, 36, 38, 40, 42] %}
|
||||
|
||||
{{ sizes|filter(v => v > 38)|join(', ') }}
|
||||
{# output 40, 42 #}
|
||||
|
||||
Combined with the ``for`` tag, it allows to filter the items to iterate over:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for v in sizes|filter(v => v > 38) -%}
|
||||
{{ v }}
|
||||
{% endfor %}
|
||||
{# output 40 42 #}
|
||||
|
||||
It also works with mappings:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set sizes = {
|
||||
xs: 34,
|
||||
s: 36,
|
||||
m: 38,
|
||||
l: 40,
|
||||
xl: 42,
|
||||
} %}
|
||||
|
||||
{% for k, v in sizes|filter(v => v > 38) -%}
|
||||
{{ k }} = {{ v }}
|
||||
{% endfor %}
|
||||
{# output l = 40 xl = 42 #}
|
||||
|
||||
The arrow function also receives the key as a second argument:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for k, v in sizes|filter((v, k) => v > 38 and k != "xl") -%}
|
||||
{{ k }} = {{ v }}
|
||||
{% endfor %}
|
||||
{# output l = 40 #}
|
||||
|
||||
Note that the arrow function has access to the current context.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``array``: The sequence or mapping
|
||||
* ``arrow``: The arrow function
|
22
vendor/twig/twig/doc/filters/first.rst
vendored
Normal file
22
vendor/twig/twig/doc/filters/first.rst
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
``first``
|
||||
=========
|
||||
|
||||
The ``first`` filter returns the first "element" of a sequence, a mapping, or
|
||||
a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3, 4]|first }}
|
||||
{# outputs 1 #}
|
||||
|
||||
{{ { a: 1, b: 2, c: 3, d: 4 }|first }}
|
||||
{# outputs 1 #}
|
||||
|
||||
{{ '1234'|first }}
|
||||
{# outputs 1 #}
|
||||
|
||||
.. note::
|
||||
|
||||
It also works with objects implementing the `Traversable`_ interface.
|
||||
|
||||
.. _`Traversable`: https://www.php.net/manual/en/class.traversable.php
|
18
vendor/twig/twig/doc/filters/format.rst
vendored
Normal file
18
vendor/twig/twig/doc/filters/format.rst
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
``format``
|
||||
==========
|
||||
|
||||
The ``format`` filter formats a given string by replacing the placeholders
|
||||
(placeholders follows the `sprintf`_ notation):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ "I like %s and %s."|format(foo, "bar") }}
|
||||
|
||||
{# outputs I like foo and bar
|
||||
if the foo parameter equals to the foo string. #}
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`replace<replace>`
|
||||
|
||||
.. _`sprintf`: https://www.php.net/sprintf
|
77
vendor/twig/twig/doc/filters/format_currency.rst
vendored
Normal file
77
vendor/twig/twig/doc/filters/format_currency.rst
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
``format_currency``
|
||||
===================
|
||||
|
||||
The ``format_currency`` filter formats a number as a currency:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# €1,000,000.00 #}
|
||||
{{ '1000000'|format_currency('EUR') }}
|
||||
|
||||
You can pass attributes to tweak the output:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# €12.34 #}
|
||||
{{ '12.345'|format_currency('EUR', {rounding_mode: 'floor'}) }}
|
||||
|
||||
{# €1,000,000.0000 #}
|
||||
{{ '1000000'|format_currency('EUR', {fraction_digit: 4}) }}
|
||||
|
||||
The list of supported options:
|
||||
|
||||
* ``grouping_used``;
|
||||
* ``decimal_always_shown``;
|
||||
* ``max_integer_digit``;
|
||||
* ``min_integer_digit``;
|
||||
* ``integer_digit``;
|
||||
* ``max_fraction_digit``;
|
||||
* ``min_fraction_digit``;
|
||||
* ``fraction_digit``;
|
||||
* ``multiplier``;
|
||||
* ``grouping_size``;
|
||||
* ``rounding_mode``;
|
||||
* ``rounding_increment``;
|
||||
* ``format_width``;
|
||||
* ``padding_position``;
|
||||
* ``secondary_grouping_size``;
|
||||
* ``significant_digits_used``;
|
||||
* ``min_significant_digits_used``;
|
||||
* ``max_significant_digits_used``;
|
||||
* ``lenient_parse``.
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 1.000.000,00 € #}
|
||||
{{ '1000000'|format_currency('EUR', locale='de') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``format_currency`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``currency``: The currency
|
||||
* ``attrs``: A map of attributes
|
||||
* ``locale``: The locale
|
36
vendor/twig/twig/doc/filters/format_date.rst
vendored
Normal file
36
vendor/twig/twig/doc/filters/format_date.rst
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
``format_date``
|
||||
===============
|
||||
|
||||
The ``format_date`` filter formats a date. It behaves in the exact same way as
|
||||
the :doc:`format_datetime<format_datetime>` filter, but without the time.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``format_date`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
||||
* ``dateFormat``: The date format
|
||||
* ``pattern``: A date time pattern
|
||||
* ``timezone``: The date timezone
|
||||
* ``calendar``: The calendar (Gregorian by default)
|
73
vendor/twig/twig/doc/filters/format_datetime.rst
vendored
Normal file
73
vendor/twig/twig/doc/filters/format_datetime.rst
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
``format_datetime``
|
||||
===================
|
||||
|
||||
The ``format_datetime`` filter formats a date time:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# Aug 7, 2019, 11:39:12 PM #}
|
||||
{{ '2019-08-07 23:39:12'|format_datetime() }}
|
||||
|
||||
You can tweak the output for the date part and the time part:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 23:39 #}
|
||||
{{ '2019-08-07 23:39:12'|format_datetime('none', 'short', locale='fr') }}
|
||||
|
||||
{# 07/08/2019 #}
|
||||
{{ '2019-08-07 23:39:12'|format_datetime('short', 'none', locale='fr') }}
|
||||
|
||||
{# mercredi 7 août 2019 23:39:12 UTC #}
|
||||
{{ '2019-08-07 23:39:12'|format_datetime('full', 'full', locale='fr') }}
|
||||
|
||||
Supported values are: ``none``, ``short``, ``medium``, ``long``, and ``full``.
|
||||
|
||||
For greater flexiblity, you can even define your own pattern (see the `ICU user
|
||||
guide
|
||||
<https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax>`_
|
||||
for supported patterns).
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 11 oclock PM, GMT #}
|
||||
{{ '2019-08-07 23:39:12'|format_datetime(pattern="hh 'oclock' a, zzzz") }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 7 août 2019 23:39:12 #}
|
||||
{{ '2019-08-07 23:39:12'|format_datetime(locale='fr') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``format_datetime`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
||||
* ``dateFormat``: The date format
|
||||
* ``timeFormat``: The time format
|
||||
* ``pattern``: A date time pattern
|
||||
* ``timezone``: The date timezone
|
||||
* ``calendar``: The calendar (Gregorian by default)
|
117
vendor/twig/twig/doc/filters/format_number.rst
vendored
Normal file
117
vendor/twig/twig/doc/filters/format_number.rst
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
``format_number``
|
||||
=================
|
||||
|
||||
The ``format_number`` filter formats a number:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ '12.345'|format_number }}
|
||||
|
||||
You can pass attributes to tweak the output:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 12.34 #}
|
||||
{{ '12.345'|format_number({rounding_mode: 'floor'}) }}
|
||||
|
||||
{# 1000000.0000 #}
|
||||
{{ '1000000'|format_number({fraction_digit: 4}) }}
|
||||
|
||||
The list of supported options:
|
||||
|
||||
* ``grouping_used``;
|
||||
* ``decimal_always_shown``;
|
||||
* ``max_integer_digit``;
|
||||
* ``min_integer_digit``;
|
||||
* ``integer_digit``;
|
||||
* ``max_fraction_digit``;
|
||||
* ``min_fraction_digit``;
|
||||
* ``fraction_digit``;
|
||||
* ``multiplier``;
|
||||
* ``grouping_size``;
|
||||
* ``rounding_mode``;
|
||||
* ``rounding_increment``;
|
||||
* ``format_width``;
|
||||
* ``padding_position``;
|
||||
* ``secondary_grouping_size``;
|
||||
* ``significant_digits_used``;
|
||||
* ``min_significant_digits_used``;
|
||||
* ``max_significant_digits_used``;
|
||||
* ``lenient_parse``.
|
||||
|
||||
Besides plain numbers, the filter can also format numbers in various styles:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 1,234% #}
|
||||
{{ '12.345'|format_number(style='percent') }}
|
||||
|
||||
{# twelve point three four five #}
|
||||
{{ '12.345'|format_number(style='spellout') }}
|
||||
|
||||
{# 12 sec. #}
|
||||
{{ '12'|format_duration_number }}
|
||||
|
||||
The list of supported styles:
|
||||
|
||||
* ``decimal``;
|
||||
* ``currency``;
|
||||
* ``percent``;
|
||||
* ``scientific``;
|
||||
* ``spellout``;
|
||||
* ``ordinal``;
|
||||
* ``duration``.
|
||||
|
||||
As a shortcut, you can use the ``format_*_number`` filters by replacing `*` with
|
||||
a style:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 1,234% #}
|
||||
{{ '12.345'|format_percent_number }}
|
||||
|
||||
{# twelve point three four five #}
|
||||
{{ '12.345'|format_spellout_number }}
|
||||
|
||||
You can pass attributes to tweak the output:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 12.3% #}
|
||||
{{ '0.12345'|format_percent_number({rounding_mode: 'floor', fraction_digit: 1}) }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# 12,345 #}
|
||||
{{ '12.345'|format_number(locale='fr') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``format_number`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
||||
* ``attrs``: A map of attributes
|
||||
* ``style``: The style of the number output
|
36
vendor/twig/twig/doc/filters/format_time.rst
vendored
Normal file
36
vendor/twig/twig/doc/filters/format_time.rst
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
``format_time``
|
||||
===============
|
||||
|
||||
The ``format_time`` filter formats a time. It behaves in the exact same way as
|
||||
the :doc:`format_datetime<format_datetime>` filter, but without the date.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``format_time`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
||||
* ``timeFormat``: The time format
|
||||
* ``pattern``: A date time pattern
|
||||
* ``timezone``: The date timezone
|
||||
* ``calendar``: The calendar (Gregorian by default)
|
77
vendor/twig/twig/doc/filters/html_to_markdown.rst
vendored
Normal file
77
vendor/twig/twig/doc/filters/html_to_markdown.rst
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
``html_to_markdown``
|
||||
====================
|
||||
|
||||
The ``html_to_markdown`` filter converts a block of HTML to Markdown:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply html_to_markdown %}
|
||||
<html>
|
||||
<h1>Hello!</h1>
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
You can also use the filter on an entire template which you ``include``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('some_template.html.twig')|html_to_markdown }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``html_to_markdown`` filter is part of the ``MarkdownExtension`` which
|
||||
is not installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/markdown-extra
|
||||
|
||||
On Symfony projects, you can automatically enable it by installing the
|
||||
``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Or add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Markdown\MarkdownExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new MarkdownExtension());
|
||||
|
||||
If you are not using Symfony, you must also register the extension runtime::
|
||||
|
||||
use Twig\Extra\Markdown\DefaultMarkdown;
|
||||
use Twig\Extra\Markdown\MarkdownRuntime;
|
||||
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
||||
|
||||
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
|
||||
public function load($class) {
|
||||
if (MarkdownRuntime::class === $class) {
|
||||
return new MarkdownRuntime(new DefaultMarkdown());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
``html_to_markdown`` is just a frontend; the actual conversion is done by one of
|
||||
the following compatible libraries, from which you can choose:
|
||||
|
||||
* `league/html-to-markdown`_
|
||||
* `michelf/php-markdown`_
|
||||
* `erusev/parsedown`_
|
||||
|
||||
Depending on the library, you can also add some options by passing them as an argument
|
||||
to the filter. Example for ``league/html-to-markdown``:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply html_to_markdown({hard_break: false}) %}
|
||||
<html>
|
||||
<h1>Hello!</h1>
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
.. _league/html-to-markdown: https://github.com/thephpleague/html-to-markdown
|
||||
.. _michelf/php-markdown: https://github.com/michelf/php-markdown
|
||||
.. _erusev/parsedown: https://github.com/erusev/parsedown
|
60
vendor/twig/twig/doc/filters/index.rst
vendored
Normal file
60
vendor/twig/twig/doc/filters/index.rst
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
Filters
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
abs
|
||||
batch
|
||||
capitalize
|
||||
column
|
||||
convert_encoding
|
||||
country_name
|
||||
currency_name
|
||||
currency_symbol
|
||||
data_uri
|
||||
date
|
||||
date_modify
|
||||
default
|
||||
escape
|
||||
filter
|
||||
first
|
||||
format
|
||||
format_currency
|
||||
format_date
|
||||
format_datetime
|
||||
format_number
|
||||
format_time
|
||||
html_to_markdown
|
||||
inline_css
|
||||
inky_to_html
|
||||
join
|
||||
json_encode
|
||||
keys
|
||||
language_name
|
||||
last
|
||||
length
|
||||
locale_name
|
||||
lower
|
||||
map
|
||||
markdown_to_html
|
||||
merge
|
||||
nl2br
|
||||
number_format
|
||||
raw
|
||||
reduce
|
||||
replace
|
||||
reverse
|
||||
round
|
||||
slice
|
||||
slug
|
||||
sort
|
||||
spaceless
|
||||
split
|
||||
striptags
|
||||
timezone_name
|
||||
title
|
||||
trim
|
||||
u
|
||||
upper
|
||||
url_encode
|
42
vendor/twig/twig/doc/filters/inky_to_html.rst
vendored
Normal file
42
vendor/twig/twig/doc/filters/inky_to_html.rst
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
``inky_to_html``
|
||||
================
|
||||
|
||||
The ``inky_to_html`` filter processes an `inky email template
|
||||
<https://github.com/zurb/inky>`_:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply inky_to_html %}
|
||||
<row>
|
||||
<columns large="6"></columns>
|
||||
<columns large="6"></columns>
|
||||
</row>
|
||||
{% endapply %}
|
||||
|
||||
You can also use the filter on an included file:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('some_template.inky.twig')|inky_to_html }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``inky_to_html`` filter is part of the ``InkyExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/inky-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Inky\InkyExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new InkyExtension());
|
66
vendor/twig/twig/doc/filters/inline_css.rst
vendored
Normal file
66
vendor/twig/twig/doc/filters/inline_css.rst
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
``inline_css``
|
||||
==============
|
||||
|
||||
The ``inline_css`` filter inline CSS styles in HTML documents:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply inline_css %}
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
p { color: red; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello CSS!</p>
|
||||
</body>
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
You can also add some stylesheets by passing them as arguments to the filter:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply inline_css(source("some_styles.css"), source("another.css")) %}
|
||||
<html>
|
||||
<body>
|
||||
<p>Hello CSS!</p>
|
||||
</body>
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
Styles loaded via the filter override the styles defined in the ``<style>`` tag
|
||||
of the HTML document.
|
||||
|
||||
You can also use the filter on an included file:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('some_template.html.twig')|inline_css }}
|
||||
|
||||
{{ include('some_template.html.twig')|inline_css(source("some_styles.css")) }}
|
||||
|
||||
Note that the CSS inliner works on an entire HTML document, not a fragment.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``inline_css`` filter is part of the ``CssInlinerExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/cssinliner-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\CssInliner\CssInlinerExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new CssInlinerExtension());
|
32
vendor/twig/twig/doc/filters/join.rst
vendored
Normal file
32
vendor/twig/twig/doc/filters/join.rst
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
``join``
|
||||
========
|
||||
|
||||
The ``join`` filter returns a string which is the concatenation of the items
|
||||
of a sequence:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3]|join }}
|
||||
{# returns 123 #}
|
||||
|
||||
The separator between elements is an empty string per default, but you can
|
||||
define it with the optional first parameter:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3]|join('|') }}
|
||||
{# outputs 1|2|3 #}
|
||||
|
||||
A second parameter can also be provided that will be the separator used between
|
||||
the last two items of the sequence:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3]|join(', ', ' and ') }}
|
||||
{# outputs 1, 2 and 3 #}
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``glue``: The separator
|
||||
* ``and``: The separator for the last pair of input items
|
23
vendor/twig/twig/doc/filters/json_encode.rst
vendored
Normal file
23
vendor/twig/twig/doc/filters/json_encode.rst
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
``json_encode``
|
||||
===============
|
||||
|
||||
The ``json_encode`` filter returns the JSON representation of a value:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ data|json_encode() }}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `json_encode`_ function.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``options``: A bitmask of `json_encode options`_: ``{{
|
||||
data|json_encode(constant('JSON_PRETTY_PRINT')) }}``.
|
||||
Combine constants using :ref:`bitwise operators<template_logic>`:
|
||||
``{{ data|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_HEX_QUOT')) }}``
|
||||
|
||||
.. _`json_encode`: https://www.php.net/json_encode
|
||||
.. _`json_encode options`: https://www.php.net/manual/en/json.constants.php
|
11
vendor/twig/twig/doc/filters/keys.rst
vendored
Normal file
11
vendor/twig/twig/doc/filters/keys.rst
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
``keys``
|
||||
========
|
||||
|
||||
The ``keys`` filter returns the keys of an array. It is useful when you want to
|
||||
iterate over the keys of an array:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for key in array|keys %}
|
||||
...
|
||||
{% endfor %}
|
47
vendor/twig/twig/doc/filters/language_name.rst
vendored
Normal file
47
vendor/twig/twig/doc/filters/language_name.rst
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
``language_name``
|
||||
=================
|
||||
|
||||
The ``language_name`` filter returns the language name given its two-letter
|
||||
code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# German #}
|
||||
{{ 'de'|language_name }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# allemand #}
|
||||
{{ 'de'|language_name('fr') }}
|
||||
|
||||
{# français canadien #}
|
||||
{{ 'fr_CA'|language_name('fr_FR') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``language_name`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
22
vendor/twig/twig/doc/filters/last.rst
vendored
Normal file
22
vendor/twig/twig/doc/filters/last.rst
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
``last``
|
||||
========
|
||||
|
||||
The ``last`` filter returns the last "element" of a sequence, a mapping, or
|
||||
a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ [1, 2, 3, 4]|last }}
|
||||
{# outputs 4 #}
|
||||
|
||||
{{ { a: 1, b: 2, c: 3, d: 4 }|last }}
|
||||
{# outputs 4 #}
|
||||
|
||||
{{ '1234'|last }}
|
||||
{# outputs 4 #}
|
||||
|
||||
.. note::
|
||||
|
||||
It also works with objects implementing the `Traversable`_ interface.
|
||||
|
||||
.. _`Traversable`: https://www.php.net/manual/en/class.traversable.php
|
19
vendor/twig/twig/doc/filters/length.rst
vendored
Normal file
19
vendor/twig/twig/doc/filters/length.rst
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
``length``
|
||||
==========
|
||||
|
||||
The ``length`` filter returns the number of items of a sequence or mapping, or
|
||||
the length of a string.
|
||||
|
||||
For objects that implement the ``Countable`` interface, ``length`` will use the
|
||||
return value of the ``count()`` method.
|
||||
|
||||
For objects that implement the ``__toString()`` magic method (and not ``Countable``),
|
||||
it will return the length of the string provided by that method.
|
||||
|
||||
For objects that implement the ``Traversable`` interface, ``length`` will use the return value of the ``iterator_count()`` method.
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% if users|length > 10 %}
|
||||
...
|
||||
{% endif %}
|
47
vendor/twig/twig/doc/filters/locale_name.rst
vendored
Normal file
47
vendor/twig/twig/doc/filters/locale_name.rst
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
``locale_name``
|
||||
===============
|
||||
|
||||
The ``locale_name`` filter returns the locale name given its two-letter
|
||||
code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# German #}
|
||||
{{ 'de'|locale_name }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# allemand #}
|
||||
{{ 'de'|locale_name('fr') }}
|
||||
|
||||
{# français (Canada) #}
|
||||
{{ 'fr_CA'|locale_name('fr_FR') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``locale_name`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
10
vendor/twig/twig/doc/filters/lower.rst
vendored
Normal file
10
vendor/twig/twig/doc/filters/lower.rst
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
``lower``
|
||||
=========
|
||||
|
||||
The ``lower`` filter converts a value to lowercase:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'WELCOME'|lower }}
|
||||
|
||||
{# outputs 'welcome' #}
|
34
vendor/twig/twig/doc/filters/map.rst
vendored
Normal file
34
vendor/twig/twig/doc/filters/map.rst
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
``map``
|
||||
=======
|
||||
|
||||
The ``map`` filter applies an arrow function to the elements of a sequence or a
|
||||
mapping. The arrow function receives the value of the sequence or mapping:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set people = [
|
||||
{first: "Bob", last: "Smith"},
|
||||
{first: "Alice", last: "Dupond"},
|
||||
] %}
|
||||
|
||||
{{ people|map(p => "#{p.first} #{p.last}")|join(', ') }}
|
||||
{# outputs Bob Smith, Alice Dupond #}
|
||||
|
||||
The arrow function also receives the key as a second argument:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set people = {
|
||||
"Bob": "Smith",
|
||||
"Alice": "Dupond",
|
||||
} %}
|
||||
|
||||
{{ people|map((last, first) => "#{first} #{last}")|join(', ') }}
|
||||
{# outputs Bob Smith, Alice Dupond #}
|
||||
|
||||
Note that the arrow function has access to the current context.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``arrow``: The arrow function
|
72
vendor/twig/twig/doc/filters/markdown_to_html.rst
vendored
Normal file
72
vendor/twig/twig/doc/filters/markdown_to_html.rst
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
``markdown_to_html``
|
||||
====================
|
||||
|
||||
The ``markdown_to_html`` filter converts a block of Markdown to HTML:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply markdown_to_html %}
|
||||
Title
|
||||
======
|
||||
|
||||
Hello!
|
||||
{% endapply %}
|
||||
|
||||
Note that you can indent the Markdown content as leading whitespaces will be
|
||||
removed consistently before conversion:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply markdown_to_html %}
|
||||
Title
|
||||
======
|
||||
|
||||
Hello!
|
||||
{% endapply %}
|
||||
|
||||
You can also use the filter on an included file or a variable:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('some_template.markdown.twig')|markdown_to_html }}
|
||||
|
||||
{{ changelog|markdown_to_html }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``markdown_to_html`` filter is part of the ``MarkdownExtension`` which
|
||||
is not installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/markdown-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Markdown\MarkdownExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new MarkdownExtension());
|
||||
|
||||
If you are not using Symfony, you must also register the extension runtime::
|
||||
|
||||
use Twig\Extra\Markdown\DefaultMarkdown;
|
||||
use Twig\Extra\Markdown\MarkdownRuntime;
|
||||
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
||||
|
||||
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
|
||||
public function load($class) {
|
||||
if (MarkdownRuntime::class === $class) {
|
||||
return new MarkdownRuntime(new DefaultMarkdown());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Afterwards you need to install a markdown library of your choice. Some of them are
|
||||
mentioned in the ``require-dev`` section of the ``twig/markdown-extra`` package.
|
48
vendor/twig/twig/doc/filters/merge.rst
vendored
Normal file
48
vendor/twig/twig/doc/filters/merge.rst
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
``merge``
|
||||
=========
|
||||
|
||||
The ``merge`` filter merges an array with another array:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set values = [1, 2] %}
|
||||
|
||||
{% set values = values|merge(['apple', 'orange']) %}
|
||||
|
||||
{# values now contains [1, 2, 'apple', 'orange'] #}
|
||||
|
||||
New values are added at the end of the existing ones.
|
||||
|
||||
The ``merge`` filter also works on hashes:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}
|
||||
|
||||
{% set items = items|merge({ 'peugeot': 'car', 'renault': 'car' }) %}
|
||||
|
||||
{# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car', 'renault': 'car' } #}
|
||||
|
||||
For hashes, the merging process occurs on the keys: if the key does not
|
||||
already exist, it is added but if the key already exists, its value is
|
||||
overridden.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you want to ensure that some values are defined in an array (by given
|
||||
default values), reverse the two elements in the call:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
|
||||
|
||||
{% set items = { 'apple': 'unknown' }|merge(items) %}
|
||||
|
||||
{# items now contains { 'apple': 'fruit', 'orange': 'fruit' } #}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `array_merge`_ function. It supports
|
||||
Traversable objects by transforming those to arrays.
|
||||
|
||||
.. _`array_merge`: https://www.php.net/array_merge
|
19
vendor/twig/twig/doc/filters/nl2br.rst
vendored
Normal file
19
vendor/twig/twig/doc/filters/nl2br.rst
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
``nl2br``
|
||||
=========
|
||||
|
||||
The ``nl2br`` filter inserts HTML line breaks before all newlines in a string:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{{ "I like Twig.\nYou will like it too."|nl2br }}
|
||||
{# outputs
|
||||
|
||||
I like Twig.<br />
|
||||
You will like it too.
|
||||
|
||||
#}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``nl2br`` filter pre-escapes the input before applying the
|
||||
transformation.
|
51
vendor/twig/twig/doc/filters/number_format.rst
vendored
Normal file
51
vendor/twig/twig/doc/filters/number_format.rst
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
``number_format``
|
||||
=================
|
||||
|
||||
The ``number_format`` filter formats numbers. It is a wrapper around PHP's
|
||||
`number_format`_ function:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 200.35|number_format }}
|
||||
|
||||
You can control the number of decimal places, decimal point, and thousands
|
||||
separator using the additional arguments:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 9800.333|number_format(2, '.', ',') }}
|
||||
|
||||
To format negative numbers or math calculation, wrap the previous statement
|
||||
with parentheses (needed because of Twig's :ref:`precedence of operators
|
||||
<twig-expressions>`):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ -9800.333|number_format(2, '.', ',') }} {# outputs : -9 #}
|
||||
{{ (-9800.333)|number_format(2, '.', ',') }} {# outputs : -9,800.33 #}
|
||||
{{ 1 + 0.2|number_format(2) }} {# outputs : 1.2 #}
|
||||
{{ (1 + 0.2)|number_format(2) }} {# outputs : 1.20 #}
|
||||
|
||||
If no formatting options are provided then Twig will use the default formatting
|
||||
options of:
|
||||
|
||||
* 0 decimal places.
|
||||
* ``.`` as the decimal point.
|
||||
* ``,`` as the thousands separator.
|
||||
|
||||
These defaults can be changed through the core extension::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setNumberFormat(3, '.', ',');
|
||||
|
||||
The defaults set for ``number_format`` can be over-ridden upon each call using the
|
||||
additional parameters.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``decimal``: The number of decimal points to display
|
||||
* ``decimal_point``: The character(s) to use for the decimal point
|
||||
* ``thousand_sep``: The character(s) to use for the thousands separator
|
||||
|
||||
.. _`number_format`: https://www.php.net/number_format
|
12
vendor/twig/twig/doc/filters/raw.rst
vendored
Normal file
12
vendor/twig/twig/doc/filters/raw.rst
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
``raw``
|
||||
=======
|
||||
|
||||
The ``raw`` filter marks the value as being "safe", which means that in an
|
||||
environment with automatic escaping enabled this variable will not be escaped
|
||||
if ``raw`` is the last filter applied to it:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% autoescape %}
|
||||
{{ var|raw }} {# var won't be escaped #}
|
||||
{% endautoescape %}
|
29
vendor/twig/twig/doc/filters/reduce.rst
vendored
Normal file
29
vendor/twig/twig/doc/filters/reduce.rst
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
``reduce``
|
||||
==========
|
||||
|
||||
The ``reduce`` filter iteratively reduces a sequence or a mapping to a single
|
||||
value using an arrow function, so as to reduce it to a single value. The arrow
|
||||
function receives the return value of the previous iteration and the current
|
||||
value of the sequence or mapping:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set numbers = [1, 2, 3] %}
|
||||
|
||||
{{ numbers|reduce((carry, v) => carry + v) }}
|
||||
{# output 6 #}
|
||||
|
||||
The ``reduce`` filter takes an ``initial`` value as a second argument:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ numbers|reduce((carry, v) => carry + v, 10) }}
|
||||
{# output 16 #}
|
||||
|
||||
Note that the arrow function has access to the current context.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``arrow``: The arrow function
|
||||
* ``initial``: The initial value
|
27
vendor/twig/twig/doc/filters/replace.rst
vendored
Normal file
27
vendor/twig/twig/doc/filters/replace.rst
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
``replace``
|
||||
===========
|
||||
|
||||
The ``replace`` filter formats a given string by replacing the placeholders
|
||||
(placeholders are free-form):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ "I like %this% and %that%."|replace({'%this%': foo, '%that%': "bar"}) }}
|
||||
|
||||
{# outputs I like foo and bar
|
||||
if the foo parameter equals to the foo string. #}
|
||||
|
||||
{# using % as a delimiter is purely conventional and optional #}
|
||||
|
||||
{{ "I like this and --that--."|replace({'this': foo, '--that--': "bar"}) }}
|
||||
|
||||
{# outputs I like foo and bar #}
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``from``: The placeholder values
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`format<format>`
|
44
vendor/twig/twig/doc/filters/reverse.rst
vendored
Normal file
44
vendor/twig/twig/doc/filters/reverse.rst
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
``reverse``
|
||||
===========
|
||||
|
||||
The ``reverse`` filter reverses a sequence, a mapping, or a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for user in users|reverse %}
|
||||
...
|
||||
{% endfor %}
|
||||
|
||||
{{ '1234'|reverse }}
|
||||
|
||||
{# outputs 4321 #}
|
||||
|
||||
.. tip::
|
||||
|
||||
For sequences and mappings, numeric keys are not preserved. To reverse
|
||||
them as well, pass ``true`` as an argument to the ``reverse`` filter:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for key, value in {1: "a", 2: "b", 3: "c"}|reverse %}
|
||||
{{ key }}: {{ value }}
|
||||
{%- endfor %}
|
||||
|
||||
{# output: 0: c 1: b 2: a #}
|
||||
|
||||
{% for key, value in {1: "a", 2: "b", 3: "c"}|reverse(true) %}
|
||||
{{ key }}: {{ value }}
|
||||
{%- endfor %}
|
||||
|
||||
{# output: 3: c 2: b 1: a #}
|
||||
|
||||
.. note::
|
||||
|
||||
It also works with objects implementing the `Traversable`_ interface.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``preserve_keys``: Preserve keys when reversing a mapping or a sequence.
|
||||
|
||||
.. _`Traversable`: https://www.php.net/Traversable
|
34
vendor/twig/twig/doc/filters/round.rst
vendored
Normal file
34
vendor/twig/twig/doc/filters/round.rst
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
``round``
|
||||
=========
|
||||
|
||||
The ``round`` filter rounds a number to a given precision:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 42.55|round }}
|
||||
{# outputs 43 #}
|
||||
|
||||
{{ 42.55|round(1, 'floor') }}
|
||||
{# outputs 42.5 #}
|
||||
|
||||
The ``round`` filter takes two optional arguments; the first one specifies the
|
||||
precision (default is ``0``) and the second the rounding method (default is
|
||||
``common``):
|
||||
|
||||
* ``common`` rounds either up or down (rounds the value up to precision decimal
|
||||
places away from zero, when it is half way there -- making 1.5 into 2 and
|
||||
-1.5 into -2);
|
||||
|
||||
* ``ceil`` always rounds up;
|
||||
|
||||
* ``floor`` always rounds down.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``//`` operator is equivalent to ``|round(0, 'floor')``.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``precision``: The rounding precision
|
||||
* ``method``: The rounding method
|
68
vendor/twig/twig/doc/filters/slice.rst
vendored
Normal file
68
vendor/twig/twig/doc/filters/slice.rst
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
``slice``
|
||||
===========
|
||||
|
||||
The ``slice`` filter extracts a slice of a sequence, a mapping, or a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in [1, 2, 3, 4, 5]|slice(1, 2) %}
|
||||
{# will iterate over 2 and 3 #}
|
||||
{% endfor %}
|
||||
|
||||
{{ '12345'|slice(1, 2) }}
|
||||
|
||||
{# outputs 23 #}
|
||||
|
||||
You can use any valid expression for both the start and the length:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in [1, 2, 3, 4, 5]|slice(start, length) %}
|
||||
{# ... #}
|
||||
{% endfor %}
|
||||
|
||||
As syntactic sugar, you can also use the ``[]`` notation:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in [1, 2, 3, 4, 5][start:length] %}
|
||||
{# ... #}
|
||||
{% endfor %}
|
||||
|
||||
{{ '12345'[1:2] }} {# will display "23" #}
|
||||
|
||||
{# you can omit the first argument -- which is the same as 0 #}
|
||||
{{ '12345'[:2] }} {# will display "12" #}
|
||||
|
||||
{# you can omit the last argument -- which will select everything till the end #}
|
||||
{{ '12345'[2:] }} {# will display "345" #}
|
||||
|
||||
The ``slice`` filter works as the `array_slice`_ PHP function for arrays and
|
||||
`mb_substr`_ for strings with a fallback to `substr`_.
|
||||
|
||||
If the start is non-negative, the sequence will start at that start in the
|
||||
variable. If start is negative, the sequence will start that far from the end
|
||||
of the variable.
|
||||
|
||||
If length is given and is positive, then the sequence will have up to that
|
||||
many elements in it. If the variable is shorter than the length, then only the
|
||||
available variable elements will be present. If length is given and is
|
||||
negative then the sequence will stop that many elements from the end of the
|
||||
variable. If it is omitted, then the sequence will have everything from offset
|
||||
up until the end of the variable.
|
||||
|
||||
.. note::
|
||||
|
||||
It also works with objects implementing the `Traversable`_ interface.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``start``: The start of the slice
|
||||
* ``length``: The size of the slice
|
||||
* ``preserve_keys``: Whether to preserve key or not (when the input is an array)
|
||||
|
||||
.. _`Traversable`: https://www.php.net/manual/en/class.traversable.php
|
||||
.. _`array_slice`: https://www.php.net/array_slice
|
||||
.. _`mb_substr`: https://www.php.net/mb-substr
|
||||
.. _`substr`: https://www.php.net/substr
|
59
vendor/twig/twig/doc/filters/slug.rst
vendored
Normal file
59
vendor/twig/twig/doc/filters/slug.rst
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
``slug``
|
||||
========
|
||||
|
||||
The ``slug`` filter transforms a given string into another string that
|
||||
only includes safe ASCII characters.
|
||||
|
||||
Here is an example:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Wôrķšƥáçè ~~sèťtïñğš~~'|slug }}
|
||||
Workspace-settings
|
||||
|
||||
The default separator between words is a dash (``-``), but you can
|
||||
define a selector of your choice by passing it as an argument:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Wôrķšƥáçè ~~sèťtïñğš~~'|slug('/') }}
|
||||
Workspace/settings
|
||||
|
||||
The slugger automatically detects the language of the original
|
||||
string, but you can also specify it explicitly using the second
|
||||
argument:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ '...'|slug('-', 'ko') }}
|
||||
|
||||
The ``slug`` filter uses the method by the same name in Symfony's
|
||||
`AsciiSlugger <https://symfony.com/doc/current/components/string.html#slugger>`_.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``slug`` filter is part of the ``StringExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/string-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\String\StringExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new StringExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``separator``: The separator that is used to join words (defaults to ``-``)
|
||||
* ``locale``: The locale of the original string (if none is specified, it will be automatically detected)
|
42
vendor/twig/twig/doc/filters/sort.rst
vendored
Normal file
42
vendor/twig/twig/doc/filters/sort.rst
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
``sort``
|
||||
========
|
||||
|
||||
The ``sort`` filter sorts an array:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for user in users|sort %}
|
||||
...
|
||||
{% endfor %}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `asort`_ function to maintain index
|
||||
association. It supports Traversable objects by transforming
|
||||
those to arrays.
|
||||
|
||||
You can pass an arrow function to sort the array:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% set fruits = [
|
||||
{ name: 'Apples', quantity: 5 },
|
||||
{ name: 'Oranges', quantity: 2 },
|
||||
{ name: 'Grapes', quantity: 4 },
|
||||
] %}
|
||||
|
||||
{% for fruit in fruits|sort((a, b) => a.quantity <=> b.quantity)|column('name') %}
|
||||
{{ fruit }}
|
||||
{% endfor %}
|
||||
|
||||
{# output in this order: Oranges, Grapes, Apples #}
|
||||
|
||||
Note the usage of the `spaceship`_ operator to simplify the comparison.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``arrow``: An arrow function
|
||||
|
||||
.. _`asort`: https://www.php.net/asort
|
||||
.. _`spaceship`: https://www.php.net/manual/en/language.operators.comparison.php
|
56
vendor/twig/twig/doc/filters/spaceless.rst
vendored
Normal file
56
vendor/twig/twig/doc/filters/spaceless.rst
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
``spaceless``
|
||||
=============
|
||||
|
||||
Use the ``spaceless`` filter to remove whitespace *between HTML tags*, not
|
||||
whitespace within HTML tags or whitespace in plain text:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{{
|
||||
"<div>
|
||||
<strong>foo</strong>
|
||||
</div>
|
||||
"|spaceless }}
|
||||
|
||||
{# output will be <div><strong>foo</strong></div> #}
|
||||
|
||||
You can combine ``spaceless`` with the ``apply`` tag to apply the transformation
|
||||
on large amounts of HTML:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply spaceless %}
|
||||
<div>
|
||||
<strong>foo</strong>
|
||||
</div>
|
||||
{% endapply %}
|
||||
|
||||
{# output will be <div><strong>foo</strong></div> #}
|
||||
|
||||
This tag is not meant to "optimize" the size of the generated HTML content but
|
||||
merely to avoid extra whitespace between HTML tags to avoid browser rendering
|
||||
quirks under some circumstances.
|
||||
|
||||
.. caution::
|
||||
|
||||
As the filter uses a regular expression behind the scenes, its performance
|
||||
is directly related to the text size you are working on (remember that
|
||||
filters are executed at runtime).
|
||||
|
||||
.. tip::
|
||||
|
||||
If you want to optimize the size of the generated HTML content, gzip
|
||||
compress the output instead.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you want to create a tag that actually removes all extra whitespace in
|
||||
an HTML string, be warned that this is not as easy as it seems to be
|
||||
(think of ``textarea`` or ``pre`` tags for instance). Using a third-party
|
||||
library like Tidy is probably a better idea.
|
||||
|
||||
.. tip::
|
||||
|
||||
For more information on whitespace control, read the
|
||||
:ref:`dedicated section <templates-whitespace-control>` of the documentation and learn how
|
||||
you can also use the whitespace control modifier on your tags.
|
50
vendor/twig/twig/doc/filters/split.rst
vendored
Normal file
50
vendor/twig/twig/doc/filters/split.rst
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
``split``
|
||||
=========
|
||||
|
||||
The ``split`` filter splits a string by the given delimiter and returns a list
|
||||
of strings:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set foo = "one,two,three"|split(',') %}
|
||||
{# foo contains ['one', 'two', 'three'] #}
|
||||
|
||||
You can also pass a ``limit`` argument:
|
||||
|
||||
* If ``limit`` is positive, the returned array will contain a maximum of
|
||||
limit elements with the last element containing the rest of string;
|
||||
|
||||
* If ``limit`` is negative, all components except the last -limit are
|
||||
returned;
|
||||
|
||||
* If ``limit`` is zero, then this is treated as 1.
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set foo = "one,two,three,four,five"|split(',', 3) %}
|
||||
{# foo contains ['one', 'two', 'three,four,five'] #}
|
||||
|
||||
If the ``delimiter`` is an empty string, then value will be split by equal
|
||||
chunks. Length is set by the ``limit`` argument (one character by default).
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set foo = "123"|split('') %}
|
||||
{# foo contains ['1', '2', '3'] #}
|
||||
|
||||
{% set bar = "aabbcc"|split('', 2) %}
|
||||
{# bar contains ['aa', 'bb', 'cc'] #}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `explode`_ or `str_split`_ (if delimiter is
|
||||
empty) functions for string splitting.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``delimiter``: The delimiter
|
||||
* ``limit``: The limit argument
|
||||
|
||||
.. _`explode`: https://www.php.net/explode
|
||||
.. _`str_split`: https://www.php.net/str_split
|
29
vendor/twig/twig/doc/filters/striptags.rst
vendored
Normal file
29
vendor/twig/twig/doc/filters/striptags.rst
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
``striptags``
|
||||
=============
|
||||
|
||||
The ``striptags`` filter strips SGML/XML tags and replace adjacent whitespace
|
||||
by one space:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ some_html|striptags }}
|
||||
|
||||
You can also provide tags which should not be stripped:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{{ some_html|striptags('<br><p>') }}
|
||||
|
||||
In this example, the ``<br/>``, ``<br>``, ``<p>``, and ``</p>`` tags won't be
|
||||
removed from the string.
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `strip_tags`_ function.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``allowable_tags``: Tags which should not be stripped
|
||||
|
||||
.. _`strip_tags`: https://www.php.net/strip_tags
|
46
vendor/twig/twig/doc/filters/timezone_name.rst
vendored
Normal file
46
vendor/twig/twig/doc/filters/timezone_name.rst
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
``timezone_name``
|
||||
=================
|
||||
|
||||
The ``timezone_name`` filter returns the timezone name given a timezone identifier:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# Central European Time (Paris) #}
|
||||
{{ 'Europe/Paris'|timezone_name }}
|
||||
|
||||
{# Pacific Time (Los Angeles) #}
|
||||
{{ 'America/Los_Angeles'|timezone_name }}
|
||||
|
||||
By default, the filter uses the current locale. You can pass it explicitly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# heure du Pacifique nord-américain (Los Angeles) #}
|
||||
{{ 'America/Los_Angeles'|timezone_name('fr') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``timezone_name`` filter is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``locale``: The locale
|
11
vendor/twig/twig/doc/filters/title.rst
vendored
Normal file
11
vendor/twig/twig/doc/filters/title.rst
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
``title``
|
||||
=========
|
||||
|
||||
The ``title`` filter returns a titlecased version of the value. Words will
|
||||
start with uppercase letters, all remaining characters are lowercase:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'my first car'|title }}
|
||||
|
||||
{# outputs 'My First Car' #}
|
39
vendor/twig/twig/doc/filters/trim.rst
vendored
Normal file
39
vendor/twig/twig/doc/filters/trim.rst
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
``trim``
|
||||
========
|
||||
|
||||
The ``trim`` filter strips whitespace (or other characters) from the beginning
|
||||
and end of a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ ' I like Twig. '|trim }}
|
||||
|
||||
{# outputs 'I like Twig.' #}
|
||||
|
||||
{{ ' I like Twig.'|trim('.') }}
|
||||
|
||||
{# outputs ' I like Twig' #}
|
||||
|
||||
{{ ' I like Twig. '|trim(side='left') }}
|
||||
|
||||
{# outputs 'I like Twig. ' #}
|
||||
|
||||
{{ ' I like Twig. '|trim(' ', 'right') }}
|
||||
|
||||
{# outputs ' I like Twig.' #}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `trim`_, `ltrim`_, and `rtrim`_ functions.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``character_mask``: The characters to strip
|
||||
|
||||
* ``side``: The default is to strip from the left and the right (`both`) sides, but `left`
|
||||
and `right` will strip from either the left side or right side only
|
||||
|
||||
.. _`trim`: https://www.php.net/trim
|
||||
.. _`ltrim`: https://www.php.net/ltrim
|
||||
.. _`rtrim`: https://www.php.net/rtrim
|
87
vendor/twig/twig/doc/filters/u.rst
vendored
Normal file
87
vendor/twig/twig/doc/filters/u.rst
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
``u``
|
||||
=====
|
||||
|
||||
The ``u`` filter wraps a text in a Unicode object (a `Symfony UnicodeString
|
||||
instance <https://symfony.com/doc/current/components/string.html>`_) that
|
||||
exposes methods to "manipulate" the string.
|
||||
|
||||
Let's see some common use cases.
|
||||
|
||||
Wrapping a text to a given number of characters:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Symfony String + Twig = <3'|u.wordwrap(5) }}
|
||||
Symfony
|
||||
String
|
||||
+
|
||||
Twig
|
||||
= <3
|
||||
|
||||
Truncating a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Lorem ipsum'|u.truncate(8) }}
|
||||
Lorem ip
|
||||
|
||||
{{ 'Lorem ipsum'|u.truncate(8, '...') }}
|
||||
Lorem...
|
||||
|
||||
The ``truncate`` method also accepts a third argument to preserve whole words:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Lorem ipsum dolor'|u.truncate(10, '...', false) }}
|
||||
Lorem ipsum...
|
||||
|
||||
Converting a string to *snake* case or *camelCase*:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'SymfonyStringWithTwig'|u.snake }}
|
||||
symfony_string_with_twig
|
||||
|
||||
{{ 'symfony_string with twig'|u.camel.title }}
|
||||
SymfonyStringWithTwig
|
||||
|
||||
You can also chain methods:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'Symfony String + Twig = <3'|u.wordwrap(5).upper }}
|
||||
SYMFONY
|
||||
STRING
|
||||
+
|
||||
TWIG
|
||||
= <3
|
||||
|
||||
For large strings manipulation, use the ``apply`` tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply u.wordwrap(5) %}
|
||||
Some large amount of text...
|
||||
{% endapply %}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``u`` filter is part of the ``StringExtension`` which is not installed
|
||||
by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/string-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\String\StringExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new StringExtension());
|
10
vendor/twig/twig/doc/filters/upper.rst
vendored
Normal file
10
vendor/twig/twig/doc/filters/upper.rst
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
``upper``
|
||||
=========
|
||||
|
||||
The ``upper`` filter converts a value to uppercase:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ 'welcome'|upper }}
|
||||
|
||||
{# outputs 'WELCOME' #}
|
23
vendor/twig/twig/doc/filters/url_encode.rst
vendored
Normal file
23
vendor/twig/twig/doc/filters/url_encode.rst
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
``url_encode``
|
||||
==============
|
||||
|
||||
The ``url_encode`` filter percent encodes a given string as URL segment
|
||||
or an array as query string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ "path-seg*ment"|url_encode }}
|
||||
{# outputs "path-seg%2Ament" #}
|
||||
|
||||
{{ "string with spaces"|url_encode }}
|
||||
{# outputs "string%20with%20spaces" #}
|
||||
|
||||
{{ {'param': 'value', 'foo': 'bar'}|url_encode }}
|
||||
{# outputs "param=value&foo=bar" #}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `rawurlencode`_ or the `http_build_query`_ function.
|
||||
|
||||
.. _`rawurlencode`: https://www.php.net/rawurlencode
|
||||
.. _`http_build_query`: https://www.php.net/http_build_query
|
23
vendor/twig/twig/doc/functions/attribute.rst
vendored
Normal file
23
vendor/twig/twig/doc/functions/attribute.rst
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
``attribute``
|
||||
=============
|
||||
|
||||
The ``attribute`` function can be used to access a "dynamic" attribute of a
|
||||
variable:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ attribute(object, method) }}
|
||||
{{ attribute(object, method, arguments) }}
|
||||
{{ attribute(array, item) }}
|
||||
|
||||
In addition, the ``defined`` test can check for the existence of a dynamic
|
||||
attribute:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ attribute(object, method) is defined ? 'Method exists' : 'Method does not exist' }}
|
||||
|
||||
.. note::
|
||||
|
||||
The resolution algorithm is the same as the one used for the ``.``
|
||||
notation, except that the item can be any valid expression.
|
37
vendor/twig/twig/doc/functions/block.rst
vendored
Normal file
37
vendor/twig/twig/doc/functions/block.rst
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
``block``
|
||||
=========
|
||||
|
||||
When a template uses inheritance and if you want to print a block multiple
|
||||
times, use the ``block`` function:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
|
||||
<h1>{{ block('title') }}</h1>
|
||||
|
||||
{% block body %}{% endblock %}
|
||||
|
||||
The ``block`` function can also be used to display one block from another
|
||||
template:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ block("title", "common_blocks.twig") }}
|
||||
|
||||
Use the ``defined`` test to check if a block exists in the context of the
|
||||
current template:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% if block("footer") is defined %}
|
||||
...
|
||||
{% endif %}
|
||||
|
||||
{% if block("footer", "common_blocks.twig") is defined %}
|
||||
...
|
||||
{% endif %}
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`
|
23
vendor/twig/twig/doc/functions/constant.rst
vendored
Normal file
23
vendor/twig/twig/doc/functions/constant.rst
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
``constant``
|
||||
============
|
||||
|
||||
``constant`` returns the constant value for a given string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ some_date|date(constant('DATE_W3C')) }}
|
||||
{{ constant('Namespace\\Classname::CONSTANT_NAME') }}
|
||||
|
||||
You can read constants from object instances as well:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ constant('RSS', date) }}
|
||||
|
||||
Use the ``defined`` test to check if a constant is defined:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% if constant('SOME_CONST') is defined %}
|
||||
...
|
||||
{% endif %}
|
32
vendor/twig/twig/doc/functions/country_timezones.rst
vendored
Normal file
32
vendor/twig/twig/doc/functions/country_timezones.rst
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
``country_timezones``
|
||||
=====================
|
||||
|
||||
The ``country_timezones`` function returns the names of the timezones associated
|
||||
with a given country code:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# Europe/Paris #}
|
||||
{{ country_timezones('FR')|join(', ') }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``country_timezones`` function is part of the ``IntlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/intl-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new IntlExtension());
|
28
vendor/twig/twig/doc/functions/cycle.rst
vendored
Normal file
28
vendor/twig/twig/doc/functions/cycle.rst
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
``cycle``
|
||||
=========
|
||||
|
||||
The ``cycle`` function cycles on an array of values:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set start_year = date() | date('Y') %}
|
||||
{% set end_year = start_year + 5 %}
|
||||
|
||||
{% for year in start_year..end_year %}
|
||||
{{ cycle(['odd', 'even'], loop.index0) }}
|
||||
{% endfor %}
|
||||
|
||||
The array can contain any number of values:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set fruits = ['apple', 'orange', 'citrus'] %}
|
||||
|
||||
{% for i in 0..10 %}
|
||||
{{ cycle(fruits, i) }}
|
||||
{% endfor %}
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``position``: The cycle position
|
44
vendor/twig/twig/doc/functions/date.rst
vendored
Normal file
44
vendor/twig/twig/doc/functions/date.rst
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
``date``
|
||||
========
|
||||
|
||||
Converts an argument to a date to allow date comparison:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% if date(user.created_at) < date('-2days') %}
|
||||
{# do something #}
|
||||
{% endif %}
|
||||
|
||||
The argument must be in one of PHP’s supported `date and time formats`_.
|
||||
|
||||
You can pass a timezone as the second argument:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% if date(user.created_at) < date('-2days', 'Europe/Paris') %}
|
||||
{# do something #}
|
||||
{% endif %}
|
||||
|
||||
If no argument is passed, the function returns the current date:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% if date(user.created_at) < date() %}
|
||||
{# always! #}
|
||||
{% endif %}
|
||||
|
||||
.. note::
|
||||
|
||||
You can set the default timezone globally by calling ``setTimezone()`` on
|
||||
the ``core`` extension instance::
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setTimezone('Europe/Paris');
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``date``: The date
|
||||
* ``timezone``: The timezone
|
||||
|
||||
.. _`date and time formats`: https://www.php.net/manual/en/datetime.formats.php
|
66
vendor/twig/twig/doc/functions/dump.rst
vendored
Normal file
66
vendor/twig/twig/doc/functions/dump.rst
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
``dump``
|
||||
========
|
||||
|
||||
The ``dump`` function dumps information about a template variable. This is
|
||||
mostly useful to debug a template that does not behave as expected by
|
||||
introspecting its variables:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ dump(user) }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``dump`` function is not available by default. You must add the
|
||||
``\Twig\Extension\DebugExtension`` extension explicitly when creating your Twig
|
||||
environment::
|
||||
|
||||
$twig = new \Twig\Environment($loader, [
|
||||
'debug' => true,
|
||||
// ...
|
||||
]);
|
||||
$twig->addExtension(new \Twig\Extension\DebugExtension());
|
||||
|
||||
Even when enabled, the ``dump`` function won't display anything if the
|
||||
``debug`` option on the environment is not enabled (to avoid leaking debug
|
||||
information on a production server).
|
||||
|
||||
In an HTML context, wrap the output with a ``pre`` tag to make it easier to
|
||||
read:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
<pre>
|
||||
{{ dump(user) }}
|
||||
</pre>
|
||||
|
||||
.. tip::
|
||||
|
||||
Using a ``pre`` tag is not needed when `XDebug`_ is enabled and
|
||||
``html_errors`` is ``on``; as a bonus, the output is also nicer with
|
||||
XDebug enabled.
|
||||
|
||||
You can debug several variables by passing them as additional arguments:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ dump(user, categories) }}
|
||||
|
||||
If you don't pass any value, all variables from the current context are
|
||||
dumped:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ dump() }}
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Twig uses the PHP `var_dump`_ function.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``context``: The context to dump
|
||||
|
||||
.. _`XDebug`: https://xdebug.org/docs/display
|
||||
.. _`var_dump`: https://www.php.net/var_dump
|
35
vendor/twig/twig/doc/functions/html_classes.rst
vendored
Normal file
35
vendor/twig/twig/doc/functions/html_classes.rst
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
``html_classes``
|
||||
================
|
||||
|
||||
The ``html_classes`` function returns a string by conditionally joining class
|
||||
names together:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
<p class="{{ html_classes('a-class', 'another-class', {
|
||||
'errored': object.errored,
|
||||
'finished': object.finished,
|
||||
'pending': object.pending,
|
||||
}) }}">How are you doing?</p>
|
||||
|
||||
.. note::
|
||||
|
||||
The ``html_classes`` function is part of the ``HtmlExtension`` which is not
|
||||
installed by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/html-extra
|
||||
|
||||
Then, on Symfony projects, install the ``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Otherwise, add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Html\HtmlExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new HtmlExtension());
|
77
vendor/twig/twig/doc/functions/include.rst
vendored
Normal file
77
vendor/twig/twig/doc/functions/include.rst
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
``include``
|
||||
===========
|
||||
|
||||
The ``include`` function returns the rendered content of a template:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('template.html') }}
|
||||
{{ include(some_var) }}
|
||||
|
||||
Included templates have access to the variables of the active context.
|
||||
|
||||
If you are using the filesystem loader, the templates are looked for in the
|
||||
paths defined by it.
|
||||
|
||||
The context is passed by default to the template but you can also pass
|
||||
additional variables:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# template.html will have access to the variables from the current context and the additional ones provided #}
|
||||
{{ include('template.html', {foo: 'bar'}) }}
|
||||
|
||||
You can disable access to the context by setting ``with_context`` to
|
||||
``false``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# only the foo variable will be accessible #}
|
||||
{{ include('template.html', {foo: 'bar'}, with_context = false) }}
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# no variables will be accessible #}
|
||||
{{ include('template.html', with_context = false) }}
|
||||
|
||||
And if the expression evaluates to a ``\Twig\Template`` or a
|
||||
``\Twig\TemplateWrapper`` instance, Twig will use it directly::
|
||||
|
||||
// {{ include(template) }}
|
||||
|
||||
$template = $twig->load('some_template.twig');
|
||||
|
||||
$twig->display('template.twig', ['template' => $template]);
|
||||
|
||||
When you set the ``ignore_missing`` flag, Twig will return an empty string if
|
||||
the template does not exist:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('sidebar.html', ignore_missing = true) }}
|
||||
|
||||
You can also provide a list of templates that are checked for existence before
|
||||
inclusion. The first template that exists will be rendered:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include(['page_detailed.html', 'page.html']) }}
|
||||
|
||||
If ``ignore_missing`` is set, it will fall back to rendering nothing if none
|
||||
of the templates exist, otherwise it will throw an exception.
|
||||
|
||||
When including a template created by an end user, you should consider
|
||||
sandboxing it:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include('page.html', sandboxed = true) }}
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``template``: The template to render
|
||||
* ``variables``: The variables to pass to the template
|
||||
* ``with_context``: Whether to pass the current context variables or not
|
||||
* ``ignore_missing``: Whether to ignore missing templates or not
|
||||
* ``sandboxed``: Whether to sandbox the template or not
|
22
vendor/twig/twig/doc/functions/index.rst
vendored
Normal file
22
vendor/twig/twig/doc/functions/index.rst
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Functions
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
attribute
|
||||
block
|
||||
constant
|
||||
cycle
|
||||
date
|
||||
dump
|
||||
html_classes
|
||||
include
|
||||
max
|
||||
min
|
||||
parent
|
||||
random
|
||||
range
|
||||
source
|
||||
country_timezones
|
||||
template_from_string
|
17
vendor/twig/twig/doc/functions/max.rst
vendored
Normal file
17
vendor/twig/twig/doc/functions/max.rst
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
``max``
|
||||
=======
|
||||
|
||||
``max`` returns the biggest value of a sequence or a set of values:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ max(1, 3, 2) }}
|
||||
{{ max([1, 3, 2]) }}
|
||||
|
||||
When called with a mapping, max ignores keys and only compares values:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ max({2: "e", 1: "a", 3: "b", 5: "d", 4: "c"}) }}
|
||||
{# returns "e" #}
|
||||
|
17
vendor/twig/twig/doc/functions/min.rst
vendored
Normal file
17
vendor/twig/twig/doc/functions/min.rst
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
``min``
|
||||
=======
|
||||
|
||||
``min`` returns the lowest value of a sequence or a set of values:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ min(1, 3, 2) }}
|
||||
{{ min([1, 3, 2]) }}
|
||||
|
||||
When called with a mapping, min ignores keys and only compares values:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ min({2: "e", 3: "a", 1: "b", 5: "d", 4: "c"}) }}
|
||||
{# returns "a" #}
|
||||
|
22
vendor/twig/twig/doc/functions/parent.rst
vendored
Normal file
22
vendor/twig/twig/doc/functions/parent.rst
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
``parent``
|
||||
==========
|
||||
|
||||
When a template uses inheritance, it's possible to render the contents of the
|
||||
parent block when overriding a block by using the ``parent`` function:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block sidebar %}
|
||||
<h3>Table Of Contents</h3>
|
||||
...
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
|
||||
The ``parent()`` call will return the content of the ``sidebar`` block as
|
||||
defined in the ``base.html`` template.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`extends<../tags/extends>`, :doc:`block<../functions/block>`, :doc:`block<../tags/block>`
|
25
vendor/twig/twig/doc/functions/random.rst
vendored
Normal file
25
vendor/twig/twig/doc/functions/random.rst
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
``random``
|
||||
==========
|
||||
|
||||
The ``random`` function returns a random value depending on the supplied
|
||||
parameter type:
|
||||
|
||||
* a random item from a sequence;
|
||||
* a random character from a string;
|
||||
* a random integer between 0 and the integer parameter (inclusive).
|
||||
* a random integer between the integer parameter (when negative) and 0 (inclusive).
|
||||
* a random integer between the first integer and the second integer parameter (inclusive).
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
|
||||
{{ random('ABC') }} {# example output: C #}
|
||||
{{ random() }} {# example output: 15386094 (works as the native PHP mt_rand function) #}
|
||||
{{ random(5) }} {# example output: 3 #}
|
||||
{{ random(50, 100) }} {# example output: 63 #}
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``values``: The values
|
||||
* ``max``: The max value when values is an integer
|
58
vendor/twig/twig/doc/functions/range.rst
vendored
Normal file
58
vendor/twig/twig/doc/functions/range.rst
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
``range``
|
||||
=========
|
||||
|
||||
Returns a list containing an arithmetic progression of integers:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in range(0, 3) %}
|
||||
{{ i }},
|
||||
{% endfor %}
|
||||
|
||||
{# outputs 0, 1, 2, 3, #}
|
||||
|
||||
When step is given (as the third parameter), it specifies the increment (or
|
||||
decrement for negative values):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in range(0, 6, 2) %}
|
||||
{{ i }},
|
||||
{% endfor %}
|
||||
|
||||
{# outputs 0, 2, 4, 6, #}
|
||||
|
||||
.. note::
|
||||
|
||||
Note that if the start is greater than the end, ``range`` assumes a step of
|
||||
``-1``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in range(3, 0) %}
|
||||
{{ i }},
|
||||
{% endfor %}
|
||||
|
||||
{# outputs 3, 2, 1, 0, #}
|
||||
|
||||
The Twig built-in ``..`` operator is just syntactic sugar for the ``range``
|
||||
function (with a step of ``1``, or ``-1`` if the start is greater than the end):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for i in 0..3 %}
|
||||
{{ i }},
|
||||
{% endfor %}
|
||||
|
||||
.. tip::
|
||||
|
||||
The ``range`` function works as the native PHP `range`_ function.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``low``: The first value of the sequence.
|
||||
* ``high``: The highest possible value of the sequence.
|
||||
* ``step``: The increment between elements of the sequence.
|
||||
|
||||
.. _`range`: https://www.php.net/range
|
26
vendor/twig/twig/doc/functions/source.rst
vendored
Normal file
26
vendor/twig/twig/doc/functions/source.rst
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
``source``
|
||||
==========
|
||||
|
||||
The ``source`` function returns the content of a template without rendering it:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ source('template.html') }}
|
||||
{{ source(some_var) }}
|
||||
|
||||
When you set the ``ignore_missing`` flag, Twig will return an empty string if
|
||||
the template does not exist:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ source('template.html', ignore_missing = true) }}
|
||||
|
||||
The function uses the same template loaders as the ones used to include
|
||||
templates. So, if you are using the filesystem loader, the templates are looked
|
||||
for in the paths defined by it.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``name``: The name of the template to read
|
||||
* ``ignore_missing``: Whether to ignore missing templates or not
|
37
vendor/twig/twig/doc/functions/template_from_string.rst
vendored
Normal file
37
vendor/twig/twig/doc/functions/template_from_string.rst
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
``template_from_string``
|
||||
========================
|
||||
|
||||
The ``template_from_string`` function loads a template from a string:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include(template_from_string("Hello {{ name }}")) }}
|
||||
{{ include(template_from_string(page.template)) }}
|
||||
|
||||
To ease debugging, you can also give the template a name that will be part of
|
||||
any related error message:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include(template_from_string(page.template, "template for page " ~ page.name)) }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``template_from_string`` function is not available by default. You
|
||||
must add the ``\Twig\Extension\StringLoaderExtension`` extension explicitly when
|
||||
creating your Twig environment::
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new \Twig\Extension\StringLoaderExtension());
|
||||
|
||||
.. note::
|
||||
|
||||
Even if you will probably always use the ``template_from_string`` function
|
||||
with the ``include`` function, you can use it with any tag or function that
|
||||
takes a template as an argument (like the ``embed`` or ``extends`` tags).
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``template``: The template
|
||||
* ``name``: A name for the template
|
19
vendor/twig/twig/doc/index.rst
vendored
Normal file
19
vendor/twig/twig/doc/index.rst
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Twig
|
||||
====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
intro
|
||||
installation
|
||||
templates
|
||||
api
|
||||
advanced
|
||||
internals
|
||||
deprecated
|
||||
recipes
|
||||
coding_standards
|
||||
tags/index
|
||||
filters/index
|
||||
functions/index
|
||||
tests/index
|
10
vendor/twig/twig/doc/installation.rst
vendored
Normal file
10
vendor/twig/twig/doc/installation.rst
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
Install `Composer`_ and run the following command to get the latest version:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
composer require "twig/twig:^3.0"
|
||||
|
||||
.. _`Composer`: https://getcomposer.org/download/
|
140
vendor/twig/twig/doc/internals.rst
vendored
Normal file
140
vendor/twig/twig/doc/internals.rst
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
Twig Internals
|
||||
==============
|
||||
|
||||
Twig is very extensible and you can hack it. Keep in mind that you
|
||||
should probably try to create an extension before hacking the core, as most
|
||||
features and enhancements can be handled with extensions. This chapter is also
|
||||
useful for people who want to understand how Twig works under the hood.
|
||||
|
||||
How does Twig work?
|
||||
-------------------
|
||||
|
||||
The rendering of a Twig template can be summarized into four key steps:
|
||||
|
||||
* **Load** the template: If the template is already compiled, load it and go
|
||||
to the *evaluation* step, otherwise:
|
||||
|
||||
* First, the **lexer** tokenizes the template source code into small pieces
|
||||
for easier processing;
|
||||
|
||||
* Then, the **parser** converts the token stream into a meaningful tree
|
||||
of nodes (the Abstract Syntax Tree);
|
||||
|
||||
* Finally, the *compiler* transforms the AST into PHP code.
|
||||
|
||||
* **Evaluate** the template: It means calling the ``display()``
|
||||
method of the compiled template and passing it the context.
|
||||
|
||||
The Lexer
|
||||
---------
|
||||
|
||||
The lexer tokenizes a template source code into a token stream (each token is
|
||||
an instance of ``\Twig\Token``, and the stream is an instance of
|
||||
``\Twig\TokenStream``). The default lexer recognizes 13 different token types:
|
||||
|
||||
* ``\Twig\Token::BLOCK_START_TYPE``, ``\Twig\Token::BLOCK_END_TYPE``: Delimiters for blocks (``{% %}``)
|
||||
* ``\Twig\Token::VAR_START_TYPE``, ``\Twig\Token::VAR_END_TYPE``: Delimiters for variables (``{{ }}``)
|
||||
* ``\Twig\Token::TEXT_TYPE``: A text outside an expression;
|
||||
* ``\Twig\Token::NAME_TYPE``: A name in an expression;
|
||||
* ``\Twig\Token::NUMBER_TYPE``: A number in an expression;
|
||||
* ``\Twig\Token::STRING_TYPE``: A string in an expression;
|
||||
* ``\Twig\Token::OPERATOR_TYPE``: An operator;
|
||||
* ``\Twig\Token::PUNCTUATION_TYPE``: A punctuation sign;
|
||||
* ``\Twig\Token::INTERPOLATION_START_TYPE``, ``\Twig\Token::INTERPOLATION_END_TYPE``: Delimiters for string interpolation;
|
||||
* ``\Twig\Token::EOF_TYPE``: Ends of template.
|
||||
|
||||
You can manually convert a source code into a token stream by calling the
|
||||
``tokenize()`` method of an environment::
|
||||
|
||||
$stream = $twig->tokenize(new \Twig\Source($source, $identifier));
|
||||
|
||||
As the stream has a ``__toString()`` method, you can have a textual
|
||||
representation of it by echoing the object::
|
||||
|
||||
echo $stream."\n";
|
||||
|
||||
Here is the output for the ``Hello {{ name }}`` template:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
TEXT_TYPE(Hello )
|
||||
VAR_START_TYPE()
|
||||
NAME_TYPE(name)
|
||||
VAR_END_TYPE()
|
||||
EOF_TYPE()
|
||||
|
||||
.. note::
|
||||
|
||||
The default lexer (``\Twig\Lexer``) can be changed by calling
|
||||
the ``setLexer()`` method::
|
||||
|
||||
$twig->setLexer($lexer);
|
||||
|
||||
The Parser
|
||||
----------
|
||||
|
||||
The parser converts the token stream into an AST (Abstract Syntax Tree), or a
|
||||
node tree (an instance of ``\Twig\Node\ModuleNode``). The core extension defines
|
||||
the basic nodes like: ``for``, ``if``, ... and the expression nodes.
|
||||
|
||||
You can manually convert a token stream into a node tree by calling the
|
||||
``parse()`` method of an environment::
|
||||
|
||||
$nodes = $twig->parse($stream);
|
||||
|
||||
Echoing the node object gives you a nice representation of the tree::
|
||||
|
||||
echo $nodes."\n";
|
||||
|
||||
Here is the output for the ``Hello {{ name }}`` template:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
\Twig\Node\ModuleNode(
|
||||
\Twig\Node\TextNode(Hello )
|
||||
\Twig\Node\PrintNode(
|
||||
\Twig\Node\Expression\NameExpression(name)
|
||||
)
|
||||
)
|
||||
|
||||
.. note::
|
||||
|
||||
The default parser (``\Twig\TokenParser\AbstractTokenParser``) can be changed by calling the
|
||||
``setParser()`` method::
|
||||
|
||||
$twig->setParser($parser);
|
||||
|
||||
The Compiler
|
||||
------------
|
||||
|
||||
The last step is done by the compiler. It takes a node tree as an input and
|
||||
generates PHP code usable for runtime execution of the template.
|
||||
|
||||
You can manually compile a node tree to PHP code with the ``compile()`` method
|
||||
of an environment::
|
||||
|
||||
$php = $twig->compile($nodes);
|
||||
|
||||
The generated template for a ``Hello {{ name }}`` template reads as follows
|
||||
(the actual output can differ depending on the version of Twig you are
|
||||
using)::
|
||||
|
||||
/* Hello {{ name }} */
|
||||
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Template
|
||||
{
|
||||
protected function doDisplay(array $context, array $blocks = [])
|
||||
{
|
||||
// line 1
|
||||
echo "Hello ";
|
||||
echo twig_escape_filter($this->env, (isset($context["name"]) ? $context["name"] : null), "html", null, true);
|
||||
}
|
||||
|
||||
// some more code
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
The default compiler (``\Twig\Compiler``) can be changed by calling the
|
||||
``setCompiler()`` method::
|
||||
|
||||
$twig->setCompiler($compiler);
|
74
vendor/twig/twig/doc/intro.rst
vendored
Normal file
74
vendor/twig/twig/doc/intro.rst
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
Welcome to the documentation for Twig, the flexible, fast, and secure template
|
||||
engine for PHP.
|
||||
|
||||
Twig is both designer and developer friendly by sticking to PHP's principles and
|
||||
adding functionality useful for templating environments.
|
||||
|
||||
The key-features are...
|
||||
|
||||
* *Fast*: Twig compiles templates down to plain optimized PHP code. The
|
||||
overhead compared to regular PHP code was reduced to the very minimum.
|
||||
|
||||
* *Secure*: Twig has a sandbox mode to evaluate untrusted template code. This
|
||||
allows Twig to be used as a template language for applications where users
|
||||
may modify the template design.
|
||||
|
||||
* *Flexible*: Twig is powered by a flexible lexer and parser. This allows the
|
||||
developer to define their own custom tags and filters, and to create their own DSL.
|
||||
|
||||
Twig is used by many Open-Source projects like Symfony, Drupal8, eZPublish,
|
||||
phpBB, Matomo, OroCRM; and many frameworks have support for it as well like
|
||||
Slim, Yii, Laravel, and Codeigniter — just to name a few.
|
||||
|
||||
.. admonition:: Screencast
|
||||
|
||||
Like to learn from video tutorials? Check out the `SymfonyCasts Twig Tutorial`_!
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Twig 3.x needs at least **PHP 7.2.5** to run.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The recommended way to install Twig is via Composer:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
composer require "twig/twig:^3.0"
|
||||
|
||||
Basic API Usage
|
||||
---------------
|
||||
|
||||
This section gives you a brief introduction to the PHP API for Twig::
|
||||
|
||||
require_once '/path/to/vendor/autoload.php';
|
||||
|
||||
$loader = new \Twig\Loader\ArrayLoader([
|
||||
'index' => 'Hello {{ name }}!',
|
||||
]);
|
||||
$twig = new \Twig\Environment($loader);
|
||||
|
||||
echo $twig->render('index', ['name' => 'Fabien']);
|
||||
|
||||
Twig uses a loader (``\Twig\Loader\ArrayLoader``) to locate templates, and an
|
||||
environment (``\Twig\Environment``) to store its configuration.
|
||||
|
||||
The ``render()`` method loads the template passed as a first argument and
|
||||
renders it with the variables passed as a second argument.
|
||||
|
||||
As templates are generally stored on the filesystem, Twig also comes with a
|
||||
filesystem loader::
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
|
||||
$twig = new \Twig\Environment($loader, [
|
||||
'cache' => '/path/to/compilation_cache',
|
||||
]);
|
||||
|
||||
echo $twig->render('index.html', ['name' => 'Fabien']);
|
||||
|
||||
.. _`SymfonyCasts Twig Tutorial`: https://symfonycasts.com/screencast/twig
|
531
vendor/twig/twig/doc/recipes.rst
vendored
Normal file
531
vendor/twig/twig/doc/recipes.rst
vendored
Normal file
@@ -0,0 +1,531 @@
|
||||
Recipes
|
||||
=======
|
||||
|
||||
.. _deprecation-notices:
|
||||
|
||||
Displaying Deprecation Notices
|
||||
------------------------------
|
||||
|
||||
Deprecated features generate deprecation notices (via a call to the
|
||||
``trigger_error()`` PHP function). By default, they are silenced and never
|
||||
displayed nor logged.
|
||||
|
||||
To remove all deprecated feature usages from your templates, write and run a
|
||||
script along the lines of the following::
|
||||
|
||||
require_once __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$twig = create_your_twig_env();
|
||||
|
||||
$deprecations = new \Twig\Util\DeprecationCollector($twig);
|
||||
|
||||
print_r($deprecations->collectDir(__DIR__.'/templates'));
|
||||
|
||||
The ``collectDir()`` method compiles all templates found in a directory,
|
||||
catches deprecation notices, and return them.
|
||||
|
||||
.. tip::
|
||||
|
||||
If your templates are not stored on the filesystem, use the ``collect()``
|
||||
method instead. ``collect()`` takes a ``Traversable`` which must return
|
||||
template names as keys and template contents as values (as done by
|
||||
``\Twig\Util\TemplateDirIterator``).
|
||||
|
||||
However, this code won't find all deprecations (like using deprecated some Twig
|
||||
classes). To catch all notices, register a custom error handler like the one
|
||||
below::
|
||||
|
||||
$deprecations = [];
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) {
|
||||
if (E_USER_DEPRECATED === $type) {
|
||||
$deprecations[] = $msg;
|
||||
}
|
||||
});
|
||||
|
||||
// run your application
|
||||
|
||||
print_r($deprecations);
|
||||
|
||||
Note that most deprecation notices are triggered during **compilation**, so
|
||||
they won't be generated when templates are already cached.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you want to manage the deprecation notices from your PHPUnit tests, have
|
||||
a look at the `symfony/phpunit-bridge
|
||||
<https://github.com/symfony/phpunit-bridge>`_ package, which eases the
|
||||
process.
|
||||
|
||||
Making a Layout conditional
|
||||
---------------------------
|
||||
|
||||
Working with Ajax means that the same content is sometimes displayed as is,
|
||||
and sometimes decorated with a layout. As Twig layout template names can be
|
||||
any valid expression, you can pass a variable that evaluates to ``true`` when
|
||||
the request is made via Ajax and choose the layout accordingly:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% extends request.ajax ? "base_ajax.html" : "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
This is the content to be displayed.
|
||||
{% endblock %}
|
||||
|
||||
Making an Include dynamic
|
||||
-------------------------
|
||||
|
||||
When including a template, its name does not need to be a string. For
|
||||
instance, the name can depend on the value of a variable:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% include var ~ '_foo.html' %}
|
||||
|
||||
If ``var`` evaluates to ``index``, the ``index_foo.html`` template will be
|
||||
rendered.
|
||||
|
||||
As a matter of fact, the template name can be any valid expression, such as
|
||||
the following:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% include var|default('index') ~ '_foo.html' %}
|
||||
|
||||
Overriding a Template that also extends itself
|
||||
----------------------------------------------
|
||||
|
||||
A template can be customized in two different ways:
|
||||
|
||||
* *Inheritance*: A template *extends* a parent template and overrides some
|
||||
blocks;
|
||||
|
||||
* *Replacement*: If you use the filesystem loader, Twig loads the first
|
||||
template it finds in a list of configured directories; a template found in a
|
||||
directory *replaces* another one from a directory further in the list.
|
||||
|
||||
But how do you combine both: *replace* a template that also extends itself
|
||||
(aka a template in a directory further in the list)?
|
||||
|
||||
Let's say that your templates are loaded from both ``.../templates/mysite``
|
||||
and ``.../templates/default`` in this order. The ``page.twig`` template,
|
||||
stored in ``.../templates/default`` reads as follows:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# page.twig #}
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
|
||||
You can replace this template by putting a file with the same name in
|
||||
``.../templates/mysite``. And if you want to extend the original template, you
|
||||
might be tempted to write the following:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# page.twig in .../templates/mysite #}
|
||||
{% extends "page.twig" %} {# from .../templates/default #}
|
||||
|
||||
However, this will not work as Twig will always load the template from
|
||||
``.../templates/mysite``.
|
||||
|
||||
It turns out it is possible to get this to work, by adding a directory right
|
||||
at the end of your template directories, which is the parent of all of the
|
||||
other directories: ``.../templates`` in our case. This has the effect of
|
||||
making every template file within our system uniquely addressable. Most of the
|
||||
time you will use the "normal" paths, but in the special case of wanting to
|
||||
extend a template with an overriding version of itself we can reference its
|
||||
parent's full, unambiguous template path in the extends tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# page.twig in .../templates/mysite #}
|
||||
{% extends "default/page.twig" %} {# from .../templates #}
|
||||
|
||||
.. note::
|
||||
|
||||
This recipe was inspired by the following Django wiki page:
|
||||
https://code.djangoproject.com/wiki/ExtendingTemplates
|
||||
|
||||
Customizing the Syntax
|
||||
----------------------
|
||||
|
||||
Twig allows some syntax customization for the block delimiters. It's **not**
|
||||
recommended to use this feature as templates will be tied with your custom
|
||||
syntax. But for specific projects, it can make sense to change the defaults.
|
||||
|
||||
To change the block delimiters, you need to create your own lexer object::
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
|
||||
$lexer = new \Twig\Lexer($twig, [
|
||||
'tag_comment' => ['{#', '#}'],
|
||||
'tag_block' => ['{%', '%}'],
|
||||
'tag_variable' => ['{{', '}}'],
|
||||
'interpolation' => ['#{', '}'],
|
||||
]);
|
||||
$twig->setLexer($lexer);
|
||||
|
||||
Here are some configuration example that simulates some other template engines
|
||||
syntax::
|
||||
|
||||
// Ruby erb syntax
|
||||
$lexer = new \Twig\Lexer($twig, [
|
||||
'tag_comment' => ['<%#', '%>'],
|
||||
'tag_block' => ['<%', '%>'],
|
||||
'tag_variable' => ['<%=', '%>'],
|
||||
]);
|
||||
|
||||
// SGML Comment Syntax
|
||||
$lexer = new \Twig\Lexer($twig, [
|
||||
'tag_comment' => ['<!--#', '-->'],
|
||||
'tag_block' => ['<!--', '-->'],
|
||||
'tag_variable' => ['${', '}'],
|
||||
]);
|
||||
|
||||
// Smarty like
|
||||
$lexer = new \Twig\Lexer($twig, [
|
||||
'tag_comment' => ['{*', '*}'],
|
||||
'tag_block' => ['{', '}'],
|
||||
'tag_variable' => ['{$', '}'],
|
||||
]);
|
||||
|
||||
Using dynamic Object Properties
|
||||
-------------------------------
|
||||
|
||||
When Twig encounters a variable like ``article.title``, it tries to find a
|
||||
``title`` public property in the ``article`` object.
|
||||
|
||||
It also works if the property does not exist but is rather defined dynamically
|
||||
thanks to the magic ``__get()`` method; you need to also implement the
|
||||
``__isset()`` magic method like shown in the following snippet of code::
|
||||
|
||||
class Article
|
||||
{
|
||||
public function __get($name)
|
||||
{
|
||||
if ('title' == $name) {
|
||||
return 'The title';
|
||||
}
|
||||
|
||||
// throw some kind of error
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
if ('title' == $name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Accessing the parent Context in Nested Loops
|
||||
--------------------------------------------
|
||||
|
||||
Sometimes, when using nested loops, you need to access the parent context. The
|
||||
parent context is always accessible via the ``loop.parent`` variable. For
|
||||
instance, if you have the following template data::
|
||||
|
||||
$data = [
|
||||
'topics' => [
|
||||
'topic1' => ['Message 1 of topic 1', 'Message 2 of topic 1'],
|
||||
'topic2' => ['Message 1 of topic 2', 'Message 2 of topic 2'],
|
||||
],
|
||||
];
|
||||
|
||||
And the following template to display all messages in all topics:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% for topic, messages in topics %}
|
||||
* {{ loop.index }}: {{ topic }}
|
||||
{% for message in messages %}
|
||||
- {{ loop.parent.loop.index }}.{{ loop.index }}: {{ message }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
The output will be similar to:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
* 1: topic1
|
||||
- 1.1: The message 1 of topic 1
|
||||
- 1.2: The message 2 of topic 1
|
||||
* 2: topic2
|
||||
- 2.1: The message 1 of topic 2
|
||||
- 2.2: The message 2 of topic 2
|
||||
|
||||
In the inner loop, the ``loop.parent`` variable is used to access the outer
|
||||
context. So, the index of the current ``topic`` defined in the outer for loop
|
||||
is accessible via the ``loop.parent.loop.index`` variable.
|
||||
|
||||
Defining undefined Functions, Filters, and Tags on the Fly
|
||||
----------------------------------------------------------
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
The ``registerUndefinedTokenParserCallback()`` method was added in Twig
|
||||
3.2.
|
||||
|
||||
When a function/filter/tag is not defined, Twig defaults to throw a
|
||||
``\Twig\Error\SyntaxError`` exception. However, it can also call a `callback`_
|
||||
(any valid PHP callable) which should return a function/filter/tag.
|
||||
|
||||
For tags, register callbacks with ``registerUndefinedTokenParserCallback()``.
|
||||
For filters, register callbacks with ``registerUndefinedFilterCallback()``.
|
||||
For functions, use ``registerUndefinedFunctionCallback()``::
|
||||
|
||||
// auto-register all native PHP functions as Twig functions
|
||||
// NEVER do this in a project as it's NOT secure
|
||||
$twig->registerUndefinedFunctionCallback(function ($name) {
|
||||
if (function_exists($name)) {
|
||||
return new \Twig\TwigFunction($name, $name);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
If the callable is not able to return a valid function/filter/tag, it must
|
||||
return ``false``.
|
||||
|
||||
If you register more than one callback, Twig will call them in turn until one
|
||||
does not return ``false``.
|
||||
|
||||
.. tip::
|
||||
|
||||
As the resolution of functions/filters/tags is done during compilation,
|
||||
there is no overhead when registering these callbacks.
|
||||
|
||||
Validating the Template Syntax
|
||||
------------------------------
|
||||
|
||||
When template code is provided by a third-party (through a web interface for
|
||||
instance), it might be interesting to validate the template syntax before
|
||||
saving it. If the template code is stored in a ``$template`` variable, here is
|
||||
how you can do it::
|
||||
|
||||
try {
|
||||
$twig->parse($twig->tokenize(new \Twig\Source($template)));
|
||||
|
||||
// the $template is valid
|
||||
} catch (\Twig\Error\SyntaxError $e) {
|
||||
// $template contains one or more syntax errors
|
||||
}
|
||||
|
||||
If you iterate over a set of files, you can pass the filename to the
|
||||
``tokenize()`` method to get the filename in the exception message::
|
||||
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
$twig->parse($twig->tokenize(new \Twig\Source($template, $file->getFilename(), $file)));
|
||||
|
||||
// the $template is valid
|
||||
} catch (\Twig\Error\SyntaxError $e) {
|
||||
// $template contains one or more syntax errors
|
||||
}
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
This method won't catch any sandbox policy violations because the policy
|
||||
is enforced during template rendering (as Twig needs the context for some
|
||||
checks like allowed methods on objects).
|
||||
|
||||
Refreshing modified Templates when OPcache or APC is enabled
|
||||
------------------------------------------------------------
|
||||
|
||||
When using OPcache with ``opcache.validate_timestamps`` set to ``0`` or APC
|
||||
with ``apc.stat`` set to ``0`` and Twig cache enabled, clearing the template
|
||||
cache won't update the cache.
|
||||
|
||||
To get around this, force Twig to invalidate the bytecode cache::
|
||||
|
||||
$twig = new \Twig\Environment($loader, [
|
||||
'cache' => new \Twig\Cache\FilesystemCache('/some/cache/path', \Twig\Cache\FilesystemCache::FORCE_BYTECODE_INVALIDATION),
|
||||
// ...
|
||||
]);
|
||||
|
||||
Reusing a stateful Node Visitor
|
||||
-------------------------------
|
||||
|
||||
When attaching a visitor to a ``\Twig\Environment`` instance, Twig uses it to
|
||||
visit *all* templates it compiles. If you need to keep some state information
|
||||
around, you probably want to reset it when visiting a new template.
|
||||
|
||||
This can be achieved with the following code::
|
||||
|
||||
protected $someTemplateState = [];
|
||||
|
||||
public function enterNode(\Twig\Node\Node $node, \Twig\Environment $env)
|
||||
{
|
||||
if ($node instanceof \Twig\Node\ModuleNode) {
|
||||
// reset the state as we are entering a new template
|
||||
$this->someTemplateState = [];
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
Using a Database to store Templates
|
||||
-----------------------------------
|
||||
|
||||
If you are developing a CMS, templates are usually stored in a database. This
|
||||
recipe gives you a simple PDO template loader you can use as a starting point
|
||||
for your own.
|
||||
|
||||
First, let's create a temporary in-memory SQLite3 database to work with::
|
||||
|
||||
$dbh = new PDO('sqlite::memory:');
|
||||
$dbh->exec('CREATE TABLE templates (name STRING, source STRING, last_modified INTEGER)');
|
||||
$base = '{% block content %}{% endblock %}';
|
||||
$index = '
|
||||
{% extends "base.twig" %}
|
||||
{% block content %}Hello {{ name }}{% endblock %}
|
||||
';
|
||||
$now = time();
|
||||
$dbh->prepare('INSERT INTO templates (name, source, last_modified) VALUES (?, ?, ?)')->execute(['base.twig', $base, $now]);
|
||||
$dbh->prepare('INSERT INTO templates (name, source, last_modified) VALUES (?, ?, ?)')->execute(['index.twig', $index, $now]);
|
||||
|
||||
We have created a simple ``templates`` table that hosts two templates:
|
||||
``base.twig`` and ``index.twig``.
|
||||
|
||||
Now, let's define a loader able to use this database::
|
||||
|
||||
class DatabaseTwigLoader implements \Twig\Loader\LoaderInterface
|
||||
{
|
||||
protected $dbh;
|
||||
|
||||
public function __construct(PDO $dbh)
|
||||
{
|
||||
$this->dbh = $dbh;
|
||||
}
|
||||
|
||||
public function getSourceContext(string $name): Source
|
||||
{
|
||||
if (false === $source = $this->getValue('source', $name)) {
|
||||
throw new \Twig\Error\LoaderError(sprintf('Template "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
return new \Twig\Source($source, $name);
|
||||
}
|
||||
|
||||
public function exists(string $name)
|
||||
{
|
||||
return $name === $this->getValue('name', $name);
|
||||
}
|
||||
|
||||
public function getCacheKey(string $name): string
|
||||
{
|
||||
return $name;
|
||||
}
|
||||
|
||||
public function isFresh(string $name, int $time): bool
|
||||
{
|
||||
if (false === $lastModified = $this->getValue('last_modified', $name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $lastModified <= $time;
|
||||
}
|
||||
|
||||
protected function getValue($column, $name)
|
||||
{
|
||||
$sth = $this->dbh->prepare('SELECT '.$column.' FROM templates WHERE name = :name');
|
||||
$sth->execute([':name' => (string) $name]);
|
||||
|
||||
return $sth->fetchColumn();
|
||||
}
|
||||
}
|
||||
|
||||
Finally, here is an example on how you can use it::
|
||||
|
||||
$loader = new DatabaseTwigLoader($dbh);
|
||||
$twig = new \Twig\Environment($loader);
|
||||
|
||||
echo $twig->render('index.twig', ['name' => 'Fabien']);
|
||||
|
||||
Using different Template Sources
|
||||
--------------------------------
|
||||
|
||||
This recipe is the continuation of the previous one. Even if you store the
|
||||
contributed templates in a database, you might want to keep the original/base
|
||||
templates on the filesystem. When templates can be loaded from different
|
||||
sources, you need to use the ``\Twig\Loader\ChainLoader`` loader.
|
||||
|
||||
As you can see in the previous recipe, we reference the template in the exact
|
||||
same way as we would have done it with a regular filesystem loader. This is
|
||||
the key to be able to mix and match templates coming from the database, the
|
||||
filesystem, or any other loader for that matter: the template name should be a
|
||||
logical name, and not the path from the filesystem::
|
||||
|
||||
$loader1 = new DatabaseTwigLoader($dbh);
|
||||
$loader2 = new \Twig\Loader\ArrayLoader([
|
||||
'base.twig' => '{% block content %}{% endblock %}',
|
||||
]);
|
||||
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
|
||||
|
||||
$twig = new \Twig\Environment($loader);
|
||||
|
||||
echo $twig->render('index.twig', ['name' => 'Fabien']);
|
||||
|
||||
Now that the ``base.twig`` templates is defined in an array loader, you can
|
||||
remove it from the database, and everything else will still work as before.
|
||||
|
||||
Loading a Template from a String
|
||||
--------------------------------
|
||||
|
||||
From a template, you can load a template stored in a string via the
|
||||
``template_from_string`` function (via the
|
||||
``\Twig\Extension\StringLoaderExtension`` extension):
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{{ include(template_from_string("Hello {{ name }}")) }}
|
||||
|
||||
From PHP, it's also possible to load a template stored in a string via
|
||||
``\Twig\Environment::createTemplate()``::
|
||||
|
||||
$template = $twig->createTemplate('hello {{ name }}');
|
||||
echo $template->render(['name' => 'Fabien']);
|
||||
|
||||
Using Twig and AngularJS in the same Templates
|
||||
----------------------------------------------
|
||||
|
||||
Mixing different template syntaxes in the same file is not a recommended
|
||||
practice as both AngularJS and Twig use the same delimiters in their syntax:
|
||||
``{{`` and ``}}``.
|
||||
|
||||
Still, if you want to use AngularJS and Twig in the same template, there are
|
||||
two ways to make it work depending on the amount of AngularJS you need to
|
||||
include in your templates:
|
||||
|
||||
* Escaping the AngularJS delimiters by wrapping AngularJS sections with the
|
||||
``{% verbatim %}`` tag or by escaping each delimiter via ``{{ '{{' }}`` and
|
||||
``{{ '}}' }}``;
|
||||
|
||||
* Changing the delimiters of one of the template engines (depending on which
|
||||
engine you introduced last):
|
||||
|
||||
* For AngularJS, change the interpolation tags using the
|
||||
``interpolateProvider`` service, for instance at the module initialization
|
||||
time:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
angular.module('myApp', []).config(function($interpolateProvider) {
|
||||
$interpolateProvider.startSymbol('{[').endSymbol(']}');
|
||||
});
|
||||
|
||||
* For Twig, change the delimiters via the ``tag_variable`` Lexer option::
|
||||
|
||||
$env->setLexer(new \Twig\Lexer($env, [
|
||||
'tag_variable' => ['{[', ']}'],
|
||||
]));
|
||||
|
||||
.. _callback: https://www.php.net/manual/en/function.is-callable.php
|
20
vendor/twig/twig/doc/tags/apply.rst
vendored
Normal file
20
vendor/twig/twig/doc/tags/apply.rst
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
``apply``
|
||||
=========
|
||||
|
||||
The ``apply`` tag allows you to apply Twig filters on a block of template data:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply upper %}
|
||||
This text becomes uppercase
|
||||
{% endapply %}
|
||||
|
||||
You can also chain filters and pass arguments to them:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% apply lower|escape('html') %}
|
||||
<strong>SOME TEXT</strong>
|
||||
{% endapply %}
|
||||
|
||||
{# outputs "<strong>some text</strong>" #}
|
61
vendor/twig/twig/doc/tags/autoescape.rst
vendored
Normal file
61
vendor/twig/twig/doc/tags/autoescape.rst
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
``autoescape``
|
||||
==============
|
||||
|
||||
Whether automatic escaping is enabled or not, you can mark a section of a
|
||||
template to be escaped or not by using the ``autoescape`` tag:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% autoescape %}
|
||||
Everything will be automatically escaped in this block
|
||||
using the HTML strategy
|
||||
{% endautoescape %}
|
||||
|
||||
{% autoescape 'html' %}
|
||||
Everything will be automatically escaped in this block
|
||||
using the HTML strategy
|
||||
{% endautoescape %}
|
||||
|
||||
{% autoescape 'js' %}
|
||||
Everything will be automatically escaped in this block
|
||||
using the js escaping strategy
|
||||
{% endautoescape %}
|
||||
|
||||
{% autoescape false %}
|
||||
Everything will be outputted as is in this block
|
||||
{% endautoescape %}
|
||||
|
||||
When automatic escaping is enabled everything is escaped by default except for
|
||||
values explicitly marked as safe. Those can be marked in the template by using
|
||||
the :doc:`raw<../filters/raw>` filter:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% autoescape %}
|
||||
{{ safe_value|raw }}
|
||||
{% endautoescape %}
|
||||
|
||||
Functions returning template data (like :doc:`macros<macro>` and
|
||||
:doc:`parent<../functions/parent>`) always return safe markup.
|
||||
|
||||
.. note::
|
||||
|
||||
Twig is smart enough to not escape an already escaped value by the
|
||||
:doc:`escape<../filters/escape>` filter.
|
||||
|
||||
.. note::
|
||||
|
||||
Twig does not escape static expressions:
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% set hello = "<strong>Hello</strong>" %}
|
||||
{{ hello }}
|
||||
{{ "<strong>world</strong>" }}
|
||||
|
||||
Will be rendered "<strong>Hello</strong> **world**".
|
||||
|
||||
.. note::
|
||||
|
||||
The chapter :doc:`Twig for Developers<../api>` gives more information
|
||||
about when and how automatic escaping is applied.
|
12
vendor/twig/twig/doc/tags/block.rst
vendored
Normal file
12
vendor/twig/twig/doc/tags/block.rst
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
``block``
|
||||
=========
|
||||
|
||||
Blocks are used for inheritance and act as placeholders and replacements at
|
||||
the same time. They are documented in detail in the documentation for the
|
||||
:doc:`extends<../tags/extends>` tag.
|
||||
|
||||
Block names must consist of alphanumeric characters, and underscores. The first char can't be a digit and dashes are not permitted.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`block<../functions/block>`, :doc:`parent<../functions/parent>`, :doc:`use<../tags/use>`, :doc:`extends<../tags/extends>`
|
113
vendor/twig/twig/doc/tags/cache.rst
vendored
Normal file
113
vendor/twig/twig/doc/tags/cache.rst
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
``cache``
|
||||
=========
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
The ``cache`` tag was added in Twig 3.2.
|
||||
|
||||
The ``cache`` tag tells Twig to cache a template fragment:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% cache "cache key" %}
|
||||
Cached forever (depending on the cache implementation)
|
||||
{% endcache %}
|
||||
|
||||
If you want to expire the cache after a certain amount of time, specify an
|
||||
expiration in seconds via the ``ttl()`` modifier:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% cache "cache key" ttl(300) %}
|
||||
Cached for 300 seconds
|
||||
{% endcache %}
|
||||
|
||||
The cache key can be any string that does not use the following reserved
|
||||
characters ``{}()/\@:``; a good practice is to embed some useful information in
|
||||
the key that allows the cache to automatically expire when it must be
|
||||
refreshed:
|
||||
|
||||
* Give each cache a unique name and namespace it like your templates;
|
||||
|
||||
* Embed an integer that you increment whenever the template code changes (to
|
||||
automatically invalidate all current caches);
|
||||
|
||||
* Embed a unique key that is updated whenever the variables used in the
|
||||
template code changes.
|
||||
|
||||
For instance, I would use ``{% cache "blog_post;v1;" ~ post.id ~ ";" ~
|
||||
post.updated_at %}`` to cache a blog content template fragment where
|
||||
``blog_post`` describes the template fragment, ``v1`` represents the first
|
||||
version of the template code, ``post.id`` represent the id of the blog post,
|
||||
and ``post.updated_at`` returns a timestamp that represents the time where the
|
||||
blog post was last modified.
|
||||
|
||||
Using such a strategy for naming cache keys allows to avoid using a ``ttl``.
|
||||
It's like using a "validation" strategy instead of an "expiration" strategy as
|
||||
we do for HTTP caches.
|
||||
|
||||
If your cache implementation supports tags, you can also tag your cache items:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% cache "cache key" tags('blog') %}
|
||||
Some code
|
||||
{% endcache %}
|
||||
|
||||
{% cache "cache key" tags(['cms', 'blog']) %}
|
||||
Some code
|
||||
{% endcache %}
|
||||
|
||||
The ``cache`` tag creates a new "scope" for variables, meaning that the changes
|
||||
are local to the template fragment:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% set count = 1 %}
|
||||
|
||||
{% cache "cache key" tags('blog') %}
|
||||
{# Won't affect the value of count outside of the cache tag #}
|
||||
{% set count = 2 %}
|
||||
Some code
|
||||
{% endcache %}
|
||||
|
||||
{# Displays 1 #}
|
||||
{{ count }}
|
||||
|
||||
.. note::
|
||||
|
||||
The ``cache`` tag is part of the ``CacheExtension`` which is not installed
|
||||
by default. Install it first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/cache-extra
|
||||
|
||||
On Symfony projects, you can automatically enable it by installing the
|
||||
``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require twig/extra-bundle
|
||||
|
||||
Or add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Cache\CacheExtension;
|
||||
|
||||
$twig = new \Twig\Environment(...);
|
||||
$twig->addExtension(new CacheExtension());
|
||||
|
||||
If you are not using Symfony, you must also register the extension runtime::
|
||||
|
||||
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
|
||||
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
|
||||
use Twig\Extra\Cache\CacheRuntime;
|
||||
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
||||
|
||||
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
|
||||
public function load($class) {
|
||||
if (CacheRuntime::class === $class) {
|
||||
return new CacheRuntime(new TagAwareAdapter(new FilesystemAdapter()));
|
||||
}
|
||||
}
|
||||
});
|
27
vendor/twig/twig/doc/tags/deprecated.rst
vendored
Normal file
27
vendor/twig/twig/doc/tags/deprecated.rst
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
``deprecated``
|
||||
==============
|
||||
|
||||
Twig generates a deprecation notice (via a call to the ``trigger_error()``
|
||||
PHP function) where the ``deprecated`` tag is used in a template:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{# base.twig #}
|
||||
{% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %}
|
||||
{% extends 'layout.twig' %}
|
||||
|
||||
Also you can deprecate a block in the following way:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% block hey %}
|
||||
{% deprecated 'The "hey" block is deprecated, use "greet" instead.' %}
|
||||
{{ block('greet') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block greet %}
|
||||
Hey you!
|
||||
{% endblock %}
|
||||
|
||||
Note that by default, the deprecation notices are silenced and never displayed nor logged.
|
||||
See :ref:`deprecation-notices` to learn how to handle them.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user