Skip to content

Commit

Permalink
Merge branch '2.2' into 2.3
Browse files Browse the repository at this point in the history
* 2.2:
  Revert "[Console] ensure exit code between 0-254"
  fix many-to-many Propel1 ModelChoiceList
  [Console] ensure exit code between 0-254
  [DomCrawler] Fixed a fatal error when setting a value in a malformed field name.
  [Console] fix status code when Exception::getCode returns something like 0.1
  Fixed exit code for exceptions with error code 0
  instantiate valid commands only

Conflicts:
	src/Symfony/Component/Console/Application.php
  • Loading branch information
fabpot committed Jun 11, 2013
2 parents 847951e + d85ce5e commit 2f915f7
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 8 deletions.
29 changes: 26 additions & 3 deletions src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php
Expand Up @@ -255,14 +255,14 @@ public function getValuesForChoices(array $models)
*/
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
Expand All @@ -276,7 +276,30 @@ public function getIndicesForChoices(array $models)
$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;
}

/**
Expand Down
Expand Up @@ -185,4 +185,18 @@ public function testGetValuesForChoices()
$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)));
}
}
11 changes: 9 additions & 2 deletions src/Symfony/Component/Console/Application.php
Expand Up @@ -129,9 +129,16 @@ public function run(InputInterface $input = null, OutputInterface $output = null
} 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) {
Expand Down
15 changes: 15 additions & 0 deletions src/Symfony/Component/Console/Tests/ApplicationTest.php
Expand Up @@ -573,6 +573,21 @@ public function testRunReturnsIntegerExitCode()
$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
Expand Down
8 changes: 6 additions & 2 deletions src/Symfony/Component/DomCrawler/FormFieldRegistry.php
Expand Up @@ -204,8 +204,12 @@ private function getSegments($name)
{
if (preg_match('/^(?P<base>[^[]+)(?P<extra>(\[.*)|$)/', $name, $m)) {
$segments = array($m['base']);
while (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $m['extra'], $m)) {
$segments[] = $m['segment'];
while (!empty($m['extra'])) {
if (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $m['extra'], $m)) {
$segments[] = $m['segment'];
} else {
throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name));
}
}

return $segments;
Expand Down
12 changes: 12 additions & 0 deletions src/Symfony/Component/DomCrawler/Tests/FormTest.php
Expand Up @@ -292,6 +292,18 @@ public function testGetSetValue()
}
}

public function testSetValueOnMultiValuedFieldsWithMalformedName()
{
$form = $this->createForm('<form><input type="text" name="foo[bar]" value="bar" /><input type="text" name="foo[baz]" value="baz" /><input type="submit" /></form>');

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('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/HttpKernel/Bundle/Bundle.php
Expand Up @@ -189,7 +189,7 @@ public function registerCommands(Application $application)
$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());
}
}
Expand Down
@@ -0,0 +1,18 @@
<?php

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command;

use Symfony\Component\Console\Command\Command;

/**
* This command has a required parameter on the constructor and will be ignored by the default Bundle implementation.
*
* @see Symfony\Component\HttpKernel\Bundle\Bundle::registerCommands
*/
class BarCommand extends Command
{
public function __construct($example, $name = 'bar')
{

}
}

0 comments on commit 2f915f7

Please sign in to comment.