The current `loadClass()` implementation tries to load a class from the first matching prefix then stops, producing false-negative results. This is especially evident in groups of related libraries, such as Doctrine:
Doctrine
Doctrine\Common
Doctrine\Common\DataFixtures
Doctrine\DBAL
Doctrine\DBAL\Migrations
Each of these libraries is submoduled into a different vendor directory. Depending on what order these libraries are added to a UniversalClassLoader instance, classes may or may not actually be loaded. This fix continues searching registered namespaces and prefixes if the first partial match is negative.
These helpers have been removed as they do not work as expected.
Among other things, the order is not the right one when using PHP
templates, and adding assets from an included template is not
possible when using Twig templates.
This should be replaced by integrating a third-party library that
manages assets: minification, compilation, packaging, ...
If the option is true, the password is never written into the input field's value. If it is false, it is only written into the input field's value after submitting a form with errors.
The default value for "always_empty" is true.
The semantics of property paths are now:
(1) if a property path is set, it is _always_ respected (relative to the object
of the parent field)
(2) if no property path is set, the object of the parent field is _always_ ignored
Fact (2) allows us to set data into fields that is updated independently of the parent
field (like CSRF tokens, subforms with different objects etc.)
What is missing now is support for subfields that pass the object of the parent field
through to their own subfields. This functionality would be needed for GoogleMapFields,
DateRangeFields etc., which are compositions of individual fields that update the
parent object of the FieldGroup.
There are several alternatives for the latter functionality that should be discussed
in a RFC.
Original explanation from pull request:
I'm Using symfony2 with URL Rewriting to 'hide' index.php.
On form authentication, symfony2 redirect to http://host:port/index.php/login_path instead of http://host:port/login_path. I do understand that, in my case, redirect is set into one of :
FormAuthenticationEntryPoint with getUriForPath()
FormAuthenticationListener with getUriForPath()
Security/Firewal/ExceptionListener with getUri()
This path modify getUri and getUriForPath to :
remove default port from URI
remove script name if not initially present
Currently, ambiguities only arise for PHP files, as PhpFileLoader and AnnotationFileLoader would both claim support. Future conflicts may occur if the XML, YAML, or PHP loaders were to receive Directory and Glob loaders (as annotations have).
Since the "type" parameter is optional, loader resolution will default to awarding resolution to the first loader to claim support. A previous hack in PhpFileLoader to avoid an AnnotationFileLoader conflict was removed, so that should be the only lost backwards compatibility with this patch. Unit tests were also created for the various loader classes, although only the supports() method is being tested.
This implementation was proposed on the symfony-dev mailing list in response to Fabien's RFC for custom loader notation: http://groups.google.com/group/symfony-devs/browse_thread/thread/3104c1a9e45799d2/20fbe393c1afe088
Previously, HttpKernel performed request-stashing. By moving this to the Kernel class, the request is now available immediately after the kernel becomes aware of it. If the kernel is allowed to boot lazily (during the first call to handle()), this also allows an actual master Request to be available during booting.
The old "request" service definition (with a bogus class name) can be replaced with a factory-aware definition that retrieves the request directly from the kernel.
The original HttpKernel class can be deleted, as it's request-stashing will be moved to the Kernel class. FrameworkBundle's list of compiled classes must also be modified to respect this change.
To keep language consistent, three methods were changed in InputOption:
* `InputOption::acceptParameter()` -> `InputOption::acceptValue()`
* `InputOption::isParameterRequired()` -> InputOption::isValueRequired()`
* `InputOption::isParameterOptional()` -> `InputOption::isValueOptional()`
The InputDefinition::asXml() method was also modified to update the `accept_value` and `is_value_required` attributes.
When an object has a "main" many relation with related "things" (objects,
parameters, ...), the method names are normalized:
* get()
* set()
* all()
* replace()
* remove()
* clear()
* isEmpty()
* add()
* register()
* count()
* keys()
The classes below follow this method naming convention:
* BrowserKit\CookieJar -> Cookie
* BrowserKit\History -> Request
* Console\Application -> Command
* Console\Application\Helper\HelperSet -> HelperInterface
* DependencyInjection\Container -> services
* DependencyInjection\ContainerBuilder -> services
* DependencyInjection\ParameterBag\ParameterBag -> parameters
* DependencyInjection\ParameterBag\FrozenParameterBag -> parameters
* DomCrawler\Form -> FormField
* EventDispatcher\Event -> parameters
* Form\FieldGroup -> Field
* HttpFoundation\HeaderBag -> headers
* HttpFoundation\ParameterBag -> parameters
* HttpFoundation\Session -> attributes
* HttpKernel\Profiler\Profiler -> DataCollectorInterface
* Routing\RouteCollection -> Route
* Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface
* Templating\Engine -> HelperInterface
* Translation\MessageCatalogue -> messages
The usage of these methods are only allowed when it is clear that there is a
main relation:
* a CookieJar has many Cookies;
* a Container has many services and many parameters (as services is the main
relation, we use the naming convention for this relation);
* a Console Input has many arguments and many options. There is no "main"
relation, and so the naming convention does not apply.
For many relations where the convention does not apply, the following methods
must be used instead (where XXX is the name of the related thing):
* get() -> getXXX()
* set() -> setXXX()
* all() -> getXXXs()
* replace() -> setXXXs()
* remove() -> removeXXX()
* clear() -> clearXXX()
* isEmpty() -> isEmptyXXX()
* add() -> addXXX()
* register() -> registerXXX()
* count() -> countXXX()
* keys()
* removed the __call() method in Container: it means that now, there is only
one way to get a service: via the get() method;
* removed the $shared variable in the dumped Container classes (we now use
the $services variable from the parent class directly -- this is where we
have a performance improvement);
* optimized the PHP Dumper output.
This is the case for instance when you pass a variable to a template like this:
new SafeDecorator($var);
and in the template, you pass it again to another embedded template:
$view->render('...', array('var' => $var);
The second time, $var will be escaped as the SafeDecorator wrapper will have been removed
by the escaper.
The PHP native cache limiter feature has been disabled as this is now managed
by the HeaderBag class directly instead (see below.)
The HeaderBag class uses the following rules to define a sensible and
convervative default value for the Response 'Cache-Control' header:
* If no cache header is defined ('Cache-Control', 'ETag', 'Last-Modified',
and 'Expires'), 'Cache-Control' is set to 'no-cache';
* If 'Cache-Control' is empty, its value is set to "private, max-age=0,
must-revalidate";
* But if at least one 'Cache-Control' directive is set, and no 'public' or
'private' directives have been explicitely added, Symfony2 adds the
'private' directive automatically (except when 's-maxage' is set.)
So, remember to explicitly add the 'public' directive to 'Cache-Control' when
you want shared caches to store your application resources:
// The Response is private by default
$response->setEtag($etag);
$response->setLastModified($date);
$response->setMaxAge(10);
// Change the Response to be public
$response->setPublic();
// Set cache settings in one call
$response->setCache(array(
'etag' => $etag,
'last_modified' => $date,
'max_age' => 10,
'public' => true,
));
The constraint "Valid" does not accept any options or groups anymore. As per
JSR303 1.0 final, section 3.5.1 "Object graph validation" (page 39),
properties annotated with valid should be cascaded independent of the current
group (i.e. always). Thus the group "*" is not necessary anymore and was
removed from the "Valid" constraint in the Form validation.xml.
This allows the translations to be deeply nested arrays that will be flattened, allowing for namespacing of translations easily.
The following:
'key' => array('key2' => array('key3' => 'value'))
Becomes:
'key.key2.key3' => 'value'
This isn't applied to Xliff since it does not make sense within the scope of the XLIFF standard
In the dumped PHP class, we must use get() and not get*Service() methods to get services.
That's because all calls must be managed by get(). From the outside, you can call
get*Service() because as they are protected, they are caught by the __call() method;
which is not the case obviously when it is used internally.
If not, if you override a service with set(), this won't work when a service
depends on this one (the default one will still be used).
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.
Before:
/**
* @Validation({@DateTime()})
*/
After:
/**
* @validation:DateTime()
*/
The @validation:Validation() construct is not needed anymore (it is still supported
as this is useful when you have several annotations with the same class).
So, the above is equivalent to:
/**
* @validation:Validation({@validation:DateTime()})
*/
Internally, ChoiceField expects both choices and preferred_choices to be a simple array, so I replaced incomplete bits of code that attempted to not modify a possible ArrayObject and instead added type checks in the configure() method (with unit tests for expected exceptions).
Property paths such as fields[group].fields[innerGroup].data were not being resolved correctly, since the second iteration of addError() (based on "group") would attempt to call get('fields') instead of get('innerGroup'). Solution is to remember to bump the propertyPath forward if we're at the fields property
For instance, instead of $view->slots->output(...), you must now write $view['slots']->output(...)
This has been changed for two main reasons:
* To be consistent with the way we access services from the container ($container['mailer'])
* To allow better organization of helpers (names can now safely contain dots for instance -- $view['project.slots']->output(...),
whereas before, you would have written $view->get('projects.slot') or $view->{'projects.slot'})
The error_handler_level parameter (from kernel.config) has been renamed to error_handler (false to disable the error handler,
null to catch errors from error_reporting(), and a number to catch more/less errors than error_reporting())