Commit Graph

109 Commits

Author SHA1 Message Date
Fabien Potencier
920c6814fe bug #9910 fixed missing use statements (fabpot)
This PR was merged into the 2.4 branch.

Discussion
----------

fixed missing use statements

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

Commits
-------

50a6d70 fixed missing use statements
2013-12-31 12:02:51 +01:00
Fabien Potencier
50a6d706c4 fixed missing use statements 2013-12-31 11:50:12 +01:00
Fabien Potencier
ef3ae9cf45 Merge branch '2.3' into 2.4
* 2.3: (31 commits)
  Fix parent serialization of user object
  [DependencyInjection] fixed typo
  add memcache, memcached, and mongodb extensions to run skipped tests
  [DependencyInjection] Fixed support for backslashes in service ids.
  fix #9356 [Security] Logger should manipulate the user reloaded from provider
  [BrowserKit] fixes #8311 CookieJar is totally ignorant of RFC 6265 edge cases
  [HttpFoundation] fixed constants that do exist in 2.3 (only in 2.4)
  fix 5528 let ArrayNode::normalizeValue respect order of value array provided
  fix #7243 allow 0 as arraynode name
  Fixed issue in BaseDateTimeTransformer when invalid timezone cause Transformation filed exception (closes #9403).
  BinaryFileResponse should also return 416 or 200 on some range-requets
  Do normalization on tag options
  bumped Symfony version to 2.3.9
  updated VERSION for 2.3.8
  update CONTRIBUTORS for 2.3.8
  updated CHANGELOG for 2.3.8
  [Filesystem] Changed the mode for a target file in copy() to be write only.
  [Console] fixed CS
  fixed TableHelper when cell value has new line
  Improved and fixed grammar mistakes. Added pluralized messages
  ...

Conflicts:
	src/Symfony/Component/BrowserKit/Cookie.php
	src/Symfony/Component/HttpKernel/Kernel.php
	src/Symfony/Component/Routing/Matcher/UrlMatcher.php
2013-12-26 08:59:03 +01:00
Daniel Tschinder
557dfaa2c1 Remove usage of deprecated _scheme in Routing Component
Instead correctly use the array of schemes from the Route.
Also adjusted the dumpers to dump the correct data.

I extended the tests to not only test the deprecated behavior, but also
the new schemes-requirement.
2013-12-13 00:37:21 +01: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
Fabien Potencier
d477f157ce [Routing] added support for expression conditions in routes 2013-09-19 12:59:11 +02:00
bronze1man
de39bd5433 Fix some annotates 2013-09-19 11:36:05 +02:00
Jean-François Simon
c138304823 [routing] added ability for apache matcher to handle array values 2013-07-30 13:22:46 +02:00
Fabien Potencier
7d581471ce removed dead code and fixed CS 2013-07-28 20:26:16 +02:00
Fabien Potencier
94f6116f42 renamed hostname to host in the routing system (closes #6775)
As explained in #6775, this has been done for the following reasons:

1. It's also Request::getHost()
2. The term hostname has been obsoleted in
http://tools.ietf.org/html/rfc3986#appendix-D.2 and uses the host only
3. hostname in the RFC was defined as the registered domain name, but we
probably also want to match IP-Adresses with the pattern which is the
host = IP-literal / IPv4address / reg-name for.
2013-01-21 17:57:32 +01:00
Florin Patan
c2acc6c2cb Fixed most of the docblocks/unused namespaces 2012-12-19 08:09:49 +01:00
Tobias Schultze
9ab5e4f5c7 fix typos in PhpMatcherDumper 2012-12-14 23:50:21 +01:00
Pascal Borreli
60eeacd2d1 Fixed typos 2012-12-14 22:27:02 +00:00
Victor Berchet
70a69d4874 [Routing] fix typo 2012-12-11 17:22:27 +01:00
Tobias Schultze
98f3ca8395 [Routing] removed tree structure from RouteCollection 2012-11-26 18:28:37 +01:00
Fabien Potencier
077bd35f7b merged branch Tobion/routing-pcre (PR #6064)
This PR was merged into the master branch.

Commits
-------

824a0f3 [Routing] compatibility with older PCRE (pre 8)

Discussion
----------

[Routing] compatibility with older PCRE (pre 8)

#6062 for master
2012-11-19 13:32:30 +01:00
Fabien Potencier
cec11fa08a Merge branch '2.1'
* 2.1:
  [Routing] made it compatible with older PCRE version (pre 8)
  tiny refactoring for consistency
  fixed docblock return type
  Added HttpCache\Store::generateContentDigest() + changed visibility

Conflicts:
	src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php
	src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php
	src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php
	src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php
	src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php
	src/Symfony/Component/Routing/Tests/RouteCompilerTest.php
2012-11-19 13:32:16 +01:00
Tobias Schultze
824a0f3ef6 [Routing] compatibility with older PCRE (pre 8) 2012-11-19 13:02:22 +01:00
Tobias Schultze
1daefa5f4b [Routing] made it compatible with older PCRE version (pre 8) 2012-11-19 10:25:59 +01:00
Tobias Schultze
38802ea32c remove logic that could not be triggered anyway
the regex by the compiler is always valid. even if it was invalid like '' it wasn't caught by the exception and would have given a php notice.
2012-11-17 16:58:52 +01:00
Pascal Borreli
f7ea68f70c [Routing] Fixed undefined variable + typo 2012-11-17 14:39:14 +00:00
Tobias Schultze
1e1cb13faf [Routing] added more phpdoc and replaced 'array of type' by 'Type[]' 2012-11-12 16:14:50 +01:00
Tobias Schultze
26e56842dc some type fixes 2012-11-12 11:54:32 +01:00
Tobias Schultze
514e27a511 [Routing] fix PhpMatcherDumper that returned numeric-indexed params that are returned besides named placeholders by preg_match 2012-11-12 11:54:32 +01:00
Tobias Schultze
7ed3013a5b switch to array_replace instead of array_merge
we don't need the logic to merge numeric keys, as we don't have them. I could also improve the genrated code by PhpMatcherDumper a little by saving a function call.
2012-11-12 11:54:29 +01:00
Arnaud Le Blanc
6cd34570d7 fixed CS 2012-11-12 11:35:46 +01:00
Arnaud Le Blanc
a8ce6210b3 [Routing] added support for hostname in the apache matcher dumper 2012-11-12 11:35:18 +01:00
Fabien Potencier
1489021552 fixed CS 2012-11-12 11:14:25 +01:00
Arnaud Le Blanc
85d11af880 [Routing] added hostname matching support to PhpMatcherDumper 2012-11-12 11:14:24 +01:00
Fabien Potencier
a0887224bb merged branch arnaud-lb/apache-dumper (PR #5792)
This PR was merged into the master branch.

Commits
-------

c7a8f7a [Routing] fixed possible parameters conflict in apache url matcher

Discussion
----------

[Routing] fixed possible parameters conflict in apache url matcher

Bug fix: yes
Feature addition: no
Backwards compatibility break: no (as long as rewrite rules are generated after upgrading)
Symfony2 tests pass: yes

- This fixes a conflict in route parameters:

  The rewrite rules currently pass route informations through environment variables:

  `_ROUTING_DEFAULT_x`: passes the default value of parameter x
  `_ROUTING__allow_x`: passes the information that method x was allowed for this route
  `_ROUTING_x`: passes the value of parameter x

  The problem is that naming a route parameter `DEFAULT_*` or `_allow_*` would not behave as expected.

  I fixed this by namespacing all environment variables; e.g. parameters are in `_ROUTING_param_*`, defaults in `_ROUTING_default_*`, etc.

- The PR fixes a second issue: sometimes the variables are prefixed with multiple REDIRECT_. This PR handles this case by ignoring them all.

- This also improves performance a little:

  Matching a route with two parameters and two default parameters 100K times: (`$_SERVER` was copied from a real request, so with many non `_ROUTING_` variables)
  master: 6.6s
  this branch: 4.7s

---------------------------------------------------------------------------

by fabpot at 2012-10-27T13:37:24Z

Any news on this PR? Is it mergeable?

---------------------------------------------------------------------------

by arnaud-lb at 2012-10-27T14:50:08Z

There is an issue with default parameter values, I can't find how to fix that in a simple way. Before this PR, default values are never used (if a parameter is an optional not present in the url, the parameter's value is the empty string); after this PR, when a parameter is present and empty (e.g. a requirement like `.*`), its value is set to its default value.

---------------------------------------------------------------------------

by Tobion at 2012-10-29T01:36:08Z

The problem is, it's not consistent with the default php matcher. So one cannot safely exchange it with the apache matcher because it behaves differently under some (special) circumstances.

---------------------------------------------------------------------------

by fabpot at 2012-11-05T08:05:54Z

We need to move forward as I want to merge the hostname support in the routing ASAP to have plenty of time for feedback before the 2.2 release.

Does it sound reasonable to merge this PR as is an open a ticket about the remaining issue (which should not occur that often anyways)?

---------------------------------------------------------------------------

by arnaud-lb at 2012-11-05T09:22:02Z

@fabpot it sounds reasonable to me. Also, I've the hostname support branch is currently rebased so that it can be merged without this one.

---------------------------------------------------------------------------

by Tobion at 2012-11-11T21:50:20Z

Btw, does the ApacheMatcherDumper handle the _scheme requirement? It doesn't look like it. This would be another bug.
Anyway, we can probably merge this PR and open new issues for the remaining bugs.
2012-11-12 10:36:54 +01:00
Fabien Potencier
275cf8cf00 removed unused use statements 2012-11-04 09:30:21 +01:00
Arnaud Le Blanc
c7a8f7af62 [Routing] fixed possible parameters conflict in apache url matcher 2012-10-20 00:39:25 +02:00
Arnaud Le Blanc
e54d749d05 [Routing] Simplified php matcher dumper (and optimized generated matcher) 2012-10-16 20:50:15 +02:00
Tobias Schultze
4f57d69789 [Routing] removed cyclic reference Route<->CompiledRoute 2012-08-23 10:21:02 +02:00
Pascal Borreli
4c726ea64c Fixed Phpdoc 2012-07-28 16:07:17 +00:00
Fabien Potencier
7b0d100e02 merged 2.0 2012-07-13 16:05:38 +02:00
Hugo Hamon
e9d799ce2c [Routing] fixed ApacheUrlMatcher and ApachMatcherDumper classes that did not take care of default parameters in urls. 2012-07-13 10:17:40 +02:00
Fabien Potencier
d100ffaf76 fixed CS 2012-07-09 14:54:20 +02:00
Fabien Potencier
03d22b74ec fixed CS (mainly method signatures) 2012-07-09 14:43:50 +02:00
Tobias Schultze
680e732a9e [Routing] fix phpDoc
using inheritdoc where possible and removing api tag when parent interface has one
2012-06-10 21:30:17 +02:00
Fabien Potencier
335d4eab86 fixed CS 2012-05-21 22:27:15 +02:00
Fabien Potencier
c01fed0c89 fixed CS 2012-05-21 22:25:19 +02:00
Fabien Potencier
41621e42e9 fixed phpdoc @param alignment 2012-05-15 22:19:31 +02:00
Fabien Potencier
ce9791246b fixed phpdoc @param alignment 2012-05-15 18:56:32 +02:00
Fabien Potencier
26f933e7bd fixed CS 2012-05-01 15:23:48 +02:00
Tobias Schultze
cb47b03209 [Routing] small refactoring + language fixes 2012-04-12 21:23:30 +02:00
Tobias Schultze
f666836900 [Routing] simplified regex with named variables 2012-04-11 18:27:19 +02:00
Tobias Schultze
9307f5b33b [Routing] Implement bug fixes and enhancements 2012-04-11 15:45:27 +02:00
Fabien Potencier
c7ba1b9605 merged 2.0 2012-04-11 09:33:57 +02:00
Victor Berchet
6465a6987a [Routing] Fixes to handle spaces in route pattern
- The route compiler does not add extra space or line-feed,
- The generated regex does not use the 'x' modified any more,
- The PHP and apache matchers do not need to strip any chars (vs space and line feed before),
- The space characters are escaped according to the apache format
2012-04-10 17:29:34 +02:00