View file vendor/symfony/console/Output/ConsoleOutput.php

File size: 4.78Kb
  1. <?php
  2.  
  3. /*
  4. * This file is part of the Symfony package.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11.  
  12. namespace Symfony\Component\Console\Output;
  13.  
  14. use Symfony\Component\Console\Formatter\OutputFormatterInterface;
  15.  
  16. /**
  17. * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.
  18. *
  19. * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR.
  20. *
  21. * $output = new ConsoleOutput();
  22. *
  23. * This is equivalent to:
  24. *
  25. * $output = new StreamOutput(fopen('php://stdout', 'w'));
  26. * $stdErr = new StreamOutput(fopen('php://stderr', 'w'));
  27. *
  28. * @author Fabien Potencier <fabien@symfony.com>
  29. */
  30. class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
  31. {
  32. private $stderr;
  33. private array $consoleSectionOutputs = [];
  34.  
  35. /**
  36. * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
  37. * @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
  38. * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
  39. */
  40. public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
  41. {
  42. parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
  43.  
  44. if (null === $formatter) {
  45. // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter.
  46. $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated);
  47.  
  48. return;
  49. }
  50.  
  51. $actualDecorated = $this->isDecorated();
  52. $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
  53.  
  54. if (null === $decorated) {
  55. $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
  56. }
  57. }
  58.  
  59. /**
  60. * Creates a new output section.
  61. */
  62. public function section(): ConsoleSectionOutput
  63. {
  64. return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter());
  65. }
  66.  
  67. /**
  68. * {@inheritdoc}
  69. */
  70. public function setDecorated(bool $decorated)
  71. {
  72. parent::setDecorated($decorated);
  73. $this->stderr->setDecorated($decorated);
  74. }
  75.  
  76. /**
  77. * {@inheritdoc}
  78. */
  79. public function setFormatter(OutputFormatterInterface $formatter)
  80. {
  81. parent::setFormatter($formatter);
  82. $this->stderr->setFormatter($formatter);
  83. }
  84.  
  85. /**
  86. * {@inheritdoc}
  87. */
  88. public function setVerbosity(int $level)
  89. {
  90. parent::setVerbosity($level);
  91. $this->stderr->setVerbosity($level);
  92. }
  93.  
  94. /**
  95. * {@inheritdoc}
  96. */
  97. public function getErrorOutput(): OutputInterface
  98. {
  99. return $this->stderr;
  100. }
  101.  
  102. /**
  103. * {@inheritdoc}
  104. */
  105. public function setErrorOutput(OutputInterface $error)
  106. {
  107. $this->stderr = $error;
  108. }
  109.  
  110. /**
  111. * Returns true if current environment supports writing console output to
  112. * STDOUT.
  113. */
  114. protected function hasStdoutSupport(): bool
  115. {
  116. return false === $this->isRunningOS400();
  117. }
  118.  
  119. /**
  120. * Returns true if current environment supports writing console output to
  121. * STDERR.
  122. */
  123. protected function hasStderrSupport(): bool
  124. {
  125. return false === $this->isRunningOS400();
  126. }
  127.  
  128. /**
  129. * Checks if current executing environment is IBM iSeries (OS400), which
  130. * doesn't properly convert character-encodings between ASCII to EBCDIC.
  131. */
  132. private function isRunningOS400(): bool
  133. {
  134. $checks = [
  135. \function_exists('php_uname') ? php_uname('s') : '',
  136. getenv('OSTYPE'),
  137. \PHP_OS,
  138. ];
  139.  
  140. return false !== stripos(implode(';', $checks), 'OS400');
  141. }
  142.  
  143. /**
  144. * @return resource
  145. */
  146. private function openOutputStream()
  147. {
  148. if (!$this->hasStdoutSupport()) {
  149. return fopen('php://output', 'w');
  150. }
  151.  
  152. // Use STDOUT when possible to prevent from opening too many file descriptors
  153. return \defined('STDOUT') ? \STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w'));
  154. }
  155.  
  156. /**
  157. * @return resource
  158. */
  159. private function openErrorStream()
  160. {
  161. if (!$this->hasStderrSupport()) {
  162. return fopen('php://output', 'w');
  163. }
  164.  
  165. // Use STDERR when possible to prevent from opening too many file descriptors
  166. return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w'));
  167. }
  168. }