Completed
Pull Request — master (#85)
by Greg
01:36
created

WordWrapper::setPaddingFromSymfony5Style()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
namespace Consolidation\OutputFormatters\Transformations;
3
4
use Consolidation\OutputFormatters\Transformations\Wrap\CalculateWidths;
5
use Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths;
6
use Symfony\Component\Console\Helper\TableStyle;
7
8
class WordWrapper
9
{
10
    protected $width;
11
    protected $minimumWidths;
12
13
    // For now, hardcode these to match what the Symfony Table helper does.
14
    // Note that these might actually need to be adjusted depending on the
15
    // table style.
16
    protected $extraPaddingAtBeginningOfLine = 0;
17
    protected $extraPaddingAtEndOfLine = 0;
18
    protected $paddingInEachCell = 3;
19
20
    public function __construct($width)
21
    {
22
        $this->width = $width;
23
        $this->minimumWidths = new ColumnWidths();
24
    }
25
26
    /**
27
     * Calculate our padding widths from the specified table style.
28
     * @param TableStyle $style
29
     */
30
    public function setPaddingFromStyle(TableStyle $style)
31
    {
32
        if (method_exists($style, 'getBorderChars')) {
33
            return $this->setPaddingFromSymfony5Style($style);
34
        }
35
36
        $verticalBorderLen = strlen(sprintf($style->getBorderFormat(), $style->getVerticalBorderChar()));
0 ignored issues
show
Bug introduced by
The method getVerticalBorderChar() does not exist on Symfony\Component\Console\Helper\TableStyle. Did you maybe mean setVerticalBorderChars()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
37
        $paddingLen = strlen($style->getPaddingChar());
38
39
        $this->extraPaddingAtBeginningOfLine = 0;
40
        $this->extraPaddingAtEndOfLine = $verticalBorderLen;
41
        $this->paddingInEachCell = $verticalBorderLen + $paddingLen + 1;
42
    }
43
44
    /**
45
     * Calculate our padding widths from the specified table style.
46
     * @param TableStyle $style
47
     */
48
    public function setPaddingFromSymfony5Style(TableStyle $style)
49
    {
50
        $borderChars = $style->getBorderChars();
51
        $verticalBorderChar = $borderChars[1];
52
        $verticalBorderLen = strlen(sprintf($style->getBorderFormat(), $verticalBorderChar));
53
        $paddingLen = strlen($style->getPaddingChar());
54
55
        $this->extraPaddingAtBeginningOfLine = 0;
56
        $this->extraPaddingAtEndOfLine = $verticalBorderLen;
57
        $this->paddingInEachCell = $verticalBorderLen + $paddingLen + 1;
58
    }
59
60
    /**
61
     * If columns have minimum widths, then set them here.
62
     * @param array $minimumWidths
63
     */
64
    public function setMinimumWidths($minimumWidths)
65
    {
66
        $this->minimumWidths = new ColumnWidths($minimumWidths);
67
    }
68
69
    /**
70
     * Set the minimum width of just one column
71
     */
72
    public function minimumWidth($colkey, $width)
73
    {
74
        $this->minimumWidths->setWidth($colkey, $width);
75
    }
76
77
    /**
78
     * Wrap the cells in each part of the provided data table
79
     * @param array $rows
80
     * @return array
81
     */
82
    public function wrap($rows, $widths = [])
83
    {
84
        $auto_widths = $this->calculateWidths($rows, $widths);
85
86
        // If no widths were provided, then disable wrapping
87
        if ($auto_widths->isEmpty()) {
88
            return $rows;
89
        }
90
91
        // Do wordwrap on all cells.
92
        $newrows = array();
93
        foreach ($rows as $rowkey => $row) {
94
            foreach ($row as $colkey => $cell) {
95
                $newrows[$rowkey][$colkey] = $this->wrapCell($cell, $auto_widths->width($colkey));
96
            }
97
        }
98
99
        return $newrows;
100
    }
101
102
    /**
103
     * Determine what widths we'll use for wrapping.
104
     */
105
    protected function calculateWidths($rows, $widths = [])
106
    {
107
        // Widths must be provided in some form or another, or we won't wrap.
108
        if (empty($widths) && !$this->width) {
109
            return new ColumnWidths();
110
        }
111
112
        // Technically, `$widths`, if provided here, should be used
113
        // as the exact widths to wrap to. For now we'll just treat
114
        // these as minimum widths
115
        $minimumWidths = $this->minimumWidths->combine(new ColumnWidths($widths));
116
117
        $calculator = new CalculateWidths();
118
        $dataCellWidths = $calculator->calculateLongestCell($rows);
119
120
        $availableWidth = $this->width - $dataCellWidths->paddingSpace($this->paddingInEachCell, $this->extraPaddingAtEndOfLine, $this->extraPaddingAtBeginningOfLine);
121
122
        $this->minimumWidths->adjustMinimumWidths($availableWidth, $dataCellWidths);
123
124
        return $calculator->calculate($availableWidth, $dataCellWidths, $minimumWidths);
125
    }
126
127
    /**
128
     * Wrap one cell.  Guard against modifying non-strings and
129
     * then call through to wordwrap().
130
     *
131
     * @param mixed $cell
132
     * @param string $cellWidth
133
     * @return mixed
134
     */
135
    protected function wrapCell($cell, $cellWidth)
136
    {
137
        if (!is_string($cell)) {
138
            return $cell;
139
        }
140
        return wordwrap($cell, $cellWidth, "\n", true);
141
    }
142
}
143