Some explanations on how it works now:
* The Session is an optional dependency of the Request. If you create the
Request yourself (which is mandatory now in the front controller) and if
you don't inject a Session yourself (which is recommended if you want the
session to be configured via dependency injection), the Symfony2 Kernel
will associate the Session configured in the Container with the Request
automatically.
* When duplicating a request, the session is shared between the parent and
the child (that's because duplicated requests are sub-requests of the main
one most of the time.) Notice that when you use ::create(), the behavior is
the same as for the constructor; no session is attached to the Request.
* Symfony2 tries hard to not create a session cookie when it is not needed
but a Session object is always available (the cookie is only created when
"something" is stored in the session.)
* Symfony2 only starts a session when:
* A session already exists in the request ($_COOKIE[session_name()] is
defined -- this is done by RequestListener);
* There is something written in the session object (the cookie will be sent
to the Client).
* Notice that reading from the session does not start the session anymore (as
we don't need to start a new session to get the default values, and because
if a session exists, it has already been started by RequestListener.)
Because that's just not possible (have a look at the unit tests to see all possibilities
-- as you will notice, there is no way we can determine the context and whether the
data are already escaped or not).
So, we always escape data, which means that sometimes, we will try to escape already
escaped data. This is not a problem for everything except strings. That's because
strings are not wrapped with an object like everything else (for performance reason).
This means that all escapers must be able to avoid double-escaping (that's the case
for the default escapers as both htmlspecialchars() and htmlentities() have a flag
that does just this).
This is not really a bug or a big issue, but if you need to temporarily empty a routes node, Symfony shouldn't care - it's not an actual validation failure (a routes node still makes sense without an route or import children).
Fields can now easier support different data types in their underlying object.
These datatypes can be normalized to a single datatype using a normalization
transformer. The normalized value can then be transformed to the user's
representation with the value transformer (better name required?).
This fixes a bug in UniversalClassLoader when attempting to autoload class names with leading slashes:
$namespacedClass = "\\Foo\\Bar";
$pearlikeClass = "\\Foo_Bar";
$namespaced = new $namespacedClass();
$pearlike = new $pearlikeClass();
`UniversalClassLoader::loadClass()` was unable to load PEAR-like classes with leading slashes because it found the slash and assumed that the requested class was namespaced. It was unable to load namespaced classes with leading slashes because it would look them up in the autoloader's registered namespaces, and was unable to match '\Foo' to 'Foo'. One (ugly) workaround for the namespaced classes was to register all namespaces twice:
$loader->registerNamespaces(array(
'Foo' => __DIR__ . '/lib',
'\Foo' => __DIR__ . '/lib',
));
But that's not very pretty, nor does it solve the bug with PEAR-like classes. Stripping the leading slash before trying to autoload allows UniversalClassLoader to load both namespaced and PEAR-like classes.
When reading the last bit of a property path mapped to a missing array index, the method would initialize the value to an empty array. This makes sense for cases where readPropertyPath would again be called recursively, but not when the value would be immediately returned (null would be preferable in that case).
For example, we have an object with a property called "options" that's an array of arbitrary key/value pairs. That "options" property (and getOptions()) maps directly to a FieldGroup within the Form for this object. That FieldGroup contains multiple TextFields for a few expected keys in the array. As-is, if those keys were not defined, the default data set for those TextFields could end up being "Array" (string representation of an empty array). If readPropertyPath instead returns null for this case, the default data would be transformed into an empty string.
It's better to be able to fetch all the visible and all the hidden fields separately for display purposes (hidden fields in <ul> tags without an <li> do not validate)