twigphp / twig Goto Github PK
View Code? Open in Web Editor NEWTwig, the flexible, fast, and secure template language for PHP
Home Page: https://twig.symfony.com/
License: BSD 3-Clause "New" or "Revised" License
Twig, the flexible, fast, and secure template language for PHP
Home Page: https://twig.symfony.com/
License: BSD 3-Clause "New" or "Revised" License
Hi, I found this possibly bug.
Suppose I have a class named "Result" with a constructor with same name and a method named "getResult":
class Result
{
public function Result(foo, bar)
{
// object initialization
}
public function getResult()
{
// return some data
}
}
Then I assign to template vars this array:
$result = new Result(foo, bar);
array("data" => $result);
When I try to access via templates as following
{{ data.result }}
it's resolve the constructor method as the method to call instead of getResult().
I think you should discern when a method is a class constructor and when not.
Hello,
I've donwloaded the latest snapshot (with i18n support) and I've startet to run tests mit it seems not work.
Where can I get the lime package?
I get this error in each test dir: Unable to access testing/php/templates/twig/develope/test/unit/../lib/lime/LimeAutoloader.php
Thanks
Michael
An expression {{ '=' * 80 }} doesn't working
As per example at http://www.twig-project.org/book/02-Twig-for-Template-Designers
{% macro input(name, value, type, size) %}
< input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" / >
{% endmacro %}
In this case, if the value of type contains a " (double-quote) then it will not be escaped as " as it may be expected.
I am currently using Twig from commit 362613c
I think it would be better to change is_null() check to empty(), as often values are not null but simply empty.
I'm not sure, but maybe there's bug with the plural form...
I've tried a simple example, as showed in the documentation:
{% trans count %}
I have one apple.
{% plural %}
I have {{ count }} apples.
{% endtrans %}
and this get's compiled to:
echo ngettext("I have one apple.");
obviously this generates a runtime error, because ngettext expects two
more parameters...
It seems that the problem is in the if condition at line 50 of the class Twig_Node_Trans
:
if ($vars)
I think that changing this line to
if ($vars || $vars1 )
will fix the problem.
It seems that this kind of problem happens only when you use no vars on the singular form and some var on the plural form. That's why the proposed fix seems to work...
I have a loader that loads objects. If the object implements a Project_ResourceInterface, that provides a method getSource(), then the loader can handle this object and return the source.
It works very, very well. I can have the following sintax in my templates:
{{ include page.part.body }} -- or something similar
The only problem is this line at Twig_Environment class:
return $this->loadedTemplates[$name] = new $cls($this);
If $name is a object, I get a PHP Illegal offset type error. I've changed that to:
return $this->loadedTemplates[(string) $name] = new $cls($this);
and each of my resources have a __toString method that returns a unique identifier.
I think you could make that a bit more flexibe if those loadedTemplates was generated in a more flexibe way, maybe calling a method from the loader.
line 99:
case selg::BLOCK_END_TYPE:
must be
case self::BLOCK_END_TYPE:
It is ok to make nested array like this:
{{ ['Dog': ['name': 'Meow', 'has': ['tail', 'legs']]] }}
but when i'm trying to pass this array to some function
{{ table.drawAnimal(['Dog': ['name': 'Meow', 'has': ['tail', 'legs']]]) }}
i'm getting Fatal error: Maximum function nesting level of '100' reached, aborting!
but this is ok:
{{ table.drawAnimal(['Dog': ['name': 'Meow']]) }}
Hi all,
I plan to use twig in an opensource projects.
How can I support multiple language packs with the php function gettext (http://www.php.net/manual/en/function.gettext.php)?
Is there a filter available for this?
Many thanks
Michael
Node_Set could be used within custom nodes but it necessary to have an ability to specify a variable name results will be assigned to. For now it is hard coded as '$context'. The idea is to extend the class with a new method setVarName():
--- a/lib/Twig/Node/Set.php Wed Feb 17 15:18:58 2010 +0300 +++ b/lib/Twig/Node/Set.php Wed Feb 17 17:03:18 2010 +0300 @@ -5,6 +5,7 @@ protected $names; protected $values; protected $isMultitarget; + protected $var_name = '$context'; public function __construct($isMultitarget, $names, $values, $lineno, $tag = null) { @@ -15,6 +16,12 @@ $this->values = $values; } + public function setVarName($var_name) { + $this->var_name = $var_name; + + return $this; + } + public function __toString() { $repr = array(get_class($this).'('.($this->isMultitarget ? implode(', ', $this->names) : $this->names).','); @@ -62,7 +69,8 @@ } $compiler - ->raw('$context[') + ->raw($this->var_name) + ->raw('[') ->string($node->getName()) ->raw(']') ; @@ -72,7 +80,8 @@ else { $compiler - ->write('$context[') + ->write($this->var_name) + ->write('[') ->string($this->names->getName()) ->raw(']') ;
Hello !
I read the documentation and in the one for developpers ( http://www.twig-project.org/book/03-Twig-for-Developers ), it shows the use of nl2br filter.
Usefull filter ! So, I decided to use it.
However, it doesn't exist in the latest git release, I had to add it by and to the Twig_Extension_Core class.
Thanks for your fix :) and thanks a lot for your tool !
For a macro defined like this:
{% macro fancy_box(content,title) %}
<div class="box">
<div class="top"><h3>{{ title }}</h3></div>
<div class="content">{{ content }}</div>
<div class="bottom"></div>
</div>
{% endmacro %}
Instead of having to define all arguments first (or type them inline), it would be more natural to call it like this:
<div class="sidebar">
{% layout.fancy_box('Recent Posts') %}
<ul>
{% for link in recentPosts %}
<li><a href="{{ link.href }}">{{ link.title }}</a></li>
{% else %}
<li>No recent posts</li>
{% endfor %}
</ul>
{% end layout.fancy_box %}
</div>
Something like this lets designers easily build up abstractions on unavoidably messy chunks of HTML, such as one may often end up with when (e.g.) building resilient layouts that support older browsers. Of course we can already achieve the same thing with macros if we're willing to define the content chunk with a {% set %} tag first, but that hides the structure of the document: A 'fancy_box' is essentially an elaborate wrapper of its main content, and its better if it can look like it. We could also achieve something more like my desired calling syntax by writing fancy_box as a filter, but then we have design matters wrapped up in our PHP extension to Twig.
As far as the actual behavior of this syntax, the block content should become the first argument, pushing other arguments down. (So the block content becomes 'content', the first argument becomes 'title'.) This won't always make sense for macros not designed to be used this way, but I don't think that matters very much. I don't know if the tags can be implemented like I've suggested. Maybe it has to be:
{% use layout.fancy_box('Recent Posts') %}
...
{% enduse %}
Or something like that.
Is there any possibility of seeing a smarter trim_blocks
?
For example, here is some output while using trim_blocks
and my interpretation of what would be preferred.
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
{% if test %}<title>Test conditional.</title>{% endif %}
</head>
<body>
trim_blocks
output:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
or:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test conditional.</title></head>
<body>
prefered:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
or:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test conditional.</title>
</head>
<body>
It processes things a bit worse when you're using tags in a block format rather than inline.
Maybe the addition of a pretty
environment option that behaves like above if trim_blocks
is still wanted to mimic PHP's behavior?
As twig_length_filter uses strlen for strings it returns wrong values for strings in utf8 encoding.
I propose to implement it in this way:
function twig_length_filter($aValue) {
return is_string($aValue) ? mb_strlen($aValue, mb_detect_encoding($aValue)) : count($aValue);
}
Probably checks for multibyte support should be added.
Hello,
it's very common that one wants to color even and odd rows of a list/table/etc. with alternative colors. That's why I'm suggesting a shortcut variable 'loop.parity' that yields 'even' or 'odd'. It could be used like this:
<tr class="{{ loop.parity }}">...</tr>
Very readable, and it also makes the css code more readable.
Here's a patch:
*** Twig.orig/Node/For.php Wed Mar 17 21:39:34 2010 --- Twig/Node/For.php Thu Mar 18 02:17:57 2010 *************** *** 90,95 **** --- 90,96 ---- ->write(" 'revindex' => \$length,\n") ->write(" 'first' => true,\n") ->write(" 'last' => 1 === \$length,\n") + ->write(" 'parity' => 'odd',\n") ->write(");\n") ; } *************** *** 120,125 **** --- 121,127 ---- ->write("--\$context['loop']['revindex'];\n") ->write("\$context['loop']['first'] = false;\n") ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") + ->write("\$context['loop']['parity'] = (\$context['loop']['parity']==='even'?'odd':'even');\n") ; }
Class Twig_Extension
contain method getTokenParsers
wich return array of instances.
Does it possible return just class names and create they instances on demand? We can make memory usage lower by this.
Twig_TokenParser::getTag
need to be static.
When you do something like that :
{% for i in 1..nbLine %}
The "k" variable get back to 0 a the end of the second loop. Maybe not a bug , but the fact that it gets the context as it was before the loop began is not very convenient.
http://groups.google.com/group/twig-users/browse_thread/thread/f0fe0940519519d
I have objects with a few 'virtual' properties that are handled by the _ _get and _ _set magic functions. Twig doesn't check for this if i use something like {{ foo.bar }}.
According to the manual:
* check if foo is an array and bar a valid element;
* if not, and if foo is an object, check that bar is a valid property;
* if not, and if foo is an object, check that bar is a valid method;
* if not, and if foo is an object, check that getBar is a valid method;
* if not, return a null value.
I would like to see "if not, and if foo is an object, check that _ _get is a valid method and bar is returned by it" to this list.
Hello,
I wrote a custom filter that, in addition to doing the basic htmlspecialchars() type conversion, converts any \n to
. I named the filter "custom_br".
I'm using the autoescape functionality, and I'm pondering whether it was a good idea that certain filters could be marked as "escape-safe".
That is: currently I have to write in the template:
{{ myVariable|custom_br|safe }}
I feel that the "|safe" part is kind of unneeded, or somehow "wrong".
Comments?
Implementation:
Currently the getFilters() hook returns an array of filters like this:
return array(
'custom_br' => array('my_function_name', false)
);
I suggest an alternative syntax:
return array(
'custom_br' => array(
'function' => 'my_function_name' # required
'safe' => true, # optional
'passEnv' => false, # optional
)
)
);
This would allow adding further features, such as a 'deterministic' => true for adding performance.
AFAIK:
The option of YAML frontmatter at the beginning of a template is a great way to bootstrap template developers into the world of rendering templates they are developing. It increases the speed of development because template developers can see the consequences of their changes right away.
I've come up with a proof-of-concept that works on the command line with help from the sfYaml library: http://gist.github.com/319596
I've just created a node visitor and noticed, that it does not works inside macros. Problem is in Twig_Node_Module::getNodes(), there are should be something like this:
public function getNodes()
{
return array_merge(array($this->body), $this->blocks, $this->macros);
}
Now there is no support for calling closures. Call to 1st-level closure {{ closure('test') }} causes syntax error, call 2nd-level (and more) closure {{ some.closure('test') }} causes php error (can't convert closure to string)
Hello, I propose add two filters to Twig:
limitWords
limitChars
Instead of
"mb_strtolower(mb_substr($string, 1, mb_strlen($string), $env->getCharset()));"
there must be
"mb_strtolower(mb_substr($string, 1, mb_strlen($string), $env->getCharset()), $env->getCharset());"
I propose replace
$var = rand(1, 999999);
with
static $i = 0;
$var = $i++;
How do you access object properties (public or via __get method)?
Looks like setCurrentBlock was removed, but all references to it were not:
Fatal error: Call to undefined method Twig_Parser::setCurrentBlock() in /twig/lib/Twig/TokenParser/Display.php on line 21
I have the following code:
{% block head %}
This is the content of the HEAD block
{% block assets %}
This is the content of the ASSETS block
{% endblock assets %}
{% parent %} // LINE 13
{% endblock head %}
And i receive the following error:
Twig_SyntaxError: Calling "parent" outside a block is forbidden in layout.html at line 13
where the line 13 is the marked one!
Is this a Twig bug or a wrong usage of blocks and parent nodes?
Hello, Fabien.
Some time ago we have discuss about possibility make for
tag faster when magic variable .loop
not needed. You have implemented this feature in 0.9.5, thanks.
But:
02-Twig-for-Template-Designers.markdown
.loop
and don't want always print "without loop". Yes, I'm very lazy =). So: can you add settings for for
tag: by default make .loop
avalible in templates or not.Hello,
I have found a probrem:
Using a twig template contains the code like below causes fatal error;
Fatal error: Call to a member function getType() on a non-object in /www/testapp/lib/vendor/Twig/lib/Twig/TokenStream.php on line 87
{% if test=1 %}
something
//eof
The Twig documentation mentions:
+: Adds two objects together. Usually the objects are numbers but if both are strings or lists you can concatenate them this way. This however is not the preferred way to concatenate strings! For string concatenation have a look at the ~ operator. {{ 1 + 1 }} is 2.
However, the following code:
{{ 'hello' + 'world' }}
Produces:
0
So instead, the ~ operator must be used:
{{ 'hello' ~ 'world' }}
Which results in the expected:
helloworld
Since using a plus with PHP's mixed types is kind of messy, I would suggest dropping it for concatenation and using the ~ operator instead, and adjusting that in the docs.
I have not researched why it's not working as advertised.
It will be great to have not only "inline" macro executing syntax like
{{ mymacros.macro(arg1, arg2) }}
but also have additional "block" syntax, to pass blocks of code as arguments
{% emacro mymacros.macro %}
{% param arg1 %}
<h1>Heading</h1>
{% endparam %}
{% param arg2 %}
<p>Some markup</p>
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endparam %}
{% endemacro %}
Also we can leave "inline" way to pass arguments, but "block" arguments have advantage
{% emacro mymacros.macro('<h1>Heading</h1>') %}
{% param arg2 %}
<p>Some markup</p>
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endparam %}
{% endemacro %}
Hello Twig team,
This is not a bug actually.
I'm trying to make my own tag and parse it, but got some troubles.
Tag "hkfield" looks something like this:
{% hkfield name render "form" class "inp-black" style "width:120px" %}
where "name" is the object passed to template, all other string is key=>value pairs of parameters.
i.e. render="form"
There are can be some variable count of any type of parameters.
I try to parse them something like this
class HkFieldTokenParser extends Twig_TokenParser
{
public function parse(Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
$params = array();
$paramName = null;
while (!$stream->isEOF())
{
$token = $stream->next();
if ($token->getType()==Twig_Token::NAME_TYPE)
{
$paramName = $token->getValue();
$params[$paramName] = null;
}
if ($token->getType()==Twig_Token::STRING_TYPE)
{
$params[$paramName] = $token->getValue();
}
}
unset($params['name']);
return new HkFieldNode($name, $params, $lineno, $this->getTag());
}
public function getTag()
{
return 'hkfield';
}
}
The problem is: my object "name" renders correctly, but all the content of template which goes after my custom tag is missing.
Please help me understand the twig logic.
I am missing the nl2br filter
'nl2br' => new Twig_Filter_Function('nl2br'),[/code]
Hi,
We've just come up with a use case where we may want to be able to treat macros like any other variable (which is what they are) and nest a call to another macro from within a macro call itself, and have the output returned for use in the other macro.
An example if this would be:
{% macro row(label, content) %}
{% macro input(name, type, value) %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
{% endmacro %}
{% import "test.tpl" as form %}
{{ form.row(
'Label',
form.input('test', 'text', 'Value')
) }}
The problem is, this isn't possible at the moment for a few reasons:
I've just committed a change to my fork that allows the above to work, and also means that macros aren't passed through the escaper. Commit is here: http://github.com/chrisboulton/Twig/commit/4183bcc64c766c46fdeb2fe871c4cea50e0d32da
Any interest in pulling this in to the official releases?
There's a few things I don't like about what I've done - specifically the need to use ob_start() and ob_get_clean() to fetch the content of the macros - so improvements on that are welcome.
How do I write a 'truncate' filter so that it works with or without auto-escaping?
Let's say that myvar contains the string 'foo&bar'. Then, myvar|trunc(5) should yield 'foo&b'.
But if I have (html) auto-escaping on, the filter breaks! The filter function gets 'foo& bar' and thus returns 'foo&a' which is both logically incorrect AND invalid html.
Suggestion to fix: auto-escape only after the filters.
By default uses html autoescaping type. How can I change autoescape to js? Something like this
<head>
{% autoescape on js %}
<script type="text/javaxcript">
var lang = {
placeholder : {{lang.placeholder}},
txt2 : {{lang.txt2}}
}
</script>
{% endautoescape %}
obj['prop'] will return value only if obj is array and there is no way to get object property if we have it's name in a variable: obj[propName] will return null
In the getAttribute method, method_exists is used to see if the given twig template variable has a given method available. This should be changed to use is_callable instead to add support for magic methods.
(1) Create a large template
(2) The beginning of the template should be text only
(3) At the end of the template, have a for loop
Twig won't notice the for loop. It will think of it as text.
asdfasdfadsfadsfads
(repeat that maybe 300 times or so)
{% for x in y %}
print "bob"
Expected: A lot of text followed by an empty for loop
Seen: A lot of text followed by the literal characters { - % - - f - o - r ......
If it matters, I'm also using the sandbox extension and PHP 5.2.5
It would be great if expressions can be used within {% extends %} tag like in {% include %}
Example:
{% extends basePath ~ modulePath ~ 'my.html' %}
I'm trying to trim some whitespaces in templates so I introduced a new
filter trim (mapped to PHP's trim). I noticed that
{% filter trim %}
...some output...
{% endfilter %}
works fine alone, inside {% block %} but not inside {% macro %}.
Also checked with some pre-defined filters as upper.
{{ someimport.somemacro(somevar)|upper }} also doesn't works.
Quote from docs:
For convenience sake
foo.bar
does the following things on
the PHP layer:
- check if
foo
is an array andbar
a valid element;
-----
- if not, and if
foo
is an object, check thatbar
is a valid property;- if not, and if
foo
is an object, check thatbar
is a valid method
(even ifbar
is the constructor - use__construct()
instead);- if not, and if
foo
is an object, check thatgetBar
is a valid method;
-----
- if not, return a
null
value.
I propose add to options possibility to disable all steps between -----
. Yes, I can use foo['bar']
in templates for this, but foo.bar
more usable.
Hi,
Page:
columns:...
relations:
Category: { class: Category, foreignAlias: Pages, onDelete: CASCADE }
and then
{% for page in category.pages %}
Twig will not call category->getPages(), it checks whether exist function category->getpages() ... its ok in php but Doctrine itself seems case sensitive and it will not work. If i try category.Pages instead, it will end up with same result (is there somewhere strtolower on args?).
I think that in
Twig/lib/Twig/Node/Block.php lib/Twig/Node/Block.php on line 68
instead :
->write(sprintf("public function block_%s($context)\n", $this->name), "{\n")
must be:
->write(sprintf("public function block_%s(&$context)\n", $this->name), "{\n")
This need in case when need set value to context in child template and then parent read that value.
{% if key == formData[name] %} is true when key = 0 and formData[name] = 'all'
If I do the following this fixes it but it is nasty: {% if key~ == formData[name] %}
Since I'm having problems formatting this in GIT... I'll have to pastebin the information:
Variables passed to macros are not automaticaly escaped, but autoescape is turned on
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.