diff --git a/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php b/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php index 589c0235f5..a29ae0cd11 100644 --- a/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php +++ b/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php @@ -255,14 +255,14 @@ class ModelChoiceList extends ObjectChoiceList */ public function getIndicesForChoices(array $models) { + $indices = array(); + if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as indices // Attention: This optimization does not check choices for existence if ($this->identifierAsIndex) { - $indices = array(); - foreach ($models as $model) { if ($model instanceof $this->class) { // Make sure to convert to the right format @@ -276,7 +276,30 @@ class ModelChoiceList extends ObjectChoiceList $this->load(); } - return parent::getIndicesForChoices($models); + /* + * Overwriting default implementation. + * + * The two objects may represent the same entry in the database, + * but if they originated from different queries, there are not the same object within the code. + * + * This happens when using m:n relations with either sides model as data_class of the form. + * The choicelist will retrieve the list of available related models with a different query, resulting in different objects. + */ + $choices = $this->fixChoices($models); + foreach ($this->getChoices() as $i => $choice) { + foreach ($choices as $j => $givenChoice) { + if ($this->getIdentifierValues($choice) === $this->getIdentifierValues($givenChoice)) { + $indices[] = $i; + unset($choices[$j]); + + if (0 === count($choices)) { + break 2; + } + } + } + } + + return $indices; } /** diff --git a/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php b/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php index 748b1cd9b1..59f1367f2a 100644 --- a/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php +++ b/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php @@ -185,4 +185,18 @@ class ModelChoiceListTest extends Propel1TestCase $this->assertEquals(array(1, 2), $choiceList->getValuesForChoices(array($item1, $item2))); $this->assertEquals(array(1, 2), $choiceList->getIndicesForChoices(array($item1, $item2))); } + + public function testDifferentEqualObjectsAreChoosen() + { + $item = new Item(1, 'Foo'); + $choiceList = new ModelChoiceList( + self::ITEM_CLASS, + 'value', + array($item) + ); + + $choosenItem = new Item(1, 'Foo'); + + $this->assertEquals(array(1), $choiceList->getIndicesForChoices(array($choosenItem))); + } } diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index d97ad35e67..a3998a82e7 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -129,9 +129,16 @@ class Application } else { $this->renderException($e, $output); } - $exitCode = $e->getCode(); - $exitCode = $exitCode ? (is_numeric($exitCode) ? (int) $exitCode : 1) : 0; + $exitCode = $e->getCode(); + if (is_numeric($exitCode)) { + $exitCode = (int) $exitCode; + if (0 === $exitCode) { + $exitCode = 1; + } + } else { + $exitCode = 1; + } } if ($this->autoExit) { diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 60ea14154d..bc1f038bc6 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -573,6 +573,21 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception'); } + public function testRunReturnsExitCodeOneForExceptionCodeZero() + { + $exception = new \Exception('', 0); + + $application = $this->getMock('Symfony\Component\Console\Application', array('doRun')); + $application->setAutoExit(false); + $application->expects($this->once()) + ->method('doRun') + ->will($this->throwException($exception)); + + $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); + + $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0'); + } + /** * @expectedException \LogicException * @dataProvider getAddingAlreadySetDefinitionElementData diff --git a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php index 5144ac739c..677a9aad31 100644 --- a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php +++ b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php @@ -204,8 +204,12 @@ class FormFieldRegistry { if (preg_match('/^(?P[^[]+)(?P(\[.*)|$)/', $name, $m)) { $segments = array($m['base']); - while (preg_match('/^\[(?P.*?)\](?P.*)$/', $m['extra'], $m)) { - $segments[] = $m['segment']; + while (!empty($m['extra'])) { + if (preg_match('/^\[(?P.*?)\](?P.*)$/', $m['extra'], $m)) { + $segments[] = $m['segment']; + } else { + throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name)); + } } return $segments; diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 43e4f372f9..61f89434eb 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -292,6 +292,18 @@ class FormTest extends \PHPUnit_Framework_TestCase } } + public function testSetValueOnMultiValuedFieldsWithMalformedName() + { + $form = $this->createForm('
'); + + try { + $form['foo[bar'] = 'bar'; + $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.'); + } + } + public function testOffsetUnset() { $form = $this->createForm('
'); diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index c4ba0d1aab..215d1e1862 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -189,7 +189,7 @@ abstract class Bundle extends ContainerAware implements BundleInterface $ns .= '\\'.strtr($relativePath, '/', '\\'); } $r = new \ReflectionClass($ns.'\\'.$file->getBasename('.php')); - if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) { + if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) { $application->add($r->newInstance()); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php new file mode 100644 index 0000000000..b9a5417d94 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php @@ -0,0 +1,18 @@ +