From e7dfdab05f9a4f9d068d27e22089fe420a9ea5dc Mon Sep 17 00:00:00 2001 From: geoffrey Date: Mon, 11 Jan 2010 12:24:08 +0100 Subject: [PATCH] [Console] implemented helpers and moved formatter and ask* methods to their own helpers --- .../Components/Console/Command/Command.php | 103 +++++---------- .../FormatterHelper.php} | 23 ++-- .../Components/Console/Helper/Helper.php | 45 +++++++ .../Console/Helper/HelperInterface.php | 43 +++++++ .../Components/Console/Helper/HelperSet.php | 105 ++++++++++++++++ .../Console/Helper/InteractHelper.php | 119 ++++++++++++++++++ .../Console/Helper/FormatterHelperTest.php | 28 +++++ .../Console/Output/FormatterTest.php | 26 ---- 8 files changed, 389 insertions(+), 103 deletions(-) rename src/Symfony/Components/Console/{Output/Formatter.php => Helper/FormatterHelper.php} (76%) create mode 100644 src/Symfony/Components/Console/Helper/Helper.php create mode 100644 src/Symfony/Components/Console/Helper/HelperInterface.php create mode 100644 src/Symfony/Components/Console/Helper/HelperSet.php create mode 100644 src/Symfony/Components/Console/Helper/InteractHelper.php create mode 100644 tests/unit/Symfony/Components/Console/Helper/FormatterHelperTest.php delete mode 100644 tests/unit/Symfony/Components/Console/Output/FormatterTest.php diff --git a/src/Symfony/Components/Console/Command/Command.php b/src/Symfony/Components/Console/Command/Command.php index 68385097ef..5642d128db 100644 --- a/src/Symfony/Components/Console/Command/Command.php +++ b/src/Symfony/Components/Console/Command/Command.php @@ -7,8 +7,10 @@ use Symfony\Components\Console\Input\InputOption; use Symfony\Components\Console\Input\InputArgument; use Symfony\Components\Console\Input\InputInterface; use Symfony\Components\Console\Output\OutputInterface; -use Symfony\Components\Console\Output\Formatter; use Symfony\Components\Console\Application; +use Symfony\Components\Console\Helper\HelperSet; +use Symfony\Components\Console\Helper\FormatterHelper; +use Symfony\Components\Console\Helper\InteractHelper; /* * This file is part of the symfony framework. @@ -42,15 +44,27 @@ class Command /** * Constructor. + * + * @param string $name + * @param HelperSet $helperSet A helper set instance */ - public function __construct($name = null) + public function __construct($name = null, HelperSet $helperSet = null) { $this->definition = new InputDefinition(); $this->ignoreValidationErrors = false; $this->applicationDefinitionMerged = false; - $this->formatter = new Formatter(); $this->aliases = array(); + if (null === $helperSet) + { + $helperSet = new HelperSet(array( + new FormatterHelper(), + new InteractHelper(), + )); + } + + $this->setHelperSet($helperSet); + if (null !== $name) { $this->setName($name); @@ -389,90 +403,39 @@ class Command } /** - * Asks a question to the user. + * Set a helper set to be used with the command. * - * @param OutputInterface $output - * @param string|array $question The question to ask - * @param string $default The default answer if none is given by the user - * - * @param string The user answer + * @param HelperSet $helperSet The helper set */ - static public function ask(OutputInterface $output, $question, $default = null) + public function setHelperSet(HelperSet $helperSet) { - // @codeCoverageIgnoreStart - $output->write($question); + $this->helperSet = $helperSet; - $ret = trim(fgets(STDIN)); - - return $ret ? $ret : $default; - // @codeCoverageIgnoreEnd + $helperSet->setCommand($this); } /** - * Asks a confirmation to the user. + * Get the helper set associated with the command * - * The question will be asked until the user answer by nothing, yes, or no. - * - * @param OutputInterface $output - * @param string|array $question The question to ask - * @param Boolean $default The default answer if the user enters nothing - * - * @param Boolean true if the user has confirmed, false otherwise + * @return HelperSet */ - static public function askConfirmation(OutputInterface $output, $question, $default = true) + public function getHelperSet() { - // @codeCoverageIgnoreStart - $answer = 'z'; - while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) - { - $answer = static::ask($output, $question); - } - - if (false === $default) - { - return $answer && 'y' == strtolower($answer[0]); - } - else - { - return !$answer || 'y' == strtolower($answer[0]); - } - // @codeCoverageIgnoreEnd + return $this->helperSet; } /** - * Asks for a value and validates the response. + * Gets a helper value. * - * @param OutputInterface $output - * @param string|array $question - * @param Closure $validator - * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) + * @param string $name The helper name * - * @return mixed + * @return mixed The helper value + * + * @throws \InvalidArgumentException if the helper is not defined */ - static public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false) + public function __get($name) { - // @codeCoverageIgnoreStart - $error = null; - while (false === $attempts || $attempts--) - { - if (null !== $error) - { - $output->write($this->formatter->formatBlock($error->getMessage(), 'error')); - } - - $value = static::ask($output, $question, null); - - try - { - return $validator($value); - } - catch (\Exception $error) - { - } - } - - throw $error; - // @codeCoverageIgnoreEnd + return $this->helperSet->get($name); } /** diff --git a/src/Symfony/Components/Console/Output/Formatter.php b/src/Symfony/Components/Console/Helper/FormatterHelper.php similarity index 76% rename from src/Symfony/Components/Console/Output/Formatter.php rename to src/Symfony/Components/Console/Helper/FormatterHelper.php index 8a1efd0e4b..4eac10b4b8 100644 --- a/src/Symfony/Components/Console/Output/Formatter.php +++ b/src/Symfony/Components/Console/Helper/FormatterHelper.php @@ -1,6 +1,6 @@ */ -class Formatter +class FormatterHelper extends Helper { + /** + * Returns the helper's canonical name + */ + public function getName() + { + return 'formatter'; + } + /** * Formats a message within a section. * @@ -27,7 +35,7 @@ class Formatter * @param string $message The message * @param string $style The style to apply to the section */ - static public function formatSection($section, $message, $style = 'info') + public function formatSection($section, $message, $style = 'info') { return sprintf("<%s>[%s] %s", $style, $section, $style, $message); } @@ -41,7 +49,7 @@ class Formatter * * @return string The formatter message */ - static public function formatBlock($messages, $style, $large = false) + public function formatBlock($messages, $style, $large = false) { if (!is_array($messages)) { @@ -53,13 +61,13 @@ class Formatter foreach ($messages as $message) { $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); - $len = max(static::strlen($message) + ($large ? 4 : 2), $len); + $len = max($this->strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? array(str_repeat(' ', $len)) : array(); foreach ($lines as $line) { - $messages[] = $line.str_repeat(' ', $len - static::strlen($line)); + $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); } if ($large) { @@ -74,8 +82,9 @@ class Formatter return implode("\n", $messages); } - static protected function strlen($string) + protected function strlen($string) { return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string); } } + diff --git a/src/Symfony/Components/Console/Helper/Helper.php b/src/Symfony/Components/Console/Helper/Helper.php new file mode 100644 index 0000000000..642e7a67c7 --- /dev/null +++ b/src/Symfony/Components/Console/Helper/Helper.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Helper is the base class for all helper classes. + * + * @package symfony + * @subpackage templating + * @author Fabien Potencier + */ +abstract class Helper implements HelperInterface +{ + protected + $helperSet = null; + + /** + * Sets the helper set associated with this helper. + * + * @param HelperSet $helperSet A HelperSet instance + */ + public function setHelperSet(HelperSet $helperSet = null) + { + $this->helperSet = $helperSet; + } + + /** + * Gets the helper set associated with this helper. + * + * @return HelperSet A HelperSet instance + */ + public function getHelperSet() + { + return $this->helperSet; + } +} diff --git a/src/Symfony/Components/Console/Helper/HelperInterface.php b/src/Symfony/Components/Console/Helper/HelperInterface.php new file mode 100644 index 0000000000..a3474fc610 --- /dev/null +++ b/src/Symfony/Components/Console/Helper/HelperInterface.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * HelperInterface is the interface all helpers must implement. + * + * @package symfony + * @subpackage templating + * @author Fabien Potencier + */ +interface HelperInterface +{ + /** + * Returns the canonical name of this helper. + * + * @return string The canonical name + */ + function getName(); + + /** + * Sets the helper set associated with this helper. + * + * @param HelperSet $helperSet A HelperSet instance + */ + function setHelperSet(HelperSet $helperSet = null); + + /** + * Gets the helper set associated with this helper. + * + * @return HelperSet A HelperSet instance + */ + function getHelperSet(); +} diff --git a/src/Symfony/Components/Console/Helper/HelperSet.php b/src/Symfony/Components/Console/Helper/HelperSet.php new file mode 100644 index 0000000000..b71e9bd1b7 --- /dev/null +++ b/src/Symfony/Components/Console/Helper/HelperSet.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * HelperSet represents a set of helpers to be used with a command. + * + * @package symfony + * @subpackage templating + * @author Fabien Potencier + */ +class HelperSet +{ + protected + $helpers = array(), + $command = null; + + public function __construct(array $helpers = array()) + { + foreach ($helpers as $alias => $helper) + { + $this->set($helper, is_int($alias) ? null : $alias); + } + } + + /** + * Sets a helper. + * + * @param HelperInterface $value The helper instance + * @param string $alias An alias + */ + public function set(HelperInterface $helper, $alias = null) + { + $this->helpers[$helper->getName()] = $helper; + if (null !== $alias) + { + $this->helpers[$alias] = $helper; + } + + $helper->setHelperSet($this); + } + + /** + * Returns true if the helper if defined. + * + * @param string $name The helper name + * + * @return Boolean true if the helper is defined, false otherwise + */ + public function has($name) + { + return isset($this->helpers[$name]); + } + + /** + * Gets a helper value. + * + * @param string $name The helper name + * + * @return HelperInterface The helper instance + * + * @throws \InvalidArgumentException if the helper is not defined + */ + public function get($name) + { + if (!$this->has($name)) + { + throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); + } + + return $this->helpers[$name]; + } + + /** + * Sets the command associated with this helper set. + * + * @param Command $command A Command instance + */ + public function setCommand(Command $command = null) + { + $this->command = $command; + } + + /** + * Gets the command associated with this helper set. + * + * @return Command A Command instance + */ + public function getCommand() + { + return $this->command; + } +} + diff --git a/src/Symfony/Components/Console/Helper/InteractHelper.php b/src/Symfony/Components/Console/Helper/InteractHelper.php new file mode 100644 index 0000000000..0054ab08d3 --- /dev/null +++ b/src/Symfony/Components/Console/Helper/InteractHelper.php @@ -0,0 +1,119 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * The Interact class provides helpers to interact with the user. + * + * @package symfony + * @subpackage cli + * @author Fabien Potencier + */ +class InteractHelper extends Helper +{ + /** + * Returns the helper's canonical name + */ + public function getName() + { + return 'interact'; + } + + /** + * Asks a question to the user. + * + * @param OutputInterface $output + * @param string|array $question The question to ask + * @param string $default The default answer if none is given by the user + * + * @param string The user answer + */ + public function ask(OutputInterface $output, $question, $default = null) + { + // @codeCoverageIgnoreStart + $output->write($question); + + $ret = trim(fgets(STDIN)); + + return $ret ? $ret : $default; + // @codeCoverageIgnoreEnd + } + + /** + * Asks a confirmation to the user. + * + * The question will be asked until the user answer by nothing, yes, or no. + * + * @param OutputInterface $output + * @param string|array $question The question to ask + * @param Boolean $default The default answer if the user enters nothing + * + * @param Boolean true if the user has confirmed, false otherwise + */ + public function askConfirmation(OutputInterface $output, $question, $default = true) + { + // @codeCoverageIgnoreStart + $answer = 'z'; + while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) + { + $answer = $this->ask($output, $question); + } + + if (false === $default) + { + return $answer && 'y' == strtolower($answer[0]); + } + else + { + return !$answer || 'y' == strtolower($answer[0]); + } + // @codeCoverageIgnoreEnd + } + + /** + * Asks for a value and validates the response. + * + * @param OutputInterface $output + * @param string|array $question + * @param Closure $validator + * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) + * + * @return mixed + */ + public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false) + { + // @codeCoverageIgnoreStart + $error = null; + while (false === $attempts || $attempts--) + { + if (null !== $error) + { + $output->write($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); + } + + $value = $this->ask($output, $question, null); + + try + { + return $validator($value); + } + catch (\Exception $error) + { + } + } + + throw $error; + // @codeCoverageIgnoreEnd + } +} diff --git a/tests/unit/Symfony/Components/Console/Helper/FormatterHelperTest.php b/tests/unit/Symfony/Components/Console/Helper/FormatterHelperTest.php new file mode 100644 index 0000000000..0fd2199b61 --- /dev/null +++ b/tests/unit/Symfony/Components/Console/Helper/FormatterHelperTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require_once __DIR__.'/../../../../bootstrap.php'; + +use Symfony\Components\Console\Helper\FormatterHelper; + +$formatter = new FormatterHelper(); + +$t = new LimeTest(4); + +// ::formatSection() +$t->diag('::formatSection()'); +$t->is($formatter->formatSection('cli', 'Some text to display'), '[cli] Some text to display', '::formatSection() formats a message in a section'); + +// ::formatBlock() +$t->diag('::formatBlock()'); +$t->is($formatter->formatBlock('Some text to display', 'error'), ' Some text to display ', '::formatBlock() formats a message in a block'); +$t->is($formatter->formatBlock(array('Some text to display', 'foo bar'), 'error'), " Some text to display \n foo bar ", '::formatBlock() formats a message in a block'); + +$t->is($formatter->formatBlock('Some text to display', 'error', true), " \n Some text to display \n ", '::formatBlock() formats a message in a block'); diff --git a/tests/unit/Symfony/Components/Console/Output/FormatterTest.php b/tests/unit/Symfony/Components/Console/Output/FormatterTest.php deleted file mode 100644 index 401706e13d..0000000000 --- a/tests/unit/Symfony/Components/Console/Output/FormatterTest.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -require_once __DIR__.'/../../../../bootstrap.php'; - -use Symfony\Components\Console\Output\Formatter; - -$t = new LimeTest(4); - -// ::formatSection() -$t->diag('::formatSection()'); -$t->is(Formatter::formatSection('cli', 'Some text to display'), '[cli] Some text to display', '::formatSection() formats a message in a section'); - -// ::formatBlock() -$t->diag('::formatBlock()'); -$t->is(Formatter::formatBlock('Some text to display', 'error'), ' Some text to display ', '::formatBlock() formats a message in a block'); -$t->is(Formatter::formatBlock(array('Some text to display', 'foo bar'), 'error'), " Some text to display \n foo bar ", '::formatBlock() formats a message in a block'); - -$t->is(Formatter::formatBlock('Some text to display', 'error', true), " \n Some text to display \n ", '::formatBlock() formats a message in a block');