Merge branch '3.2' into 3.3

* 3.2:
  [Console] ChoiceQuestion must have choices
  [Filesystem] improve error handling in lock()
  [FrameworkBundle][Console] Fix the override of a command registered by the kernel
This commit is contained in:
Fabien Potencier 2017-05-28 07:08:56 -07:00
commit daac6dbb41
6 changed files with 82 additions and 3 deletions

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Console;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -118,6 +119,13 @@ class Application extends BaseApplication
return parent::getLongVersion().sprintf(' (kernel: <comment>%s</>, env: <comment>%s</>, debug: <comment>%s</>)', $this->kernel->getName(), $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false');
}
public function add(Command $command)
{
$this->registerCommands();
return parent::add($command);
}
protected function registerCommands()
{
if ($this->commandsRegistered) {

View File

@ -115,6 +115,21 @@ class ApplicationTest extends TestCase
$tester->run(array('command' => 'foo'));
}
public function testBundleCommandCanOverriddeAPreExistingCommandWithTheSameName()
{
$command = new Command('example');
$bundle = $this->createBundleMock(array($command));
$kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
$newCommand = new Command('example');
$application->add($newCommand);
$this->assertSame($newCommand, $application->get('example'));
}
private function getKernel(array $bundles, $useDispatcher = false)
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();

View File

@ -34,6 +34,10 @@ class ChoiceQuestion extends Question
*/
public function __construct($question, array $choices, $default = null)
{
if (!$choices) {
throw new \LogicException('Choice question must have at least 1 choice available.');
}
parent::__construct($question, $default);
$this->choices = $choices;

View File

@ -803,6 +803,15 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
$dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question);
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage Choice question must have at least 1 choice available.
*/
public function testEmptyChoices()
{
new ChoiceQuestion('Question', array(), 'irrelevant');
}
protected function getInputStream($input)
{
$stream = fopen('php://memory', 'r+', false);

View File

@ -68,8 +68,12 @@ class LockHandler
return true;
}
$error = null;
// Silence error reporting
set_error_handler(function () {});
set_error_handler(function ($errno, $msg) use (&$error) {
$error = $msg;
});
if (!$this->handle = fopen($this->file, 'r')) {
if ($this->handle = fopen($this->file, 'x')) {
@ -82,8 +86,7 @@ class LockHandler
restore_error_handler();
if (!$this->handle) {
$error = error_get_last();
throw new IOException($error['message'], 0, null, $this->file);
throw new IOException($error, 0, null, $this->file);
}
// On Windows, even if PHP doc says the contrary, LOCK_NB works, see

View File

@ -12,6 +12,8 @@
namespace Symfony\Component\Filesystem\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\LockHandler;
class LockHandlerTest extends TestCase
@ -40,6 +42,44 @@ class LockHandlerTest extends TestCase
new LockHandler('lock', '/');
}
public function testErrorHandlingInLockIfLockPathBecomesUnwritable()
{
// skip test on Windows; PHP can't easily set file as unreadable on Windows
if ('\\' === DIRECTORY_SEPARATOR) {
$this->markTestSkipped('This test cannot run on Windows.');
}
$lockPath = sys_get_temp_dir().'/'.uniqid();
$e = null;
$wrongMessage = null;
try {
mkdir($lockPath);
$lockHandler = new LockHandler('lock', $lockPath);
chmod($lockPath, 0444);
$lockHandler->lock();
} catch (IOException $e) {
if (false === strpos($e->getMessage(), 'Permission denied')) {
$wrongMessage = $e->getMessage();
} else {
$this->addToAssertionCount(1);
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
}
if (is_dir($lockPath)) {
$fs = new Filesystem();
$fs->remove($lockPath);
}
$this->assertInstanceOf('Symfony\Component\Filesystem\Exception\IOException', $e, sprintf('Expected IOException to be thrown, got %s instead.', get_class($e)));
$this->assertNull($wrongMessage, sprintf('Expected exception message to contain "Permission denied", got "%s" instead.', $wrongMessage));
}
public function testConstructSanitizeName()
{
$lock = new LockHandler('<?php echo "% hello word ! %" ?>');