Skip to content

Commit 8dae222

Browse files
committed
Table console output
1 parent 590279c commit 8dae222

File tree

4 files changed

+173
-7
lines changed

4 files changed

+173
-7
lines changed

lib/Core/Pipeline.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function __invoke(): Generator
3636
if (false === $response instanceof Signal && false === is_array($response)) {
3737
throw new InvalidYieldedValue(sprintf(
3838
'All yielded values must be arrays or Signals, got "%s"',
39-
gettype($data)
39+
gettype($response)
4040
));
4141
}
4242

lib/Extension/Console/ConsoleExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpBench\Pipeline\Core\PipelineExtension;
66
use PhpBench\Pipeline\Core\Stage;
77
use PhpBench\Pipeline\Extension\Console\Stage\Redraw;
8+
use PhpBench\Pipeline\Extension\Console\Stage\Table;
89

910
class ConsoleExtension implements PipelineExtension
1011
{
@@ -17,6 +18,7 @@ public function __construct()
1718
{
1819
$this->stages = [
1920
'console/redraw' => new Redraw(),
21+
'console/table' => new Table(),
2022
];
2123
}
2224

lib/Extension/Console/Stage/Table.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace PhpBench\Pipeline\Extension\Console\Stage;
4+
5+
use PhpBench\Pipeline\Core\Stage;
6+
use Generator;
7+
use PhpBench\Pipeline\Core\Schema;
8+
use PhpBench\Pipeline\Extension\Console\Util\ConsoleUtil;
9+
10+
class Table implements Stage
11+
{
12+
private const PADDING = 1;
13+
14+
public function __invoke(): Generator
15+
{
16+
list($config, $data) = yield;
17+
18+
while (true) {
19+
$table = (array) $data;
20+
21+
foreach ($table as &$row) {
22+
$row = (array) $row;
23+
24+
foreach ($row as &$value) {
25+
if (is_scalar($value)) {
26+
continue;
27+
}
28+
29+
$value = json_encode($value);
30+
}
31+
}
32+
33+
$headers = $this->headers($table);
34+
$separator = $this->separatorRow($headers);
35+
array_unshift($table, $separator);
36+
array_unshift($table, $headers);
37+
38+
$widths = $this->widths($table);
39+
$table = $this->table($table, $widths);
40+
41+
42+
list($config, $data) = yield [ implode(PHP_EOL, $table) ];
43+
}
44+
}
45+
46+
private function headers(array $table): array
47+
{
48+
foreach ($table as $row) {
49+
return array_keys($row);
50+
}
51+
52+
return [];
53+
}
54+
55+
private function widths(array $table): array
56+
{
57+
$widths = [];
58+
59+
foreach ($table as $row) {
60+
foreach (array_values($row) as $colNumber => $value) {
61+
$width = mb_strlen($value) + self::PADDING;
62+
if (false === isset($widths[$colNumber]) || $widths[$colNumber] < $width) {
63+
$widths[$colNumber] = $width;
64+
}
65+
}
66+
}
67+
68+
return $widths;
69+
}
70+
71+
private function separatorRow(array $headers): array
72+
{
73+
return array_map(function ($header) {
74+
return str_repeat('-', iconv_strlen($header));
75+
}, $headers);
76+
}
77+
78+
private function table(array $data, array $widths): array
79+
{
80+
$table = [];
81+
foreach ($data as $row) {
82+
$tableRow = [];
83+
84+
foreach (array_values($row) as $colNumber => $value) {
85+
$width = $widths[$colNumber];
86+
$tableRow[] = ConsoleUtil::pad($value, $width);
87+
}
88+
89+
$table[] = implode('', $tableRow);
90+
}
91+
92+
return $table;
93+
}
94+
95+
public function configure(Schema $schema)
96+
{
97+
}
98+
}

tests/Unit/Extension/Console/Stage/TableTest.php

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,85 @@ public function testTransformsInputIntoATable(array $input, string $expected)
1414
$pipeline = $this->pipeline()
1515
->stage('console/table');
1616

17-
$output = $pipeline->run($input);
17+
$output = $pipeline->build()->generator($input)->current();
1818

19-
$this->assertEquals($expected, $output);
19+
$this->assertEquals([ $expected ], $output);
2020
}
2121

2222
public function provideTransformsInputIntoATable()
2323
{
24-
yield 'single array element' => [
24+
yield 'from single array element' => [
2525
[ 'hallo' ],
2626
<<<EOT
27-
0
28-
-----
29-
hallo
27+
0
28+
-
29+
hallo
30+
EOT
31+
];
32+
33+
yield 'from single array element with key' => [
34+
[ 'tchuss' => 'hallo' ],
35+
<<<EOT
36+
0
37+
-
38+
hallo
39+
EOT
40+
];
41+
42+
yield 'from single row, single column' => [
43+
[
44+
[ 'tchuss' => 'hallo' ],
45+
],
46+
<<<EOT
47+
tchuss
48+
------
49+
hallo
50+
EOT
51+
];
52+
53+
yield 'from single row, multiple columns' => [
54+
[
55+
[ 'tchuss' => 'hallo', 'ciao' => 'goodbye' ],
56+
],
57+
<<<EOT
58+
tchuss ciao
59+
------ ----
60+
hallo goodbye
61+
EOT
62+
];
63+
64+
yield 'from multiple rows, multiple columns' => [
65+
[
66+
[ 'tchuss' => 'hallo', 'ciao' => 'goodbye' ],
67+
[ 'tchuss' => 'bienvenu', 'ciao' => 'aurevoir' ],
68+
],
69+
<<<EOT
70+
tchuss ciao
71+
------ ----
72+
hallo goodbye
73+
bienvenu aurevoir
74+
EOT
75+
];
76+
77+
yield 'where header longer than value' => [
78+
[
79+
[ 'this is a header' => 'value' ],
80+
],
81+
<<<EOT
82+
this is a header
83+
----------------
84+
value
85+
EOT
86+
];
87+
88+
yield 'non-scalar value' => [
89+
[
90+
[ 'blah' => ['value'] ],
91+
],
92+
<<<EOT
93+
blah
94+
----
95+
["value"]
3096
EOT
3197
];
3298
}

0 commit comments

Comments
 (0)