ConsoleIO.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\IO;
  12. use Symfony\Component\Console\Input\InputInterface;
  13. use Symfony\Component\Console\Output\ConsoleOutputInterface;
  14. use Symfony\Component\Console\Output\OutputInterface;
  15. use Symfony\Component\Console\Helper\HelperSet;
  16. use Symfony\Component\Console\Question\ConfirmationQuestion;
  17. use Symfony\Component\Console\Question\Question;
  18. /**
  19. * The Input/Output helper.
  20. *
  21. * @author François Pluchino <francois.pluchino@opendisplay.com>
  22. * @author Jordi Boggiano <j.boggiano@seld.be>
  23. */
  24. class ConsoleIO extends BaseIO
  25. {
  26. protected $input;
  27. protected $output;
  28. protected $helperSet;
  29. protected $lastMessage;
  30. protected $lastMessageErr;
  31. private $startTime;
  32. /**
  33. * Constructor.
  34. *
  35. * @param InputInterface $input The input instance
  36. * @param OutputInterface $output The output instance
  37. * @param HelperSet $helperSet The helperSet instance
  38. */
  39. public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
  40. {
  41. $this->input = $input;
  42. $this->output = $output;
  43. $this->helperSet = $helperSet;
  44. }
  45. public function enableDebugging($startTime)
  46. {
  47. $this->startTime = $startTime;
  48. }
  49. /**
  50. * {@inheritDoc}
  51. */
  52. public function isInteractive()
  53. {
  54. return $this->input->isInteractive();
  55. }
  56. /**
  57. * {@inheritDoc}
  58. */
  59. public function isDecorated()
  60. {
  61. return $this->output->isDecorated();
  62. }
  63. /**
  64. * {@inheritDoc}
  65. */
  66. public function isVerbose()
  67. {
  68. return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
  69. }
  70. /**
  71. * {@inheritDoc}
  72. */
  73. public function isVeryVerbose()
  74. {
  75. return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
  76. }
  77. /**
  78. * {@inheritDoc}
  79. */
  80. public function isDebug()
  81. {
  82. return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
  83. }
  84. /**
  85. * {@inheritDoc}
  86. */
  87. public function write($messages, $newline = true)
  88. {
  89. $this->doWrite($messages, $newline, false);
  90. }
  91. /**
  92. * {@inheritDoc}
  93. */
  94. public function writeError($messages, $newline = true)
  95. {
  96. $this->doWrite($messages, $newline, true);
  97. }
  98. /**
  99. * @param array $messages
  100. * @param boolean $newline
  101. * @param boolean $stderr
  102. */
  103. private function doWrite($messages, $newline, $stderr)
  104. {
  105. if (null !== $this->startTime) {
  106. $memoryUsage = memory_get_usage() / 1024 / 1024;
  107. $timeSpent = microtime(true) - $this->startTime;
  108. $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
  109. return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
  110. }, (array) $messages);
  111. }
  112. if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
  113. $this->output->getErrorOutput()->write($messages, $newline);
  114. $this->lastMessageErr = join($newline ? "\n" : '', (array) $messages);
  115. return;
  116. }
  117. $this->output->write($messages, $newline);
  118. $this->lastMessage = join($newline ? "\n" : '', (array) $messages);
  119. }
  120. /**
  121. * {@inheritDoc}
  122. */
  123. public function overwrite($messages, $newline = true, $size = null)
  124. {
  125. $this->doOverwrite($messages, $newline, $size, false);
  126. }
  127. /**
  128. * {@inheritDoc}
  129. */
  130. public function overwriteError($messages, $newline = true, $size = null)
  131. {
  132. $this->doOverwrite($messages, $newline, $size, true);
  133. }
  134. /**
  135. * @param array $messages
  136. * @param boolean $newline
  137. * @param integer $size
  138. * @param boolean $stderr
  139. */
  140. private function doOverwrite($messages, $newline, $size, $stderr)
  141. {
  142. // messages can be an array, let's convert it to string anyway
  143. $messages = join($newline ? "\n" : '', (array) $messages);
  144. // since overwrite is supposed to overwrite last message...
  145. if (!isset($size)) {
  146. // removing possible formatting of lastMessage with strip_tags
  147. $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
  148. }
  149. // ...let's fill its length with backspaces
  150. $this->doWrite(str_repeat("\x08", $size), false, $stderr);
  151. // write the new message
  152. $this->doWrite($messages, false, $stderr);
  153. $fill = $size - strlen(strip_tags($messages));
  154. if ($fill > 0) {
  155. // whitespace whatever has left
  156. $this->doWrite(str_repeat(' ', $fill), false, $stderr);
  157. // move the cursor back
  158. $this->doWrite(str_repeat("\x08", $fill), false, $stderr);
  159. }
  160. if ($newline) {
  161. $this->doWrite('', true, $stderr);
  162. }
  163. if ($stderr) {
  164. $this->lastMessageErr = $messages;
  165. } else {
  166. $this->lastMessage = $messages;
  167. }
  168. }
  169. /**
  170. * {@inheritDoc}
  171. */
  172. public function ask($question, $default = null)
  173. {
  174. $output = $this->output;
  175. if ($output instanceof ConsoleOutputInterface) {
  176. $output = $output->getErrorOutput();
  177. }
  178. /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
  179. $helper = $this->helperSet->get('question');
  180. $question = new Question($question, $default);
  181. return $helper->ask($this->input, $output, $question);
  182. }
  183. /**
  184. * {@inheritDoc}
  185. */
  186. public function askConfirmation($question, $default = true)
  187. {
  188. $output = $this->output;
  189. if ($output instanceof ConsoleOutputInterface) {
  190. $output = $output->getErrorOutput();
  191. }
  192. /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
  193. $helper = $this->helperSet->get('question');
  194. $question = new ConfirmationQuestion($question, $default);
  195. return $helper->ask($this->input, $output, $question);
  196. }
  197. /**
  198. * {@inheritDoc}
  199. */
  200. public function askAndValidate($question, $validator, $attempts = null, $default = null)
  201. {
  202. $output = $this->output;
  203. if ($output instanceof ConsoleOutputInterface) {
  204. $output = $output->getErrorOutput();
  205. }
  206. /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
  207. $helper = $this->helperSet->get('question');
  208. $question = new Question($question, $default);
  209. $question->setValidator($validator);
  210. $question->setMaxAttempts($attempts);
  211. return $helper->ask($this->input, $output, $question);
  212. }
  213. /**
  214. * {@inheritDoc}
  215. */
  216. public function askAndHideAnswer($question)
  217. {
  218. $this->writeError($question, false);
  219. return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
  220. }
  221. }