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