Completed
Push — master ( b0d00a...787657 )
by Todd
08:33
created

Table::getFormatOutput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 3
ccs 1
cts 1
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
namespace Garden\Cli;
3
4
/**
5
 * Used to write a formatted table to the console.
6
 */
7
class Table {
8
    /// Properties ///
9
10
    /**
11
     * @var array An array of column widths.
12
     */
13
    protected $columnWidths;
14
15
    /**
16
     * @var bool Whether or not to format the console commands.
17
     */
18
    protected $formatOutput = true;
19
20
    /**
21
     * @var array An array of the row data.
22
     */
23
    protected $rows;
24
25
    /**
26
     * @var array|null A pointer to the current row.
27
     */
28
    protected $currentRow;
29
30
    /**
31
     * @var int The maximum width of the table.
32
     */
33
    public $maxWidth = 80;
34
35
    /**
36
     * @var int The left padding on each cell.
37
     */
38
    public $padding = 3;
39
40
    /**
41
     * @var int The left indent on the table.
42
     */
43
    public $indent = 2;
44
45
46
    /// Methods ///
47
48
    /**
49
     * Initialize an instance of the {@link Table} class.
50
     */
51 6
    public function __construct() {
52 6
        $this->formatOutput = Cli::guessFormatOutput();
53 6
        $this->reset();
54
    }
55
56
    /**
57
     * Backwards compatibility for the **format** property.
58
     *
59
     * @param string $name Must be **format**.
60
     * @return bool|null Returns {@link getFormatOutput()} or null if {@link $name} isn't **format**.
61
     */
62 6
    public function __get($name) {
63 6
        if ($name === 'format') {
64
            trigger_error("Cli->format is deprecated. Use Cli->getFormatOutput() instead.", E_USER_DEPRECATED);
65
            return $this->getFormatOutput();
66
        }
67 6
        return null;
68 6
    }
69
70 6
    /**
71 6
     * Backwards compatibility for the **format** property.
72
     *
73
     * @param string $name Must be **format**.
74
     * @param bool $value One of **true** or **false**.
75
     */
76
    public function __set($name, $value) {
77
        if ($name === 'format') {
78
            trigger_error("Cli->format is deprecated. Use Cli->setFormatOutput() instead.", E_USER_DEPRECATED);
79
            $this->setFormatOutput($value);
80 6
        }
81 6
    }
82
83
    /**
84
     * Get whether or not output should be formatted.
85
     *
86
     * @return boolean Returns **true** if output should be formatted or **false** otherwise.
87
     */
88
    public function getFormatOutput() {
89
        return $this->formatOutput;
90 3
    }
91 3
92
    /**
93
     * Set whether or not output should be formatted.
94
     *
95
     * @param boolean $formatOutput Whether or not to format output.
96
     * @return LogFormatter Returns `$this` for fluent calls.
97
     */
98
    public function setFormatOutput($formatOutput) {
99
        $this->formatOutput = $formatOutput;
100
        return $this;
101
    }
102
103
    /**
104
     * Add a cell to the table.
105
     *
106
     * @param string $text The text of the cell.
107
     * @param array $wrap A two element array used to wrap the text in the cell.
108
     * @return $this Returns this object for fluent calls.
109
     */
110
    protected function addCell($text, $wrap = ['', '']) {
111
        if ($this->currentRow === null) {
112
            $this->row();
113
        }
114
115
        $i = count($this->currentRow);
116
        $this->columnWidths[$i] = max(strlen($text), Cli::val($i, $this->columnWidths, 0)); // max column width
117
118
        $this->currentRow[$i] = [$text, $wrap];
119
        return $this;
120
    }
121
122
    /**
123
     * Adds a cell.
124
     *
125
     * @param string $text The text of the cell.
126
     * @return $this Returns this object for fluent calls.
127
     */
128
    public function cell($text) {
129
        return $this->addCell($text);
130
    }
131
132
    /**
133
     * Adds a bold cell.
134
     *
135
     * @param string $text The text of the cell.
136
     * @return $this Returns this object for fluent calls.
137 6
     */
138 6
    public function bold($text) {
139 6
        return $this->addCell($text, ["\033[1m", "\033[0m"]);
140 6
    }
141 6
142
    /**
143
     * Adds a red cell.
144
     *
145
     * @param string $text The text of the cell.
146
     * @return $this Returns this object for fluent calls.
147
     */
148 6
    public function red($text) {
149 6
        return $this->addCell($text, ["\033[1;31m", "\033[0m"]);
150 6
    }
151 6
152
    /**
153
     * Adds a green cell.
154
     *
155
     * @param string $text The text of the cell.
156
     * @return $this Returns this object for fluent calls.
157 6
     */
158
    public function green($text) {
159 6
        return $this->addCell($text, ["\033[1;32m", "\033[0m"]);
160 6
    }
161
162 6
    /**
163 6
     * Adds a blue cell.
164 6
     *
165
     * @param string $text The text of the cell.
166
     * @return $this Returns this object for fluent calls.
167 6
     */
168 6
    public function blue($text) {
169 6
        return $this->addCell($text, ["\033[1;34m", "\033[0m"]);
170
    }
171
172 6
    /**
173 6
     * Adds a purple cell.
174 6
     * 
175
     * @param string $text The text of the cell.
176 6
     * @return $this Returns this object for fluent calls.
177 6
     */
178 6
    public function purple($text) {
179 6
        return $this->addCell($text, ["\033[0;35m", "\033[0m"]);
180
    }
181
182 6
    /**
183 6
     * Reset the table so another one can be written with the same object.
184 6
     */
185
    public function reset() {
186 6
        $this->columnWidths = [];
187 6
        $this->rows = [];
188 6
        $this->currentRow = null;
189 6
    }
190
191 2
    /**
192
     * Start a new row.
193
     * 
194 6
     * @return $this Returns this object for fluent calls.
195 2
     */
196 2
    public function row() {
197 4
        $this->rows[] = [];
198
        $this->currentRow =& $this->rows[count($this->rows) - 1];
199 6
        return $this;
200
    }
201 2
202 2
    /**
203 6
     * Writes the final table.
204 6
     */
205 6
    public function write() {
206 6
        // Determine the width of the last column.
207 6
        $columnWidths = array_sum($this->columnWidths);
208
        $totalWidth = $this->indent + $columnWidths + $this->padding * (count($this->columnWidths) - 1);
209
210
        $lastWidth = end($this->columnWidths) + $this->maxWidth - $totalWidth;
211
        $lastWidth = max($lastWidth, 10); // min width of 10
212
        $this->columnWidths[count($this->columnWidths) - 1] = $lastWidth;
213
214
        // Loop through each row and write it.
215
        foreach ($this->rows as $row) {
216
            $rowLines = [];
217
            $lineCount = 0;
218
219
            // Split the cells into lines.
220
            foreach ($row as $i => $cell) {
221
                list($text,) = $cell;
222
                $width = $this->columnWidths[$i];
223
224
                $lines = Cli::breakLines($text, $width, $i < count($this->columnWidths) - 1);
225
                $rowLines[] = $lines;
226
                $lineCount = max($lineCount, count($lines));
227
            }
228
229
            // Write all of the lines.
230
            for ($i = 0; $i < $lineCount; $i++) {
231
                foreach ($rowLines as $j => $lines) {
232
                    $padding = $j === 0 ? $this->indent : $this->padding;
233
234
                    if (isset($lines[$i])) {
235
                        if(isset($row[$i])) {
236
                            $wrap = $row[$i][1];
237
                        } else {
238
                            // if we're out of array, use the latest wraps
239
                            $wrap = $row[count($row)-1][1];
240
                        }
241
242
                        if ($this->formatOutput) {
243
                            echo str_repeat(' ', $padding).$wrap[0].$lines[$i].$wrap[1];
244
                        } else {
245
                            echo str_repeat(' ', $padding).$lines[$i];
246
                        }
247
                    } elseif ($j < count($this->columnWidths) - 1) {
248
                        // This is an empty line. Write the spaces.
249
                        echo str_repeat(' ', $padding + $this->columnWidths[$j]);
250
                    }
251
                }
252
                echo PHP_EOL;
253
            }
254
        }
255
    }
256
}
257