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 @@
+