@@ -35,6 +35,9 @@ class Table
35
35
private const SEPARATOR_BOTTOM = 3 ;
36
36
private const BORDER_OUTSIDE = 0 ;
37
37
private const BORDER_INSIDE = 1 ;
38
+ private const DISPLAY_ORIENTATION_DEFAULT = 'default ' ;
39
+ private const DISPLAY_ORIENTATION_HORIZONTAL = 'horizontal ' ;
40
+ private const DISPLAY_ORIENTATION_VERTICAL = 'vertical ' ;
38
41
39
42
private ?string $ headerTitle = null ;
40
43
private ?string $ footerTitle = null ;
@@ -49,6 +52,7 @@ class Table
49
52
private array $ columnWidths = [];
50
53
private array $ columnMaxWidths = [];
51
54
private bool $ rendered = false ;
55
+ private string $ displayOrientation = self ::DISPLAY_ORIENTATION_DEFAULT ;
52
56
53
57
private static array $ styles ;
54
58
@@ -277,7 +281,14 @@ public function setFooterTitle(?string $title): static
277
281
*/
278
282
public function setHorizontal (bool $ horizontal = true ): static
279
283
{
280
- $ this ->horizontal = $ horizontal ;
284
+ $ this ->displayOrientation = $ horizontal ? self ::DISPLAY_ORIENTATION_HORIZONTAL : self ::DISPLAY_ORIENTATION_DEFAULT ;
285
+
286
+ return $ this ;
287
+ }
288
+
289
+ public function setVertical (bool $ vertical = true ): self
290
+ {
291
+ $ this ->displayOrientation = $ vertical ? self ::DISPLAY_ORIENTATION_VERTICAL : self ::DISPLAY_ORIENTATION_DEFAULT ;
281
292
282
293
return $ this ;
283
294
}
@@ -298,8 +309,13 @@ public function setHorizontal(bool $horizontal = true): static
298
309
public function render ()
299
310
{
300
311
$ divider = new TableSeparator ();
301
- if ($ this ->horizontal ) {
302
- $ rows = [];
312
+ $ isCellWithColspan = static fn ($ cell ): bool => $ cell instanceof TableCell && $ cell ->getColspan () >= 2 ;
313
+
314
+ $ horizontal = self ::DISPLAY_ORIENTATION_HORIZONTAL === $ this ->displayOrientation ;
315
+ $ vertical = self ::DISPLAY_ORIENTATION_VERTICAL === $ this ->displayOrientation ;
316
+
317
+ $ rows = [];
318
+ if ($ horizontal ) {
303
319
foreach ($ this ->headers [0 ] ?? [] as $ i => $ header ) {
304
320
$ rows [$ i ] = [$ header ];
305
321
foreach ($ this ->rows as $ row ) {
@@ -308,13 +324,42 @@ public function render()
308
324
}
309
325
if (isset ($ row [$ i ])) {
310
326
$ rows [$ i ][] = $ row [$ i ];
311
- } elseif ($ rows [ $ i ][ 0 ] instanceof TableCell && $ rows [$ i ][0 ]-> getColspan () >= 2 ) {
327
+ } elseif ($ isCellWithColspan ( $ rows [$ i ][0 ]) ) {
312
328
// Noop, there is a "title"
313
329
} else {
314
330
$ rows [$ i ][] = null ;
315
331
}
316
332
}
317
333
}
334
+ } elseif ($ vertical ) {
335
+ $ maxHeaderLength = array_reduce ($ this ->headers [0 ] ?? [], static fn (int $ max , string $ header ) => max ($ max , mb_strlen ($ header )), 0 );
336
+
337
+ foreach ($ this ->rows as $ row ) {
338
+ if ($ row instanceof TableSeparator) {
339
+ continue ;
340
+ }
341
+
342
+ if (0 < \count ($ rows )) {
343
+ $ rows [] = [$ divider ];
344
+ }
345
+
346
+ $ containsColspan = 0 < \count (array_filter ($ row , $ isCellWithColspan ));
347
+
348
+ $ headers = $ this ->headers [0 ] ?? [];
349
+ $ maxRows = max (\count ($ headers ), \count ($ row ));
350
+ for ($ i = 0 ; $ i < $ maxRows ; ++$ i ) {
351
+ $ cell = (string ) ($ row [$ i ] ?? '' );
352
+ if ([] !== $ headers && !$ containsColspan ) {
353
+ $ rows [] = [sprintf (
354
+ '<comment>%s</>: %s ' ,
355
+ str_pad ($ headers [$ i ] ?? '' , $ maxHeaderLength , ' ' , \STR_PAD_LEFT ),
356
+ $ cell
357
+ )];
358
+ } elseif (!empty ($ cell )) {
359
+ $ rows [] = [$ cell ];
360
+ }
361
+ }
362
+ }
318
363
} else {
319
364
$ rows = array_merge ($ this ->headers , [$ divider ], $ this ->rows );
320
365
}
@@ -324,8 +369,8 @@ public function render()
324
369
$ rows = $ this ->buildTableRows ($ rows );
325
370
$ this ->calculateColumnsWidth ($ rows );
326
371
327
- $ isHeader = !$ this -> horizontal ;
328
- $ isFirstRow = $ this -> horizontal ;
372
+ $ isHeader = !$ horizontal ;
373
+ $ isFirstRow = $ horizontal ;
329
374
$ hasTitle = (bool ) $ this ->headerTitle ;
330
375
foreach ($ rows as $ row ) {
331
376
if ($ divider === $ row ) {
@@ -352,7 +397,12 @@ public function render()
352
397
$ isFirstRow = false ;
353
398
$ hasTitle = false ;
354
399
}
355
- if ($ this ->horizontal ) {
400
+ if ($ vertical ) {
401
+ $ isHeader = false ;
402
+ $ isFirstRow = false ;
403
+ }
404
+
405
+ if ($ horizontal ) {
356
406
$ this ->renderRow ($ row , $ this ->style ->getCellRowFormat (), $ this ->style ->getCellHeaderFormat ());
357
407
} else {
358
408
$ this ->renderRow ($ row , $ isHeader ? $ this ->style ->getCellHeaderFormat () : $ this ->style ->getCellRowFormat ());
0 commit comments