Commit Graph

15319 Commits

Author SHA1 Message Date
tweini 90d59ea6cd Update FormTypeCsrfExtension.php
There is no need to store the FormFactory in an Attribute.
The FormFactory can be retrieved directly.
2013-09-25 07:26:45 +02:00
Fabien Potencier 5ebaad33e6 added a note about why the debug dispatcher cannot be used everywhere 2013-09-23 18:04:04 +02:00
Fabien Potencier 5ed1d01449 Merge branch '2.3'
* 2.3:
  Revert "merged branch fabpot/event-dispatcher-debug (PR #9068)"
2013-09-23 17:56:38 +02:00
Fabien Potencier c60a8e962b Merge branch '2.2' into 2.3
* 2.2:
  Revert "merged branch fabpot/event-dispatcher-debug (PR #9068)"

Conflicts:
	src/Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.php
	src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.php
2013-09-23 17:56:30 +02:00
Fabien Potencier c2f935593d Revert "merged branch fabpot/event-dispatcher-debug (PR #9068)"
This reverts commit 1843b82015, reversing
changes made to 510960ed31.
2013-09-23 17:54:49 +02:00
Fabien Potencier c43c35cd17 [ExpressionLanguage] fixed CS 2013-09-23 12:22:40 +02:00
Fabien Potencier db00c3f510 merged branch adrienbrault/expression-cache (PR #9095)
This PR was squashed before being merged into the master branch (closes #9095).

Discussion
----------

[ExpressionLanguage] Introduce a ParserCacheInterface with array/doctrine implementations

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | N/A
| License       | MIT
| Doc PR        | N/A

Commits
-------

c8e6799 [ExpressionLanguage] Introduce a ParserCacheInterface with array/doctrine implementations
2013-09-23 12:19:21 +02:00
Adrien Brault c8e679970e [ExpressionLanguage] Introduce a ParserCacheInterface with array/doctrine implementations 2013-09-23 12:19:21 +02:00
Fabien Potencier 92e940fd14 merged branch fabpot/max-password-length (PR #9100)
This PR was merged into the master branch.

Discussion
----------

[Security] limited the password length passed to encoders

Commits
-------

f7d0ec6 [Security] limited the password length passed to encoders
2013-09-23 09:32:35 +02:00
Fabien Potencier f7d0ec6f4a [Security] limited the password length passed to encoders 2013-09-23 09:15:09 +02:00
Fabien Potencier b1542f0620 Merge branch '2.3'
* 2.3:
  [Locale] added support for the position argument to NumberFormatter::parse()
  [Locale] added some more stubs for the number formatter
  [Yaml] fixed typo
  [Yaml] fixed a test on PHP < 5.4
  [DomCrawler]Crawler guess charset from html
  fixed PHP 5.3 compatibility
  [Yaml] reverted previous merge partially (refs #8897)
  [Security] remove unused logger
  [Security] fix typo
  [Yaml] Fixed filename in the ParseException message
2013-09-22 20:04:51 +02:00
Fabien Potencier 775a39c5c3 Merge branch '2.2' into 2.3
* 2.2:
  [Locale] added support for the position argument to NumberFormatter::parse()
  [Locale] added some more stubs for the number formatter
  [Yaml] fixed typo
  [Yaml] fixed a test on PHP < 5.4
  [DomCrawler]Crawler guess charset from html
  fixed PHP 5.3 compatibility
  [Yaml] reverted previous merge partially (refs #8897)
  [Security] remove unused logger
  [Security] fix typo
  [Yaml] Fixed filename in the ParseException message

Conflicts:
	src/Symfony/Component/Console/Input/InputDefinition.php
	src/Symfony/Component/Locale/Stub/StubNumberFormatter.php
	src/Symfony/Component/Locale/Tests/Stub/StubNumberFormatterTest.php
2013-09-22 20:04:39 +02:00
Fabien Potencier 55560e0590 merged branch fabpot/locale-fix (PR #9098)
This PR was merged into the 2.2 branch.

Discussion
----------

[Locale] added some more stubs for the number formatter

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8588, #6045
| License       | MIT
| Doc PR        | n/a

I've used this snippet of code to populate the default values for the en locale:

```php
for ($style = 0; $style <= 8; $style++) {
    $f = new \NumberFormatter('en', $style);
    echo 'array(';
    for ($i = 0; $i <= 17; $i++) {
        echo "'".$f->getSymbol($i)."', ";
    }

    echo "),\n";
}
```

Commits
-------

3108c71 [Locale] added support for the position argument to NumberFormatter::parse()
0774c79 [Locale] added some more stubs for the number formatter
2013-09-22 19:46:20 +02:00
Fabien Potencier 3108c715db [Locale] added support for the position argument to NumberFormatter::parse() 2013-09-22 19:34:01 +02:00
Fabien Potencier 0774c79678 [Locale] added some more stubs for the number formatter 2013-09-22 19:34:01 +02:00
Fabien Potencier 2e87d1d3f9 [Yaml] fixed typo 2013-09-22 19:30:19 +02:00
Fabien Potencier 213b888ea4 [Yaml] fixed a test on PHP < 5.4 2013-09-22 19:26:55 +02:00
Fabien Potencier 8aa685bbe9 merged branch fabpot/expression-language-tweaks (PR #9091)
This PR was merged into the master branch.

Discussion
----------

[ExpressionLanguage] made minor tweaks

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9087
| License       | MIT
| Doc PR        | n/a

 * made ExpressionLanguage::parse return an ParsedExpression instance
 * optimized the size of the serialization of expressions

Commits
-------

e869136 [ExpressionLanguage] renamed addFunction() to register()
5076ec7 [ExpressionLanguage] optimized serialization of nodes and expressions
60b9f85 [ExpressionLanguage] made ExpressionLanguage::parse return an ParsedExpression instance
2013-09-21 20:31:30 +02:00
Fabien Potencier 846fd49800 merged branch tecbot/patch-1 (PR #9092)
This PR was merged into the master branch.

Discussion
----------

use "translator" alias not "translator.default"

Validator is the only instance which references to the "translator.default" service. It should reference to the "translator" service so the validator can use a custom validator if the user overwrites the "translator" alias.

Commits
-------

9e38819 use "translator" alias not "translator.default"
2013-09-21 20:26:04 +02:00
Fabien Potencier e8691366ce [ExpressionLanguage] renamed addFunction() to register() 2013-09-21 20:20:49 +02:00
Adrien Brault 5076ec7e90 [ExpressionLanguage] optimized serialization of nodes and expressions 2013-09-21 20:20:49 +02:00
Fabien Potencier 60b9f856fd [ExpressionLanguage] made ExpressionLanguage::parse return an ParsedExpression instance 2013-09-21 20:20:49 +02:00
Thomas Adam 9e38819cef use "translator" alias not "translator.default" 2013-09-20 15:35:24 +02:00
Fabien Potencier f73aa37064 merged branch bronze1man/pr-2.2-crawler (PR #9074)
This PR was squashed before being merged into the 2.2 branch (closes #9074).

Discussion
----------

[DomCrawler]Crawler guess charset from html

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |  #9061
| License       | MIT
| Doc PR        | n/a

Commits
-------

e5282e8 [DomCrawler]Crawler guess charset from html
2013-09-19 18:37:12 +02:00
bronze1man e5282e8ec0 [DomCrawler]Crawler guess charset from html 2013-09-19 18:37:12 +02:00
Fabien Potencier 8552aa4834 fixed PHP 5.3 compatibility 2013-09-19 18:27:31 +02:00
Fabien Potencier 38f7ef0539 [Yaml] reverted previous merge partially (refs #8897) 2013-09-19 18:24:31 +02:00
Fabien Potencier 1b789d2d16 merged branch unkind/bugfix-yaml-parse-exception (PR #8897)
This PR was merged into the 2.2 branch.

Discussion
----------

[Yaml] Fixed filename in the ParseException message

| Q             | A
| ------------- | ---
| Bug fix?      | sort of
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | —
| License       | MIT
| Doc PR        | —

Yaml component throws an exception with corrupt filename because of `json_encode`:

```
[Symfony\Component\Yaml\Exception\ParseException]
A YAML file cannot contain tabs as indentation in "\/var\/www\/app\/config.yml" at line 42 (near "	foo: bar").
```

Commits
-------

da44651 [Yaml] Fixed filename in the ParseException message
2013-09-19 18:22:28 +02:00
Fabien Potencier 77d3a857da merged branch liuggio/master (PR #9077)
This PR was merged into the master branch.

Discussion
----------

[HttpKernel] [Fragment] Fixed CS

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        |  -

Only two simple CS fixes.

Commits
-------

7d53314 [HttpKernel] Fragment Fixed CS
2013-09-19 18:16:36 +02:00
Fabien Potencier ca62f65887 merged branch fabpot/expression-engine (PR #8913)
This PR was merged into the master branch.

Discussion
----------

New Component: Expression Language

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8850, #7352
| License       | MIT
| Doc PR        | not yet

TODO:

 - [ ] write documentation
 - [x] add tests for the new component
 - [x] implement expression support for access rules in the security component
 - [x] find a better character/convention for expressions in the YAML format
 - [x] check the performance of the evaluation mode
 - [x] better error messages in the evaluation mode
 - [x] add support in the Routing
 - [x] add support in the Validator

The ExpressionLanguage component provides an engine that can compile and
evaluate expressions.

An expression is a one-liner that returns a value (mostly, but not limited to, Booleans).

It is a strip-down version of Twig (only the expression part of it is
implemented.) Like Twig, the expression is lexed, parsed, and
compiled/evaluated. So, it is immune to external injections by design.

If we compare it to Twig, here are the main big differences:

 * only support for Twig expressions
 * no ambiguity for calls (foo.bar is only valid for properties, foo['bar'] is only valid for array calls, and foo.bar() is required for method calls)
 * no support for naming conventions in method calls (if the method is named getFoo(), you must use getFoo() and not foo())
 * no notion of a line for errors, but a cursor (we are mostly talking about one-liners here)
 * removed everything specific to the templating engine (like output escaping or filters)
 * no support for named arguments in method calls
 * only one extension point with functions (no possibility to define new operators, ...)
 * and probably even more I don't remember right now
 * there is no need for a runtime environment, the compiled PHP string is self-sufficient

An open question is whether we keep the difference betweens arrays and hashes.

The other big difference with Twig is that it can work in two modes (possible
because of the restrictions described above):

 * compilation: the expression is compiled to PHP and is self-sufficient
 * evaluation: the expression is evaluated without being compiled to PHP (the node tree produced by the parser can be serialized and evaluated afterwards -- so it can be saved on disk or in a database to speed up things when needed)

Let's see a simple example:

```php
$language = new ExpressionLanguage();

echo $language->evaluate('1 + 1');
// will echo 2

echo $language->compile('1 + 2');
// will echo "(1 + 2)"
```

The language supports:

 * all basic math operators (with precedence rules):
    * unary: not, !, -, +
    * binary: or, ||, and, &&, b-or, b-xor, b-and, ==, ===, !=, !==, <, >, >=, <=, not in, in, .., +, -, ~, *, /, %, **

 * all literals supported by Twig: strings, numbers, arrays (`[1, 2]`), hashes
   (`{a: "b"}`), Booleans, and null.

 * simple variables (`foo`), array accesses (`foo[1]`), property accesses
   (`foo.bar`), and method calls (`foo.bar(1, 2)`).

 * the ternary operator: `true ? true : false` (and all the shortcuts
   implemented in Twig).

 * function calls (`constant('FOO')` -- `constant` is the only built-in
   functions).

 * and of course, any combination of the above.

The compilation is better for performances as the end result is just a plain PHP string without any runtime. For the evaluation, we need to tokenize, parse, and evaluate the nodes on the fly. This can be optimized by using a `ParsedExpression` or a `SerializedParsedExpression` instead:

```php
$nodes = $language->parse($expr, $names);
$expression = new SerializedParsedExpression($expr, serialize($nodes));

// You can now store the expression in a DB for later reuse

// a SerializedParsedExpression can be evaluated like any other expressions,
// but under the hood, the lexer and the parser won't be used at all, so it''s much faster.
$language->evaluate($expression);
```
That's all folks!

I can see many use cases for this new component, and we have two use cases in
Symfony that we can implement right away.

## Using Expressions in the Service Container

The first one is expression support in the service container (it would replace
#8850) -- anywhere you can pass an argument in the service container, you can
use an expression:

```php
$c->register('foo', 'Foo')->addArgument(new Expression('bar.getvalue()'));
```

You have access to the service container via `this`:

    container.get("bar").getvalue(container.getParameter("value"))

The implementation comes with two functions that simplifies expressions
(`service()` to get a service, and `parameter` to get a parameter value). The
previous example can be simplified to:

    service("bar").getvalue(parameter("value"))

Here is how to use it in XML:

```xml
<parameters>
    <parameter key="value">foobar</parameter>
</parameters>
<services>
    <service id="foo" class="Foo">
        <argument type="expression">service('bar').getvalue(parameter('value'))</argument>
    </service>
    <service id="bar" class="Bar" />
</services>
```

and in YAML (I chose the syntax randomly ;)):

```yaml
parameters:
    value: foobar

services:
    bar:
        class: Bar

    foo:
        class: Foo
        arguments: [@=service("bar").getvalue(parameter("value"))]
```

When using the container builder, Symfony uses the evaluator, but with the PHP
dumper, the compiler is used, and there is no overhead as the expression
engine is not needed at runtime. The expression above would be compiled to:

```php
$this->get("bar")->getvalue($this->getParameter("value"))
```

## Using Expression for Security Access Control Rules

The second use case in Symfony is for access rules.

As we all know, the way to configure the security access control rules is confusing, which might lead to insecure applications (see http://symfony.com/blog/security-access-control-documentation-issue for more information).

Here is how the new `allow_if` works:

```yaml
access_control:
    - { path: ^/_internal/secure, allow_if: "'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" }
```

This one restricts the URLs starting with `/_internal/secure` to people browsing from the localhost. Here, `request` is the current Request instance. In the expression, there is access to the following variables:

 * `request`
 * `token`
 * `user`

And to the following functions:

 * `is_anonymous`
 * `is_authenticated`
 * `is_fully_authenticated`
 * `is_rememberme`
 * `has_role`

You can also use expressions in Twig, which works well with the `is_granted` function:

```jinja
{% if is_granted(expression('has_role("FOO")')) %}
   ...
{% endif %}
```

## Using Expressions in the Routing

Out of the box, Symfony can only match an incoming request based on some pre-determined variables (like the path info, the method, the scheme, ...). But some people want to be able to match on more complex logic, based on other information of the Request object. That's why we introduced `RequestMatcherInterface` recently (but we no default implementation in Symfony itself).

The first change I've made (not related to expression support) is implement this interface for the default `UrlMatcher`. It was simple enough.

Then, I've added a new `condition` configuration for Route objects, which allow you to add any valid expression. An expression has access to the `request` and to the routing `context`.

Here is how one would configure it in a YAML file:

```yaml
hello:
    path: /hello/{name}
    condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') =~ '/firefox/i'"
```

Why do I keep the context as all the data are also available in the request? Because you can also use the condition without using the RequestMatcherInterface, in which case, you don't have access to the request. So, the previous example is equivalent to:

```yaml
hello:
    path: /hello/{name}
    condition: "request.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') =~ '/firefox/i'"
```

When using the PHP dumper, there is no overhead as the condition is compiled. Here is how it looks like:

```php
// hello
if (0 === strpos($pathinfo, '/hello') && preg_match('#^/hello/(?P<name>[^/]++)$#s', $pathinfo, $matches) && (in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD")) && preg_match("/firefox/i", $request->headers->get("User-Agent")))) {
    return $this->mergeDefaults(array_replace($matches, array('_route' => 'hello')), array ());
}
```

Be warned that conditions are not taken into account when generating a URL.

## Using Expressions in the Validator

There is a new Expression constraint that you can put on a class. The expression is then evaluated for validation:

```php
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @Assert\Condition(condition="this.getFoo() == 'fo'", message="Not good!")
 */
class Obj
{
    public function getFoo()
    {
        return 'foo';
    }
}
```

In the expression, you get access to the current object via the `this` variable.

## Dynamic annotations

The expression language component is also very useful in annotations. the SensoLabs FrameworkExtraBundle leverages this possibility to implement HTTP validation caching in the `@Cache` annotation and to add a new `@Security` annotation (see sensiolabs/SensioFrameworkExtraBundle#238.)

Commits
-------

d4ebbfd [Validator] Renamed Condition to Expression and added possibility to set it onto properties
a3b3a78 [Validator] added a constraint that runs an expression
1bcfb40 added optimized versions of expressions
984bd38 mades things more consistent for the end user
d477f15 [Routing] added support for expression conditions in routes
86ac8d7 [ExpressionLanguage] improved performance
e369d14 added a Twig extension to create Expression instances
38b7fde added support for expression in control access rules
2777ac7 [HttpFoundation] added ExpressionRequestMatcher
c25abd9 [DependencyInjection] added support for expressions in the service container
3a41781 [ExpressionLanguage] added support for regexes
9d98fa2 [ExpressionLanguage] added the component
2013-09-19 13:00:34 +02:00
Bernhard Schussek d4ebbfd02d [Validator] Renamed Condition to Expression and added possibility to set it onto properties 2013-09-19 12:59:33 +02:00
Fabien Potencier a3b3a78237 [Validator] added a constraint that runs an expression 2013-09-19 12:59:12 +02:00
Fabien Potencier 1bcfb40eb5 added optimized versions of expressions 2013-09-19 12:59:12 +02:00
Fabien Potencier 984bd38568 mades things more consistent for the end user 2013-09-19 12:59:11 +02:00
Fabien Potencier d477f157ce [Routing] added support for expression conditions in routes 2013-09-19 12:59:11 +02:00
Fabien Potencier 86ac8d7547 [ExpressionLanguage] improved performance 2013-09-19 12:59:11 +02:00
Fabien Potencier e369d14a2c added a Twig extension to create Expression instances 2013-09-19 12:59:11 +02:00
Fabien Potencier 38b7fde8ed added support for expression in control access rules 2013-09-19 12:59:11 +02:00
Fabien Potencier 2777ac7854 [HttpFoundation] added ExpressionRequestMatcher 2013-09-19 12:59:11 +02:00
Fabien Potencier c25abd9c72 [DependencyInjection] added support for expressions in the service container 2013-09-19 12:59:10 +02:00
Fabien Potencier 3a41781640 [ExpressionLanguage] added support for regexes 2013-09-19 12:59:10 +02:00
Fabien Potencier 9d98fa25ec [ExpressionLanguage] added the component 2013-09-19 12:59:10 +02:00
Fabien Potencier ed60d39767 Merge brant pushch '2.3'
* 2.3:
  Fix `use` statements in HttpKernel\Client
2013-09-19 12:55:38 +02:00
Fabien Potencier 714d719383 merged branch stloyd/bugfix/use_statement (PR #9079)
This PR was merged into the 2.3 branch.

Discussion
----------

Fix `use` statements in HttpKernel\Client

Commits
-------

5d5ea9a Fix `use` statements in HttpKernel\Client
2013-09-19 12:55:30 +02:00
Joseph Bielawski 5d5ea9a992 Fix `use` statements in HttpKernel\Client 2013-09-19 12:49:28 +02:00
Fabien Potencier 8d6131f7f4 Merge branch '2.3'
* 2.3:
  fixed Git conflict
2013-09-19 12:37:07 +02:00
Fabien Potencier d502e32cb5 fixed Git conflict 2013-09-19 12:35:49 +02:00
Giulio De Donato 7d53314b36 [HttpKernel] Fragment Fixed CS 2013-09-19 12:32:30 +02:00
Fabien Potencier 6a36fb6311 merged branch Tobion/security-fix-typo (PR #9069)
This PR was merged into the 2.2 branch.

Discussion
----------

[Security] fix typo and remove unused logger

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT

Commits
-------

a33cc51 [Security] remove unused logger
62de9c1 [Security] fix typo
2013-09-19 11:48:50 +02:00
Fabien Potencier 12c0b74eac merged branch nicolas-bastien/remove_unsued_statement (PR #9075)
This PR was merged into the master branch.

Discussion
----------

[Security] Remove unused use statement

Commits
-------

6981669 Remove unused use statement
2013-09-19 11:48:08 +02:00