Skip to content

Commit fd910eb

Browse files
committed
bug #39160 [Console] Use a partial buffer in SymfonyStyle (jderusse)
This PR was merged into the 4.4 branch. Discussion ---------- [Console] Use a partial buffer in SymfonyStyle | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #39156 | License | MIT | Doc PR | - Symfony style needs to buffer output in order to get the last 2 chars in order to prepend Block. By using a `BufferedOutput` symfony bufferize everything while it not needed. This PR adds a new `TrimmedBufferOutput` that keep only the N last chars. Commits ------- 18fca29 Use a partial buffer in SymfonyStyle
2 parents fb161ec + 18fca29 commit fd910eb

File tree

3 files changed

+86
-5
lines changed

3 files changed

+86
-5
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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\Exception\InvalidArgumentException;
15+
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
16+
17+
/**
18+
* A BufferedOutput that keeps only the last N chars.
19+
*
20+
* @author Jérémy Derussé <jeremy@derusse.com>
21+
*/
22+
class TrimmedBufferOutput extends Output
23+
{
24+
private $maxLength;
25+
private $buffer = '';
26+
27+
public function __construct(
28+
?int $verbosity = self::VERBOSITY_NORMAL,
29+
bool $decorated = false,
30+
OutputFormatterInterface $formatter = null,
31+
int $maxLength
32+
) {
33+
if ($maxLength <= 0) {
34+
throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength));
35+
}
36+
37+
parent::__construct($verbosity, $decorated, $formatter);
38+
$this->maxLength = $maxLength;
39+
}
40+
41+
/**
42+
* Empties buffer and returns its content.
43+
*
44+
* @return string
45+
*/
46+
public function fetch()
47+
{
48+
$content = $this->buffer;
49+
$this->buffer = '';
50+
51+
return $content;
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
protected function doWrite($message, $newline)
58+
{
59+
$this->buffer .= $message;
60+
61+
if ($newline) {
62+
$this->buffer .= \PHP_EOL;
63+
}
64+
65+
$this->buffer = substr($this->buffer, 0 - $this->maxLength);
66+
}
67+
}

src/Symfony/Component/Console/Style/SymfonyStyle.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
use Symfony\Component\Console\Helper\TableCell;
2222
use Symfony\Component\Console\Helper\TableSeparator;
2323
use Symfony\Component\Console\Input\InputInterface;
24-
use Symfony\Component\Console\Output\BufferedOutput;
2524
use Symfony\Component\Console\Output\OutputInterface;
25+
use Symfony\Component\Console\Output\TrimmedBufferOutput;
2626
use Symfony\Component\Console\Question\ChoiceQuestion;
2727
use Symfony\Component\Console\Question\ConfirmationQuestion;
2828
use Symfony\Component\Console\Question\Question;
@@ -46,7 +46,7 @@ class SymfonyStyle extends OutputStyle
4646
public function __construct(InputInterface $input, OutputInterface $output)
4747
{
4848
$this->input = $input;
49-
$this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
49+
$this->bufferedOutput = new TrimmedBufferOutput($output->getVerbosity(), false, clone $output->getFormatter(), \DIRECTORY_SEPARATOR === '\\' ? 4 : 2);
5050
// Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
5151
$width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
5252
$this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
@@ -449,9 +449,8 @@ private function autoPrependText(): void
449449

450450
private function writeBuffer(string $message, bool $newLine, int $type): void
451451
{
452-
// We need to know if the two last chars are PHP_EOL
453-
// Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
454-
$this->bufferedOutput->write(substr($message, -4), $newLine, $type);
452+
// We need to know if the last chars are PHP_EOL
453+
$this->bufferedOutput->write($message, $newLine, $type);
455454
}
456455

457456
private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array

src/Symfony/Component/Console/Tests/Style/SymfonyStyleTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Console\Command\Command;
1616
use Symfony\Component\Console\Formatter\OutputFormatter;
17+
use Symfony\Component\Console\Input\ArrayInput;
1718
use Symfony\Component\Console\Input\InputInterface;
1819
use Symfony\Component\Console\Output\ConsoleOutputInterface;
20+
use Symfony\Component\Console\Output\NullOutput;
1921
use Symfony\Component\Console\Output\OutputInterface;
2022
use Symfony\Component\Console\Style\SymfonyStyle;
2123
use Symfony\Component\Console\Tester\CommandTester;
@@ -115,4 +117,17 @@ public function testGetErrorStyleUsesTheCurrentOutputIfNoErrorOutputIsAvailable(
115117

116118
$this->assertInstanceOf(SymfonyStyle::class, $style->getErrorStyle());
117119
}
120+
121+
public function testMemoryConsumption()
122+
{
123+
$io = new SymfonyStyle(new ArrayInput([]), new NullOutput());
124+
$str = 'teststr';
125+
$io->writeln($str, SymfonyStyle::VERBOSITY_QUIET);
126+
$start = memory_get_usage();
127+
for ($i = 0; $i < 100; ++$i) {
128+
$io->writeln($str, SymfonyStyle::VERBOSITY_QUIET);
129+
}
130+
131+
$this->assertSame(0, memory_get_usage() - $start);
132+
}
118133
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy