1 | <?php |
||
7 | class Table |
||
8 | { |
||
9 | /** |
||
10 | * Holds all content rows |
||
11 | * |
||
12 | * @var array |
||
13 | */ |
||
14 | protected $rows; |
||
15 | |||
16 | /** |
||
17 | * Holds all header cells |
||
18 | * |
||
19 | * @var array |
||
20 | */ |
||
21 | protected $header; |
||
22 | |||
23 | /** |
||
24 | * Attributes for the table |
||
25 | * |
||
26 | * @var array |
||
27 | */ |
||
28 | protected $attributes; |
||
29 | |||
30 | /** |
||
31 | * Table's caption |
||
32 | * |
||
33 | * @var string |
||
34 | */ |
||
35 | protected $caption; |
||
36 | |||
37 | /** |
||
38 | * Prepare a table |
||
39 | * |
||
40 | * @param array|null $header |
||
41 | * @param array|null $rows |
||
42 | * @param array $attributes |
||
43 | * @param string|null $caption |
||
44 | */ |
||
45 | 63 | public function __construct($header = null, $rows = null, $attributes = [], $caption = null) |
|
52 | |||
53 | /** |
||
54 | * Set the header |
||
55 | * |
||
56 | * @param array $header |
||
57 | */ |
||
58 | 63 | public function setHeader(array $header) |
|
62 | |||
63 | /** |
||
64 | * Set the rows |
||
65 | * |
||
66 | * @param array $content |
||
67 | */ |
||
68 | 63 | public function setRows(array $content) |
|
72 | |||
73 | /** |
||
74 | * Set the attributes |
||
75 | * |
||
76 | * @param array $attributes |
||
77 | */ |
||
78 | 63 | public function setAttributes(array $attributes) |
|
82 | |||
83 | /** |
||
84 | * Set the caption |
||
85 | * |
||
86 | * @param $caption |
||
87 | */ |
||
88 | 63 | public function setCaption($caption) |
|
92 | |||
93 | /** |
||
94 | * Render the whole table |
||
95 | * |
||
96 | * @return string |
||
97 | */ |
||
98 | 15 | public function render() |
|
99 | { |
||
100 | 15 | $has_header = count($this->header); |
|
101 | 15 | $has_rows = count($this->rows); |
|
102 | |||
103 | 15 | $this->prepareTableClasses($has_header); |
|
104 | |||
105 | 15 | $output = '<table' . $this->attributes($this->attributes) . ">\n"; |
|
106 | |||
107 | 15 | if (isset($this->caption)) { |
|
108 | 3 | $output .= '<caption>' . $this->caption . "</caption>\n"; |
|
109 | } |
||
110 | |||
111 | // Format the table header: |
||
112 | 15 | if ($has_header) { |
|
113 | 9 | $output .= $this->themeTableHead($has_rows); |
|
114 | } |
||
115 | |||
116 | 15 | $footer_rows = ''; |
|
117 | |||
118 | // Format the table rows: |
||
119 | 15 | if ($has_rows) { |
|
120 | 6 | $output .= "<tbody>\n"; |
|
121 | 6 | foreach ($this->rows as $row) { |
|
122 | 6 | $rendered = $this->themeTableRow($row); |
|
123 | 6 | if (array_key_exists('footer', $row) && $row['footer'] == true) { |
|
124 | 3 | $footer_rows .= $rendered; |
|
125 | } else { |
||
126 | 6 | $output .= $rendered; |
|
127 | } |
||
128 | } |
||
129 | 6 | $output .= "</tbody>\n"; |
|
130 | } |
||
131 | |||
132 | 15 | if ($footer_rows != '') { |
|
133 | 3 | $output .= "<tfoot>\n$footer_rows</tfoot>\n"; |
|
134 | } |
||
135 | |||
136 | 15 | $output .= "</table>\n"; |
|
137 | |||
138 | 15 | return $output; |
|
139 | } |
||
140 | |||
141 | /** |
||
142 | * Prepare the classes for the table |
||
143 | * |
||
144 | * @param $has_header |
||
145 | */ |
||
146 | 27 | private function prepareTableClasses($has_header) |
|
147 | { |
||
148 | 27 | $default_classes = ['table']; |
|
149 | |||
150 | 27 | if (!empty($this->attributes['class'])) { |
|
151 | 6 | $items = explode(' ', $this->attributes['class']); |
|
152 | 6 | $default_classes = array_merge($default_classes, $items); |
|
153 | } |
||
154 | |||
155 | //if no class starts with "table-" will add striped tables |
||
156 | 27 | if (empty($this->attributes['class']) || !$this->is_in_array('/^table-/', $default_classes)) { |
|
157 | 24 | $default_classes[] = 'table-striped'; |
|
158 | } |
||
159 | |||
160 | // Add sticky headers, if applicable. |
||
161 | 27 | if ($has_header) { |
|
162 | 18 | $default_classes[] = 'sticky-enabled'; |
|
163 | } |
||
164 | |||
165 | 27 | $this->attributes['class'] = implode(' ', $default_classes); |
|
166 | 27 | } |
|
167 | |||
168 | /** |
||
169 | * Render the header |
||
170 | * |
||
171 | * @param bool $has_rows |
||
172 | * @return string |
||
173 | */ |
||
174 | 21 | private function themeTableHead($has_rows) |
|
182 | |||
183 | /** |
||
184 | * Render a complete row |
||
185 | * |
||
186 | * @param array $row |
||
187 | * @param bool $header do we render th ? |
||
188 | * @return string |
||
189 | */ |
||
190 | 33 | private function themeTableRow($row, $header = false) |
|
191 | { |
||
192 | 33 | $attributes = []; |
|
193 | 33 | $row_content = ''; |
|
194 | |||
195 | 33 | $cells = $row; |
|
196 | |||
197 | // Check if we're dealing with a simple or complex row |
||
198 | 33 | if (isset($row['data'])) { |
|
199 | 9 | unset($row['footer']); |
|
200 | 9 | foreach ($row as $key => $value) { |
|
201 | 9 | if ($key == 'data') { |
|
202 | 9 | $cells = $value; |
|
203 | } else { |
||
204 | 6 | $attributes[$key] = $value; |
|
205 | } |
||
206 | } |
||
207 | } |
||
208 | |||
209 | 33 | if (count($cells)) { |
|
210 | // Build row |
||
211 | 33 | $row_content .= '<tr' . $this->attributes($attributes) . '>'; |
|
212 | 33 | foreach ($cells as $cell) { |
|
213 | 33 | $row_content .= $this->themeTableCell($cell, $header); |
|
214 | } |
||
215 | 33 | $row_content .= "</tr>\n"; |
|
216 | } |
||
217 | |||
218 | 33 | return $row_content; |
|
219 | } |
||
220 | |||
221 | /** |
||
222 | * Theme a single cell |
||
223 | * |
||
224 | * @param array $cell |
||
225 | * @param string $header |
||
226 | * @return string |
||
227 | */ |
||
228 | 45 | private function themeTableCell($cell, $header = null) |
|
229 | { |
||
230 | 45 | $attributes = ''; |
|
231 | |||
232 | 45 | if (is_array($cell)) { |
|
233 | 12 | $data = isset($cell['data']) ? $cell['data'] : ''; |
|
234 | 12 | $header |= isset($cell['header']); |
|
235 | 12 | unset($cell['data']); |
|
236 | 12 | unset($cell['header']); |
|
237 | 12 | $attributes = $this->attributes($cell); |
|
238 | } else { |
||
239 | 39 | $data = $cell; |
|
240 | } |
||
241 | |||
242 | 45 | if ($header) { |
|
243 | 24 | $output = "<th$attributes>$data</th>"; |
|
244 | } else { |
||
245 | 27 | $output = "<td$attributes>$data</td>"; |
|
246 | } |
||
247 | |||
248 | 45 | return $output; |
|
249 | } |
||
250 | |||
251 | /** |
||
252 | * Return a themed table. |
||
253 | * |
||
254 | * @param $header array |
||
255 | * An array containing the table headers. Each element of the array can be |
||
256 | * either a localized string or an associative array with the following keys: |
||
257 | * - "data": The localized title of the table column. |
||
258 | * - "field": The database field represented in the table column (required if |
||
259 | * user is to be able to sort on this column). |
||
260 | * - "sort": A default sort order for this column ("asc" or "desc"). |
||
261 | * - Any HTML attributes, such as "colspan", to apply to the column header cell. |
||
262 | * @param $rows array |
||
263 | * An array of table rows. Every row is an array of cells, or an associative |
||
264 | * array with the following keys: |
||
265 | * - "data": an array of cells |
||
266 | * - Any HTML attributes, such as "class", to apply to the table row. |
||
267 | * |
||
268 | * Each cell can be either a string or an associative array with the following keys: |
||
269 | * - "data": The string to display in the table cell. |
||
270 | * - "header": Indicates this cell is a header. |
||
271 | * - Any HTML attributes, such as "colspan", to apply to the table cell. |
||
272 | * |
||
273 | * Here's an example for $rows: |
||
274 | * <code> |
||
275 | * $rows = array( |
||
276 | * // Simple row |
||
277 | * array( |
||
278 | * 'Cell 1', 'Cell 2', 'Cell 3' |
||
279 | * ), |
||
280 | * // Row with attributes on the row and some of its cells. |
||
281 | * array( |
||
282 | * 'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => 'funky' |
||
283 | * ) |
||
284 | * ); |
||
285 | * </code> |
||
286 | * |
||
287 | * @param $attributes array An array of HTML attributes to apply to the table tag. |
||
288 | * @param $caption string A localized string to use for the <caption> tag. |
||
289 | * @return string An HTML string representing the table. |
||
290 | */ |
||
291 | 15 | public static function quick($header, $rows, $attributes = [], $caption = null) |
|
297 | |||
298 | /** |
||
299 | * is in array ? with a regex as needle |
||
300 | * |
||
301 | * @param string $pattern |
||
302 | * @param array $subjectArray |
||
303 | * @return bool |
||
304 | */ |
||
305 | 6 | protected function is_in_array($pattern, array $subjectArray, &$allMatches = [], $flags = null, $offset = null) |
|
315 | |||
316 | /** |
||
317 | * Build an HTML attribute string from an array. |
||
318 | * |
||
319 | * Taken form Illuminate/html, copied as it has far too much dependencies (13 !) and we only need these 10 lines |
||
320 | * |
||
321 | * @param array $attributes |
||
322 | * @return string |
||
323 | */ |
||
324 | 45 | protected function attributes($attributes) |
|
343 | } |
||
344 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.