/2012/sample-tonic/src/Doctrine/Symfony/Component/Console/Formatter/OutputFormatter.php

https://bitbucket.org/alessandro-aglietti/itis-leonardo-da-vinci · PHP · 230 lines · 98 code · 28 blank · 104 comment · 14 complexity · 9462eba2f2808c4c82b26540e5b1e6eb MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Console\Formatter;
  11. /**
  12. * Formatter class for console output.
  13. *
  14. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  15. *
  16. * @api
  17. */
  18. class OutputFormatter implements OutputFormatterInterface
  19. {
  20. /**
  21. * The pattern to phrase the format.
  22. */
  23. const FORMAT_PATTERN = '#<(/?)([a-z][a-z0-9_=;-]+)?>([^<]*)#is';
  24. private $decorated;
  25. private $styles = array();
  26. private $styleStack;
  27. /**
  28. * Initializes console output formatter.
  29. *
  30. * @param Boolean $decorated Whether this formatter should actually decorate strings
  31. * @param array $styles Array of "name => FormatterStyle" instances
  32. *
  33. * @api
  34. */
  35. public function __construct($decorated = null, array $styles = array())
  36. {
  37. $this->decorated = (Boolean) $decorated;
  38. $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
  39. $this->setStyle('info', new OutputFormatterStyle('green'));
  40. $this->setStyle('comment', new OutputFormatterStyle('yellow'));
  41. $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
  42. foreach ($styles as $name => $style) {
  43. $this->setStyle($name, $style);
  44. }
  45. $this->styleStack = new OutputFormatterStyleStack();
  46. }
  47. /**
  48. * Sets the decorated flag.
  49. *
  50. * @param Boolean $decorated Whether to decorate the messages or not
  51. *
  52. * @api
  53. */
  54. public function setDecorated($decorated)
  55. {
  56. $this->decorated = (Boolean) $decorated;
  57. }
  58. /**
  59. * Gets the decorated flag.
  60. *
  61. * @return Boolean true if the output will decorate messages, false otherwise
  62. *
  63. * @api
  64. */
  65. public function isDecorated()
  66. {
  67. return $this->decorated;
  68. }
  69. /**
  70. * Sets a new style.
  71. *
  72. * @param string $name The style name
  73. * @param OutputFormatterStyleInterface $style The style instance
  74. *
  75. * @api
  76. */
  77. public function setStyle($name, OutputFormatterStyleInterface $style)
  78. {
  79. $this->styles[strtolower($name)] = $style;
  80. }
  81. /**
  82. * Checks if output formatter has style with specified name.
  83. *
  84. * @param string $name
  85. *
  86. * @return Boolean
  87. *
  88. * @api
  89. */
  90. public function hasStyle($name)
  91. {
  92. return isset($this->styles[strtolower($name)]);
  93. }
  94. /**
  95. * Gets style options from style with specified name.
  96. *
  97. * @param string $name
  98. *
  99. * @return OutputFormatterStyleInterface
  100. *
  101. * @throws \InvalidArgumentException When style isn't defined
  102. *
  103. * @api
  104. */
  105. public function getStyle($name)
  106. {
  107. if (!$this->hasStyle($name)) {
  108. throw new \InvalidArgumentException('Undefined style: '.$name);
  109. }
  110. return $this->styles[strtolower($name)];
  111. }
  112. /**
  113. * Formats a message according to the given styles.
  114. *
  115. * @param string $message The message to style
  116. *
  117. * @return string The styled message
  118. *
  119. * @api
  120. */
  121. public function format($message)
  122. {
  123. return preg_replace_callback(self::FORMAT_PATTERN, array($this, 'replaceStyle'), $message);
  124. }
  125. /**
  126. * @return OutputFormatterStyleStack
  127. */
  128. public function getStyleStack()
  129. {
  130. return $this->styleStack;
  131. }
  132. /**
  133. * Replaces style of the output.
  134. *
  135. * @param array $match
  136. *
  137. * @return string The replaced style
  138. */
  139. private function replaceStyle($match)
  140. {
  141. if ('' === $match[2]) {
  142. if ('/' === $match[1]) {
  143. // we got "</>" tag
  144. $this->styleStack->pop();
  145. return $this->applyStyle($this->styleStack->getCurrent(), $match[3]);
  146. }
  147. // we got "<>" tag
  148. return '<>'.$match[3];
  149. }
  150. if (isset($this->styles[strtolower($match[2])])) {
  151. $style = $this->styles[strtolower($match[2])];
  152. } else {
  153. $style = $this->createStyleFromString($match[2]);
  154. if (false === $style) {
  155. return $match[0];
  156. }
  157. }
  158. if ('/' === $match[1]) {
  159. $this->styleStack->pop($style);
  160. } else {
  161. $this->styleStack->push($style);
  162. }
  163. return $this->applyStyle($this->styleStack->getCurrent(), $match[3]);
  164. }
  165. /**
  166. * Tries to create new style instance from string.
  167. *
  168. * @param string $string
  169. *
  170. * @return OutputFormatterStyle|Boolean false if string is not format string
  171. */
  172. private function createStyleFromString($string)
  173. {
  174. if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
  175. return false;
  176. }
  177. $style = new OutputFormatterStyle();
  178. foreach ($matches as $match) {
  179. array_shift($match);
  180. if ('fg' == $match[0]) {
  181. $style->setForeground($match[1]);
  182. } elseif ('bg' == $match[0]) {
  183. $style->setBackground($match[1]);
  184. } else {
  185. $style->setOption($match[1]);
  186. }
  187. }
  188. return $style;
  189. }
  190. /**
  191. * Applies style to text if must be applied.
  192. *
  193. * @param OutputFormatterStyleInterface $style Style to apply
  194. * @param string $text Input text
  195. *
  196. * @return string string Styled text
  197. */
  198. private function applyStyle(OutputFormatterStyleInterface $style, $text)
  199. {
  200. return $this->isDecorated() && strlen($text) > 0 ? $style->apply($text) : $text;
  201. }
  202. }