Merge branch 'master' of github:MaksSlesarenko/symfony into added-support-for-propel-enum-types-forms

This commit is contained in:
Maks Slesarenko 2013-01-13 16:51:39 -05:00
commit 2a7ecf76c2
347 changed files with 8438 additions and 3092 deletions

View File

@ -14,11 +14,9 @@
After:
```
{% render url('post_list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
{% render controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
```
where `post_list` is the route name for the `BlogBundle:Post:list` controller.
### HttpFoundation
* The MongoDbSessionHandler default field names and timestamp type have changed.
@ -64,6 +62,66 @@
Symfony\Component\Form\Exception namespace or to create custom exception
classes for your purpose.
* Translating validation errors is now optional. You can still do so
manually if you like, or you can simplify your templates to simply output
the already translated message.
Before:
```
{{
error.messagePluralization is null
? error.messageTemplate|trans(error.messageParameters, 'validators')
: error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
}}
```
After:
```
{{ error.message }}
```
* FormType, ModelType and PropertyPathMapper now have constructors. If you
extended these classes, you should call the parent constructor now.
Note that you are not recommended to extend FormType nor ModelType. You should
extend AbstractType instead and use the Form component's own inheritance
mechanism (`AbstractType::getParent()`).
Before:
```
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
class CustomMapper extends PropertyPathMapper
{
public function __construct()
{
// ...
}
// ...
}
```
After:
```
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
class CustomMapper extends PropertyPathMapper
{
public function __construct()
{
parent::__construct();
// ...
}
// ...
}
```
#### Deprecations
* The methods `getParent()`, `setParent()` and `hasParent()` in
@ -71,6 +129,94 @@
You should not rely on these methods in your form type because the parent
of a form can change after building it.
* The class PropertyPath and related classes were deprecated and moved to a
dedicated component PropertyAccess. If you used any of these classes or
interfaces, you should adapt the namespaces now. During the move,
InvalidPropertyException was renamed to NoSuchPropertyException.
Before:
```
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Util\PropertyPathBuilder;
use Symfony\Component\Form\Util\PropertyPathInterface;
use Symfony\Component\Form\Util\PropertyPathIterator;
use Symfony\Component\Form\Util\PropertyPathIteratorInterface;
use Symfony\Component\Form\Exception\InvalidPropertyException;
use Symfony\Component\Form\Exception\InvalidPropertyPathException;
use Symfony\Component\Form\Exception\PropertyAccessDeniedException;
```
After:
```
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
use Symfony\Component\PropertyAccess\PropertyPathIterator;
use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use Symfony\Component\PropertyAccess\Exception\PropertyAccessDeniedException;
```
Also, `FormUtil::singularify()` was split away into a class StringUtil
in the new component.
Before:
```
use Symfony\Component\Form\Util\FormUtil;
$singular = FormUtil::singularify($plural);
```
After:
```
use Symfony\Component\PropertyAccess\StringUtil;
$singular = StringUtil::singularify($plural);
```
The methods `getValue()` and `setValue()` were moved to a new class
PropertyAccessor.
Before:
```
use Symfony\Component\Form\Util\PropertyPath;
$propertyPath = new PropertyPath('some.path');
$value = $propertyPath->getValue($object);
$propertyPath->setValue($object, 'new value');
```
After (alternative 1):
```
use Symfony\Component\PropertyAccess\PropertyAccess;
$accessor = PropertyAccess::getPropertyAccessor();
$value = $propertyAccessor->getValue($object, 'some.path');
$accessor->setValue($object, 'some.path', 'new value');
```
After (alternative 2):
```
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyPath;
$accessor = PropertyAccess::getPropertyAccessor();
$propertyPath = new PropertyPath('some.path');
$value = $propertyAccessor->getValue($object, $propertyPath);
$accessor->setValue($object, $propertyPath, 'new value');
```
### Routing
* RouteCollection does not behave like a tree structure anymore but as a flat
@ -186,6 +332,27 @@
}
```
* The sources of the pluralized messages in translation files have changed
from the singular to the pluralized version. If you created custom
translation files for validator errors, you should adapt them.
Before:
<trans-unit id="6">
<source>You must select at least {{ limit }} choices.</source>
<target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
</trans-unit>
After:
<trans-unit id="6">
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
<target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
</trans-unit>
Check the file src/Symfony/Component/Validator/Resources/translations/validators.en.xlf
for the new message sources.
#### Deprecations
* The interface `ClassMetadataFactoryInterface` was deprecated and will be
@ -368,7 +535,12 @@
<?php echo $view['actions']->render($view['router']->generate('post_list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
```
where `post_list` is the route name for the `BlogBundle:Post:list` controller.
where `post_list` is the route name for the `BlogBundle:Post:list`
controller, or if you don't want to create a route:
```
<?php echo $view['actions']->render(new ControllerReference('BlogBundle:Post:list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
```
#### Configuration

View File

@ -18,7 +18,8 @@
"require": {
"php": ">=5.3.3",
"doctrine/common": ">2.2,<2.4-dev",
"twig/twig": ">=1.11.0,<2.0-dev"
"twig/twig": ">=1.11.0,<2.0-dev",
"psr/log": "~1.0"
},
"replace": {
"symfony/browser-kit": "self.version",
@ -59,7 +60,7 @@
"doctrine/data-fixtures": "1.0.*",
"doctrine/dbal": ">=2.2,<2.4-dev",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"monolog/monolog": ">=1.0,<1.3-dev",
"monolog/monolog": "~1.3",
"propel/propel1": "dev-master"
},
"autoload": {

View File

@ -1,6 +1,12 @@
CHANGELOG
=========
2.2.0
-----
* added an optional PropertyAccessorInterface parameter to DoctrineType,
EntityType and EntityChoiceList
2.1.0
-----

View File

@ -15,6 +15,7 @@ use Symfony\Component\Form\Exception\Exception;
use Symfony\Component\Form\Exception\StringCastException;
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
* A choice list presenting a list of Doctrine entities as choices
@ -86,17 +87,18 @@ class EntityChoiceList extends ObjectChoiceList
/**
* Creates a new entity choice list.
*
* @param ObjectManager $manager An EntityManager instance
* @param string $class The class name
* @param string $labelPath The property path used for the label
* @param EntityLoaderInterface $entityLoader An optional query builder
* @param array $entities An array of choices
* @param array $preferredEntities An array of preferred choices
* @param string $groupPath A property path pointing to the property used
* to group the choices. Only allowed if
* the choices are given as flat array.
* @param ObjectManager $manager An EntityManager instance
* @param string $class The class name
* @param string $labelPath The property path used for the label
* @param EntityLoaderInterface $entityLoader An optional query builder
* @param array $entities An array of choices
* @param array $preferredEntities An array of preferred choices
* @param string $groupPath A property path pointing to the property used
* to group the choices. Only allowed if
* the choices are given as flat array.
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
*/
public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null)
public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null, PropertyAccessorInterface $propertyAccessor = null)
{
$this->em = $manager;
$this->entityLoader = $entityLoader;
@ -122,7 +124,7 @@ class EntityChoiceList extends ObjectChoiceList
$entities = array();
}
parent::__construct($entities, $labelPath, $preferredEntities, $groupPath);
parent::__construct($entities, $labelPath, $preferredEntities, $groupPath, null, $propertyAccessor);
}
/**
@ -329,7 +331,7 @@ class EntityChoiceList extends ObjectChoiceList
protected function createIndex($entity)
{
if ($this->idAsIndex) {
return current($this->getIdentifierValues($entity));
return $this->fixIndex(current($this->getIdentifierValues($entity)));
}
return parent::createIndex($entity);
@ -355,6 +357,23 @@ class EntityChoiceList extends ObjectChoiceList
return parent::createValue($entity);
}
/**
* {@inheritdoc}
*/
protected function fixIndex($index)
{
$index = parent::fixIndex($index);
// If the ID is a single-field integer identifier, it is used as
// index. Replace any leading minus by underscore to make it a valid
// form name.
if ($this->idAsIndex && $index < 0) {
$index = strtr($index, '-', '_');
}
return $index;
}
/**
* Loads the list with entities.
*/

View File

@ -13,6 +13,7 @@ namespace Symfony\Bridge\Doctrine\Form;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\PropertyAccess\PropertyAccess;
class DoctrineOrmExtension extends AbstractExtension
{
@ -26,7 +27,7 @@ class DoctrineOrmExtension extends AbstractExtension
protected function loadTypes()
{
return array(
new Type\EntityType($this->registry),
new Type\EntityType($this->registry, PropertyAccess::getPropertyAccessor()),
);
}

View File

@ -22,6 +22,8 @@ use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
abstract class DoctrineType extends AbstractType
{
@ -35,9 +37,15 @@ abstract class DoctrineType extends AbstractType
*/
private $choiceListCache = array();
public function __construct(ManagerRegistry $registry)
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null)
{
$this->registry = $registry;
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
}
public function buildForm(FormBuilderInterface $builder, array $options)
@ -54,6 +62,7 @@ abstract class DoctrineType extends AbstractType
{
$choiceListCache =& $this->choiceListCache;
$registry = $this->registry;
$propertyAccessor = $this->propertyAccessor;
$type = $this;
$loader = function (Options $options) use ($type) {
@ -64,7 +73,7 @@ abstract class DoctrineType extends AbstractType
return null;
};
$choiceList = function (Options $options) use (&$choiceListCache, &$time) {
$choiceList = function (Options $options) use (&$choiceListCache, $propertyAccessor) {
// Support for closures
$propertyHash = is_object($options['property'])
? spl_object_hash($options['property'])
@ -118,7 +127,8 @@ abstract class DoctrineType extends AbstractType
$options['loader'],
$options['choices'],
$options['preferred_choices'],
$options['group_by']
$options['group_by'],
$propertyAccessor
);
}

View File

@ -11,7 +11,7 @@
namespace Symfony\Bridge\Doctrine\Logger;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Doctrine\DBAL\Logging\SQLLogger;

View File

@ -312,4 +312,47 @@ class EntityChoiceListTest extends DoctrineOrmTestCase
$this->assertSame(array(0 => $entity1, 1 => $entity2), $choiceList->getChoices());
}
public function testMinusReplacedByUnderscoreInNegativeIntIds()
{
$entity1 = new SingleIdentEntity(-1, 'Foo');
$entity2 = new SingleIdentEntity(1, 'Bar');
// Persist for managed state
$this->em->persist($entity1);
$this->em->persist($entity2);
$this->em->flush();
$choiceList = new EntityChoiceList(
$this->em,
self::SINGLE_IDENT_CLASS,
'name'
);
$this->assertSame(array('_1' => $entity1, 1 => $entity2), $choiceList->getChoices());
$this->assertSame(array('_1', 1), $choiceList->getIndicesForChoices(array($entity1, $entity2)));
$this->assertSame(array('_1', 1), $choiceList->getIndicesForValues(array('-1', '1')));
}
public function testMinusReplacedByUnderscoreIfNotLoaded()
{
$entity1 = new SingleIdentEntity(-1, 'Foo');
$entity2 = new SingleIdentEntity(1, 'Bar');
// Persist for managed state
$this->em->persist($entity1);
$this->em->persist($entity2);
$this->em->flush();
$choiceList = new EntityChoiceList(
$this->em,
self::SINGLE_IDENT_CLASS,
'name'
);
// no getChoices()!
$this->assertSame(array('_1', 1), $choiceList->getIndicesForChoices(array($entity1, $entity2)));
$this->assertSame(array('_1', 1), $choiceList->getIndicesForValues(array('-1', '1')));
}
}

View File

@ -90,6 +90,7 @@ class EntityTypeTest extends TypeTestCase
parent::tearDown();
$this->em = null;
$this->emRegistry = null;
}
protected function getExtensions()

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Doctrine\Tests\Validator\Constraints;
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleIdentEntity;
@ -132,7 +133,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
$metadataFactory->addMetadata($metadata);
$validatorFactory = $this->createValidatorFactory($uniqueValidator);
return new Validator($metadataFactory, $validatorFactory);
return new Validator($metadataFactory, $validatorFactory, new DefaultTranslator());
}
private function createSchema($em)

View File

@ -47,10 +47,7 @@ class DebugHandler extends TestHandler implements DebugLoggerInterface
public function countErrors()
{
$cnt = 0;
$levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT);
if (defined('Monolog\Logger::EMERGENCY')) {
$levels[] = Logger::EMERGENCY;
}
$levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY);
foreach ($levels as $level) {
if (isset($this->recordsByLevel[$level])) {
$cnt += count($this->recordsByLevel[$level]);

View File

@ -22,6 +22,38 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
*/
class Logger extends BaseLogger implements LoggerInterface, DebugLoggerInterface
{
/**
* @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible.
*/
public function emerg($message, array $context = array())
{
return parent::addRecord(BaseLogger::EMERGENCY, $message, $context);
}
/**
* @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible.
*/
public function crit($message, array $context = array())
{
return parent::addRecord(BaseLogger::CRITICAL, $message, $context);
}
/**
* @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible.
*/
public function err($message, array $context = array())
{
return parent::addRecord(BaseLogger::ERROR, $message, $context);
}
/**
* @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible.
*/
public function warn($message, array $context = array())
{
return parent::addRecord(BaseLogger::WARNING, $message, $context);
}
/**
* @see Symfony\Component\HttpKernel\Log\DebugLoggerInterface
*/

View File

@ -18,7 +18,7 @@
"require": {
"php": ">=5.3.3",
"symfony/http-kernel": "2.2.*",
"monolog/monolog": ">=1.0,<1.3-dev"
"monolog/monolog": "~1.3"
},
"autoload": {
"psr-0": { "Symfony\\Bridge\\Monolog\\": "" }

View File

@ -5,6 +5,9 @@ CHANGELOG
-----
* added a collection type for the I18n behavior
* added an optional PropertyAccessorInterface parameter to ModelType and
ModelChoiceList
* [BC BREAK] ModelType now has a constructor
2.1.0
-----

View File

@ -18,6 +18,7 @@ use \Persistent;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Form\Exception\StringCastException;
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
* Widely inspired by the EntityChoiceList.
@ -69,16 +70,17 @@ class ModelChoiceList extends ObjectChoiceList
*
* @see Symfony\Bridge\Propel1\Form\Type\ModelType How to use the preferred choices.
*
* @param string $class The FQCN of the model class to be loaded.
* @param string $labelPath A property path pointing to the property used for the choice labels.
* @param array $choices An optional array to use, rather than fetching the models.
* @param ModelCriteria $queryObject The query to use retrieving model data from database.
* @param string $groupPath A property path pointing to the property used to group the choices.
* @param array|ModelCriteria $preferred The preferred items of this choice.
* Either an array if $choices is given,
* or a ModelCriteria to be merged with the $queryObject.
* @param string $class The FQCN of the model class to be loaded.
* @param string $labelPath A property path pointing to the property used for the choice labels.
* @param array $choices An optional array to use, rather than fetching the models.
* @param ModelCriteria $queryObject The query to use retrieving model data from database.
* @param string $groupPath A property path pointing to the property used to group the choices.
* @param array|ModelCriteria $preferred The preferred items of this choice.
* Either an array if $choices is given,
* or a ModelCriteria to be merged with the $queryObject.
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
*/
public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null, $preferred = array())
public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null, $preferred = array(), PropertyAccessorInterface $propertyAccessor = null)
{
$this->class = $class;
@ -104,7 +106,7 @@ class ModelChoiceList extends ObjectChoiceList
$this->identifierAsIndex = true;
}
parent::__construct($choices, $labelPath, $preferred, $groupPath);
parent::__construct($choices, $labelPath, $preferred, $groupPath, null, $propertyAccessor);
}
/**

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Propel1\Form;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\PropertyAccess\PropertyAccess;
/**
* Represents the Propel form extension, which loads the Propel functionality.
@ -23,7 +24,7 @@ class PropelExtension extends AbstractExtension
protected function loadTypes()
{
return array(
new Type\ModelType(),
new Type\ModelType(PropertyAccess::getPropertyAccessor()),
new Type\TranslationCollectionType(),
new Type\TranslationType()
);

View File

@ -17,6 +17,8 @@ use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
* ModelType class.
@ -48,6 +50,16 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
*/
class ModelType extends AbstractType
{
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
{
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['multiple']) {
@ -57,14 +69,17 @@ class ModelType extends AbstractType
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$choiceList = function (Options $options) {
$propertyAccessor = $this->propertyAccessor;
$choiceList = function (Options $options) use ($propertyAccessor) {
return new ModelChoiceList(
$options['class'],
$options['property'],
$options['choices'],
$options['query'],
$options['group_by'],
$options['preferred_choices']
$options['preferred_choices'],
$propertyAccessor
);
};

View File

@ -12,7 +12,7 @@
namespace Symfony\Bridge\Propel1\Logger;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Psr\Log\LoggerInterface;
/**
* PropelLogger.
@ -73,7 +73,7 @@ class PropelLogger
public function crit($message)
{
if (null !== $this->logger) {
$this->logger->crit($message);
$this->logger->critical($message);
}
}
@ -85,7 +85,7 @@ class PropelLogger
public function err($message)
{
if (null !== $this->logger) {
$this->logger->err($message);
$this->logger->error($message);
}
}
@ -97,7 +97,7 @@ class PropelLogger
public function warning($message)
{
if (null !== $this->logger) {
$this->logger->warn($message);
$this->logger->warning($message);
}
}

View File

@ -26,6 +26,10 @@ class ModelChoiceListTest extends Propel1TestCase
if (!class_exists('Symfony\Component\Form\Form')) {
$this->markTestSkipped('The "Form" component is not available');
}
if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccessor')) {
$this->markTestSkipped('The "PropertyAccessor" component is not available');
}
}
public function testEmptyChoicesReturnsEmpty()

View File

@ -17,7 +17,7 @@
],
"require": {
"php": ">=5.3.3",
"swiftmailer/swiftmailer": ">=4.2.0,<4.3-dev"
"swiftmailer/swiftmailer": ">=4.2.0,<4.4-dev"
},
"suggest": {
"symfony/http-kernel": "2.2.*"

View File

@ -4,9 +4,13 @@ CHANGELOG
2.2.0
-----
* [BC BREAK] restricted the `render` tag to only accept URIs as reference (the signature changed)
* added a render function to render a request
* added a `controller` function to help generating controller references
* added a `render_esi` and a `render_hinclude` function
* [BC BREAK] restricted the `render` tag to only accept URIs or ControllerReference instances (the signature changed)
* added a `render` function to render a request
* The `app` global variable is now injected even when using the twig service directly.
* Added an optional parameter to the `path` and `url` function which allows to generate
relative paths (e.g. "../parent-file") and scheme-relative URLs (e.g. "//example.com/dir/file").
2.1.0
-----

View File

@ -11,83 +11,65 @@
namespace Symfony\Bridge\Twig\Extension;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\HttpContentRenderer;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
* Provides integration with the HttpKernel component.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HttpKernelExtension extends \Twig_Extension implements EventSubscriberInterface
class HttpKernelExtension extends \Twig_Extension
{
private $kernel;
private $request;
private $renderer;
/**
* Constructor.
*
* @param HttpKernelInterface $kernel A HttpKernelInterface install
* @param HttpContentRenderer $renderer A HttpContentRenderer instance
*/
public function __construct(HttpKernelInterface $kernel)
public function __construct(HttpContentRenderer $renderer)
{
$this->kernel = $kernel;
$this->renderer = $renderer;
}
public function getFunctions()
{
return array(
'render' => new \Twig_Function_Method($this, 'render', array('needs_environment' => true, 'is_safe' => array('html'))),
'render' => new \Twig_Function_Method($this, 'render', array('is_safe' => array('html'))),
'render_*' => new \Twig_Function_Method($this, 'renderStrategy', array('is_safe' => array('html'))),
'controller' => new \Twig_Function_Method($this, 'controller'),
);
}
/**
* Renders a URI.
*
* @param \Twig_Environment $twig A \Twig_Environment instance
* @param string $uri The URI to render
* @param string $uri A URI
* @param array $options An array of options
*
* @return string The Response content
*
* @throws \RuntimeException
* @see Symfony\Component\HttpKernel\HttpContentRenderer::render()
*/
public function render(\Twig_Environment $twig, $uri)
public function render($uri, $options = array())
{
if (null !== $this->request) {
$cookies = $this->request->cookies->all();
$server = $this->request->server->all();
} else {
$cookies = array();
$server = array();
}
$options = $this->renderer->fixOptions($options);
$subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server);
if (null !== $this->request && $this->request->getSession()) {
$subRequest->setSession($this->request->getSession());
}
$strategy = isset($options['strategy']) ? $options['strategy'] : 'default';
unset($options['strategy']);
$response = $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
if (!$response->isSuccessful()) {
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
}
return $response->getContent();
return $this->renderer->render($uri, $strategy, $options);
}
public function onKernelRequest(GetResponseEvent $event)
public function renderStrategy($strategy, $uri, $options = array())
{
$this->request = $event->getRequest();
return $this->renderer->render($uri, $strategy, $options);
}
public static function getSubscribedEvents()
public function controller($controller, $attributes = array(), $query = array())
{
return array(
KernelEvents::REQUEST => array('onKernelRequest'),
);
return new ControllerReference($controller, $attributes, $query);
}
public function getName()

View File

@ -40,14 +40,14 @@ class RoutingExtension extends \Twig_Extension
);
}
public function getPath($name, $parameters = array())
public function getPath($name, $parameters = array(), $relative = false)
{
return $this->generator->generate($name, $parameters, false);
return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
}
public function getUrl($name, $parameters = array())
public function getUrl($name, $parameters = array(), $schemeRelative = false)
{
return $this->generator->generate($name, $parameters, true);
return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
}
/**

View File

@ -275,11 +275,7 @@
{% if errors|length > 0 %}
<ul>
{% for error in errors %}
<li>{{
error.messagePluralization is null
? error.messageTemplate|trans(error.messageParameters, 'validators')
: error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
}}</li>
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}

View File

@ -13,8 +13,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension;
use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
use Symfony\Bridge\Twig\Tests\TestCase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpContentRenderer;
class HttpKernelExtensionTest extends TestCase
{
@ -31,7 +30,7 @@ class HttpKernelExtensionTest extends TestCase
public function testRenderWithoutMasterRequest()
{
$kernel = $this->getKernel($this->returnValue(new Response('foo')));
$kernel = $this->getHttpContentRenderer($this->returnValue('foo'));
$this->assertEquals('foo', $this->renderTemplate($kernel));
}
@ -41,7 +40,7 @@ class HttpKernelExtensionTest extends TestCase
*/
public function testRenderWithError()
{
$kernel = $this->getKernel($this->throwException(new \Exception('foo')));
$kernel = $this->getHttpContentRenderer($this->throwException(new \Exception('foo')));
$loader = new \Twig_Loader_Array(array('index' => '{{ render("foo") }}'));
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
@ -50,23 +49,20 @@ class HttpKernelExtensionTest extends TestCase
$this->renderTemplate($kernel);
}
protected function getKernel($return)
protected function getHttpContentRenderer($return)
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$kernel
->expects($this->once())
->method('handle')
->will($return)
;
$strategy = $this->getMock('Symfony\\Component\\HttpKernel\\RenderingStrategy\\RenderingStrategyInterface');
$strategy->expects($this->once())->method('getName')->will($this->returnValue('default'));
$strategy->expects($this->once())->method('render')->will($return);
return $kernel;
return new HttpContentRenderer(array($strategy));
}
protected function renderTemplate(HttpKernelInterface $kernel, $template = '{{ render("foo") }}')
protected function renderTemplate(HttpContentRenderer $renderer, $template = '{{ render("foo") }}')
{
$loader = new \Twig_Loader_Array(array('index' => $template));
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
$twig->addExtension(new HttpKernelExtension($kernel));
$twig->addExtension(new HttpKernelExtension($renderer));
return $twig->render('index');
}

View File

@ -4,11 +4,16 @@ CHANGELOG
2.2.0
-----
* [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs as reference
* added a new `uri_signer` service to help sign URIs
* deprecated `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` and `Symfony\Bundle\FrameworkBundle\HttpKernel::forward()`
* deprecated the `Symfony\Bundle\FrameworkBundle\HttpKernel` class in favor of `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel`
* added support for adding new HTTP content rendering strategies (like ESI and Hinclude)
in the DIC via the `kernel.content_renderer_strategy` tag
* [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs or ControllerReference instances
* `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument
must now be a URI (the `generateInternalUri()` method was removed)
* The internal routes have been removed (`Resources/config/routing/internal.xml`)
* The `render` method of the `actions` templating helper signature and arguments changed:
must now be a URI or a ControllerReference instance (the `generateInternalUri()` method was removed)
* The internal routes (`Resources/config/routing/internal.xml`) have been replaced with a new proxy route (`Resources/config/routing/proxy.xml`)
* The `render` method of the `actions` templating helper signature and arguments changed
* replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver
* replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher
* added Client::enableProfiler()

View File

@ -11,16 +11,18 @@
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\HttpFoundation\Request;
/**
* Controller is a simple implementation of a Controller.
@ -34,15 +36,17 @@ class Controller extends ContainerAware
/**
* Generates a URL from the given parameters.
*
* @param string $route The name of the route
* @param mixed $parameters An array of parameters
* @param Boolean $absolute Whether to generate an absolute URL
* @param string $route The name of the route
* @param mixed $parameters An array of parameters
* @param Boolean|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
*
* @return string The generated URL
*
* @see UrlGeneratorInterface
*/
public function generateUrl($route, $parameters = array(), $absolute = false)
public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
{
return $this->container->get('router')->generate($route, $parameters, $absolute);
return $this->container->get('router')->generate($route, $parameters, $referenceType);
}
/**
@ -56,7 +60,10 @@ class Controller extends ContainerAware
*/
public function forward($controller, array $path = array(), array $query = array())
{
return $this->container->get('http_kernel')->forward($controller, $path, $query);
$path['_controller'] = $controller;
$subRequest = $this->container->get('request')->duplicate($query, null, $path);
return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
/**

View File

@ -11,7 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;

View File

@ -12,8 +12,9 @@
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Redirects a request to another URL.
@ -45,7 +46,7 @@ class RedirectController extends ContainerAware
$attributes = $this->container->get('request')->attributes->get('_route_params');
unset($attributes['route'], $attributes['permanent']);
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, true), $permanent ? 301 : 302);
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302);
}
/**

View File

@ -28,6 +28,6 @@ class AddValidatorInitializersPass implements CompilerPassInterface
$initializers[] = new Reference($id);
}
$container->getDefinition('validator')->replaceArgument(2, $initializers);
$container->getDefinition('validator')->replaceArgument(4, $initializers);
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
/**
* Adds services tagged kernel.content_renderer_strategy as HTTP content rendering strategies.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HttpRenderingStrategyPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition('http_content_renderer')) {
return;
}
$definition = $container->getDefinition('http_content_renderer');
foreach (array_keys($container->findTaggedServiceIds('kernel.content_renderer_strategy')) as $id) {
// We must assume that the class value has been correctly filled, even if the service is created by a factory
$class = $container->getDefinition($id)->getClass();
$refClass = new \ReflectionClass($class);
$interface = 'Symfony\Component\HttpKernel\RenderingStrategy\RenderingStrategyInterface';
if (!$refClass->implementsInterface($interface)) {
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
}
$definition->addMethodCall('addStrategy', array(new Reference($id)));
}
}
}

View File

@ -370,6 +370,7 @@ class Configuration implements ConfigurationInterface
->children()
->scalarNode('cache')->end()
->booleanNode('enable_annotations')->defaultFalse()->end()
->scalarNode('translation_domain')->defaultValue('validators')->end()
->end()
->end()
->end()

View File

@ -41,6 +41,7 @@ class FrameworkExtension extends Extension
$loader->load('web.xml');
$loader->load('services.xml');
$loader->load('content_generator.xml');
// A translator must always be registered (as support is included by
// default in the Form component). If disabled, an identity translator
@ -527,6 +528,11 @@ class FrameworkExtension extends Extension
$dirs[] = dirname($r->getFilename()).'/Resources/translations';
}
if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) {
$r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException');
$dirs[] = dirname($r->getFilename()).'/../../Resources/translations';
}
$overridePath = $container->getParameter('kernel.root_dir').'/Resources/%s/translations';
foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
$reflection = new \ReflectionClass($class);
@ -574,6 +580,7 @@ class FrameworkExtension extends Extension
{
$loader->load('validator.xml');
$container->setParameter('validator.translation_domain', $config['translation_domain']);
$container->setParameter('validator.mapping.loader.xml_files_loader.mapping_files', $this->getValidatorXmlMappingFiles($container));
$container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $this->getValidatorYamlMappingFiles($container));

View File

@ -25,6 +25,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilder
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CompilerDebugDumpPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\HttpRenderingStrategyPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Scope;
@ -65,6 +66,7 @@ class FrameworkBundle extends Bundle
$container->addCompilerPass(new AddCacheClearerPass());
$container->addCompilerPass(new TranslationExtractorPass());
$container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new HttpRenderingStrategyPass(), PassConfig::TYPE_AFTER_REMOVING);
if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);

View File

@ -11,54 +11,20 @@
namespace Symfony\Bundle\FrameworkBundle;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\HttpKernel as BaseHttpKernel;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel;
/**
* This HttpKernel is used to manage scope changes of the DI container.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @deprecated This class is deprecated in 2.2 and will be removed in 2.3
*/
class HttpKernel extends BaseHttpKernel
class HttpKernel extends ContainerAwareHttpKernel
{
protected $container;
private $esiSupport;
public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver)
{
parent::__construct($dispatcher, $controllerResolver);
$this->container = $container;
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$request->headers->set('X-Php-Ob-Level', ob_get_level());
$this->container->enterScope('request');
$this->container->set('request', $request, 'request');
try {
$response = parent::handle($request, $type, $catch);
} catch (\Exception $e) {
$this->container->leaveScope('request');
throw $e;
}
$this->container->leaveScope('request');
return $response;
}
/**
* Forwards the request to another controller.
*
@ -67,9 +33,13 @@ class HttpKernel extends BaseHttpKernel
* @param array $query An array of request query parameters
*
* @return Response A Response instance
*
* @deprecated in 2.2, will be removed in 2.3
*/
public function forward($controller, array $attributes = array(), array $query = array())
{
trigger_error('forward() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED);
$attributes['_controller'] = $controller;
$subRequest = $this->container->get('request')->duplicate($query, null, $attributes);
@ -96,97 +66,18 @@ class HttpKernel extends BaseHttpKernel
*
* @throws \RuntimeException
* @throws \Exception
*
* @deprecated in 2.2, will be removed in 2.3 (use Symfony\Component\HttpKernel\HttpContentRenderer::render() instead)
*/
public function render($uri, array $options = array())
{
$request = $this->container->get('request');
trigger_error('render() is deprecated since version 2.2 and will be removed in 2.3. Use Symfony\Component\HttpKernel\HttpContentRenderer::render() instead.', E_USER_DEPRECATED);
$options = array_merge(array(
'ignore_errors' => !$this->container->getParameter('kernel.debug'),
'alt' => null,
'standalone' => false,
'comment' => '',
'default' => null,
), $options);
$options = $this->renderer->fixOptions($options);
if (null === $this->esiSupport) {
$this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($request);
}
$strategy = isset($options['strategy']) ? $options['strategy'] : 'default';
unset($options['strategy']);
if ($this->esiSupport && (true === $options['standalone'] || 'esi' === $options['standalone'])) {
return $this->container->get('esi')->renderIncludeTag($uri, $options['alt'], $options['ignore_errors'], $options['comment']);
}
if ('js' === $options['standalone']) {
$defaultContent = null;
$templating = $this->container->get('templating');
if ($options['default']) {
if ($templating->exists($options['default'])) {
$defaultContent = $templating->render($options['default']);
} else {
$defaultContent = $options['default'];
}
} elseif ($template = $this->container->getParameter('templating.hinclude.default_template')) {
$defaultContent = $templating->render($template);
}
return $this->renderHIncludeTag($uri, $defaultContent);
}
$subRequest = Request::create($uri, 'get', array(), $request->cookies->all(), array(), $request->server->all());
if ($session = $request->getSession()) {
$subRequest->setSession($session);
}
$level = ob_get_level();
try {
$response = $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
if (!$response->isSuccessful()) {
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode()));
}
if (!$response instanceof StreamedResponse) {
return $response->getContent();
}
$response->sendContent();
} catch (\Exception $e) {
if ($options['alt']) {
$alt = $options['alt'];
unset($options['alt']);
return $this->render($alt, $options);
}
if (!$options['ignore_errors']) {
throw $e;
}
// let's clean up the output buffers that were created by the sub-request
while (ob_get_level() > $level) {
ob_get_clean();
}
}
}
/**
* Renders an HInclude tag.
*
* @param string $uri A URI
* @param string $defaultContent Default content
*
* @return string
*/
public function renderHIncludeTag($uri, $defaultContent = null)
{
return sprintf('<hx:include src="%s">%s</hx:include>', $uri, $defaultContent);
}
public function hasEsiSupport()
{
return $this->esiSupport;
$this->container->get('http_content_renderer')->render($uri, $strategy, $options);
}
}

View File

@ -0,0 +1,43 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="http_content_renderer.class">Symfony\Component\HttpKernel\HttpContentRenderer</parameter>
<parameter key="http_content_renderer.strategy.default.class">Symfony\Component\HttpKernel\RenderingStrategy\DefaultRenderingStrategy</parameter>
<parameter key="http_content_renderer.strategy.hinclude.class">Symfony\Component\HttpKernel\RenderingStrategy\HIncludeRenderingStrategy</parameter>
<parameter key="http_content_renderer.strategy.hinclude.global_template"></parameter>
<parameter key="http_content_renderer.listener.router_proxy.class">Symfony\Component\HttpKernel\EventListener\RouterProxyListener</parameter>
</parameters>
<services>
<service id="http_content_renderer" class="%http_content_renderer.class%">
<tag name="kernel.event_subscriber" />
<argument type="collection" />
<argument>%kernel.debug%</argument>
</service>
<service id="http_content_renderer.strategy.default" class="%http_content_renderer.strategy.default.class%">
<tag name="kernel.content_renderer_strategy" />
<argument type="service" id="http_kernel" />
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>
<service id="http_content_renderer.strategy.hinclude" class="%http_content_renderer.strategy.hinclude.class%">
<tag name="kernel.content_renderer_strategy" />
<argument type="service" id="templating" on-invalid="null" />
<argument type="service" id="uri_signer" />
<argument>%http_content_renderer.strategy.hinclude.global_template%</argument>
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>
<!-- FIXME: make the listener registration optional via a configuration setting? -->
<service id="http_content_renderer.listener.router_proxy" class="%http_content_renderer.listener.router_proxy.class%">
<tag name="kernel.event_subscriber" />
<argument type="service" id="uri_signer" />
</service>
</services>
</container>

View File

@ -7,14 +7,22 @@
<parameters>
<parameter key="esi.class">Symfony\Component\HttpKernel\HttpCache\Esi</parameter>
<parameter key="esi_listener.class">Symfony\Component\HttpKernel\EventListener\EsiListener</parameter>
<parameter key="http_content_renderer.strategy.esi.class">Symfony\Component\HttpKernel\RenderingStrategy\EsiRenderingStrategy</parameter>
</parameters>
<services>
<service id="esi" class="%esi.class%" />
<service id="esi_listener" class="%esi_listener.class%">
<tag name="kernel.event_subscriber" />
<argument type="service" id="esi" on-invalid="ignore" />
<tag name="kernel.event_subscriber" />
<argument type="service" id="esi" on-invalid="ignore" />
</service>
<service id="http_content_renderer.strategy.esi" class="%http_content_renderer.strategy.esi.class%">
<tag name="kernel.content_renderer_strategy" />
<argument type="service" id="esi" />
<argument type="service" id="http_content_renderer.strategy.default" />
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>
</services>
</container>

View File

@ -10,6 +10,7 @@
<parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
<parameter key="form.extension.class">Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension</parameter>
<parameter key="form.type_guesser.validator.class">Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser</parameter>
<parameter key="property_accessor.class">Symfony\Component\PropertyAccess\PropertyAccessor</parameter>
</parameters>
<services>
@ -53,11 +54,15 @@
<argument type="service" id="validator.mapping.class_metadata_factory" />
</service>
<!-- PropertyAccessor -->
<service id="property_accessor" class="%property_accessor.class%" />
<!-- CoreExtension -->
<service id="form.type.field" class="Symfony\Component\Form\Extension\Core\Type\FieldType">
<tag name="form.type" alias="field" />
</service>
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
<argument type="service" id="property_accessor"/>
<tag name="form.type" alias="form" />
</service>
<service id="form.type.birthday" class="Symfony\Component\Form\Extension\Core\Type\BirthdayType">

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_proxy" pattern="/_proxy/{_controller}.{_format}" />
</routes>

View File

@ -11,6 +11,7 @@
<parameter key="cache_warmer.class">Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate</parameter>
<parameter key="cache_clearer.class">Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer</parameter>
<parameter key="file_locator.class">Symfony\Component\HttpKernel\Config\FileLocator</parameter>
<parameter key="uri_signer.class">Symfony\Component\HttpKernel\UriSigner</parameter>
</parameters>
<services>
@ -51,5 +52,9 @@
<argument type="service" id="kernel" />
<argument>%kernel.root_dir%/Resources</argument>
</service>
<service id="uri_signer" class="%uri_signer.class%">
<argument>%kernel.secret%</argument>
</service>
</services>
</container>

View File

@ -81,7 +81,7 @@
<service id="templating.helper.actions" class="%templating.helper.actions.class%">
<tag name="templating.helper" alias="actions" />
<argument type="service" id="http_kernel" />
<argument type="service" id="http_content_renderer" />
</service>
<service id="templating.helper.code" class="%templating.helper.code.class%">

View File

@ -23,6 +23,8 @@
<service id="validator" class="%validator.class%">
<argument type="service" id="validator.mapping.class_metadata_factory" />
<argument type="service" id="validator.validator_factory" />
<argument type="service" id="translator.default" />
<argument>%validator.translation_domain%</argument>
<argument type="collection" />
</service>

View File

@ -1,21 +1,7 @@
<?php if ($errors): ?>
<ul>
<?php foreach ($errors as $error): ?>
<li><?php
if (null === $error->getMessagePluralization()) {
echo $view['translator']->trans(
$error->getMessageTemplate(),
$error->getMessageParameters(),
'validators'
);
} else {
echo $view['translator']->transChoice(
$error->getMessageTemplate(),
$error->getMessagePluralization(),
$error->getMessageParameters(),
'validators'
);
}?></li>
<li><?php echo $error->getMessage() ?></li>
<?php endforeach; ?>
</ul>
<?php endif ?>

View File

@ -1,21 +0,0 @@
<?php if ($errors): ?>
<ul>
<?php foreach ($errors as $error): ?>
<li><?php
if (null === $error->getMessagePluralization()) {
echo $view['translator']->trans(
$error->getMessageTemplate(),
$error->getMessageParameters(),
'validators'
);
} else {
echo $view['translator']->transChoice(
$error->getMessageTemplate(),
$error->getMessagePluralization(),
$error->getMessageParameters(),
'validators'
);
}?></li>
<?php endforeach; ?>
</ul>
<?php endif ?>

View File

@ -14,7 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Routing;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Psr\Log\LoggerInterface;
/**
* DelegatingLoader delegates route loading to other loaders using a loader resolver.

View File

@ -12,7 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Templating;
use Symfony\Component\Templating\DebuggerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Psr\Log\LoggerInterface;
/**
* Binds the Symfony templating loader debugger to the Symfony logger.

View File

@ -12,7 +12,8 @@
namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
use Symfony\Component\Templating\Helper\Helper;
use Symfony\Bundle\FrameworkBundle\HttpKernel;
use Symfony\Component\HttpKernel\HttpContentRenderer;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
* ActionsHelper manages action inclusions.
@ -21,16 +22,16 @@ use Symfony\Bundle\FrameworkBundle\HttpKernel;
*/
class ActionsHelper extends Helper
{
protected $kernel;
private $renderer;
/**
* Constructor.
*
* @param HttpKernel $kernel A HttpKernel instance
* @param HttpContentRenderer $renderer A HttpContentRenderer instance
*/
public function __construct(HttpKernel $kernel)
public function __construct(HttpContentRenderer $renderer)
{
$this->kernel = $kernel;
$this->renderer = $renderer;
}
/**
@ -41,11 +42,21 @@ class ActionsHelper extends Helper
*
* @return string
*
* @see Symfony\Bundle\FrameworkBundle\HttpKernel::render()
* @see Symfony\Component\HttpKernel\HttpContentRenderer::render()
*/
public function render($uri, array $options = array())
{
return $this->kernel->render($uri, $options);
$options = $this->renderer->fixOptions($options);
$strategy = isset($options['strategy']) ? $options['strategy'] : 'default';
unset($options['strategy']);
return $this->renderer->render($uri, $strategy, $options);
}
public function controller($controller, $attributes = array(), $query = array())
{
return new ControllerReference($controller, $attributes, $query);
}
/**

View File

@ -36,15 +36,17 @@ class RouterHelper extends Helper
/**
* Generates a URL from the given parameters.
*
* @param string $name The name of the route
* @param mixed $parameters An array of parameters
* @param Boolean $absolute Whether to generate an absolute URL
* @param string $name The name of the route
* @param mixed $parameters An array of parameters
* @param Boolean|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
*
* @return string The generated URL
*
* @see UrlGeneratorInterface
*/
public function generate($name, $parameters = array(), $absolute = false)
public function generate($name, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
{
return $this->generator->generate($name, $parameters, $absolute);
return $this->generator->generate($name, $parameters, $referenceType);
}
/**

View File

@ -0,0 +1,105 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\HttpRenderingStrategyPass;
class HttpRenderingStrategyPassTest extends \PHPUnit_Framework_TestCase
{
/**
* Tests that content rendering not implementing RenderingStrategyInterface
* trigger an exception.
*
* @expectedException \InvalidArgumentException
*/
public function testContentRendererWithoutInterface()
{
// one service, not implementing any interface
$services = array(
'my_content_renderer' => array(),
);
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$definition->expects($this->atLeastOnce())
->method('getClass')
->will($this->returnValue('stdClass'));
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));
// We don't test kernel.content_renderer_strategy here
$builder->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
->will($this->returnValue($services));
$builder->expects($this->atLeastOnce())
->method('getDefinition')
->will($this->returnValue($definition));
$pass = new HttpRenderingStrategyPass();
$pass->process($builder);
}
public function testValidContentRenderer()
{
$services = array(
'my_content_renderer' => array(),
);
$renderer = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$renderer
->expects($this->once())
->method('addMethodCall')
->with('addStrategy', array(new Reference('my_content_renderer')))
;
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$definition->expects($this->atLeastOnce())
->method('getClass')
->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RenderingStrategyService'));
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));
// We don't test kernel.content_renderer_strategy here
$builder->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
->will($this->returnValue($services));
$builder->expects($this->atLeastOnce())
->method('getDefinition')
->will($this->onConsecutiveCalls($renderer, $definition));
$pass = new HttpRenderingStrategyPass();
$pass->process($builder);
}
}
class RenderingStrategyService implements \Symfony\Component\HttpKernel\RenderingStrategy\RenderingStrategyInterface
{
public function render($uri, Request $request = null, array $options = array())
{
}
public function getName()
{
return 'test';
}
}

View File

@ -205,6 +205,11 @@ abstract class FrameworkExtensionTest extends TestCase
$files,
'->registerTranslatorConfiguration() finds Form translation resources'
);
$this->assertContains(
'Symfony/Component/Security/Resources/translations/security.en.xlf',
$files,
'->registerTranslatorConfiguration() finds Security translation resources'
);
$calls = $container->getDefinition('translator.default')->getMethodCalls();
$this->assertEquals('fr', $calls[0][1][0]);

View File

@ -29,7 +29,8 @@
"doctrine/common": ">=2.2,<2.4-dev"
},
"require-dev": {
"symfony/finder": "2.2.*"
"symfony/finder": "2.2.*",
"symfony/security": "2.2.*"
},
"suggest": {
"symfony/console": "2.2.*",

View File

@ -55,36 +55,40 @@ class LogoutUrlHelper extends Helper
}
/**
* Generate the relative logout URL for the firewall.
* Generates the absolute logout path for the firewall.
*
* @param string $key The firewall key
* @return string The relative logout URL
*
* @return string The logout path
*/
public function getLogoutPath($key)
{
return $this->generateLogoutUrl($key, false);
return $this->generateLogoutUrl($key, UrlGeneratorInterface::ABSOLUTE_PATH);
}
/**
* Generate the absolute logout URL for the firewall.
* Generates the absolute logout URL for the firewall.
*
* @param string $key The firewall key
* @return string The absolute logout URL
*
* @return string The logout URL
*/
public function getLogoutUrl($key)
{
return $this->generateLogoutUrl($key, true);
return $this->generateLogoutUrl($key, UrlGeneratorInterface::ABSOLUTE_URL);
}
/**
* Generate the logout URL for the firewall.
* Generates the logout URL for the firewall.
*
* @param string $key The firewall key
* @param Boolean|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
*
* @param string $key The firewall key
* @param Boolean $absolute Whether to generate an absolute URL
* @return string The logout URL
*
* @throws \InvalidArgumentException if no LogoutListener is registered for the key
*/
private function generateLogoutUrl($key, $absolute)
private function generateLogoutUrl($key, $referenceType)
{
if (!array_key_exists($key, $this->listeners)) {
throw new \InvalidArgumentException(sprintf('No LogoutListener found for firewall key "%s".', $key));
@ -97,13 +101,13 @@ class LogoutUrlHelper extends Helper
if ('/' === $logoutPath[0]) {
$request = $this->container->get('request');
$url = ($absolute ? $request->getUriForPath($logoutPath) : $request->getBasePath() . $logoutPath);
$url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($logoutPath) : $request->getBasePath() . $logoutPath;
if (!empty($parameters)) {
$url .= '?' . http_build_query($parameters);
}
} else {
$url = $this->router->generate($logoutPath, $parameters, $absolute);
$url = $this->router->generate($logoutPath, $parameters, $referenceType);
}
return $url;

View File

@ -12,9 +12,10 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FormLoginBundle\Security;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
class LocalizedFormFailureHandler implements AuthenticationFailureHandlerInterface
@ -28,6 +29,6 @@ class LocalizedFormFailureHandler implements AuthenticationFailureHandlerInterfa
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new RedirectResponse($this->router->generate('localized_login_path', array(), true));
return new RedirectResponse($this->router->generate('localized_login_path', array(), UrlGeneratorInterface::ABSOLUTE_URL));
}
}

View File

@ -90,8 +90,7 @@
<service id="twig.extension.httpkernel" class="%twig.extension.httpkernel.class%">
<tag name="twig.extension" />
<tag name="kernel.event_subscriber" />
<argument type="service" id="http_kernel" />
<argument type="service" id="http_content_renderer" />
</service>
<service id="twig.extension.form" class="%twig.extension.form.class%" public="false">

View File

@ -12,8 +12,8 @@
in {{ trace.file|format_file(trace.line) }}&nbsp;
{% spaceless %}
<a href="#" onclick="toggle('trace-{{ prefix ~ '-' ~ i }}'); switchIcons('icon-{{ prefix ~ '-' ~ i }}-open', 'icon-{{ prefix ~ '-' ~ i }}-close'); return false;">
<img class="toggle" id="icon-{{ prefix ~ '-' ~ i }}-close" alt="-" src="data:image/gif;base64,R0lGODlhEgASAMQSANft94TG57Hb8GS44ez1+mC24IvK6ePx+Wa44dXs92+942e54o3L6W2844/M6dnu+P/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABIALAAAAAASABIAQAVCoCQBTBOd6Kk4gJhGBCTPxysJb44K0qD/ER/wlxjmisZkMqBEBW5NHrMZmVKvv9hMVsO+hE0EoNAstEYGxG9heIhCADs=" style="visibility: {{ 0 == i ? 'display' : 'hidden' }}" />
<img class="toggle" id="icon-{{ prefix ~ '-' ~ i }}-open" alt="+" src="data:image/gif;base64,R0lGODlhEgASAMQTANft99/v+Ga44bHb8ITG52S44dXs9+z1+uPx+YvK6WC24G+944/M6W28443L6dnu+Ge54v/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABMALAAAAAASABIAQAVS4DQBTiOd6LkwgJgeUSzHSDoNaZ4PU6FLgYBA5/vFID/DbylRGiNIZu74I0h1hNsVxbNuUV4d9SsZM2EzWe1qThVzwWFOAFCQFa1RQq6DJB4iIQA7" style="visibility: {{ 0 == i ? 'hidden' : 'display' }}; margin-left: -18px" />
<img class="toggle" id="icon-{{ prefix ~ '-' ~ i }}-close" alt="-" src="data:image/gif;base64,R0lGODlhEgASAMQSANft94TG57Hb8GS44ez1+mC24IvK6ePx+Wa44dXs92+942e54o3L6W2844/M6dnu+P/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABIALAAAAAASABIAQAVCoCQBTBOd6Kk4gJhGBCTPxysJb44K0qD/ER/wlxjmisZkMqBEBW5NHrMZmVKvv9hMVsO+hE0EoNAstEYGxG9heIhCADs=" style="visibility: {{ 0 == i ? 'visible' : 'hidden' }}" />
<img class="toggle" id="icon-{{ prefix ~ '-' ~ i }}-open" alt="+" src="data:image/gif;base64,R0lGODlhEgASAMQTANft99/v+Ga44bHb8ITG52S44dXs9+z1+uPx+YvK6WC24G+944/M6W28443L6dnu+Ge54v/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABMALAAAAAASABIAQAVS4DQBTiOd6LkwgJgeUSzHSDoNaZ4PU6FLgYBA5/vFID/DbylRGiNIZu74I0h1hNsVxbNuUV4d9SsZM2EzWe1qThVzwWFOAFCQFa1RQq6DJB4iIQA7" style="visibility: {{ 0 == i ? 'hidden' : 'visible' }}; margin-left: -18px" />
</a>
{% endspaceless %}
<div id="trace-{{ prefix ~ '-' ~ i }}" style="display: {{ 0 == i ? 'block' : 'none' }}" class="trace">

View File

@ -5,8 +5,8 @@
{{ exception.class|abbr_class }}: {{ exception.message|nl2br|format_file_from_text }}&nbsp;
{% spaceless %}
<a href="#" onclick="toggle('traces-{{ position }}', 'traces'); switchIcons('icon-traces-{{ position }}-open', 'icon-traces-{{ position }}-close'); return false;">
<img class="toggle" id="icon-traces-{{ position }}-close" alt="-" src="data:image/gif;base64,R0lGODlhEgASAMQSANft94TG57Hb8GS44ez1+mC24IvK6ePx+Wa44dXs92+942e54o3L6W2844/M6dnu+P/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABIALAAAAAASABIAQAVCoCQBTBOd6Kk4gJhGBCTPxysJb44K0qD/ER/wlxjmisZkMqBEBW5NHrMZmVKvv9hMVsO+hE0EoNAstEYGxG9heIhCADs=" style="visibility: {{ 0 == count ? 'display' : 'hidden' }}" />
<img class="toggle" id="icon-traces-{{ position }}-open" alt="+" src="data:image/gif;base64,R0lGODlhEgASAMQTANft99/v+Ga44bHb8ITG52S44dXs9+z1+uPx+YvK6WC24G+944/M6W28443L6dnu+Ge54v/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABMALAAAAAASABIAQAVS4DQBTiOd6LkwgJgeUSzHSDoNaZ4PU6FLgYBA5/vFID/DbylRGiNIZu74I0h1hNsVxbNuUV4d9SsZM2EzWe1qThVzwWFOAFCQFa1RQq6DJB4iIQA7" style="visibility: {{ 0 == count ? 'hidden' : 'display' }}; margin-left: -18px" />
<img class="toggle" id="icon-traces-{{ position }}-close" alt="-" src="data:image/gif;base64,R0lGODlhEgASAMQSANft94TG57Hb8GS44ez1+mC24IvK6ePx+Wa44dXs92+942e54o3L6W2844/M6dnu+P/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABIALAAAAAASABIAQAVCoCQBTBOd6Kk4gJhGBCTPxysJb44K0qD/ER/wlxjmisZkMqBEBW5NHrMZmVKvv9hMVsO+hE0EoNAstEYGxG9heIhCADs=" style="visibility: {{ 0 == count ? 'visible' : 'hidden' }}" />
<img class="toggle" id="icon-traces-{{ position }}-open" alt="+" src="data:image/gif;base64,R0lGODlhEgASAMQTANft99/v+Ga44bHb8ITG52S44dXs9+z1+uPx+YvK6WC24G+944/M6W28443L6dnu+Ge54v/+/l614P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABMALAAAAAASABIAQAVS4DQBTiOd6LkwgJgeUSzHSDoNaZ4PU6FLgYBA5/vFID/DbylRGiNIZu74I0h1hNsVxbNuUV4d9SsZM2EzWe1qThVzwWFOAFCQFa1RQq6DJB4iIQA7" style="visibility: {{ 0 == count ? 'hidden' : 'visible' }}; margin-left: -18px" />
</a>
{% endspaceless %}
</h2>

View File

@ -35,6 +35,10 @@
<span class="sf-toolbar-status sf-toolbar-status-{{ collector.hasxdebug ? 'green' : 'red' }}">xdebug</span>
<span class="sf-toolbar-status sf-toolbar-status-{{ collector.hasaccelerator ? 'green' : 'red' }}">accel</span>
</div>
<div class="sf-toolbar-info-piece">
<b>PHP SAPI</b>
<span>{{ collector.sapiName }}</span>
</div>
{% endspaceless %}
{% endset %}
{% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': false } %}

View File

@ -23,7 +23,7 @@ class OutputFormatter implements OutputFormatterInterface
/**
* The pattern to phrase the format.
*/
const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]+)?>((?:(?!\\\\?<).)*)#is';
const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]+)?>((?: [^<\\\\]+ | (?!<(?:/?[a-z]|/>)). | .(?<=\\\\<) )*)#isx';
private $decorated;
private $styles = array();

View File

@ -73,6 +73,26 @@ class FormatterStyleTest extends \PHPUnit_Framework_TestCase
);
}
public function testStyleMatchingNotGreedy()
{
$formatter = new OutputFormatter(true);
$this->assertEquals(
"(\033[32m>=2.0,<2.3\033[0m)",
$formatter->format('(<info>>=2.0,<2.3</info>)')
);
}
public function testStyleEscaping()
{
$formatter = new OutputFormatter(true);
$this->assertEquals(
"(\033[32mz>=2.0,<a2.3\033[0m)",
$formatter->format('(<info>'.$formatter->escape('z>=2.0,<a2.3').'</info>)')
);
}
public function testDeepNestedStyles()
{
$formatter = new OutputFormatter(true);

View File

@ -34,6 +34,7 @@ class TokenizerTest extends \PHPUnit_Framework_TestCase
{
$this->assertEquals('foo[class=foo bar ]', $this->tokensToString($this->tokenizer->tokenize('foo[class="foo bar"]')), '->tokenize() lexes an input string and returns an array of tokens');
$this->assertEquals("foo[class=foo Abar ]", $this->tokensToString($this->tokenizer->tokenize('foo[class="foo \\65 bar"]')), '->tokenize() lexes an input string and returns an array of tokens');
$this->assertEquals("img[alt= ]", $this->tokensToString($this->tokenizer->tokenize('img[alt=""]')), '->tokenize() lexes an input string and returns an array of tokens');
}
/**

View File

@ -129,7 +129,7 @@ class Tokenizer
}
$result = substr($s, $start, $next - $start);
if ('\\' === $result[strlen($result) - 1]) {
if (strlen($result) > 0 && '\\' === $result[strlen($result) - 1]) {
// next quote character is escaped
$pos = $next + 1;
continue;

View File

@ -89,7 +89,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
// resolve invalid behavior
if ($exists && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
$arguments[$k] = new Reference($id);
$arguments[$k] = new Reference($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $argument->isStrict());
} elseif (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
$arguments[$k] = null;
} elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {

View File

@ -229,24 +229,7 @@ class PhpDumper extends Dumper
throw new ServiceCircularReferenceException($id, array($id));
}
$arguments = array();
foreach ($sDefinition->getArguments() as $argument) {
$arguments[] = $this->dumpValue($argument);
}
if (null !== $sDefinition->getFactoryMethod()) {
if (null !== $sDefinition->getFactoryClass()) {
$code .= sprintf(" \$%s = call_user_func(array(%s, '%s')%s);\n", $name, $this->dumpValue($sDefinition->getFactoryClass()), $sDefinition->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
} elseif (null !== $sDefinition->getFactoryService()) {
$code .= sprintf(" \$%s = %s->%s(%s);\n", $name, $this->getServiceCall($sDefinition->getFactoryService()), $sDefinition->getFactoryMethod(), implode(', ', $arguments));
} else {
throw new RuntimeException('Factory service or factory class must be defined in service definition for '.$id);
}
} elseif (false !== strpos($class, '$')) {
$code .= sprintf(" \$class = %s;\n \$%s = new \$class(%s);\n", $class, $name, implode(', ', $arguments));
} else {
$code .= sprintf(" \$%s = new \\%s(%s);\n", $name, substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
}
$code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');
if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
$code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
@ -297,11 +280,6 @@ class PhpDumper extends Dumper
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
}
$arguments = array();
foreach ($definition->getArguments() as $value) {
$arguments[] = $this->dumpValue($value);
}
$simple = $this->isSimpleInstance($id, $definition);
$instantiation = '';
@ -320,19 +298,7 @@ class PhpDumper extends Dumper
$instantiation .= ' = ';
}
if (null !== $definition->getFactoryMethod()) {
if (null !== $definition->getFactoryClass()) {
$code = sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : '');
} elseif (null !== $definition->getFactoryService()) {
$code = sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments));
} else {
throw new RuntimeException('Factory method requires a factory service or factory class in service definition for '.$id);
}
} elseif (false !== strpos($class, '$')) {
$code = sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
} else {
$code = sprintf(" $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
}
$code = $this->addNewInstance($id, $definition, $return, $instantiation);
if (!$simple) {
$code .= "\n";
@ -611,6 +577,34 @@ EOF;
return $publicServices.$aliasServices.$privateServices;
}
private function addNewInstance($id, Definition $definition, $return, $instantiation)
{
$class = $this->dumpValue($definition->getClass());
$arguments = array();
foreach ($definition->getArguments() as $value) {
$arguments[] = $this->dumpValue($value);
}
if (null !== $definition->getFactoryMethod()) {
if (null !== $definition->getFactoryClass()) {
return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : '');
}
if (null !== $definition->getFactoryService()) {
return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments));
}
throw new RuntimeException('Factory method requires a factory service or factory class in service definition for '.$id);
}
if (false !== strpos($class, '$')) {
return sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
}
return sprintf(" $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
}
/**
* Adds the class headers.
*
@ -958,8 +952,9 @@ EOF;
/**
* Checks if a service id has a reference
*
* @param string $id
* @param array $arguments
* @param string $id
* @param array $arguments
* @param Boolean $deep
*
* @return Boolean
*/

View File

@ -61,6 +61,20 @@ class ResolveInvalidReferencesPassTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array(), $def->getProperties());
}
public function testStrictFlagIsPreserved()
{
$container = new ContainerBuilder();
$container->register('bar');
$def = $container
->register('foo')
->addArgument(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE, false))
;
$this->process($container);
$this->assertFalse($def->getArgument(0)->isStrict());
}
protected function process(ContainerBuilder $container)
{
$pass = new ResolveInvalidReferencesPass();

View File

@ -198,7 +198,7 @@ class Command
public function end()
{
if (null === $this->parent) {
throw new \RuntimeException('Calling end on root command dont makes sense.');
throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
}
return $this->parent;
@ -251,6 +251,7 @@ class Command
* Insert a string or a Command instance before the bit at given position $index (index starts from 0).
*
* @param string|Command $bit
* @param integer $index
*
* @return Command The current Command instance
*/

View File

@ -51,10 +51,20 @@ abstract class AbstractType implements FormTypeInterface
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC'));
$resolver->setDefaults($this->getDefaultOptions(array()));
$resolver->addAllowedValues($this->getAllowedOptionValues(array()));
restore_error_handler();
$defaults = $this->getDefaultOptions(array());
$allowedTypes = $this->getAllowedOptionValues(array());
if (!empty($defaults)) {
trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
$resolver->setDefaults($defaults);
}
if (!empty($allowedTypes)) {
trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
$resolver->addAllowedValues($allowedTypes);
}
}
/**
@ -69,8 +79,6 @@ abstract class AbstractType implements FormTypeInterface
*/
public function getDefaultOptions(array $options)
{
trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
return array();
}
@ -86,8 +94,6 @@ abstract class AbstractType implements FormTypeInterface
*/
public function getAllowedOptionValues(array $options)
{
trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
return array();
}

View File

@ -44,10 +44,20 @@ abstract class AbstractTypeExtension implements FormTypeExtensionInterface
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC'));
$resolver->setDefaults($this->getDefaultOptions());
$resolver->addAllowedValues($this->getAllowedOptionValues());
restore_error_handler();
$defaults = $this->getDefaultOptions(array());
$allowedTypes = $this->getAllowedOptionValues(array());
if (!empty($defaults)) {
trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
$resolver->setDefaults($defaults);
}
if (!empty($allowedTypes)) {
trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
$resolver->addAllowedValues($allowedTypes);
}
}
/**
@ -60,8 +70,6 @@ abstract class AbstractTypeExtension implements FormTypeExtensionInterface
*/
public function getDefaultOptions()
{
trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
return array();
}
@ -75,8 +83,6 @@ abstract class AbstractTypeExtension implements FormTypeExtensionInterface
*/
public function getAllowedOptionValues()
{
trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED);
return array();
}
}

View File

@ -12,6 +12,16 @@ CHANGELOG
* deprecated FormException and introduced ExceptionInterface instead
* [BC BREAK] FormException is now an interface
* protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig()
* [BC BREAK] inserted argument `$message` in the constructor of `FormError`
* the PropertyPath class and related classes were moved to a dedicated
PropertyAccess component. During the move, InvalidPropertyException was
renamed to NoSuchPropertyException. FormUtil was split: FormUtil::singularify()
can now be found in Symfony\Component\PropertyAccess\StringUtil. The methods
getValue() and setValue() from PropertyPath were extracted into a new class
PropertyAccessor.
* added an optional PropertyAccessorInterface parameter to FormType,
ObjectChoiceList and PropertyPathMapper
* [BC BREAK] PropertyPathMapper and FormType now have a constructor
2.1.0
-----

View File

@ -27,7 +27,7 @@ class CallbackValidator implements FormValidatorInterface
*/
public function __construct($callback)
{
trigger_error('CallbackValidator is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED);
trigger_error('CallbackValidator is deprecated since version 2.1 and will be removed in 2.3. Use the FormEvents::POST_BIND event instead.', E_USER_DEPRECATED);
$this->callback = $callback;
}

View File

@ -11,9 +11,11 @@
namespace Symfony\Component\Form\Extension\Core\ChoiceList;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Exception\StringCastException;
use Symfony\Component\Form\Exception\InvalidPropertyException;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
* A choice list for object choices.
@ -32,6 +34,11 @@ use Symfony\Component\Form\Exception\InvalidPropertyException;
*/
class ObjectChoiceList extends ChoiceList
{
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
/**
* The property path used to obtain the choice label.
*
@ -56,28 +63,30 @@ class ObjectChoiceList extends ChoiceList
/**
* Creates a new object choice list.
*
* @param array|\Traversable $choices The array of choices. Choices may also be given
* as hierarchy of unlimited depth by creating nested
* arrays. The title of the sub-hierarchy can be
* stored in the array key pointing to the nested
* array. The topmost level of the hierarchy may also
* be a \Traversable.
* @param string $labelPath A property path pointing to the property used
* for the choice labels. The value is obtained
* by calling the getter on the object. If the
* path is NULL, the object's __toString() method
* is used instead.
* @param array $preferredChoices A flat array of choices that should be
* presented to the user with priority.
* @param string $groupPath A property path pointing to the property used
* to group the choices. Only allowed if
* the choices are given as flat array.
* @param string $valuePath A property path pointing to the property used
* for the choice values. If not given, integers
* are generated instead.
* @param array|\Traversable $choices The array of choices. Choices may also be given
* as hierarchy of unlimited depth by creating nested
* arrays. The title of the sub-hierarchy can be
* stored in the array key pointing to the nested
* array. The topmost level of the hierarchy may also
* be a \Traversable.
* @param string $labelPath A property path pointing to the property used
* for the choice labels. The value is obtained
* by calling the getter on the object. If the
* path is NULL, the object's __toString() method
* is used instead.
* @param array $preferredChoices A flat array of choices that should be
* presented to the user with priority.
* @param string $groupPath A property path pointing to the property used
* to group the choices. Only allowed if
* the choices are given as flat array.
* @param string $valuePath A property path pointing to the property used
* for the choice values. If not given, integers
* are generated instead.
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
*/
public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null)
public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null)
{
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
$this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null;
$this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null;
$this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null;
@ -108,8 +117,8 @@ class ObjectChoiceList extends ChoiceList
}
try {
$group = $this->groupPath->getValue($choice);
} catch (InvalidPropertyException $e) {
$group = $this->propertyAccessor->getValue($choice, $this->groupPath);
} catch (NoSuchPropertyException $e) {
// Don't group items whose group property does not exist
// see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf
$group = null;
@ -150,7 +159,7 @@ class ObjectChoiceList extends ChoiceList
protected function createValue($choice)
{
if ($this->valuePath) {
return (string) $this->valuePath->getValue($choice);
return (string) $this->propertyAccessor->getValue($choice, $this->valuePath);
}
return parent::createValue($choice);
@ -163,7 +172,7 @@ class ObjectChoiceList extends ChoiceList
$labels[$i] = array();
$this->extractLabels($choice, $labels[$i]);
} elseif ($this->labelPath) {
$labels[$i] = $this->labelPath->getValue($choice);
$labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath);
} elseif (method_exists($choice, '__toString')) {
$labels[$i] = (string) $choice;
} else {

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Form\Extension\Core;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\PropertyAccess\PropertyAccess;
/**
* Represents the main form extension, which loads the core functionality.
@ -24,7 +25,7 @@ class CoreExtension extends AbstractExtension
{
return array(
new Type\FieldType(),
new Type\FormType(),
new Type\FormType(PropertyAccess::getPropertyAccessor()),
new Type\BirthdayType(),
new Type\CheckboxType(),
new Type\ChoiceType(),

View File

@ -14,9 +14,31 @@ namespace Symfony\Component\Form\Extension\Core\DataMapper;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
* A data mapper using property paths to read/write data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class PropertyPathMapper implements DataMapperInterface
{
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
/**
* Creates a new property path mapper.
*
* @param PropertyAccessorInterface $propertyAccessor
*/
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
{
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
}
/**
* {@inheritdoc}
*/
@ -39,7 +61,7 @@ class PropertyPathMapper implements DataMapperInterface
$config = $form->getConfig();
if (null !== $propertyPath && $config->getMapped()) {
$form->setData($propertyPath->getValue($data));
$form->setData($this->propertyAccessor->getValue($data, $propertyPath));
}
}
}
@ -70,8 +92,8 @@ class PropertyPathMapper implements DataMapperInterface
if (null !== $propertyPath && $config->getMapped() && $form->isSynchronized() && !$form->isDisabled()) {
// If the data is identical to the value in $data, we are
// dealing with a reference
if (!is_object($data) || !$config->getByReference() || $form->getData() !== $propertyPath->getValue($data)) {
$propertyPath->setValue($data, $form->getData());
if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) {
$this->propertyAccessor->setValue($data, $propertyPath, $form->getData());
}
}
}

View File

@ -20,9 +20,21 @@ use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
use Symfony\Component\Form\Exception\Exception;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
class FormType extends AbstractType
{
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
{
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
}
/**
* {@inheritdoc}
*/
@ -41,7 +53,7 @@ class FormType extends AbstractType
->setCompound($options['compound'])
->setData(isset($options['data']) ? $options['data'] : null)
->setDataLocked(isset($options['data']))
->setDataMapper($options['compound'] ? new PropertyPathMapper() : null)
->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
;
if ($options['trim']) {

View File

@ -12,7 +12,7 @@
namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPath;
/**
* @author Bernhard Schussek <bschussek@gmail.com>

View File

@ -13,9 +13,9 @@ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
use Symfony\Component\Form\Util\PropertyPathIterator;
use Symfony\Component\Form\Util\PropertyPathBuilder;
use Symfony\Component\Form\Util\PropertyPathIteratorInterface;
use Symfony\Component\PropertyAccess\PropertyPathIterator;
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface;
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPathIterator;
use Symfony\Component\Form\FormError;
use Symfony\Component\Validator\ConstraintViolation;
@ -123,6 +123,7 @@ class ViolationMapper implements ViolationMapperInterface
// Only add the error if the form is synchronized
if ($this->acceptsErrors($scope)) {
$scope->addError(new FormError(
$violation->getMessage(),
$violation->getMessageTemplate(),
$violation->getMessageParameters(),
$violation->getMessagePluralization()
@ -264,7 +265,7 @@ class ViolationMapper implements ViolationMapperInterface
$propertyPathBuilder->remove(0, $i + 1);
$i = 0;
} else {
/* @var \Symfony\Component\Form\Util\PropertyPathInterface $propertyPath */
/* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */
$propertyPath = $scope->getPropertyPath();
if (null === $propertyPath) {

View File

@ -11,8 +11,8 @@
namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Util\PropertyPathInterface;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
/**
* @author Bernhard Schussek <bschussek@gmail.com>

View File

@ -11,7 +11,7 @@
namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;
use Symfony\Component\Form\Util\PropertyPathIterator;
use Symfony\Component\PropertyAccess\PropertyPathIterator;
/**
* @author Bernhard Schussek <bschussek@gmail.com>

View File

@ -16,8 +16,8 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\AlreadyBoundException;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Util\FormUtil;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PropertyAccess\PropertyPath;
/**
* Form represents a form.
@ -367,11 +367,12 @@ class Form implements \IteratorAggregate, FormInterface
// Hook to change content of the data
if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA) || $dispatcher->hasListeners(FormEvents::SET_DATA)) {
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC'));
$event = new FormEvent($this, $modelData);
restore_error_handler();
$dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event);
// BC until 2.3
if ($dispatcher->hasListeners(FormEvents::SET_DATA)) {
trigger_error('The FormEvents::SET_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_SET_DATA event instead.', E_USER_DEPRECATED);
}
$dispatcher->dispatch(FormEvents::SET_DATA, $event);
$modelData = $event->getData();
}
@ -532,17 +533,18 @@ class Form implements \IteratorAggregate, FormInterface
// Hook to change content of the data bound by the browser
if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) {
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC'));
$event = new FormEvent($this, $submittedData);
restore_error_handler();
$dispatcher->dispatch(FormEvents::PRE_BIND, $event);
// BC until 2.3
if ($dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) {
trigger_error('The FormEvents::BIND_CLIENT_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_BIND event instead.', E_USER_DEPRECATED);
}
$dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event);
$submittedData = $event->getData();
}
// Check whether the form is compound.
// This check is preferrable over checking the number of children,
// This check is preferable over checking the number of children,
// since forms without children may also be compound.
// (think of empty collection forms)
if ($this->config->getCompound()) {
@ -594,11 +596,12 @@ class Form implements \IteratorAggregate, FormInterface
// Hook to change content of the data into the normalized
// representation
if ($dispatcher->hasListeners(FormEvents::BIND) || $dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) {
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC'));
$event = new FormEvent($this, $normData);
restore_error_handler();
$dispatcher->dispatch(FormEvents::BIND, $event);
// BC until 2.3
if ($dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) {
trigger_error('The FormEvents::BIND_NORM_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::BIND event instead.', E_USER_DEPRECATED);
}
$dispatcher->dispatch(FormEvents::BIND_NORM_DATA, $event);
$normData = $event->getData();
}
@ -621,10 +624,14 @@ class Form implements \IteratorAggregate, FormInterface
}
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC'));
foreach ($this->config->getValidators() as $validator) {
$validators = $this->config->getValidators();
restore_error_handler();
foreach ($validators as $validator) {
trigger_error(sprintf('FormConfigInterface::getValidators() is deprecated since 2.1 and will be removed in 2.3. Convert your %s class to a listener on the FormEvents::POST_BIND event.', get_class($validator)), E_USER_DEPRECATED);
$validator->validate($this);
}
restore_error_handler();
return $this;
}
@ -837,7 +844,7 @@ class Form implements \IteratorAggregate, FormInterface
*/
public function getChildren()
{
trigger_error('getChilren() is deprecated since version 2.1 and will be removed in 2.3. Use all() instead.', E_USER_DEPRECATED);
trigger_error('getChildren() is deprecated since version 2.1 and will be removed in 2.3. Use all() instead.', E_USER_DEPRECATED);
return $this->all();
}

View File

@ -204,6 +204,20 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB
return count($this->children);
}
/**
* {@inheritdoc}
*/
public function getFormConfig()
{
$config = parent::getFormConfig();
$config->parent = null;
$config->children = array();
$config->unresolvedChildren = array();
return $config;
}
/**
* {@inheritdoc}
*/
@ -287,12 +301,12 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB
*/
public function getTypes()
{
trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED);
if ($this->locked) {
throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
}
trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED);
$types = array();
for ($type = $this->getType(); null !== $type; $type = $type->getParent()) {

View File

@ -14,8 +14,8 @@ namespace Symfony\Component\Form;
use Symfony\Component\Form\Exception\BadMethodCallException;
use Symfony\Component\Form\Exception\Exception;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Util\PropertyPathInterface;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;

View File

@ -117,7 +117,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets the data mapper used by the form.
*
* @param DataMapperInterface $dataMapper
* @param DataMapperInterface $dataMapper
*
* @return self The configuration object.
*/
@ -126,7 +126,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Set whether the form is disabled.
*
* @param Boolean $disabled Whether the form is disabled
* @param Boolean $disabled Whether the form is disabled
*
* @return self The configuration object.
*/
@ -135,7 +135,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets the data used for the client data when no value is bound.
*
* @param mixed $emptyData The empty data.
* @param mixed $emptyData The empty data.
*
* @return self The configuration object.
*/
@ -144,7 +144,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets whether errors bubble up to the parent.
*
* @param Boolean $errorBubbling
* @param Boolean $errorBubbling
*
* @return self The configuration object.
*/
@ -162,9 +162,9 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets the property path that the form should be mapped to.
*
* @param null|string|PropertyPathInterface $propertyPath The property path or null if the path
* should be set automatically based on
* the form's name.
* @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath
* The property path or null if the path should be set
* automatically based on the form's name.
*
* @return self The configuration object.
*/
@ -174,7 +174,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
* Sets whether the form should be mapped to an element of its
* parent's data.
*
* @param Boolean $mapped Whether the form should be mapped.
* @param Boolean $mapped Whether the form should be mapped.
*
* @return self The configuration object.
*/
@ -183,7 +183,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets whether the form's data should be modified by reference.
*
* @param Boolean $byReference Whether the data should be
* @param Boolean $byReference Whether the data should be
* modified by reference.
*
* @return self The configuration object.
@ -193,7 +193,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets whether the form should be virtual.
*
* @param Boolean $virtual Whether the form should be virtual.
* @param Boolean $virtual Whether the form should be virtual.
*
* @return self The configuration object.
*/
@ -202,7 +202,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
/**
* Sets whether the form should be compound.
*
* @param Boolean $compound Whether the form should be compound.
* @param Boolean $compound Whether the form should be compound.
*
* @return self The configuration object.
*
@ -235,7 +235,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface
* this configuration. The data can only be modified then by
* binding the form.
*
* @param Boolean $locked Whether to lock the default data.
* @param Boolean $locked Whether to lock the default data.
*
* @return self The configuration object.
*/

View File

@ -35,7 +35,7 @@ interface FormConfigInterface
/**
* Returns the property path that the form should be mapped to.
*
* @return null|Util\PropertyPathInterface The property path.
* @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path.
*/
public function getPropertyPath();

View File

@ -18,6 +18,11 @@ namespace Symfony\Component\Form;
*/
class FormError
{
/**
* @var string
*/
private $message;
/**
* The template for the error message
* @var string
@ -41,16 +46,19 @@ class FormError
*
* Any array key in $messageParameters will be used as a placeholder in
* $messageTemplate.
* @see \Symfony\Component\Translation\Translator
*
* @param string $messageTemplate The template for the error message
* @param string $message The translated error message
* @param string|null $messageTemplate The template for the error message
* @param array $messageParameters The parameters that should be
* substituted in the message template.
* @param integer|null $messagePluralization The value for error message pluralization
*
* @see \Symfony\Component\Translation\Translator
*/
public function __construct($messageTemplate, array $messageParameters = array(), $messagePluralization = null)
public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null)
{
$this->messageTemplate = $messageTemplate;
$this->message = $message;
$this->messageTemplate = $messageTemplate ?: $message;
$this->messageParameters = $messageParameters;
$this->messagePluralization = $messagePluralization;
}
@ -62,7 +70,7 @@ class FormError
*/
public function getMessage()
{
return strtr($this->messageTemplate, $this->messageParameters);
return $this->message;
}
/**

View File

@ -166,7 +166,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
/**
* Returns the property path that the form is mapped to.
*
* @return Util\PropertyPathInterface The property path.
* @return \Symfony\Component\PropertyAccess\PropertyPathInterface The property path.
*/
public function getPropertyPath();

View File

@ -12,7 +12,7 @@
</trans-unit>
<trans-unit id="30">
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
<target>El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari</target>
<target>El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari.</target>
</trans-unit>
</body>
</file>

View File

@ -11,7 +11,7 @@
<target>Den oploadede fil var for stor. Opload venligst en mindre fil.</target>
</trans-unit>
<trans-unit id="30">
<source>The CSRF token is invalid.</source>
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
<target>CSRF nøglen er ugyldig.</target>
</trans-unit>
</body>

View File

@ -2,9 +2,6 @@
namespace Symfony\Component\Form\Test;
use Symfony\Component\Form\FormInterface as NonTestFormInterface;
use Symfony\Component\Form\FormEvent;
class DeprecationErrorHandler
{
public static function handle($errorNumber, $message, $file, $line, $context)
@ -24,13 +21,4 @@ class DeprecationErrorHandler
return false;
}
public static function getFormEvent(NonTestFormInterface $form, $data)
{
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle'));
$event = new FormEvent($form, $data);
restore_error_handler();
return $event;
}
}

View File

@ -19,7 +19,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
public function testRow()
{
$form = $this->factory->createNamed('name', 'text');
$form->addError(new FormError('Error!'));
$form->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$html = $this->renderRow($view);
@ -58,7 +58,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
public function testRepeatedRow()
{
$form = $this->factory->createNamed('name', 'repeated');
$form->addError(new FormError('Error!'));
$form->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$html = $this->renderRow($view);
@ -398,7 +398,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
)
->getForm();
$form->get('child')->addError(new FormError('Error!'));
$form->get('child')->addError(new FormError('[trans]Error![/trans]'));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div

View File

@ -283,8 +283,8 @@ abstract class AbstractLayoutTest extends FormIntegrationTestCase
public function testErrors()
{
$form = $this->factory->createNamed('name', 'text');
$form->addError(new FormError('Error 1'));
$form->addError(new FormError('Error 2'));
$form->addError(new FormError('[trans]Error 1[/trans]'));
$form->addError(new FormError('[trans]Error 2[/trans]'));
$view = $form->createView();
$html = $this->renderErrors($view);
@ -1151,7 +1151,7 @@ abstract class AbstractLayoutTest extends FormIntegrationTestCase
{
$child = $this->factory->createNamed('date', 'date');
$form = $this->factory->createNamed('form', 'form')->add($child);
$child->addError(new FormError('Error!'));
$child->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$this->assertEmpty($this->renderErrors($view));
@ -1676,7 +1676,7 @@ abstract class AbstractLayoutTest extends FormIntegrationTestCase
{
$child = $this->factory->createNamed('time', 'time');
$form = $this->factory->createNamed('form', 'form')->add($child);
$child->addError(new FormError('Error!'));
$child->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$this->assertEmpty($this->renderErrors($view));

View File

@ -18,7 +18,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
public function testRow()
{
$form = $this->factory->createNamed('name', 'text');
$form->addError(new FormError('Error!'));
$form->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$html = $this->renderRow($view);
@ -91,7 +91,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
public function testRepeatedRowWithErrors()
{
$form = $this->factory->createNamed('name', 'repeated');
$form->addError(new FormError('Error!'));
$form->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$html = $this->renderRow($view);
@ -250,7 +250,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
)
->getForm();
$form->get('child')->addError(new FormError('Error!'));
$form->get('child')->addError(new FormError('[trans]Error![/trans]'));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/table

View File

@ -231,9 +231,7 @@ class CompoundFormTest extends AbstractFormTest
$this->form->remove('foo');
$this->assertNull($child->getParent());
set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle'));
$this->assertFalse($this->form->hasChildren());
restore_error_handler();
$this->assertCount(0, $this->form);
}
/**

View File

@ -39,6 +39,9 @@ class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase
private $obj4;
/**
* @var ObjectChoiceList
*/
private $list;
protected function setUp()

View File

@ -11,10 +11,8 @@
namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormConfigInterface;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
@ -29,14 +27,24 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
*/
private $dispatcher;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $propertyAccessor;
protected function setUp()
{
if (!class_exists('Symfony\Component\EventDispatcher\Event')) {
$this->markTestSkipped('The "EventDispatcher" component is not available');
}
if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) {
$this->markTestSkipped('The "PropertyAccess" component is not available');
}
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
$this->mapper = new PropertyPathMapper();
$this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface');
$this->mapper = new PropertyPathMapper($this->propertyAccessor);
}
/**
@ -45,7 +53,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
*/
private function getPropertyPath($path)
{
return $this->getMockBuilder('Symfony\Component\Form\Util\PropertyPath')
return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath')
->setConstructorArgs(array($path))
->setMethods(array('getValue', 'setValue'))
->getMock();
@ -84,9 +92,9 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('getValue')
->with($car)
->with($car, $propertyPath)
->will($this->returnValue($engine));
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -107,9 +115,9 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('getValue')
->with($car)
->with($car, $propertyPath)
->will($this->returnValue($engine));
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -143,7 +151,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$car = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('getValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -161,7 +169,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
{
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('getValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -180,9 +188,9 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('getValue')
->with($car)
->with($car, $propertyPath)
->will($this->returnValue($engine));
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -211,9 +219,9 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('setValue')
->with($car, $engine);
->with($car, $propertyPath, $engine);
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setByReference(false);
@ -230,9 +238,9 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('setValue')
->with($car, $engine);
->with($car, $propertyPath, $engine);
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setByReference(true);
@ -250,12 +258,12 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$propertyPath = $this->getPropertyPath('engine');
// $car already contains the reference of $engine
$propertyPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('getValue')
->with($car)
->with($car, $propertyPath)
->will($this->returnValue($engine));
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('setValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -273,7 +281,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('setValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -291,7 +299,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$car = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('setValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -309,7 +317,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('setValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -327,7 +335,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$engine = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$propertyPath->expects($this->never())
$this->propertyAccessor->expects($this->never())
->method('setValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
@ -347,14 +355,14 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$parentPath = $this->getPropertyPath('name');
$childPath = $this->getPropertyPath('engine');
$parentPath->expects($this->never())
->method('getValue');
$parentPath->expects($this->never())
->method('setValue');
// getValue() and setValue() must never be invoked for $parentPath
$childPath->expects($this->once())
$this->propertyAccessor->expects($this->once())
->method('getValue')
->with($car, $childPath);
$this->propertyAccessor->expects($this->once())
->method('setValue')
->with($car, $engine);
->with($car, $childPath, $engine);
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setPropertyPath($parentPath);

View File

@ -11,9 +11,9 @@
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener;
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\Form\Test\DeprecationErrorHandler;
class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase
{
@ -42,7 +42,7 @@ class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase
{
$data = '1';
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$this->listener->preBind($event);
@ -53,7 +53,7 @@ class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase
{
$data = '0';
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$this->listener->preBind($event);
@ -64,7 +64,7 @@ class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase
{
$data = '';
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$this->listener->preBind($event);

View File

@ -11,8 +11,8 @@
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener;
use Symfony\Component\Form\Test\DeprecationErrorHandler;
class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase
{
@ -27,7 +27,7 @@ class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase
{
$data = "www.symfony.com";
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$filter = new FixUrlProtocolListener('http');
$filter->onBind($event);
@ -39,7 +39,7 @@ class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase
{
$data = "http://www.symfony.com";
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$filter = new FixUrlProtocolListener('http');
$filter->onBind($event);
@ -51,7 +51,7 @@ class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase
{
$data = "ftp://www.symfony.com";
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$filter = new FixUrlProtocolListener('http');
$filter->onBind($event);

View File

@ -11,8 +11,8 @@
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
use Symfony\Component\Form\Test\DeprecationErrorHandler;
abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
{
@ -84,7 +84,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
// The original object was modified
@ -108,7 +108,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
// The original object was modified
@ -133,7 +133,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
// We still have the original object
@ -157,7 +157,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
// The original object was modified
@ -182,7 +182,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
// We still have the original object
@ -201,7 +201,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
public function testRequireArrayOrTraversable($allowAdd, $allowDelete)
{
$newData = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener = new MergeCollectionListener($allowAdd, $allowDelete);
$listener->onBind($event);
}
@ -215,7 +215,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
$this->assertSame($originalData, $event->getData());
@ -233,7 +233,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
$this->assertSame($newData, $event->getData());
@ -251,7 +251,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
$this->form->setData($originalData);
$event = DeprecationErrorHandler::getFormEvent($this->form, $newData);
$event = new FormEvent($this->form, $newData);
$listener->onBind($event);
$this->assertNull($event->getData());

View File

@ -13,7 +13,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\Test\DeprecationErrorHandler;
use Symfony\Component\Form\FormEvent;
class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
{
@ -80,7 +80,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($this->getForm('2')));
$data = array(1 => 'string', 2 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array('max_length' => '10'), false, false);
$listener->preSetData($event);
@ -95,7 +95,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
public function testPreSetDataRequiresArrayOrTraversable()
{
$data = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->preSetData($event);
}
@ -105,7 +105,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->factory->expects($this->never())->method('createNamed');
$data = null;
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->preSetData($event);
}
@ -120,7 +120,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($this->getForm('1')));
$data = array(0 => 'string', 1 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array('max_length' => 10), true, false);
$listener->preBind($event);
@ -134,7 +134,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = array(0 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
@ -148,7 +148,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('0'));
$data = array();
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
@ -161,7 +161,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = array(0 => 'string', 2 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->preBind($event);
@ -176,7 +176,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
public function testPreBindRequiresArrayOrTraversable()
{
$data = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->preBind($event);
}
@ -186,7 +186,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = null;
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
@ -199,7 +199,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = '';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
@ -211,7 +211,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->onBind($event);
@ -223,7 +223,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->onBind($event);
@ -236,7 +236,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
public function testOnBindNormDataRequiresArrayOrTraversable()
{
$data = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->onBind($event);
}
@ -246,7 +246,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
$this->form->add($this->getForm('1'));
$data = null;
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->onBind($event);

View File

@ -11,8 +11,8 @@
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
use Symfony\Component\Form\Test\DeprecationErrorHandler;
class TrimListenerTest extends \PHPUnit_Framework_TestCase
{
@ -27,7 +27,7 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase
{
$data = " Foo! ";
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$filter = new TrimListener();
$filter->preBind($event);
@ -39,7 +39,7 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase
{
$data = 1234;
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$filter = new TrimListener();
$filter->preBind($event);
@ -60,7 +60,7 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase
$data = $data."ab\ncd".$data;
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$event = DeprecationErrorHandler::getFormEvent($form, $data);
$event = new FormEvent($form, $data);
$filter = new TrimListener();
$filter->preBind($event);

View File

@ -11,8 +11,6 @@
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

View File

@ -11,7 +11,7 @@
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Tests\Fixtures\Author;

Some files were not shown because too many files have changed in this diff Show More