8000 [Console] Centralize input stream in base Input class by chalasr · Pull Request #18999 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Console] Centralize input stream in base Input class #18999

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/Symfony/Component/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Console\Helper\ProcessHelper;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
Expand Down Expand Up @@ -769,8 +770,19 @@ protected function configureIO(InputInterface $input, OutputInterface $output)

if (true === $input->hasParameterOption(array('--no-interaction', '-n'), true)) {
$input->setInteractive(false);
} elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
$inputStream = $this->getHelperSet()->get('question')->getInputStream();
} elseif (function_exists('posix_isatty')) {
Copy link
Contributor
@ogizanagi ogizanagi Jun 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably not be removed entirely yet (for BC reasons) ?
Or should QuestionHelper::setInputStream && QuestionHelper::getInputStream methods call $input->setStream && $input->getStream ?

Copy link
Member Author
@chalasr chalasr Jun 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.
Detecting a possible null helper then null inputStream here would be much logic.
I would prefer calling Input::setStream in QuestionHelper::setInputStream while setting the QuestionHelper::$inputStream (for BC reasons too) then return it in QuestionHelper::getInputStream() assuming that if it is set in the QuestionHelper, it will not be from the Input in the meantime.
We can't access the Input from QuestionHelper setInputStream/getInputStream, it don't take the input as member but only as ask() argument. Will write some ugly checks...

$inputStream = null;

if ($input instanceof StreamableInputInterface) {
$inputStream = $input->getStream();
}

// This check ensures that calling QuestionHelper::setInputStream() works
// To be removed in 4.0 (in the same time as QuestionHelper::setInputStream)
if (!$inputStream && $this->getHelperSet()->has('question')) {
$inputStream = $this->getHelperSet()->get('question')->getInputStream(false);
}

if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
$input->setInteractive(false);
}
Expand Down
19 changes: 18 additions & 1 deletion src/Symfony/Component/Console/Helper/QuestionHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
Expand Down Expand Up @@ -52,6 +53,10 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu
return $question->getDefault();
}

if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) {
$this->inputStream = $stream;
}

if (!$question->getValidator()) {
return $this->doAsk($output, $question);
}
Expand All @@ -68,12 +73,17 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu
*
* This is mainly useful for testing purpose.
*
* @deprecated since version 3.2, to be removed in 4.0. Use
* StreamableInputInterface::setStream() instead.
*
* @param resource $stream The input stream
*
* @throws InvalidArgumentException In case the stream is not a resource
*/
public function setInputStream($stream)
{
@trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s:setStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED);

if (!is_resource($stream)) {
throw new InvalidArgumentException('Input stream must be a valid resource.');
}
Expand All @@ -84,10 +94,17 @@ public function setInputStream($stream)
/**
* Returns the helper's input stream.
8000 *
* @deprecated since version 3.2, to be removed in 4.0. Use
* StreamableInputInterface::getStream() instead.
*
* @return resource
*/
public function getInputStream()
public function getInputStream($triggerDeprecationError = true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding a new argument here is a BC break

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #19072

{
if ($triggerDeprecationError) {
@trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s:getStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED);
}

return $this->inputStream;
}

8000 Expand Down
19 changes: 18 additions & 1 deletion src/Symfony/Component/Console/Input/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class Input implements InputInterface
abstract class Input implements InputInterface, StreamableInputInterface
{
/**
* @var InputDefinition
*/
protected $definition;
protected $stream;
protected $options = array();
protected $arguments = array();
protected $interactive = true;
Expand Down Expand Up @@ -233,4 +234,20 @@ public function escapeToken($token)
{
return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
}

/**
* {@inheritdoc}
*/
public function setStream($stream)
{
$this->stream = $stream;
}

/**
* {@inheritdoc}
*/
public function getStream()
{
return $this->stream;
}
}
37 changes: 37 additions & 0 deletions src/Symfony/Component/Console/Input/StreamableInputInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?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\Component\Console\Input;

/**
* StreamableInputInterface is the interface implemented by all input classes
* that have an input stream.
*
* @author Robin Chalas <robin.chalas@gmail.com>
*/
interface StreamableInputInterface extends InputInterface
{
/**
* Sets the input stream to read from when interacting with the user.
*
* This is mainly useful for testing purpose.
*
* @param resource $stream The input stream
*/
public function setStream($stream);

/**
* Returns the input stream.
*
* @return resource|null
*/
public function getStream();
}
2 changes: 1 addition & 1 deletion src/Symfony/Component/Console/Tests/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ public function testCanCheckIfTerminalIsInteractive()

$this->assertFalse($tester->getInput()->hasParameterOption(array('--no-interaction', '-n')));

$inputStream = $application->getHelperSet()->get('question')->getInputStream();
$inputStream = $tester->getInput()->getStream();
$this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream));
}
}
Expand Down
Loading
0