Updated to Symfony 2.1 BETA3

This commit is contained in:
Polonkai Gergely
2012-07-16 21:40:19 +02:00
parent 7a06301624
commit 9d0d2ce524
1551 changed files with 157774 additions and 5177 deletions

View File

@@ -0,0 +1 @@
phpunit.xml

View File

@@ -0,0 +1,4 @@
vendor
composer.phar
composer.lock
phpunit.xml

View File

@@ -0,0 +1,3 @@
/vendor/
/composer.lock

5
vendor/symfony/symfony/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
phpunit.xml
composer.lock
composer.phar
autoload.php
/vendor/

57
vendor/symfony/symfony/README.md vendored Normal file
View File

@@ -0,0 +1,57 @@
README
======
[![Build Status](https://secure.travis-ci.org/symfony/symfony.png?branch=master)](http://travis-ci.org/symfony/symfony)
What is Symfony2?
-----------------
Symfony2 is a PHP 5.3 full-stack web framework. It is written with speed and
flexibility in mind. It allows developers to build better and easy to maintain
websites with PHP.
Symfony can be used to develop all kind of websites, from your personal blog
to high traffic ones like Dailymotion or Yahoo! Answers.
Requirements
------------
Symfony2 is only supported on PHP 5.3.3 and up.
Be warned that PHP versions before 5.3.8 are known to be buggy and might not
work for you:
* before PHP 5.3.4, if you get "Notice: Trying to get property of
non-object", you've hit a known PHP bug (see
https://bugs.php.net/bug.php?id=52083 and
https://bugs.php.net/bug.php?id=50027);
* before PHP 5.3.8, if you get an error involving annotations, you've hit a
known PHP bug (see https://bugs.php.net/bug.php?id=55156).
Installation
------------
The best way to install Symfony2 is to download the Symfony Standard Edition
available at [http://symfony.com/download][1].
Documentation
-------------
The "[Quick Tour][2]" tutorial gives you a first feeling of the framework. If,
like us, you think that Symfony2 can help speed up your development and take
the quality of your work to the next level, read the official
[Symfony2 documentation][3].
Contributing
------------
Symfony2 is an open source, community-driven project. If you'd like to contribute,
please read the [Contributing Code][4] part of the documentation. If you're submitting
a pull request, please follow the guidelines in the [Submitting a Patch][5] section.
[1]: http://symfony.com/download
[2]: http://symfony.com/get_started
[3]: http://symfony.com/doc/current/
[4]: http://symfony.com/doc/current/contributing/code/index.html
[5]: http://symfony.com/doc/current/contributing/code/patches.html#check-list

View File

@@ -13,6 +13,15 @@
configuration (i.e. `config.yml`), merging could yield a set of base URL's
for multiple environments.
* The priorities for the built-in listeners have changed:
2.0 2.1
security.firewall request 64 8
locale listener early_request 253 255
request -1 16
router listener early_request 255 128
request 10 32
### Doctrine
* The DoctrineBundle is moved from the Symfony repository to the Doctrine repository.
@@ -67,7 +76,7 @@
### HttpFoundation
* [BC BREAK] The current locale for the user is not stored anymore in the session
* The current locale for the user is not stored anymore in the session
You can simulate the old behavior by registering a listener that looks like the following, if the paramater which handle locale value in the request is `_locale`:
@@ -134,7 +143,7 @@
public function equals(UserInterface $user) { /* ... */ }
// ...
}
```
```
After:
@@ -146,6 +155,7 @@
// ...
}
```
* The custom factories for the firewall configuration are now
registered during the build method of bundles instead of being registered
by the end-user. This means that you will you need to remove the 'factories'
@@ -190,7 +200,7 @@
implementations of this interface to reflect this change.
* The `UserPassword` constraint has moved from the Security Bundle to the Security Component:
Before:
```
@@ -239,6 +249,16 @@
public function finishView(FormViewInterface $view, FormInterface $form, array $options)
```
* The method `createBuilder` was removed from `FormTypeInterface` for performance
reasons. It is now not possible anymore to use custom implementations of
`FormBuilderInterface` for specific form types.
If you are in such a situation, you can subclass `FormRegistry` instead and override
`resolveType` to return a custom `ResolvedFormTypeInterface` implementation, within
which you can create your own `FormBuilderInterface` implementation. You should
register this custom registry class under the service name "form.registry" in order
to replace the default implementation.
* If you previously inherited from `FieldType`, you should now inherit from
`FormType`. You should also set the option `compound` to `false` if your field
is not supposed to contain child fields.
@@ -556,6 +576,30 @@
{% endblock %}
````
* Custom styling of individual rows of a collection form has been removed for
performance reasons. Instead, all rows now have the same block name, where
the word "entry" replaces the previous occurence of the row index.
Before:
```
{% block _author_tags_0_label %}
{# ... #}
{% endblock %}
{% block _author_tags_1_label %}
{# ... #}
{% endblock %}
```
After:
```
{% block _author_tags_entry_label %}
{# ... #}
{% endblock %}
```
#### Other BC Breaks
* The order of the first two arguments of the methods `createNamed` and
@@ -635,6 +679,20 @@
`getChoices()` and `getChoicesByValues()`. For the latter two, no
replacement exists.
* HTML attributes are now passed in the `label_attr` variable for the `form_label` function.
Before:
```
{{ form_label(form.name, 'Your Name', { 'attr': {'class': 'foo'} }) }}
```
After:
```
{{ form_label(form.name, 'Your Name', { 'label_attr': {'class': 'foo'} }) }}
```
* `EntitiesToArrayTransformer` and `EntityToIdTransformer` were removed.
The former was replaced by `CollectionToArrayTransformer` in combination
with `EntityChoiceList`, the latter is not required in the core anymore.
@@ -860,6 +918,7 @@
* `getClientData`
* `getChildren`
* `hasChildren`
* `bindRequest`
Before:
@@ -891,6 +950,20 @@
if (count($form) > 0) {
```
Instead of `bindRequest`, you should now simply call `bind`:
Before:
```
$form->bindRequest($request);
```
After:
```
$form->bind($request);
```
* The option "validation_constraint" was deprecated and will be removed
in Symfony 2.3. You should use the option "constraints" instead,
where you can pass one or more constraints for a form.
@@ -922,6 +995,64 @@
));
```
Be aware that constraints will now only be validated if they belong
to the validated group! So if you validate a form in group "Custom"
and previously did:
```
$builder->add('name', 'text', array(
'validation_constraint' => new NotBlank(),
));
```
Then you need to add the constraint to the group "Custom" now:
```
$builder->add('name', 'text', array(
'constraints' => new NotBlank(array('groups' => 'Custom')),
));
```
* The options "data_timezone" and "user_timezone" in `DateType`,
`DateTimeType` and `TimeType` were deprecated and will be removed in
Symfony 2.3. They were renamed to "model_timezone" and "view_timezone".
Before:
```
$builder->add('scheduledFor', 'date', array(
'data_timezone' => 'UTC',
'user_timezone' => 'America/New_York',
));
```
After:
```
$builder->add('scheduledFor', 'date', array(
'model_timezone' => 'UTC',
'view_timezone' => 'America/New_York',
));
```
* The methods `addType`, `hasType` and `getType` in `FormFactory` are deprecated
and will be removed in Symfony 2.3. You should use the methods with the same
name on the `FormRegistry` instead.
Before:
```
$this->get('form.factory')->addType(new MyFormType());
```
After:
```
$registry = $this->get('form.registry');
$registry->addType($registry->resolveType(new MyFormType()));
```
### Validator
* The methods `setMessage()`, `getMessageTemplate()` and
@@ -1057,6 +1188,54 @@
private $recursiveCollection;
```
* The `Size`, `Min` and `Max` constraints were deprecated and will be removed in
Symfony 2.3. You should use the new constraint `Range` instead.
Before:
```
/** @Assert\Size(min = 2, max = 16) */
private $numberOfCpus;
```
After:
```
/** @Assert\Range(min = 2, max = 16) */
private $numberOfCpus;
```
Before:
```
/** @Assert\Min(2) */
private $numberOfCpus;
```
After:
```
/** @Assert\Range(min = 2) */
private $numberOfCpus;
```
* The `MinLength` and `MaxLength` constraints were deprecated and will be
removed in Symfony 2.3. You should use the new constraint `Length` instead.
Before:
```
/** @Assert\MinLength(8) */
private $password;
```
After:
```
/** @Assert\Length(min = 8) */
private $password;
```
### Session
* Flash messages now return an array based on their type. The old method is

45
vendor/symfony/symfony/phpunit.xml.dist vendored Normal file
View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="autoload.php.dist"
>
<php>
<ini name="intl.default_locale" value="en"/>
</php>
<testsuites>
<testsuite name="Symfony Test Suite">
<directory>./src/Symfony/Bridge/*/Tests/</directory>
<directory>./src/Symfony/Component/*/Tests/</directory>
<directory>./src/Symfony/Bundle/*/Tests/</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>benchmark</group>
</exclude>
</groups>
<filter>
<whitelist>
<directory>./src/Symfony/</directory>
<exclude>
<directory>./src/Symfony/Bridge/*/Tests</directory>
<directory>./src/Symfony/Component/*/Tests</directory>
<directory>./src/Symfony/Bundle/*/Tests</directory>
<directory>./src/Symfony/Bundle/*/Resources</directory>
<directory>./src/Symfony/Component/*/Resources</directory>
<directory>./src/Symfony/Component/*/*/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@@ -7,3 +7,4 @@ CHANGELOG
* added a default implementation of the ManagerRegistry
* added a session storage for Doctrine DBAL
* DoctrineOrmTypeGuesser now guesses "collection" for array Doctrine type
* DoctrineType now caches its choice lists in order to improve performance

View File

@@ -15,6 +15,12 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
/**
* Registers event listeners and subscribers to the available doctrine connections.
*
* @author Jeremy Mikola <jmikola@gmail.com>
* @author Alexander <iam.asm89@gmail.com>
*/
class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
{
private $connections;
@@ -38,6 +44,9 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
$this->tagPrefix = $tagPrefix;
}
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
if (!$container->hasParameter($this->connections)) {
@@ -80,35 +89,34 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
private function groupByConnection(array $services, $isListener = false)
{
$grouped = array();
foreach (array_keys($this->connections) as $con) {
foreach ($allCons = array_keys($this->connections) as $con) {
$grouped[$con] = array();
}
foreach ($services as $id => $instances) {
foreach ($instances as $instance) {
$cons = isset($instance['connection']) ? array($instance['connection']) : array_keys($this->connections);
if ($isListener) {
if (!isset($instance['event'])) {
throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
}
$instance['event'] = array($instance['event']);
if (isset($instance['lazy']) && $instance['lazy']) {
$this->container->getDefinition($id)->setPublic(true);
}
}
$cons = isset($instance['connection']) ? array($instance['connection']) : $allCons;
foreach ($cons as $con) {
if (!isset($grouped[$con])) {
throw new \RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
}
if ($isListener) {
if (!isset($instance['event'])) {
throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
}
$instance['event'] = array($instance['event']);
if (isset($instance['lazy']) && $instance['lazy']) {
$this->container->getDefinition($id)->setPublic(true);
}
if (isset($grouped[$con][$id])) {
$grouped[$con][$id]['event'] = array_merge($grouped[$con][$id]['event'], $instance['event']);
continue;
}
if ($isListener && isset($grouped[$con][$id])) {
$grouped[$con][$id]['event'] = array_merge($grouped[$con][$id]['event'], $instance['event']);
} else {
$grouped[$con][$id] = $instance;
}
$grouped[$con][$id] = $instance;
}
}
}

View File

@@ -23,7 +23,7 @@ interface EntityLoaderInterface
*
* @return array The entities.
*/
function getEntities();
public function getEntities();
/**
* Returns an array of entities matching the given identifiers.
@@ -35,5 +35,5 @@ interface EntityLoaderInterface
*
* @return array The entities.
*/
function getEntitiesByIds($identifier, array $values);
public function getEntitiesByIds($identifier, array $values);
}

View File

@@ -26,7 +26,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*/
class MergeDoctrineCollectionListener implements EventSubscriberInterface
{
static public function getSubscribedEvents()
public static function getSubscribedEvents()
{
// Higher priority than core MergeCollectionListener so that this one
// is called before

View File

@@ -29,6 +29,11 @@ abstract class DoctrineType extends AbstractType
*/
protected $registry;
/**
* @var array
*/
private $choiceListCache = array();
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
@@ -46,6 +51,7 @@ abstract class DoctrineType extends AbstractType
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$choiceListCache =& $this->choiceListCache;
$registry = $this->registry;
$type = $this;
@@ -59,17 +65,57 @@ abstract class DoctrineType extends AbstractType
return null;
};
$choiceList = function (Options $options) use ($registry) {
$choiceList = function (Options $options) use ($registry, &$choiceListCache, &$time) {
$manager = $registry->getManager($options['em']);
return new EntityChoiceList(
$manager,
// Support for closures
$propertyHash = is_object($options['property'])
? spl_object_hash($options['property'])
: $options['property'];
$choiceHashes = $options['choices'];
// Support for recursive arrays
if (is_array($choiceHashes)) {
// A second parameter ($key) is passed, so we cannot use
// spl_object_hash() directly (which strictly requires
// one parameter)
array_walk_recursive($choiceHashes, function ($value) {
return spl_object_hash($value);
});
}
// Support for custom loaders (with query builders)
$loaderHash = is_object($options['loader'])
? spl_object_hash($options['loader'])
: $options['loader'];
// Support for closures
$groupByHash = is_object($options['group_by'])
? spl_object_hash($options['group_by'])
: $options['group_by'];
$hash = md5(json_encode(array(
spl_object_hash($manager),
$options['class'],
$options['property'],
$options['loader'],
$options['choices'],
$options['group_by']
);
$propertyHash,
$loaderHash,
$choiceHashes,
$groupByHash
)));
if (!isset($choiceListCache[$hash])) {
$choiceListCache[$hash] = new EntityChoiceList(
$manager,
$options['class'],
$options['property'],
$options['loader'],
$options['choices'],
$options['group_by']
);
}
return $choiceListCache[$hash];
};
$resolver->setDefaults(array(

View File

@@ -26,7 +26,7 @@ interface RegistryInterface extends ManagerRegistryInterface
*
* @return string The default entity manager name
*/
function getDefaultEntityManagerName();
public function getDefaultEntityManagerName();
/**
* Gets a named entity manager.
@@ -35,14 +35,14 @@ interface RegistryInterface extends ManagerRegistryInterface
*
* @return EntityManager
*/
function getEntityManager($name = null);
public function getEntityManager($name = null);
/**
* Gets an array of all registered entity managers
*
* @return array An array of EntityManager instances
*/
function getEntityManagers();
public function getEntityManagers();
/**
* Resets a named entity manager.
@@ -61,7 +61,7 @@ interface RegistryInterface extends ManagerRegistryInterface
*
* @return EntityManager
*/
function resetEntityManager($name = null);
public function resetEntityManager($name = null);
/**
* Resolves a registered namespace alias to the full namespace.
@@ -74,14 +74,14 @@ interface RegistryInterface extends ManagerRegistryInterface
*
* @see Configuration::getEntityNamespace
*/
function getEntityNamespace($alias);
public function getEntityNamespace($alias);
/**
* Gets all connection names.
*
* @return array An array of connection names
*/
function getEntityManagerNames();
public function getEntityManagerNames();
/**
* Gets the entity manager associated with a given class.
@@ -90,5 +90,5 @@ interface RegistryInterface extends ManagerRegistryInterface
*
* @return EntityManager|null
*/
function getEntityManagerForClass($class);
public function getEntityManagerForClass($class);
}

View File

@@ -51,6 +51,27 @@ class RegisterEventListenersAndSubscribersPassTest extends \PHPUnit_Framework_Te
$this->assertEquals(array('foo', 'bar'), $calls[1][1][0]);
}
public function testProcessEventListenersWithMultipleConnections()
{
$container = $this->createBuilder(true);
$container
->register('a', 'stdClass')
->addTag('doctrine.event_listener', array(
'event' => 'onFlush',
))
;
$this->process($container);
$callsDefault = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();
$this->assertEquals('addEventListener', $callsDefault[0][0]);
$this->assertEquals(array('onFlush'), $callsDefault[0][1][0]);
$callsSecond = $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls();
$this->assertEquals($callsDefault, $callsSecond);
}
public function testProcessEventSubscribersWithPriorities()
{
$container = $this->createBuilder();
@@ -114,12 +135,22 @@ class RegisterEventListenersAndSubscribersPassTest extends \PHPUnit_Framework_Te
return $order;
}
private function createBuilder()
private function createBuilder($multipleConnections = false)
{
$container = new ContainerBuilder();
$connections = array('default' => 'doctrine.dbal.default_connection');
$container->register('doctrine.dbal.default_connection.event_manager', 'stdClass');
$container->register('doctrine.dbal.default_connection', 'stdClass');
$container->setParameter('doctrine.connections', array('default' => 'doctrine.dbal.default_connection'));
if ($multipleConnections) {
$container->register('doctrine.dbal.second_connection.event_manager', 'stdClass');
$container->register('doctrine.dbal.second_connection', 'stdClass');
$connections['second'] = 'doctrine.dbal.second_connection';
}
$container->setParameter('doctrine.connections', $connections);
return $container;
}

View File

@@ -35,7 +35,7 @@ abstract class DoctrineOrmTestCase extends \PHPUnit_Framework_TestCase
/**
* @return EntityManager
*/
static public function createTestEntityManager($paths = array())
public static function createTestEntityManager($paths = array())
{
if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
self::markTestSkipped('This test requires SQLite support in your environment');

View File

@@ -32,6 +32,6 @@ class SingleIdentEntity
public function __toString()
{
return (string)$this->name;
return (string) $this->name;
}
}

View File

@@ -0,0 +1,112 @@
<?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\Bridge\Doctrine\Tests\Form\Type;
use Symfony\Component\Form\Tests\FormPerformanceTestCase;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class EntityTypePerformanceTest extends FormPerformanceTestCase
{
const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity';
/**
* @var \Doctrine\ORM\EntityManager
*/
private $em;
protected function getExtensions()
{
$manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
$manager->expects($this->any())
->method('getManager')
->will($this->returnValue($this->em));
return array(
new CoreExtension(),
new DoctrineOrmExtension($manager)
);
}
protected function setUp()
{
if (!class_exists('Symfony\Component\Form\Form')) {
$this->markTestSkipped('The "Form" component is not available');
}
if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) {
$this->markTestSkipped('Doctrine DBAL is not available.');
}
if (!class_exists('Doctrine\Common\Version')) {
$this->markTestSkipped('Doctrine Common is not available.');
}
if (!class_exists('Doctrine\ORM\EntityManager')) {
$this->markTestSkipped('Doctrine ORM is not available.');
}
$this->em = DoctrineOrmTestCase::createTestEntityManager();
parent::setUp();
$schemaTool = new SchemaTool($this->em);
$classes = array(
$this->em->getClassMetadata(self::ENTITY_CLASS),
);
try {
$schemaTool->dropSchema($classes);
} catch (\Exception $e) {
}
try {
$schemaTool->createSchema($classes);
} catch (\Exception $e) {
}
$ids = range(1, 300);
foreach ($ids as $id) {
$name = 65 + chr($id % 57);
$this->em->persist(new SingleIdentEntity($id, $name));
}
$this->em->flush();
}
/**
* This test case is realistic in collection forms where each
* row contains the same entity field.
*
* @group benchmark
*/
public function testCollapsedEntityField()
{
$this->setMaxRunningTime(1);
for ($i = 0; $i < 20; ++$i) {
$form = $this->factory->create('entity', null, array(
'class' => self::ENTITY_CLASS,
));
// force loading of the choice list
$form->createView();
}
}
}

View File

@@ -69,7 +69,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
return $validatorFactory;
}
public function createValidator($entityManagerName, $em, $validateClass = null, $uniqueFields = null)
public function createValidator($entityManagerName, $em, $validateClass = null, $uniqueFields = null, $errorPath = null)
{
if (!$validateClass) {
$validateClass = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity';
@@ -83,7 +83,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
$uniqueValidator = new UniqueEntityValidator($registry);
$metadata = new ClassMetadata($validateClass);
$metadata->addConstraint(new UniqueEntity(array('fields' => $uniqueFields, 'em' => $entityManagerName)));
$metadata->addConstraint(new UniqueEntity(array('fields' => $uniqueFields, 'em' => $entityManagerName, 'errorPath' => $errorPath)));
$metadataFactory = $this->createMetadataFactoryMock($metadata);
$validatorFactory = $this->createValidatorFactory($uniqueValidator);
@@ -132,6 +132,29 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
$this->assertEquals('Foo', $violation->getInvalidValue());
}
public function testValidateCustomErrorPath()
{
$entityManagerName = "foo";
$em = $this->createTestEntityManager();
$this->createSchema($em);
$validator = $this->createValidator($entityManagerName, $em, null, null, 'bar');
$entity1 = new SingleIdentEntity(1, 'Foo');
$em->persist($entity1);
$em->flush();
$entity2 = new SingleIdentEntity(2, 'Foo');
$violationsList = $validator->validate($entity2);
$this->assertEquals(1, $violationsList->count(), "No violations found on entity after it was saved to the database.");
$violation = $violationsList[0];
$this->assertEquals('This value is already used.', $violation->getMessage());
$this->assertEquals('bar', $violation->getPropertyPath());
$this->assertEquals('Foo', $violation->getInvalidValue());
}
public function testValidateUniquenessWithNull()
{
$entityManagerName = "foo";

View File

@@ -25,6 +25,7 @@ class UniqueEntity extends Constraint
public $service = 'doctrine.orm.validator.unique';
public $em = null;
public $fields = array();
public $errorPath = null;
public function getRequiredOptions()
{

View File

@@ -47,6 +47,10 @@ class UniqueEntityValidator extends ConstraintValidator
throw new UnexpectedTypeException($constraint->fields, 'array');
}
if (null !== $constraint->errorPath && !is_string($constraint->errorPath)) {
throw new UnexpectedTypeException($constraint->errorPath, 'string or null');
}
$fields = (array) $constraint->fields;
if (0 === count($fields)) {
@@ -114,6 +118,8 @@ class UniqueEntityValidator extends ConstraintValidator
return;
}
$this->context->addViolationAtSubPath($fields[0], $constraint->message, array(), $criteria[$fields[0]]);
$errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];
$this->context->addViolationAtSubPath($errorPath, $constraint->message, array(), $criteria[$fields[0]]);
}
}

View File

@@ -65,6 +65,6 @@ class ModelType extends AbstractType
public function getName()
{
return 'propel_model';
return 'model';
}
}

View File

@@ -105,7 +105,7 @@ class PropelTypeGuesserTest extends Propel1TestCase
$this->assertEquals($confidence, $value->getConfidence());
}
static public function dataProviderForGuessType()
public static function dataProviderForGuessType()
{
return array(
array('is_active', 'checkbox', Guess::HIGH_CONFIDENCE),

View File

@@ -0,0 +1,2 @@
vendor/
composer.lock

View File

@@ -4,6 +4,7 @@ CHANGELOG
2.1.0
-----
* added global variables access in a form theme
* added TwigEngine
* added TwigExtractor
* added a csrf_token function

View File

@@ -245,7 +245,7 @@ class FormExtension extends \Twig_Extension
$this->varStack[$rendering]['variables'] = array_replace_recursive($this->varStack[$rendering]['variables'], $variables);
} else {
$types = $view->getVar('types');
$types[] = $custom;
$types[] = $view->getVar('full_block_name');
$typeIndex = count($types) - 1;
$this->varStack[$rendering] = array(
'variables' => array_replace_recursive($view->getVars(), $variables),
@@ -259,9 +259,11 @@ class FormExtension extends \Twig_Extension
if (isset($blocks[$types[$typeIndex]])) {
$this->varStack[$rendering]['typeIndex'] = $typeIndex;
$context = $this->environment->mergeGlobals($this->varStack[$rendering]['variables']);
// we do not call renderBlock here to avoid too many nested level calls (XDebug limits the level to 100 by default)
ob_start();
$this->template->displayBlock($types[$typeIndex], $this->varStack[$rendering]['variables'], $blocks);
$this->template->displayBlock($types[$typeIndex], $context, $blocks);
$html = ob_get_clean();
if ($mainTemplate) {

View File

@@ -20,6 +20,9 @@
{% block form_widget_compound %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% if form.parent is empty %}
{{ form_errors(form) }}
{% endif %}
{{ block('form_rows') }}
{{ form_rest(form) }}
</div>
@@ -236,6 +239,10 @@
{% block repeated_row %}
{% spaceless %}
{#
No need to render the errors here, as all errors are mapped
to the first child (see RepeatedTypeValidatorExtension).
#}
{{ block('form_rows') }}
{% endspaceless %}
{% endblock repeated_row %}
@@ -244,13 +251,7 @@
{% spaceless %}
<div>
{{ form_label(form, label|default(null)) }}
{#
If the child is a compound form, the errors are rendered inside
the container. See also block form_rows.
#}
{% if not compound %}
{{ form_errors(form) }}
{% endif %}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
@@ -298,7 +299,6 @@
{% block form_rows %}
{% spaceless %}
{{ form_errors(form) }}
{% for child in form %}
{{ form_row(child) }}
{% endfor %}

View File

@@ -7,31 +7,13 @@
{{ form_label(form, label|default(null)) }}
</td>
<td>
{% if not compound %}
{{ form_errors(form) }}
{% endif %}
{{ form_errors(form) }}
{{ form_widget(form) }}
</td>
</tr>
{% endspaceless %}
{% endblock form_row %}
{% block form_errors %}
{% spaceless %}
{% if not compound %}
{{ parent() }}
{% else %}
{% if errors|length > 0 %}
<tr>
<td colspan="2">
{{ parent() }}
</td>
</tr>
{% endif %}
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
{% block hidden_row %}
{% spaceless %}
<tr style="display: none">
@@ -45,6 +27,13 @@
{% block form_widget_compound %}
{% spaceless %}
<table {{ block('widget_container_attributes') }}>
{% if form.parent is empty and errors|length > 0 %}
<tr>
<td colspan="2">
{{ form_errors(form) }}
</td>
</tr>
{% endif %}
{{ block('form_rows') }}
{{ form_rest(form) }}
</table>

View File

@@ -52,9 +52,10 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest
'custom_widgets.html.twig',
));
$environment = new \Twig_Environment($loader);
$environment = new \Twig_Environment($loader, array('strict_variables' => true));
$environment->addExtension($this->extension);
$environment->addExtension(new TranslationExtension(new StubTranslator()));
$environment->addGlobal('global', '');
$this->extension->initRuntime($environment);
}
@@ -98,32 +99,32 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest
protected function renderEnctype(FormView $view)
{
return (string)$this->extension->renderEnctype($view);
return (string) $this->extension->renderEnctype($view);
}
protected function renderLabel(FormView $view, $label = null, array $vars = array())
{
return (string)$this->extension->renderLabel($view, $label, $vars);
return (string) $this->extension->renderLabel($view, $label, $vars);
}
protected function renderErrors(FormView $view)
{
return (string)$this->extension->renderErrors($view);
return (string) $this->extension->renderErrors($view);
}
protected function renderWidget(FormView $view, array $vars = array())
{
return (string)$this->extension->renderWidget($view, $vars);
return (string) $this->extension->renderWidget($view, $vars);
}
protected function renderRow(FormView $view, array $vars = array())
{
return (string)$this->extension->renderRow($view, $vars);
return (string) $this->extension->renderRow($view, $vars);
}
protected function renderRest(FormView $view, array $vars = array())
{
return (string)$this->extension->renderRest($view, $vars);
return (string) $this->extension->renderRest($view, $vars);
}
protected function setTheme(FormView $view, array $themes)
@@ -131,14 +132,14 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest
$this->extension->setTheme($view, $themes);
}
static public function themeBlockInheritanceProvider()
public static function themeBlockInheritanceProvider()
{
return array(
array(array('theme.html.twig'))
);
}
static public function themeInheritanceProvider()
public static function themeInheritanceProvider()
{
return array(
array(array('parent_label.html.twig'), array('child_label.html.twig'))

View File

@@ -52,9 +52,10 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest
'custom_widgets.html.twig',
));
$environment = new \Twig_Environment($loader);
$environment = new \Twig_Environment($loader, array('strict_variables' => true));
$environment->addExtension($this->extension);
$environment->addExtension(new TranslationExtension(new StubTranslator()));
$environment->addGlobal('global', '');
$this->extension->initRuntime($environment);
}
@@ -68,32 +69,32 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest
protected function renderEnctype(FormView $view)
{
return (string)$this->extension->renderEnctype($view);
return (string) $this->extension->renderEnctype($view);
}
protected function renderLabel(FormView $view, $label = null, array $vars = array())
{
return (string)$this->extension->renderLabel($view, $label, $vars);
return (string) $this->extension->renderLabel($view, $label, $vars);
}
protected function renderErrors(FormView $view)
{
return (string)$this->extension->renderErrors($view);
return (string) $this->extension->renderErrors($view);
}
protected function renderWidget(FormView $view, array $vars = array())
{
return (string)$this->extension->renderWidget($view, $vars);
return (string) $this->extension->renderWidget($view, $vars);
}
protected function renderRow(FormView $view, array $vars = array())
{
return (string)$this->extension->renderRow($view, $vars);
return (string) $this->extension->renderRow($view, $vars);
}
protected function renderRest(FormView $view, array $vars = array())
{
return (string)$this->extension->renderRest($view, $vars);
return (string) $this->extension->renderRest($view, $vars);
}
protected function setTheme(FormView $view, array $themes)

View File

@@ -1,3 +1,3 @@
{% block form_label %}
<label>child</label>
<label>{{ global }}child</label>
{% endblock form_label %}

View File

@@ -1,5 +1,16 @@
{% block _text_id_widget %}
<div id="container">
{{ form_widget(form) }}
</div>
{% spaceless %}
<div id="container">
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock _text_id_widget %}
{% block _name_entry_label %}
{% spaceless %}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
<label>Custom label: {{ label|trans({}, translation_domain) }}</label>
{% endspaceless %}
{% endblock _name_entry_label %}

View File

@@ -26,7 +26,7 @@ CHANGELOG
* [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure',
'httponly' are now prefixed with cookie_ when dumped to the container
* Added `handler_id` configuration under `session` key to represent `session.handler`
service, defaults to `session.handler.file`.
service, defaults to `session.handler.native_file`.
* Added `gc_maxlifetime`, `gc_probability`, and `gc_divisor` to session
configuration. This means session garbage collection has a
`gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines
@@ -36,5 +36,8 @@ CHANGELOG
start on demand.
* [BC BREAK] TemplateNameParser::parseFromFilename() has been moved to a dedicated
parser: TemplateFilenameParser::parse().
* [BC BREAK] Kernel parameters are replaced by their value whereever they appear
* [BC BREAK] Kernel parameters are replaced by their value wherever they appear
in Route patterns, requirements and defaults. Use '%%' as the escaped value for '%'.
* [BC BREAK] Switched behavior of flash messages to expire flash messages on retrieval
using Symfony\Component\HttpFoundation\Session\Flash\FlashBag as opposed to on
next pageload regardless of whether they are displayed or not.

View File

@@ -11,7 +11,6 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
/**
* Interface for finding all the templates.
*
@@ -24,5 +23,5 @@ interface TemplateFinderInterface
*
* @return array An array of templates of type TemplateReferenceInterface
*/
function findAllTemplates();
public function findAllTemplates();
}

View File

@@ -64,9 +64,7 @@ class RequestDataCollector extends BaseRequestDataCollector
}
/**
* Gets the route.
*
* @return string The route
* {@inheritdoc}
*/
public function getRoute()
{
@@ -74,9 +72,7 @@ class RequestDataCollector extends BaseRequestDataCollector
}
/**
* Returns the route parameters.
*
* @return array The parameters
* {@inheritdoc}
*/
public function getRouteParams()
{
@@ -84,9 +80,7 @@ class RequestDataCollector extends BaseRequestDataCollector
}
/**
* Gets the controller.
*
* @return string The controller as a string
* {@inheritdoc}
*/
public function getController()
{

View File

@@ -11,94 +11,27 @@
namespace Symfony\Bundle\FrameworkBundle\DataCollector;
use Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouterDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Bundle\FrameworkBundle\Controller\RedirectController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
/**
* RouterDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class RouterDataCollector extends DataCollector
class RouterDataCollector extends BaseRouterDataCollector
{
protected $controllers;
public function __construct()
public function guessRoute(Request $request, $controller)
{
$this->controllers = new \SplObjectStorage();
$this->data = array(
'redirect' => false,
'url' => null,
'route' => null,
);
}
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
{
if ($response instanceof RedirectResponse) {
$this->data['redirect'] = true;
$this->data['url'] = $response->getTargetUrl();
if ($this->controllers->contains($request)) {
$controller = $this->controllers[$request];
if (is_array($controller)) {
$controller = $controller[0];
}
if ($controller instanceof RedirectController) {
$this->data['route'] = $request->attributes->get('_route', 'n/a');
}
}
if (is_array($controller)) {
$controller = $controller[0];
}
}
/**
* Remembers the controller associated to each request.
*
* @param FilterControllerEvent The filter controller event
*/
public function onKernelController(FilterControllerEvent $event)
{
$this->controllers[$event->getRequest()] = $event->getController();
}
if ($controller instanceof RedirectController) {
return $request->attributes->get('_route');
}
/**
* @return Boolean Whether this request will result in a redirect
*/
public function getRedirect()
{
return $this->data['redirect'];
}
/**
* @return string|null The target URL
*/
public function getTargetUrl()
{
return $this->data['url'];
}
/**
* @return string|null The target route
*/
public function getTargetRoute()
{
return $this->data['route'];
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'router';
return parent::guessRoute($request, $controller);
}
}

View File

@@ -24,7 +24,7 @@ class CompilerDebugDumpPass implements CompilerPassInterface
$cache->write(implode("\n", $container->getCompiler()->getLog()));
}
static public function getCompilerLogFilename(ContainerInterface $container)
public static function getCompilerLogFilename(ContainerInterface $container)
{
$class = $container->getParameter('kernel.container_class');

View File

@@ -11,7 +11,6 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;
@@ -303,7 +302,7 @@ class FrameworkExtension extends Extension
$this->addClassesToCompile(array(
'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\FileSessionHandler',
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler',
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy',
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy',
$container->getDefinition('session')->getClass(),

View File

@@ -52,7 +52,7 @@ class SessionListener implements EventSubscriberInterface
$request->setSession($this->container->get('session'));
}
static public function getSubscribedEvents()
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => array('onKernelRequest', 128),

View File

@@ -49,7 +49,7 @@ class TestSessionListener implements EventSubscriberInterface
$session = $this->container->get('session');
$cookies = $event->getRequest()->cookies;
if ($cookies->has($session->getName())) {
$session->setId($cookies->get($session->getName()));
} else {
@@ -78,7 +78,7 @@ class TestSessionListener implements EventSubscriberInterface
}
}
static public function getSubscribedEvents()
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => array('onKernelRequest', 192),

View File

@@ -18,7 +18,7 @@
<services>
<service id="data_collector.config" class="%data_collector.config.class%" public="false">
<tag name="data_collector" template="WebProfilerBundle:Collector:config" id="config" priority="255" />
<argument type="service" id="kernel" />
<call method="setKernel"><argument type="service" id="kernel" /></call>
</service>
<service id="data_collector.request" class="%data_collector.request.class%">

View File

@@ -6,13 +6,14 @@
<parameters>
<parameter key="form.extension.class">Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension</parameter>
<parameter key="form.registry.class">Symfony\Component\Form\FormRegistry</parameter>
<parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
<parameter key="form.type_guesser.validator.class">Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser</parameter>
</parameters>
<services>
<!-- FormFactory -->
<service id="form.factory" class="%form.factory.class%">
<!-- FormRegistry -->
<service id="form.registry" class="%form.registry.class%">
<argument type="collection">
<!--
We don't need to be able to add more extensions.
@@ -23,6 +24,11 @@
</argument>
</service>
<!-- FormFactory -->
<service id="form.factory" class="%form.factory.class%">
<argument type="service" id="form.registry" />
</service>
<!-- DependencyInjectionExtension -->
<service id="form.extension" class="%form.extension.class%" public="false">
<argument type="service" id="service_container" />

View File

@@ -6,11 +6,11 @@
<parameters>
<parameter key="session.class">Symfony\Component\HttpFoundation\Session\Session</parameter>
<parameter key="session.flashbag.class">Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag</parameter>
<parameter key="session.flashbag.class">Symfony\Component\HttpFoundation\Session\Flash\FlashBag</parameter>
<parameter key="session.attribute_bag.class">Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag</parameter>
<parameter key="session.storage.native.class">Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage</parameter>
<parameter key="session.storage.mock_file.class">Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage</parameter>
<parameter key="session.handler.file.class">Symfony\Component\HttpFoundation\Session\Storage\Handler\FileSessionHandler</parameter>
<parameter key="session.handler.native_file.class">Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler</parameter>
<parameter key="session_listener.class">Symfony\Bundle\FrameworkBundle\EventListener\SessionListener</parameter>
</parameters>
@@ -34,7 +34,7 @@
<argument>%kernel.cache_dir%/sessions</argument>
</service>
<service id="session.handler.file" class="%session.handler.file.class%" public="false">
<service id="session.handler.native_file" class="%session.handler.native_file.class%" public="false">
<argument>%session.save_path%</argument>
</service>
@@ -45,6 +45,5 @@
<!-- for BC -->
<service id="session.storage.filesystem" alias="session.storage.mock_file" />
<service id="session.handler.native_file" alias="session.handler.file" />
</services>
</container>

View File

@@ -83,6 +83,10 @@ build: 56
color: #AA3333;
background: #f9ecec;
}
.sf-exceptionreset #logs .traces li.warning {
font-style: normal;
background: #ffcc00;
}
/* fix for Opera not liking empty <li> */
.sf-exceptionreset .traces li:after {
content: "\00A0";

View File

@@ -1,7 +1,5 @@
<div>
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
<?php if (!$compound): ?>
<?php echo $view['form']->errors($form) ?>
<?php endif ?>
<?php echo $view['form']->errors($form) ?>
<?php echo $view['form']->widget($form) ?>
</div>

View File

@@ -1,4 +1,3 @@
<?php echo $view['form']->errors($form) ?>
<?php foreach ($form as $child) : ?>
<?php echo $view['form']->row($child) ?>
<?php endforeach; ?>

View File

@@ -1,4 +1,11 @@
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php if (!$form->hasParent() && $errors): ?>
<tr>
<td colspan="2">
<?php echo $view['form']->errors($form) ?>
</td>
</tr>
<?php endif ?>
<?php echo $view['form']->renderBlock('form_rows') ?>
<?php echo $view['form']->rest($form) ?>
</div>

View File

@@ -1,51 +1,21 @@
<?php if (!$compound): ?>
<?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 ?>
<?php else: ?>
<?php if (count($errors) > 0): ?>
<tr>
<td colspan="2">
<?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 ?>
</td>
</tr>
<?php endif; ?>
<?php endif; ?>
<?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

@@ -3,9 +3,7 @@
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
</td>
<td>
<?php if (!$compound): ?>
<?php echo $view['form']->errors($form) ?>
<?php endif ?>
<?php echo $view['form']->errors($form) ?>
<?php echo $view['form']->widget($form) ?>
</td>
</tr>

View File

@@ -1,4 +1,7 @@
<table <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php if (!$form->hasParent()): ?>
<?php echo $view['form']->errors($form) ?>
<?php endif ?>
<?php echo $view['form']->renderBlock('form_rows') ?>
<?php echo $view['form']->rest($form) ?>
</table>

View File

@@ -3,4 +3,3 @@
<?php echo $view['form']->widget($form) ?>
</td>
</tr>

View File

@@ -103,9 +103,9 @@ class Router extends BaseRouter implements WarmableInterface
/**
* Replaces placeholders with the service container parameters in the given string.
*
* @param string $value The source string which might contain %placeholders%
* @param mixed $value The source string which might contain %placeholders%
*
* @return string A string where the placeholders have been replaced.
* @return mixed A string where the placeholders have been replaced, or the original value if not a string.
*
* @throws ParameterNotFoundException When a placeholder does not exist as a container parameter
* @throws RuntimeException When a container value is not a string or a numeric value
@@ -114,6 +114,10 @@ class Router extends BaseRouter implements WarmableInterface
{
$container = $this->container;
if (null === $value || false === $value || true === $value || is_object($value)) {
return $value;
}
$escapedValue = preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($container, $value) {
// skip %%
if (!isset($match[1])) {

View File

@@ -84,12 +84,6 @@ class DelegatingEngine extends BaseDelegatingEngine implements EngineInterface
*/
public function renderResponse($view, array $parameters = array(), Response $response = null)
{
if (null === $response) {
$response = new Response();
}
$response->setContent($this->render($view, $parameters));
return $response;
return $this->getEngine($view)->renderResponse($view, $parameters, $response);
}
}

View File

@@ -30,5 +30,5 @@ interface EngineInterface extends BaseEngineInterface
*
* @return Response A Response instance
*/
function renderResponse($view, array $parameters = array(), Response $response = null);
public function renderResponse($view, array $parameters = array(), Response $response = null);
}

View File

@@ -201,7 +201,7 @@ class CodeHelper extends Helper
return 'code';
}
static protected function fixCodeMarkup($line)
protected static function fixCodeMarkup($line)
{
// </span> ending tag from previous line
$opening = strpos($line, '<span');

View File

@@ -246,7 +246,7 @@ class FormHelper extends Helper
$variables = array_replace_recursive($this->varStack[$rendering]['variables'], $variables);
} else {
$types = $view->getVar('types');
$types[] = $custom;
$types[] = $view->getVar('full_block_name');
$typeIndex = count($types) - 1;
$variables = array_replace_recursive($view->getVars(), $variables);
$this->varStack[$rendering]['types'] = $types;

View File

@@ -22,8 +22,8 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
*/
abstract class WebTestCase extends \PHPUnit_Framework_TestCase
{
static protected $class;
static protected $kernel;
protected static $class;
protected static $kernel;
/**
* Creates a Client.
@@ -33,7 +33,7 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
*
* @return Client A Client instance
*/
static protected function createClient(array $options = array(), array $server = array())
protected static function createClient(array $options = array(), array $server = array())
{
if (null !== static::$kernel) {
static::$kernel->shutdown();
@@ -56,7 +56,7 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
*
* @return string The directory where phpunit.xml(.dist) is stored
*/
static protected function getPhpUnitXmlDir()
protected static function getPhpUnitXmlDir()
{
if (!isset($_SERVER['argv']) || false === strpos($_SERVER['argv'][0], 'phpunit')) {
throw new \RuntimeException('You must override the WebTestCase::createKernel() method.');
@@ -89,7 +89,7 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
*
* @return string The value of the phpunit cli configuration option
*/
static private function getPhpUnitCliConfigArgument()
private static function getPhpUnitCliConfigArgument()
{
$dir = null;
$reversedArgs = array_reverse($_SERVER['argv']);
@@ -114,7 +114,7 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
*
* @return string The Kernel class name
*/
static protected function getKernelClass()
protected static function getKernelClass()
{
$dir = isset($_SERVER['KERNEL_DIR']) ? $_SERVER['KERNEL_DIR'] : static::getPhpUnitXmlDir();
@@ -145,7 +145,7 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
*
* @return HttpKernelInterface A HttpKernelInterface instance
*/
static protected function createKernel(array $options = array())
protected static function createKernel(array $options = array())
{
if (null === static::$class) {
static::$class = static::getKernelClass();

View File

@@ -16,7 +16,6 @@ use Symfony\Bundle\FrameworkBundle\Templating\TemplateFilenameParser;
use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplateFinder;
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BaseBundle\BaseBundle;
class TemplateFinderTest extends TestCase
{
public function testFindAllTemplates()

View File

@@ -68,7 +68,6 @@ class RedirectControllerTest extends TestCase
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container
->expects($this->at(0))
->method('get')

View File

@@ -85,5 +85,5 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase
class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
{
static function getSubscribedEvents() {}
public static function getSubscribedEvents() {}
}

View File

@@ -18,4 +18,3 @@ $container->loadFromExtension('framework', array(
'cookie_httponly' => true,
),
));

View File

@@ -15,4 +15,3 @@ $container->loadFromExtension('framework', array(
'cookie_httponly' => true,
),
));

View File

@@ -17,4 +17,3 @@ session_setflash:
session_showflash:
pattern: /session_showflash
defaults: { _controller: TestBundle:Session:showFlash}

View File

@@ -17,7 +17,7 @@ use Symfony\Component\HttpKernel\Kernel;
class WebTestCase extends BaseWebTestCase
{
static public function assertRedirect($response, $location)
public static function assertRedirect($response, $location)
{
self::assertTrue($response->isRedirect(), 'Response is not a redirect, got status code: '.$response->getStatusCode());
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
@@ -42,14 +42,14 @@ class WebTestCase extends BaseWebTestCase
$fs->remove($dir);
}
static protected function getKernelClass()
protected static function getKernelClass()
{
require_once __DIR__.'/app/AppKernel.php';
return 'Symfony\Bundle\FrameworkBundle\Tests\Functional\AppKernel';
}
static protected function createKernel(array $options = array())
protected static function createKernel(array $options = array())
{
$class = self::getKernelClass();

View File

@@ -1,3 +1,2 @@
imports:
- { resource: ./../config/default.yml }

View File

@@ -48,7 +48,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
$kernel = new HttpKernel($dispatcher, $container, $resolver);
$controller = function() use($expected) {
$controller = function() use ($expected) {
return $expected;
};

View File

@@ -144,6 +144,28 @@ class RoutingTest extends \PHPUnit_Framework_TestCase
$router->getRouteCollection()->get('foo');
}
/**
* @dataProvider getNonStringValues
*/
public function testDefaultValuesAsNonStrings($value)
{
$routes = new RouteCollection();
$routes->add('foo', new Route('foo', array('foo' => $value), array('foo' => '\d+')));
$sc = $this->getServiceContainer($routes);
$router = new Router($sc, 'foo');
$route = $router->getRouteCollection()->get('foo');
$this->assertSame($value, $route->getDefault('foo'));
}
public function getNonStringValues()
{
return array(array(null), array(false), array(true), array(new \stdClass()), array(array('foo', 'bar')));
}
private function getServiceContainer(RouteCollection $routes)
{
$loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');

View File

@@ -17,7 +17,7 @@ class CodeHelperTest extends \PHPUnit_Framework_TestCase
{
protected static $helper;
static public function setUpBeforeClass()
public static function setUpBeforeClass()
{
self::$helper = new CodeHelper('txmt://open?url=file://%f&line=%l', '/root', 'UTF-8');
}

View File

@@ -33,6 +33,7 @@ class FormHelperDivLayoutTest extends AbstractDivLayoutTest
$templateNameParser = new StubTemplateNameParser($root, $rootTheme);
$loader = new FilesystemLoader(array());
$engine = new PhpEngine($templateNameParser, $loader);
$engine->addGlobal('global', '');
$this->helper = new FormHelper($engine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'), array('FrameworkBundle:Form'));
@@ -82,14 +83,14 @@ class FormHelperDivLayoutTest extends AbstractDivLayoutTest
$this->helper->setTheme($view, $themes);
}
static public function themeBlockInheritanceProvider()
public static function themeBlockInheritanceProvider()
{
return array(
array(array('TestBundle:Parent'))
);
}
static public function themeInheritanceProvider()
public static function themeInheritanceProvider()
{
return array(
array(array('TestBundle:Parent'), array('TestBundle:Child'))

View File

@@ -33,6 +33,7 @@ class FormHelperTableLayoutTest extends AbstractTableLayoutTest
$templateNameParser = new StubTemplateNameParser($root, $rootTheme);
$loader = new FilesystemLoader(array());
$engine = new PhpEngine($templateNameParser, $loader);
$engine->addGlobal('global', '');
$this->helper = new FormHelper($engine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'), array(
'FrameworkBundle:Form',

View File

@@ -1 +1 @@
<label>child</label>
<label><?php echo $global ?>child</label>

View File

@@ -0,0 +1,2 @@
<?php if (!$label) { $label = $view['form']->humanize($name); } ?>
<label>Custom label: <?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>

View File

@@ -277,7 +277,7 @@ class MainConfiguration implements ConfigurationInterface
->ifTrue(function($v) {
return true === $v['security'] && isset($v['pattern']) && !isset($v['request_matcher']);
})
->then(function($firewall) use($abstractFactoryKeys) {
->then(function($firewall) use ($abstractFactoryKeys) {
foreach ($abstractFactoryKeys as $k) {
if (!isset($firewall[$k]['check_path'])) {
continue;

View File

@@ -28,14 +28,21 @@ abstract class AbstractFactory implements SecurityFactoryInterface
{
protected $options = array(
'check_path' => '/login_check',
'login_path' => '/login',
'use_forward' => false,
);
protected $defaultSuccessHandlerOptions = array(
'always_use_default_target_path' => false,
'default_target_path' => '/',
'login_path' => '/login',
'target_path_parameter' => '_target_path',
'use_referer' => false,
);
protected $defaultFailureHandlerOptions = array(
'failure_path' => null,
'failure_forward' => false,
'login_path' => '/login',
);
public function create(ContainerBuilder $container, $id, $config, $userProviderId, $defaultEntryPointId)
@@ -71,7 +78,7 @@ abstract class AbstractFactory implements SecurityFactoryInterface
->scalarNode('failure_handler')->end()
;
foreach ($this->options as $name => $default) {
foreach (array_merge($this->options, $this->defaultSuccessHandlerOptions, $this->defaultFailureHandlerOptions) as $name => $default) {
if (is_bool($default)) {
$builder->booleanNode($name)->defaultValue($default);
} else {
@@ -80,7 +87,7 @@ abstract class AbstractFactory implements SecurityFactoryInterface
}
}
public final function addOption($name, $default = null)
final public function addOption($name, $default = null)
{
$this->options[$name] = $default;
}
@@ -149,21 +156,42 @@ abstract class AbstractFactory implements SecurityFactoryInterface
$listenerId = $this->getListenerId();
$listener = new DefinitionDecorator($listenerId);
$listener->replaceArgument(4, $id);
$listener->replaceArgument(5, array_intersect_key($config, $this->options));
// success handler
if (isset($config['success_handler'])) {
$listener->replaceArgument(6, new Reference($config['success_handler']));
}
// failure handler
if (isset($config['failure_handler'])) {
$listener->replaceArgument(7, new Reference($config['failure_handler']));
}
$listener->replaceArgument(5, new Reference($this->createAuthenticationSuccessHandler($container, $id, $config)));
$listener->replaceArgument(6, new Reference($this->createAuthenticationFailureHandler($container, $id, $config)));
$listener->replaceArgument(7, array_intersect_key($config, $this->options));
$listenerId .= '.'.$id;
$container->setDefinition($listenerId, $listener);
return $listenerId;
}
protected function createAuthenticationSuccessHandler($container, $id, $config)
{
if (isset($config['success_handler'])) {
return $config['success_handler'];
}
$successHandlerId = 'security.authentication.success_handler.'.$id;
$successHandler = $container->setDefinition($successHandlerId, new DefinitionDecorator('security.authentication.success_handler'));
$successHandler->replaceArgument(1, array_intersect_key($config, $this->defaultSuccessHandlerOptions));
$successHandler->addMethodCall('setProviderKey', array($id));
return $successHandlerId;
}
protected function createAuthenticationFailureHandler($container, $id, $config)
{
if (isset($config['failure_handler'])) {
return $config['failure_handler'];
}
$id = 'security.authentication.failure_handler.'.$id;
$failureHandler = $container->setDefinition($id, new DefinitionDecorator('security.authentication.failure_handler'));
$failureHandler->replaceArgument(2, array_intersect_key($config, $this->defaultFailureHandlerOptions));
return $id;
}
}

View File

@@ -21,11 +21,11 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*/
interface SecurityFactoryInterface
{
function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint);
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint);
function getPosition();
public function getPosition();
function getKey();
public function getKey();
function addConfiguration(NodeDefinition $builder);
public function addConfiguration(NodeDefinition $builder);
}

View File

@@ -22,9 +22,9 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*/
interface UserProviderFactoryInterface
{
function create(ContainerBuilder $container, $id, $config);
public function create(ContainerBuilder $container, $id, $config);
function getKey();
public function getKey();
function addConfiguration(NodeDefinition $builder);
public function addConfiguration(NodeDefinition $builder);
}

View File

@@ -279,18 +279,22 @@ class SecurityExtension extends Extension
if (isset($firewall['logout'])) {
$listenerId = 'security.logout_listener.'.$id;
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.logout_listener'));
$listener->replaceArgument(2, array(
$listener->replaceArgument(3, array(
'csrf_parameter' => $firewall['logout']['csrf_parameter'],
'intention' => $firewall['logout']['intention'],
'logout_path' => $firewall['logout']['path'],
'target_url' => $firewall['logout']['target'],
));
$listeners[] = new Reference($listenerId);
// add logout success handler
if (isset($firewall['logout']['success_handler'])) {
$listener->replaceArgument(3, new Reference($firewall['logout']['success_handler']));
$logoutSuccessHandlerId = $firewall['logout']['success_handler'];
} else {
$logoutSuccessHandlerId = 'security.logout.success_handler.'.$id;
$logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new DefinitionDecorator('security.logout.success_handler'));
$logoutSuccessHandler->replaceArgument(1, $firewall['logout']['target']);
}
$listener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
// add CSRF provider
if (isset($firewall['logout']['csrf_provider'])) {
@@ -625,4 +629,3 @@ class SecurityExtension extends Extension
return new MainConfiguration($this->factories, $this->userProviderFactories);
}
}

View File

@@ -27,6 +27,7 @@
<parameter key="security.logout_listener.class">Symfony\Component\Security\Http\Firewall\LogoutListener</parameter>
<parameter key="security.logout.handler.session.class">Symfony\Component\Security\Http\Logout\SessionLogoutHandler</parameter>
<parameter key="security.logout.handler.cookie_clearing.class">Symfony\Component\Security\Http\Logout\CookieClearingLogoutHandler</parameter>
<parameter key="security.logout.success_handler.class">Symfony\Component\Security\Http\Logout\DefaultLogoutSuccessHandler</parameter>
<parameter key="security.access_listener.class">Symfony\Component\Security\Http\Firewall\AccessListener</parameter>
<parameter key="security.access_map.class">Symfony\Component\Security\Http\AccessMap</parameter>
@@ -37,6 +38,9 @@
<parameter key="security.authentication.provider.pre_authenticated.class">Symfony\Component\Security\Core\Authentication\Provider\PreAuthenticatedAuthenticationProvider</parameter>
<parameter key="security.authentication.provider.anonymous.class">Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider</parameter>
<parameter key="security.authentication.success_handler.class">Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler</parameter>
<parameter key="security.authentication.failure_handler.class">Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler</parameter>
</parameters>
<services>
@@ -81,12 +85,17 @@
<service id="security.logout_listener" class="%security.logout_listener.class%" public="false" abstract="true">
<argument type="service" id="security.context" />
<argument type="service" id="security.http_utils" />
<argument type="service" id="security.logout.success_handler" />
<argument /> <!-- Options -->
<argument type="service" id="security.logout.success_handler" on-invalid="null" />
</service>
<service id="security.logout.handler.session" class="%security.logout.handler.session.class%" public="false" />
<service id="security.logout.handler.cookie_clearing" class="%security.logout.handler.cookie_clearing.class%" public="false" abstract="true" />
<service id="security.logout.success_handler" class="%security.logout.success_handler.class%" public="false" abstract="true">
<argument type="service" id="security.http_utils" />
<argument>/</argument>
</service>
<service id="security.authentication.form_entry_point" class="%security.authentication.form_entry_point.class%" public="false" abstract="true">
<argument type="service" id="http_kernel" />
</service>
@@ -98,13 +107,26 @@
<argument type="service" id="security.authentication.session_strategy" />
<argument type="service" id="security.http_utils" />
<argument />
<argument type="service" id="security.authentication.success_handler" />
<argument type="service" id="security.authentication.failure_handler" />
<argument type="collection"></argument>
<argument type="service" id="security.authentication.success_handler" on-invalid="null" />
<argument type="service" id="security.authentication.failure_handler" on-invalid="null" />
<argument type="service" id="logger" on-invalid="null" />
<argument type="service" id="event_dispatcher" on-invalid="null" />
</service>
<service id="security.authentication.success_handler" class="%security.authentication.success_handler.class%" abstract="true" public="false">
<argument type="service" id="security.http_utils" />
<argument type="collection" /> <!-- Options -->
</service>
<service id="security.authentication.failure_handler" class="%security.authentication.failure_handler.class%" abstract="true" public="false">
<tag name="monolog.logger" channel="security" />
<argument type="service" id="http_kernel" />
<argument type="service" id="security.http_utils" />
<argument type="collection" /> <!-- Options -->
<argument type="service" id="logger" on-invalid="null" />
</service>
<service id="security.authentication.listener.form"
class="%security.authentication.listener.form.class%"
parent="security.authentication.listener.abstract"

View File

@@ -18,7 +18,61 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
{
public function testCreate()
{
$factory = $this->getFactory();
list($container,
$authProviderId,
$listenerId,
$entryPointId
) = $this->callFactory('foo', array('use_forward' => true, 'failure_path' => '/foo', 'success_handler' => 'qux', 'failure_handler' => 'bar', 'remember_me' => true), 'user_provider', 'entry_point');
// auth provider
$this->assertEquals('auth_provider', $authProviderId);
// listener
$this->assertEquals('abstract_listener.foo', $listenerId);
$this->assertTrue($container->hasDefinition('abstract_listener.foo'));
$definition = $container->getDefinition('abstract_listener.foo');
$this->assertEquals(array(
'index_4' => 'foo',
'index_5' => new Reference('qux'),
'index_6' => new Reference('bar'),
'index_7' => array(
'use_forward' => true,
),
), $definition->getArguments());
// entry point
$this->assertEquals('entry_point', $entryPointId, '->create() does not change the default entry point.');
}
public function testDefaultFailureHandler()
{
list($container,
$authProviderId,
$listenerId,
$entryPointId
) = $this->callFactory('foo', array('remember_me' => true), 'user_provider', 'entry_point');
$definition = $container->getDefinition('abstract_listener.foo');
$arguments = $definition->getArguments();
$this->assertEquals(new Reference('security.authentication.failure_handler.foo'), $arguments['index_6']);
}
public function testDefaultSuccessHandler()
{
list($container,
$authProviderId,
$listenerId,
$entryPointId
) = $this->callFactory('foo', array('remember_me' => true), 'user_provider', 'entry_point');
$definition = $container->getDefinition('abstract_listener.foo');
$arguments = $definition->getArguments();
$this->assertEquals(new Reference('security.authentication.success_handler.foo'), $arguments['index_5']);
}
protected function callFactory($id, $config, $userProviderId, $defaultEntryPointId)
{
$factory = $this->getMockForAbstractClass('Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory', array());
$factory
->expects($this->once())
@@ -37,30 +91,8 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
list($authProviderId,
$listenerId,
$entryPointId
) = $factory->create($container, 'foo', array('use_forward' => true, 'failure_path' => '/foo', 'success_handler' => 'foo', 'remember_me' => true), 'user_provider', 'entry_point');
) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId);
// auth provider
$this->assertEquals('auth_provider', $authProviderId);
// listener
$this->assertEquals('abstract_listener.foo', $listenerId);
$this->assertTrue($container->hasDefinition('abstract_listener.foo'));
$definition = $container->getDefinition('abstract_listener.foo');
$this->assertEquals(array(
'index_4' => 'foo',
'index_5' => array(
'use_forward' => true,
'failure_path' => '/foo',
),
'index_6' => new Reference('foo'),
), $definition->getArguments());
// entry point
$this->assertEquals('entry_point', $entryPointId, '->create() does not change the default entry point.');
}
protected function getFactory()
{
return $this->getMockForAbstractClass('Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory', array());
return array($container, $authProviderId, $listenerId, $entryPointId);
}
}

View File

@@ -17,7 +17,7 @@ use Symfony\Component\HttpKernel\Kernel;
class WebTestCase extends BaseWebTestCase
{
static public function assertRedirect($response, $location)
public static function assertRedirect($response, $location)
{
self::assertTrue($response->isRedirect(), 'Response is not a redirect, got status code: '.substr($response, 0, 2000));
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
@@ -42,14 +42,14 @@ class WebTestCase extends BaseWebTestCase
$fs->remove($dir);
}
static protected function getKernelClass()
protected static function getKernelClass()
{
require_once __DIR__.'/app/AppKernel.php';
return 'Symfony\Bundle\SecurityBundle\Tests\Functional\AppKernel';
}
static protected function createKernel(array $options = array())
protected static function createKernel(array $options = array())
{
$class = self::getKernelClass();

View File

@@ -4,6 +4,7 @@ CHANGELOG
2.1.0
-----
* added a new setting ("paths") to configure more paths for the Twig filesystem loader
* added contextual escaping based on the template file name (disabled if you explicitly pass an autoescape option)
* added a command that extracts translation messages from templates
* added the real template name when an error occurs in a Twig template

View File

@@ -74,7 +74,7 @@ EOF
}
if (0 !== strpos($filename, '@') && !is_readable($filename)) {
throw new \RuntimeException("File or directory '%s' is not readable");
throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename));
}
$files = array();

View File

@@ -45,7 +45,7 @@ class ExceptionController extends ContainerAware
$templating = $this->container->get('templating');
$code = $exception->getStatusCode();
$response = $templating->renderResponse(
return $templating->renderResponse(
$this->findTemplate($templating, $format, $code, $this->container->get('kernel')->isDebug()),
array(
'status_code' => $code,
@@ -55,11 +55,6 @@ class ExceptionController extends ContainerAware
'currentContent' => $currentContent,
)
);
$response->setStatusCode($code);
$response->headers->replace($exception->getHeaders());
return $response;
}
/**

View File

@@ -115,6 +115,7 @@ class Configuration implements ConfigurationInterface
private function addTwigOptions(ArrayNodeDefinition $rootNode)
{
$rootNode
->fixXmlConfig('path')
->children()
->scalarNode('autoescape')->end()
->scalarNode('base_template_class')->example('Twig_Template')->end()
@@ -124,6 +125,9 @@ class Configuration implements ConfigurationInterface
->scalarNode('strict_variables')->end()
->scalarNode('auto_reload')->end()
->scalarNode('optimizations')->end()
->arrayNode('paths')
->prototype('variable')->end()
->end()
->end()
;
}

View File

@@ -60,6 +60,12 @@ class TwigExtension extends Extension
$reflClass = new \ReflectionClass('Symfony\Bridge\Twig\Extension\FormExtension');
$container->getDefinition('twig.loader')->addMethodCall('addPath', array(dirname(dirname($reflClass->getFileName())).'/Resources/views/Form'));
if (!empty($config['paths'])) {
foreach ($config['paths'] as $path) {
$container->getDefinition('twig.loader')->addMethodCall('addPath', array($path));
}
}
if (!empty($config['globals'])) {
$def = $container->getDefinition('twig');
foreach ($config['globals'] as $key => $global) {

View File

@@ -11,6 +11,7 @@
<xsd:sequence>
<xsd:element name="form" type="form" minOccurs="0" maxOccurs="1" />
<xsd:element name="global" type="global" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="path" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="auto-reload" type="xsd:string" />

View File

@@ -1,7 +1,7 @@
<ol class="traces logs">
{% for log in logs %}
<li{% if log.priorityName in ['EMERG', 'ERR', 'CRIT', 'ALERT', 'ERROR', 'CRITICAL'] %} class="error"{% endif %}>
{{ log.message }}
<li{% if log.priority >= 400 %} class="error"{% elseif log.priority >= 300 %} class="warning"{% endif %}>
{{ log.priorityName }} - {{ log.message }}
</li>
{% endfor %}
</ol>

View File

@@ -35,10 +35,6 @@ class ExceptionControllerTest extends TestCase
->expects($this->once())
->method('getStatusCode')
->will($this->returnValue(404));
$this->flatten
->expects($this->once())
->method('getHeaders')
->will($this->returnValue(array()));
$this->controller = new ExceptionController();
$this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\KernelInterface');
$this->templating = $this->getMockBuilder('Symfony\\Bundle\\TwigBundle\\TwigEngine')

View File

@@ -18,4 +18,5 @@ $container->loadFromExtension('twig', array(
'charset' => 'ISO-8859-1',
'debug' => true,
'strict_variables' => true,
'paths' => array('path1', 'path2'),
));

View File

@@ -12,5 +12,7 @@
</twig:form>
<twig:global key="foo" id="bar" type="service" />
<twig:global key="pi">3.14</twig:global>
<twig:path>path1</twig:path>
<twig:path>path2</twig:path>
</twig:config>
</container>

View File

@@ -13,3 +13,4 @@ twig:
charset: ISO-8859-1
debug: true
strict_variables: true
paths: [path1, path2]

View File

@@ -41,8 +41,8 @@ class ProfilerController extends ContainerAware
$profiler = $this->container->get('profiler');
$profiler->disable();
$panel = $this->container->get('request')->query->get('panel', 'request');
$page = $this->container->get('request')->query->get('page', 'home');
$panel = $request->query->get('panel', 'request');
$page = $request->query->get('page', 'home');
if (!$profile = $profiler->loadProfile($token)) {
return $this->container->get('templating')->renderResponse('WebProfilerBundle:Profiler:info.html.twig', array('about' => 'no_token', 'token' => $token));
@@ -104,14 +104,14 @@ class ProfilerController extends ContainerAware
*
* @return Response A Response instance
*/
public function importAction()
public function importAction(Request $request)
{
$profiler = $this->container->get('profiler');
$profiler->disable();
$router = $this->container->get('router');
$file = $this->container->get('request')->files->get('file');
$file = $request->files->get('file');
if (empty($file) || !$file->isValid()) {
return new RedirectResponse($router->generate('_profiler_info', array('about' => 'upload_error')));
@@ -144,14 +144,14 @@ class ProfilerController extends ContainerAware
/**
* Renders the Web Debug Toolbar.
*
* @param string $token The profiler token
* @param string $position The toolbar position (top, bottom, normal, or null -- use the configuration)
* @param Request $request The current Request
* @param string $token The profiler token
* @param string $position The toolbar position (top, bottom, normal, or null -- use the configuration)
*
* @return Response A Response instance
*/
public function toolbarAction($token, $position = null)
public function toolbarAction(Request $request, $token, $position = null)
{
$request = $this->container->get('request');
$session = $request->getSession();
if (null !== $session && $session->getFlashBag() instanceof AutoExpireFlashBag) {
@@ -192,14 +192,16 @@ class ProfilerController extends ContainerAware
/**
* Renders the profiler search bar.
*
* @param Request $request The current Request
*
* @return Response A Response instance
*/
public function searchBarAction()
public function searchBarAction(Request $request)
{
$profiler = $this->container->get('profiler');
$profiler->disable();
if (null === $session = $this->container->get('request')->getSession()) {
if (null === $session = $request->getSession()) {
$ip =
$method =
$url =
@@ -225,21 +227,22 @@ class ProfilerController extends ContainerAware
/**
* Search results.
*
* @param string $token The token
* @param Request $request The current Request
* @param string $token The token
*
* @return Response A Response instance
*/
public function searchResultsAction($token)
public function searchResultsAction(Request $request, $token)
{
$profiler = $this->container->get('profiler');
$profiler->disable();
$profile = $profiler->loadProfile($token);
$ip = $this->container->get('request')->query->get('ip');
$method = $this->container->get('request')->query->get('method');
$url = $this->container->get('request')->query->get('url');
$limit = $this->container->get('request')->query->get('limit');
$ip = $request->query->get('ip');
$method = $request->query->get('method');
$url = $request->query->get('url');
$limit = $request->query->get('limit');
return $this->container->get('templating')->renderResponse('WebProfilerBundle:Profiler:results.html.twig', array(
'token' => $token,
@@ -256,15 +259,15 @@ class ProfilerController extends ContainerAware
/**
* Narrow the search bar.
*
* @param Request $request The current Request
*
* @return Response A Response instance
*/
public function searchAction()
public function searchAction(Request $request)
{
$profiler = $this->container->get('profiler');
$profiler->disable();
$request = $this->container->get('request');
$ip = preg_replace('/[^:\d\.]/', '', $request->query->get('ip'));
$method = $request->query->get('method');
$url = $request->query->get('url');

View File

@@ -12,10 +12,12 @@
namespace Symfony\Bundle\WebProfilerBundle\EventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Bundle\TwigBundle\TwigEngine;
use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag;
/**
* WebDebugToolbarListener injects the Web Debug Toolbar.
@@ -27,7 +29,7 @@ use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class WebDebugToolbarListener
class WebDebugToolbarListener implements EventSubscriberInterface
{
const DISABLED = 1;
const ENABLED = 2;
@@ -124,4 +126,11 @@ class WebDebugToolbarListener
$response->setContent($content);
}
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::RESPONSE => array('onKernelResponse', -128),
);
}
}

View File

@@ -10,7 +10,7 @@
<services>
<service id="web_profiler.debug_toolbar" class="%web_profiler.debug_toolbar.class%">
<tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" priority="-128" />
<tag name="kernel.event_subscriber" />
<argument type="service" id="templating.engine.twig" />
<argument>%web_profiler.debug_toolbar.intercept_redirects%</argument>
<argument>%web_profiler.debug_toolbar.mode%</argument>

View File

@@ -309,6 +309,11 @@ ul.alt li.error {
margin-bottom: 1px;
}
ul.alt li.warning {
background-color: #ffcc00;
margin-bottom: 1px;
}
td.main, td.menu {
text-align: left;
margin: 0;

View File

@@ -146,19 +146,20 @@
</tr>
</table>
<h2>Active bundles</h2>
<table>
<tr>
<th>Name</th>
<th>Path</th>
</tr>
{% set bundles = collector.bundles %}
{% for name in bundles|keys|sort %}
<tr>
<th>{{ name }}</th>
<td>{{ bundles[name] }}</td>
</tr>
{% endfor %}
</table>
{% if collector.bundles %}
<h2>Active bundles</h2>
<table>
<tr>
<th>Name</th>
<th>Path</th>
</tr>
{% set bundles = collector.bundles %}
{% for name in bundles|keys|sort %}
<tr>
<th>{{ name }}</th>
<td>{{ bundles[name] }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endblock %}

View File

@@ -41,7 +41,7 @@
<input type="hidden" name="panel" value="logger" />
<label for="priority">Priority</label>
<select id="priority" name="priority" onchange="document.getElementById('priority-form').submit(); ">
{% for value, text in { 100: 'DEBUG', 200: 'INFO', 300: 'WARNING', 400: 'ERROR', 500: 'CRITICAL', 550: 'ALERT' } %}
{% for value, text in { 100: 'DEBUG', 200: 'INFO', 250: 'NOTICE', 300: 'WARNING', 400: 'ERROR', 500: 'CRITICAL', 550: 'ALERT', 600: 'EMERGENCY' } %}
<option value="{{ value }}"{{ value == priority ? ' selected' : '' }}>{{ text }}</option>
{% endfor %}
</select>
@@ -56,8 +56,8 @@
{% if collector.logs %}
<ul class="alt">
{% for log in collector.logs if log.priority >= priority %}
<li class="{{ cycle(['odd', 'even'], loop.index) }}{% if 'ERR' == log.priorityName or 'ERROR' == log.priorityName %} error{% endif %}">
{{ log.message }}
<li class="{{ cycle(['odd', 'even'], loop.index) }}{% if log.priority >= 400 %} error{% elseif log.priority >= 300 %} warning{% endif %}">
{{ log.priorityName }} - {{ log.message }}
{% if log.context is defined and log.context is not empty %}
<br />
<small>
@@ -65,6 +65,8 @@
</small>
{% endif %}
</li>
{% else %}
<li><em>No logs available for this priority.</em></li>
{% endfor %}
</ul>
{% else %}

View File

@@ -55,7 +55,7 @@
.sf-toolbar-block .sf-toolbar-info-piece:last-child {
padding-bottom: 0;
}
.sf-toolbar-block .sf-toolbar-info-piece a,
.sf-toolbar-block .sf-toolbar-info-piece abbr {
color: #2f2f2f;

View File

@@ -28,7 +28,7 @@ class WebProfilerExtensionTest extends TestCase
*/
private $container;
static public function assertSaneContainer(Container $container, $message = '')
public static function assertSaneContainer(Container $container, $message = '')
{
$errors = array();
foreach ($container->getServiceIds() as $id) {

View File

@@ -0,0 +1,2 @@
vendor/
composer.lock

View File

@@ -117,7 +117,7 @@ class Cookie
*
* @api
*/
static public function fromString($cookie, $url = null)
public static function fromString($cookie, $url = null)
{
$parts = explode(';', $cookie);

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