Completed
Pull Request — master (#55)
by Greg
02:17
created

WordWrapper::minimumWidth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 2
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
        $verticalBorderLen = strlen(sprintf($style->getBorderFormat(), $style->getVerticalBorderChar()));
33
        $paddingLen = strlen($style->getPaddingChar());
34
35
        $this->extraPaddingAtBeginningOfLine = 0;
36
        $this->extraPaddingAtEndOfLine = $verticalBorderLen;
37
        $this->paddingInEachCell = $verticalBorderLen + $paddingLen + 1;
38
    }
39
40
    /**
41
     * If columns have minimum widths, then set them here.
42
     * @param array $minimumWidths
43
     */
44
    public function setMinimumWidths($minimumWidths)
45
    {
46
        $this->minimumWidths = new ColumnWidths($minimumWidths);
47
    }
48
49
    /**
50
     * Set the minimum width of just one column
51
     */
52
    public function minimumWidth($colkey, $width)
53
    {
54
        $this->minimumWidths->setWidth($colkey, $width);
55
    }
56
57
    /**
58
     * Wrap the cells in each part of the provided data table
59
     * @param array $rows
60
     * @return array
61
     */
62
    public function wrap($rows, $widths = [])
63
    {
64
        $auto_widths = $this->calculateWidths($rows, $widths);
65
66
        // If no widths were provided, then disable wrapping
67
        if ($auto_widths->isEmpty()) {
68
            return $rows;
69
        }
70
71
        // Do wordwrap on all cells.
72
        $newrows = array();
73
        foreach ($rows as $rowkey => $row) {
74
            foreach ($row as $colkey => $cell) {
75
                $newrows[$rowkey][$colkey] = $this->wrapCell($cell, $auto_widths->width($colkey));
76
            }
77
        }
78
79
        return $newrows;
80
    }
81
82
    /**
83
     * Determine what widths we'll use for wrapping.
84
     */
85
    protected function calculateWidths($rows, $widths = [])
86
    {
87
        // Widths must be provided in some form or another, or we won't wrap.
88
        if (empty($widths) && !$this->width) {
89
            return new ColumnWidths();
90
        }
91
92
        // Technically, `$widths`, if provided here, should be used
93
        // as the exact widths to wrap to. For now we'll just treat
94
        // these as minimum widths
95
        $minimumWidths = $this->minimumWidths->combine(new ColumnWidths($widths));
96
97
        $calculator = new CalculateWidths();
98
        $dataCellWidths = $calculator->calculateLongestCell($rows);
99
100
        $availableWidth = $this->width - $dataCellWidths->paddingSpace($this->paddingInEachCell, $this->extraPaddingAtEndOfLine, $this->extraPaddingAtBeginningOfLine);
101
102
        $this->minimumWidths->adjustMinimumWidths($availableWidth, $dataCellWidths);
103
104
        return $calculator->calculate($availableWidth, $dataCellWidths, $minimumWidths);
105
    }
106
107
    /**
108
     * Wrap one cell.  Guard against modifying non-strings and
109
     * then call through to wordwrap().
110
     *
111
     * @param mixed $cell
112
     * @param string $cellWidth
113
     * @return mixed
114
     */
115
    protected function wrapCell($cell, $cellWidth)
116
    {
117
        if (!is_string($cell)) {
118
            return $cell;
119
        }
120
        return wordwrap($cell, $cellWidth, "\n", true);
121
    }
122
}
123