1 | <?php |
||
20 | class DataTable |
||
21 | { |
||
22 | |||
23 | /** @var Builder */ |
||
24 | private $_queryBuilder; |
||
25 | |||
26 | /** @var array */ |
||
27 | private $_headerFormatters = []; |
||
28 | |||
29 | /** @var array */ |
||
30 | private $_components = []; |
||
31 | |||
32 | /** @var string */ |
||
33 | private $_classes; |
||
34 | |||
35 | /** @var array */ |
||
36 | private $_columns = []; |
||
37 | |||
38 | /** @var array */ |
||
39 | private $_relations = []; |
||
40 | |||
41 | /** @var string */ |
||
42 | private $_noDataHtml = '<div>no data</div>'; |
||
43 | |||
44 | /** |
||
45 | * Set the base model whose data is displayed in the table. |
||
46 | * |
||
47 | * @param string $modelName |
||
48 | * @param array $columns |
||
49 | * @return $this |
||
50 | * @throws \RuntimeException |
||
51 | */ |
||
52 | 57 | public function model(string $modelName, array $columns = []): DataTable |
|
53 | { |
||
54 | 57 | if (!\class_exists($modelName) || !\is_subclass_of($modelName, Model::class)) { |
|
55 | 2 | throw new RuntimeException('Class "' . $modelName . '" does not exist or is not an active record!'); |
|
56 | } |
||
57 | |||
58 | 55 | $this->_queryBuilder = (new $modelName)->newQuery(); |
|
59 | 55 | $this->_columns = $this->_fetchColumns($columns); |
|
60 | |||
61 | 55 | return $this; |
|
62 | } |
||
63 | |||
64 | /** |
||
65 | * Returns an array of Column objects which may be bound to a formatter. |
||
66 | * |
||
67 | * @param array $columns |
||
68 | * @return array |
||
69 | */ |
||
70 | 56 | private function _fetchColumns(array $columns): array |
|
71 | { |
||
72 | 56 | $columnModels = []; |
|
73 | 56 | foreach ($columns as $column => $formatter) { |
|
74 | 46 | [$column, $formatter] = $this->_setColumnFormatter($column, $formatter); |
|
75 | 46 | $columnModels[] = new Column($column, $formatter); |
|
76 | } |
||
77 | |||
78 | 56 | return $columnModels; |
|
79 | } |
||
80 | |||
81 | /** |
||
82 | * @param $column |
||
83 | * @param $formatter |
||
84 | * @return array |
||
85 | */ |
||
86 | 46 | private function _setColumnFormatter($column, $formatter): array |
|
87 | { |
||
88 | 46 | if (\is_int($column)) { |
|
89 | 44 | $column = $formatter; |
|
90 | 44 | $formatter = null; |
|
91 | } |
||
92 | |||
93 | 46 | return [$column, $formatter]; |
|
94 | } |
||
95 | |||
96 | /** |
||
97 | * @return Builder |
||
98 | */ |
||
99 | 19 | public function query(): Builder |
|
103 | |||
104 | /** |
||
105 | * Displayed columns |
||
106 | * |
||
107 | * @param array $columns |
||
108 | * @return $this |
||
109 | */ |
||
110 | 2 | public function columns(array $columns): DataTable |
|
116 | |||
117 | /** |
||
118 | * Add a component to the data table. |
||
119 | * For example a "Paginator" or a "Sorter". |
||
120 | * |
||
121 | * @param DataComponent $component |
||
122 | * |
||
123 | * @param string|null $name |
||
124 | * @return $this|DataTable |
||
125 | */ |
||
126 | 31 | public function addComponent(DataComponent $component, ?string $name = null): DataTable |
|
127 | { |
||
128 | 31 | $component->init($this->_queryBuilder, $this->_columns); |
|
129 | 31 | $componentName = \str_replace(' ', '', Str::lower($name ?? \class_basename($component))); |
|
130 | 31 | if ($this->componentExists($componentName)) throw new MultipleComponentAssertionException(); |
|
131 | 31 | $this->_components[$componentName] = $component; |
|
132 | |||
133 | 31 | return $this; |
|
134 | } |
||
135 | |||
136 | /** |
||
137 | * Check whether a component exists for the given data table. |
||
138 | * @param string $componentName |
||
139 | * @return bool |
||
140 | */ |
||
141 | 31 | public function componentExists(string $componentName): bool |
|
142 | { |
||
143 | 31 | return \array_key_exists($componentName, $this->_components); |
|
144 | } |
||
145 | |||
146 | /** |
||
147 | * Add a formatter for the column headers. |
||
148 | * |
||
149 | * @param HeaderFormatter $headerFormatter |
||
150 | * @return DataTable |
||
151 | */ |
||
152 | 12 | public function formatHeaders(HeaderFormatter $headerFormatter): DataTable |
|
158 | |||
159 | /** |
||
160 | * Add a formatter for a column. |
||
161 | * |
||
162 | * @param string $columnName |
||
163 | * @param ColumnFormatter $columnFormatter |
||
164 | * @return DataTable |
||
165 | */ |
||
166 | 2 | public function formatColumn(string $columnName, ColumnFormatter $columnFormatter): DataTable |
|
183 | |||
184 | /** |
||
185 | * Add classes to the table. |
||
186 | * |
||
187 | * @param string $classes |
||
188 | * |
||
189 | * @return $this |
||
190 | */ |
||
191 | 1 | public function classes(string $classes): DataTable |
|
197 | |||
198 | /** |
||
199 | * Add a relation to the table. |
||
200 | * |
||
201 | * @param array $relations |
||
202 | * @return DataTable |
||
203 | */ |
||
204 | 3 | public function with(array $relations): DataTable |
|
210 | |||
211 | /** |
||
212 | * Set the HTML which should be displayed when the dataset is empty. |
||
213 | * |
||
214 | * @param string $html |
||
215 | * @return DataTable |
||
216 | */ |
||
217 | 1 | public function noDataHtml(string $html): DataTable |
|
223 | |||
224 | /** |
||
225 | * Set a view which should be displayed when the dataset is empty. |
||
226 | * |
||
227 | * @param string $viewName |
||
228 | * @return DataTable |
||
229 | */ |
||
230 | 1 | public function noDataView(string $viewName): DataTable |
|
236 | |||
237 | /** |
||
238 | * Renders the table. |
||
239 | * |
||
240 | * @return string |
||
241 | * @throws \RuntimeException |
||
242 | */ |
||
243 | 39 | public function render(): string |
|
258 | |||
259 | /** |
||
260 | * Get data which should be displayed in the table. |
||
261 | * |
||
262 | * @return Collection |
||
263 | * |
||
264 | * @throws \RuntimeException |
||
265 | */ |
||
266 | 39 | private function _getData(): Collection |
|
281 | |||
282 | 38 | private function _addRelations(): void |
|
288 | |||
289 | 34 | private function _initColumns(): void |
|
295 | |||
296 | /** |
||
297 | * @return array |
||
298 | */ |
||
299 | 34 | private function _fetchHeaders(): array |
|
309 | |||
310 | 2 | public function __get($name) |
|
316 | } |
Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a
@return
annotation as described here.