Completed
Push — version-4-wip ( 38f335 )
by Craig
03:27
created

Table::getDefaultColumnWidths()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace League\CLImate\TerminalObject\Basic;
4
5
use League\CLImate\TerminalObject\Helper\StringLength;
6
7
class Table extends BasicTerminalObject
8
{
9
    use StringLength;
10
11
    /**
12
     * The data for the table, an array of (arrays|objects)
13
     *
14
     * @var array $data
15
     */
16
    protected $data           = [];
17
18
    /**
19
     * An array of the widths of each column in the table
20
     *
21
     * @var array $column_widths
22
     */
23
    protected $column_widths  = [];
24
25
    /**
26
     * The width of the table
27
     *
28
     * @var integer $table_width
29
     */
30
    protected $table_width    = 0;
31
32
    /**
33
     * The divider between table cells
34
     *
35
     * @var string $column_divider
36
     */
37
    protected $column_divider = ' | ';
38
39
    /**
40
     * The border to divide each row of the table
41
     *
42
     * @var string $border
43
     */
44
    protected $border;
45
46
    /**
47
     * The array of rows that will ultimately be returned
48
     *
49
     * @var array $rows
50
     */
51
    protected $rows           = [];
52
53
    /**
54
     * @var string $pregix A string to be output before each row is output.
55
     */
56
    private $prefix = "";
57
58
59 32
    public function __construct(array $data, $prefix = "")
60
    {
61 32
        $this->data = $data;
62 32
        $this->prefix = $prefix;
63 32
    }
64
65
    /**
66
     * Return the built rows
67
     *
68
     * @return array
69
     */
70 32
    public function result()
71
    {
72 32
        $this->column_widths = $this->getColumnWidths();
73 32
        $this->table_width   = $this->getWidth();
74 32
        $this->border        = $this->getBorder();
75
76 32
        $this->buildHeaderRow();
77
78 32
        foreach ($this->data as $key => $columns) {
79 32
            $this->addLine($this->buildRow($columns));
80 32
            $this->addLine($this->border);
81 16
        }
82
83 32
        return $this->rows;
84
    }
85
86
    /**
87
     * Append a line to the output.
88
     *
89
     * @param string $line The line to output
90
     *
91
     * @return void
92
     */
93 32
    private function addLine($line)
94
    {
95 32
        $this->rows[] = $this->prefix . $line;
96 32
    }
97
98
99
    /**
100
     * Determine the width of the table
101
     *
102
     * @return integer
103
     */
104 32
    protected function getWidth()
105
    {
106 32
        $first_row = reset($this->data);
107 32
        $first_row = $this->buildRow($first_row);
108
109 32
        return $this->lengthWithoutTags($first_row);
110
    }
111
112
    /**
113
     * Get the border for each row based on the table width
114
     */
115 32
    protected function getBorder()
116
    {
117 32
        return (new Border())->length($this->table_width)->result();
118
    }
119
120
    /**
121
     * Check for a header row (if it's an array of associative arrays or objects),
122
     * if there is one, tack it onto the front of the rows array
123
     */
124 32
    protected function buildHeaderRow()
125
    {
126 32
        $this->addLine($this->border);
127
128 32
        $header_row = $this->getHeaderRow();
129 32
        if ($header_row) {
130 28
            $this->addLine($this->buildRow($header_row));
131 28
            $this->addLine((new Border)->char('=')->length($this->table_width)->result());
132 14
        }
133 32
    }
134
135
    /**
136
     * Get table row
137
     *
138
     * @param  mixed  $columns
139
     *
140
     * @return string
141
     */
142 32
    protected function buildRow($columns)
143
    {
144 32
        $row = [];
145
146 32
        foreach ($columns as $key => $column) {
147 32
            $row[] = $this->buildCell($key, $column);
148 16
        }
149
150 32
        $row = implode($this->column_divider, $row);
151
152 32
        return trim($this->column_divider . $row . $this->column_divider);
153
    }
154
155
    /**
156
     * Build the string for this particular table cell
157
     *
158
     * @param  mixed  $key
159
     * @param  string $column
160
     *
161
     * @return string
162
     */
163 32
    protected function buildCell($key, $column)
164
    {
165 32
        return  $this->pad($column, $this->column_widths[$key]);
166
    }
167
168
    /**
169
     * Get the header row for the table if it's an associative array or object
170
     *
171
     * @return mixed
172
     */
173 32
    protected function getHeaderRow()
174
    {
175 32
        $first_item = reset($this->data);
176
177 32
        if (is_object($first_item)) {
178 4
            $first_item = get_object_vars($first_item);
179 2
        }
180
181 32
        $keys       = array_keys($first_item);
182 32
        $first_key  = reset($keys);
183
184
        // We have an associative array (probably), let's have a header row
185 32
        if (!is_int($first_key)) {
186 28
            return array_combine($keys, $keys);
187
        }
188
189 4
        return false;
190
    }
191
192
    /**
193
     * Determine the width of each column
194
     *
195
     * @return array
196
     */
197 32
    protected function getColumnWidths()
198
    {
199 32
        $first_row = reset($this->data);
200
201 32
        if (is_object($first_row)) {
202 4
            $first_row = get_object_vars($first_row);
203 2
        }
204
205
        // Create an array with the columns as keys and values of zero
206 32
        $column_widths = $this->getDefaultColumnWidths($first_row);
207
208 32
        foreach ($this->data as $columns) {
209 32
            foreach ($columns as $key => $column) {
210 32
                $column_widths[$key] = $this->getCellWidth($column_widths[$key], $column);
211 16
            }
212 16
        }
213
214 32
        return $column_widths;
215
    }
216
217
    /**
218
     * Set up an array of default column widths
219
     *
220
     * @param array $columns
221
     *
222
     * @return array
223
     */
224 32
    protected function getDefaultColumnWidths(array $columns)
225
    {
226 32
        $widths = $this->arrayOfStrLens(array_keys($columns));
227
228 32
        return array_combine(array_keys($columns), $widths);
229
    }
230
231
    /**
232
     * Determine the width of the columns without tags
233
     *
234
     * @param array  $current_width
235
     * @param string $str
236
     *
237
     * @return integer
238
     */
239 32
    protected function getCellWidth($current_width, $str)
240
    {
241 32
        return max($current_width, $this->lengthWithoutTags($str));
242
    }
243
}
244