Merge branch '2.3'

* 2.3:
  [Form] fixes empty file-inputs get treated as extra field
  return 0 if there is no valid data
  [DependencyInjection] fixed regression where setting a service to null did not trigger a re-creation of the service when getting it
  [DependencyInjection] fixed #8570
  fixed file permission
  The ignoreAttributes itself should be ignored, too.
  [Tests] Tests on php 5.5 should pass
  [Twig] fixed TwigEngine::exists() method when a template contains a syntax error (closes #88546)
This commit is contained in:
Fabien Potencier 2013-07-27 07:01:52 +02:00
commit aa3e474aed
14 changed files with 170 additions and 4 deletions

View File

@ -0,0 +1,56 @@
<?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\Twig\Tests;
use Symfony\Bridge\Twig\TwigEngine;
class TwigEngineTest extends TestCase
{
public function testExistsWithTemplateInstances()
{
$engine = $this->getTwig();
$this->assertTrue($engine->exists($this->getMockForAbstractClass('Twig_Template', array(), '', false)));
}
public function testExistsWithNonExistentTemplates()
{
$engine = $this->getTwig();
$this->assertFalse($engine->exists('foobar'));
}
public function testExistsWithTemplateWithSyntaxErrors()
{
$engine = $this->getTwig();
$this->assertTrue($engine->exists('error'));
}
public function testExists()
{
$engine = $this->getTwig();
$this->assertTrue($engine->exists('index'));
}
protected function getTwig()
{
$twig = new \Twig_Environment(new \Twig_Loader_Array(array(
'index' => 'foo',
'error' => '{{ foo }',
)));
$parser = $this->getMock('Symfony\Component\Templating\TemplateNameParserInterface');
return new TwigEngine($twig, $parser);
}
}

View File

@ -75,9 +75,19 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
*/ */
public function exists($name) public function exists($name)
{ {
if ($name instanceof \Twig_Template) {
return true;
}
$loader = $this->environment->getLoader();
if ($loader instanceof \Twig_ExistsLoaderInterface) {
return $loader->exists($name);
}
try { try {
$this->load($name); $loader->getSource($name);
} catch (\InvalidArgumentException $e) { } catch (\Twig_Error_Loader $e) {
return false; return false;
} }

View File

@ -49,7 +49,7 @@ class RedirectController extends ContainerAware
$attributes = array(); $attributes = array();
if (false === $ignoreAttributes || is_array($ignoreAttributes)) { if (false === $ignoreAttributes || is_array($ignoreAttributes)) {
$attributes = $request->attributes->get('_route_params'); $attributes = $request->attributes->get('_route_params');
unset($attributes['route'], $attributes['permanent']); unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes']);
if ($ignoreAttributes) { if ($ignoreAttributes) {
$attributes = array_diff_key($attributes, array_flip($ignoreAttributes)); $attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
} }

View File

@ -53,6 +53,7 @@ class RedirectControllerTest extends TestCase
'route' => $route, 'route' => $route,
'permanent' => $permanent, 'permanent' => $permanent,
'additional-parameter' => 'value', 'additional-parameter' => 'value',
'ignoreAttributes' => $ignoreAttributes
), ),
); );

View File

@ -87,6 +87,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
$def->setConfigurator($parentDef->getConfigurator()); $def->setConfigurator($parentDef->getConfigurator());
$def->setFile($parentDef->getFile()); $def->setFile($parentDef->getFile());
$def->setPublic($parentDef->isPublic()); $def->setPublic($parentDef->isPublic());
$def->setLazy($parentDef->isLazy());
// overwrite with values specified in the decorator // overwrite with values specified in the decorator
$changes = $definition->getChanges(); $changes = $definition->getChanges();
@ -111,6 +112,9 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
if (isset($changes['public'])) { if (isset($changes['public'])) {
$def->setPublic($definition->isPublic()); $def->setPublic($definition->isPublic());
} }
if (isset($changes['lazy'])){
$def->setLazy($definition->isLazy());
}
// merge arguments // merge arguments
foreach ($definition->getArguments() as $k => $v) { foreach ($definition->getArguments() as $k => $v) {

View File

@ -184,6 +184,9 @@ class Container implements IntrospectableContainerInterface
/** /**
* Sets a service. * Sets a service.
* *
* Setting a service to null resets the service: has() returns false and get()
* behaves in the same way as if the service was never created.
*
* @param string $id The service identifier * @param string $id The service identifier
* @param object $service The service instance * @param object $service The service instance
* @param string $scope The scope of the service * @param string $scope The scope of the service
@ -214,6 +217,14 @@ class Container implements IntrospectableContainerInterface
if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_')).'Service')) { if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_')).'Service')) {
$this->$method(); $this->$method();
} }
if (self::SCOPE_CONTAINER !== $scope && null === $service) {
unset($this->scopedServices[$scope][$id]);
}
if (null === $service) {
unset($this->services[$id]);
}
} }
/** /**

View File

@ -149,6 +149,18 @@ class DefinitionDecorator extends Definition
return parent::setPublic($boolean); return parent::setPublic($boolean);
} }
/**
* {@inheritDoc}
*
* @api
*/
public function setLazy($boolean)
{
$this->changes['lazy'] = true;
return parent::setLazy($boolean);
}
/** /**
* Gets an argument to pass to the service constructor/factory method. * Gets an argument to pass to the service constructor/factory method.
* *

View File

@ -143,6 +143,36 @@ class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo', $def->getClass()); $this->assertEquals('foo', $def->getClass());
} }
public function testSetLazyOnServiceHasParent()
{
$container = new ContainerBuilder();
$container->register('parent','stdClass');
$container->setDefinition('child1',new DefinitionDecorator('parent'))
->setLazy(true)
;
$this->process($container);
$this->assertTrue($container->getDefinition('child1')->isLazy());
}
public function testSetLazyOnServiceIsParent()
{
$container = new ContainerBuilder();
$container->register('parent','stdClass')
->setLazy(true)
;
$container->setDefinition('child1',new DefinitionDecorator('parent'));
$this->process($container);
$this->assertTrue($container->getDefinition('child1')->isLazy());
}
protected function process(ContainerBuilder $container) protected function process(ContainerBuilder $container)
{ {
$pass = new ResolveDefinitionTemplatesPass(); $pass = new ResolveDefinitionTemplatesPass();

View File

@ -135,6 +135,16 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($foo, $sc->get('foo'), '->set() sets a service'); $this->assertEquals($foo, $sc->get('foo'), '->set() sets a service');
} }
/**
* @covers Symfony\Component\DependencyInjection\Container::set
*/
public function testSetWithNullResetTheService()
{
$sc = new Container();
$sc->set('foo', null);
$this->assertFalse($sc->has('foo'));
}
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
*/ */

View File

@ -61,6 +61,16 @@ class DefinitionDecoratorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array('public' => true), $def->getChanges()); $this->assertEquals(array('public' => true), $def->getChanges());
} }
public function testSetLazy()
{
$def = new DefinitionDecorator('foo');
$this->assertFalse($def->isLazy());
$this->assertSame($def, $def->setLazy(false));
$this->assertFalse($def->isLazy());
$this->assertEquals(array('lazy' => true), $def->getChanges());
}
public function testSetArgument() public function testSetArgument()
{ {
$def = new DefinitionDecorator('foo'); $def = new DefinitionDecorator('foo');

View File

@ -546,7 +546,7 @@ class Form implements \IteratorAggregate, FormInterface
foreach ($this->children as $name => $child) { foreach ($this->children as $name => $child) {
$fieldValue = null; $fieldValue = null;
if (isset($submittedData[$name])) { if (array_key_exists($name, $submittedData)) {
$fieldValue = $submittedData[$name]; $fieldValue = $submittedData[$name];
unset($submittedData[$name]); unset($submittedData[$name]);
} }

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Form\Tests;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Forms;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
@ -73,6 +74,19 @@ class CompoundFormTest extends AbstractFormTest
$this->form->submit(array(), false); $this->form->submit(array(), false);
} }
public function testSubmitDoesNotAddExtraFieldForNullValues()
{
$factory = Forms::createFormFactoryBuilder()
->getFormFactory();
$child = $factory->create('file', null, array('auto_initialize' => false));
$this->form->add($child);
$this->form->submit(array('file' => null));
$this->assertCount(0, $this->form->getExtraData());
}
public function testClearMissingFlagIsForwarded() public function testClearMissingFlagIsForwarded()
{ {
$child = $this->getMockForm('firstName'); $child = $this->getMockForm('firstName');

View File

@ -78,6 +78,10 @@ class TimeDataCollector extends DataCollector
*/ */
public function getDuration() public function getDuration()
{ {
if (!isset($this->data['events']['__section__'])) {
return 0;
}
$lastEvent = $this->data['events']['__section__']; $lastEvent = $this->data['events']['__section__'];
return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime(); return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime();
@ -92,6 +96,10 @@ class TimeDataCollector extends DataCollector
*/ */
public function getInitTime() public function getInitTime()
{ {
if (!isset($this->data['events']['__section__'])) {
return 0;
}
return $this->data['events']['__section__']->getOrigin() - $this->getStartTime(); return $this->data['events']['__section__']->getOrigin() - $this->getStartTime();
} }