Completed
Push — master ( a023d8...1a91bf )
by Craig
01:41
created

Table::addLine()   A

Complexity

Conditions 1
Paths 1

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 4
Code Lines 2

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
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 28
    /**
54
     * @var string $pregix A string to be output before each row is output.
55 28
     */
56 28
    private $prefix = "";
57
58
59
    public function __construct(array $data, $prefix = "")
60
    {
61
        $this->data = $data;
62
        $this->prefix = $prefix;
63 28
    }
64
65 28
    /**
66 28
     * Return the built rows
67 28
     *
68
     * @return array
69 28
     */
70
    public function result()
71 28
    {
72 28
        $this->column_widths = $this->getColumnWidths();
73 28
        $this->table_width   = $this->getWidth();
74 28
        $this->border        = $this->getBorder();
75
76 28
        $this->buildHeaderRow();
77
78
        foreach ($this->data as $key => $columns) {
79
            $this->addLine($this->buildRow($columns));
80
            $this->addLine($this->border);
81
        }
82
83
        return $this->rows;
84 28
    }
85
86 28
    /**
87 28
     * Append a line to the output.
88
     *
89 28
     * @param string $line The line to output
90
     *
91
     * @return void
92
     */
93
    private function addLine($line)
94
    {
95 28
        $this->rows[] = $this->prefix . $line;
96
    }
97 28
98
99
    /**
100
     * Determine the width of the table
101
     *
102
     * @return integer
103
     */
104 28
    protected function getWidth()
105
    {
106 28
        $first_row = reset($this->data);
107
        $first_row = $this->buildRow($first_row);
108 28
109 24
        return $this->lengthWithoutTags($first_row);
110 24
    }
111 24
112 24
    /**
113 4
     * Get the border for each row based on the table width
114
     */
115 28
    protected function getBorder()
116
    {
117
        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 28
    protected function buildHeaderRow()
125
    {
126 28
        $this->addLine($this->border);
127
128 28
        $header_row = $this->getHeaderRow();
129 28
        if ($header_row) {
130 28
            $this->addLine($this->buildRow($header_row));
131
            $this->addLine((new Border)->char('=')->length($this->table_width)->result());
132 28
        }
133
    }
134 28
135
    /**
136
     * Get table row
137
     *
138
     * @param  mixed  $columns
139
     *
140
     * @return string
141
     */
142
    protected function buildRow($columns)
143
    {
144
        $row = [];
145 28
146
        foreach ($columns as $key => $column) {
147 28
            $row[] = $this->buildCell($key, $column);
148
        }
149
150
        $row = implode($this->column_divider, $row);
151
152
        return trim($this->column_divider . $row . $this->column_divider);
153
    }
154
155 28
    /**
156
     * Build the string for this particular table cell
157 28
     *
158
     * @param  mixed  $key
159 28
     * @param  string $column
160 4
     *
161 4
     * @return string
162
     */
163 28
    protected function buildCell($key, $column)
164 28
    {
165
        return  $this->pad($column, $this->column_widths[$key]);
166
    }
167 28
168 24
    /**
169
     * Get the header row for the table if it's an associative array or object
170
     *
171 4
     * @return mixed
172
     */
173
    protected function getHeaderRow()
174
    {
175
        $first_item = reset($this->data);
176
177
        if (is_object($first_item)) {
178
            $first_item = get_object_vars($first_item);
179 28
        }
180
181 28
        $keys       = array_keys($first_item);
182
        $first_key  = reset($keys);
183 28
184 4
        // We have an associative array (probably), let's have a header row
185 4
        if (!is_int($first_key)) {
186
            return array_combine($keys, $keys);
187
        }
188 28
189
        return false;
190 28
    }
191 28
192 28
    /**
193 28
     * Determine the width of each column
194 28
     *
195
     * @return array
196 28
     */
197
    protected function getColumnWidths()
198
    {
199
        $first_row = reset($this->data);
200
201
        if (is_object($first_row)) {
202
            $first_row = get_object_vars($first_row);
203
        }
204
205
        // Create an array with the columns as keys and values of zero
206 28
        $column_widths = $this->getDefaultColumnWidths($first_row);
207
208 28
        foreach ($this->data as $columns) {
209
            foreach ($columns as $key => $column) {
210 28
                $column_widths[$key] = $this->getCellWidth($column_widths[$key], $column);
211
            }
212
        }
213
214
        return $column_widths;
215
    }
216
217
    /**
218
     * Set up an array of default column widths
219
     *
220
     * @param array $columns
221 28
     *
222
     * @return array
223 28
     */
224
    protected function getDefaultColumnWidths(array $columns)
225
    {
226
        $widths = $this->arrayOfStrLens(array_keys($columns));
227
228
        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
    protected function getCellWidth($current_width, $str)
240
    {
241
        return max($current_width, $this->lengthWithoutTags($str));
242
    }
243
}
244