فهرست منبع

[Console] implemented helpers and moved formatter and ask* methods to their own helpers

geoffrey 15 سال پیش
والد
کامیت
afcb3c906d

+ 33 - 70
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);
@@ -379,90 +393,39 @@ class Command
   }
 
   /**
-   * 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
+   * Set a helper set to be used with the command.
    *
-   * @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.
-   *
-   * The question will be asked until the user answer by nothing, yes, or no.
+   * Get the helper set associated with the command
    *
-   * @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);
   }
 
   /**

+ 16 - 7
src/Symfony/Components/Console/Output/Formatter.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace Symfony\Components\Console\Output;
+namespace Symfony\Components\Console\Helper;
 
 /*
  * This file is part of the symfony framework.
@@ -18,8 +18,16 @@ namespace Symfony\Components\Console\Output;
  * @subpackage console
  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
  */
-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> %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);
   }
 }
+

+ 45 - 0
src/Symfony/Components/Console/Helper/Helper.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Symfony\Components\Console\Helper;
+
+/*
+ * This file is part of the symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * 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 <fabien.potencier@symfony-project.com>
+ */
+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;
+  }
+}

+ 43 - 0
src/Symfony/Components/Console/Helper/HelperInterface.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace Symfony\Components\Console\Helper;
+
+/*
+ * This file is part of the symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * 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 <fabien.potencier@symfony-project.com>
+ */
+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();
+}

+ 105 - 0
src/Symfony/Components/Console/Helper/HelperSet.php

@@ -0,0 +1,105 @@
+<?php
+
+namespace Symfony\Components\Console\Helper;
+
+use Symfony\Components\Console\Command\Command;
+
+/*
+ * This file is part of the symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * 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 <fabien.potencier@symfony-project.com>
+ */
+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;
+  }
+}
+

+ 119 - 0
src/Symfony/Components/Console/Helper/InteractHelper.php

@@ -0,0 +1,119 @@
+<?php
+
+namespace Symfony\Components\Console\Helper;
+
+use Symfony\Components\Console\Output\OutputInterface;
+
+/*
+ * This file is part of the symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * 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 <fabien.potencier@symfony-project.com>
+ */
+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
+  }
+}

+ 28 - 0
tests/unit/Symfony/Components/Console/Helper/FormatterHelperTest.php

@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * 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'), '<info>[cli]</info> Some text to display', '::formatSection() formats a message in a section');
+
+// ::formatBlock()
+$t->diag('::formatBlock()');
+$t->is($formatter->formatBlock('Some text to display', 'error'), '<error> Some text to display </error>', '::formatBlock() formats a message in a block');
+$t->is($formatter->formatBlock(array('Some text to display', 'foo bar'), 'error'), "<error> Some text to display </error>\n<error> foo bar              </error>", '::formatBlock() formats a message in a block');
+
+$t->is($formatter->formatBlock('Some text to display', 'error', true), "<error>                        </error>\n<error>  Some text to display  </error>\n<error>                        </error>", '::formatBlock() formats a message in a block');

+ 0 - 26
tests/unit/Symfony/Components/Console/Output/FormatterTest.php

@@ -1,26 +0,0 @@
-<?php
-
-/*
- * This file is part of the symfony package.
- * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
- *
- * 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'), '<info>[cli]</info> Some text to display', '::formatSection() formats a message in a section');
-
-// ::formatBlock()
-$t->diag('::formatBlock()');
-$t->is(Formatter::formatBlock('Some text to display', 'error'), '<error> Some text to display </error>', '::formatBlock() formats a message in a block');
-$t->is(Formatter::formatBlock(array('Some text to display', 'foo bar'), 'error'), "<error> Some text to display </error>\n<error> foo bar              </error>", '::formatBlock() formats a message in a block');
-
-$t->is(Formatter::formatBlock('Some text to display', 'error', true), "<error>                        </error>\n<error>  Some text to display  </error>\n<error>                        </error>", '::formatBlock() formats a message in a block');