|
1
|
|
|
<?php namespace EvolutionCMS\Support; |
|
2
|
|
|
|
|
3
|
|
|
use EvolutionCMS\Interfaces\DataGridInterface; |
|
4
|
|
|
|
|
5
|
|
|
# |
|
6
|
|
|
# DataGrid Class |
|
7
|
|
|
# Created By Raymond Irving 15-Feb,2004 |
|
8
|
|
|
# Based on CLASP 2.0 (www.claspdev.com) |
|
9
|
|
|
# ----------------------------------------- |
|
10
|
|
|
# Licensed under the LGPL |
|
11
|
|
|
# ----------------------------------------- |
|
12
|
|
|
# |
|
13
|
|
|
|
|
14
|
|
|
class DataGrid implements DataGridInterface{ |
|
15
|
|
|
|
|
16
|
|
|
public $ds; // datasource |
|
17
|
|
|
public $id; |
|
18
|
|
|
public $pageSize; // pager settings |
|
19
|
|
|
public $pageNumber; |
|
20
|
|
|
public $pager; |
|
21
|
|
|
public $pagerLocation; // top-right, top-left, bottom-left, bottom-right, both-left, both-right |
|
22
|
|
|
|
|
23
|
|
|
public $cssStyle; |
|
24
|
|
|
public $cssClass; |
|
25
|
|
|
|
|
26
|
|
|
public $columnHeaderStyle; |
|
27
|
|
|
public $columnHeaderClass; |
|
28
|
|
|
public $itemStyle; |
|
29
|
|
|
public $itemClass; |
|
30
|
|
|
public $altItemStyle; |
|
31
|
|
|
public $altItemClass; |
|
32
|
|
|
|
|
33
|
|
|
public $fields; |
|
34
|
|
|
public $columns; |
|
35
|
|
|
public $colWidths; |
|
36
|
|
|
public $colAligns; |
|
37
|
|
|
public $colWraps; |
|
38
|
|
|
public $colColors; |
|
39
|
|
|
public $colTypes; // coltype1, coltype2, etc or coltype1:format1, e.g. date:%Y %m |
|
40
|
|
|
// data type: integer,float,currency,date |
|
41
|
|
|
|
|
42
|
|
|
public $header; |
|
43
|
|
|
public $footer; |
|
44
|
|
|
public $cellPadding; |
|
45
|
|
|
public $cellSpacing; |
|
46
|
|
|
|
|
47
|
|
|
public $rowAlign; // vertical alignment: top, middle, bottom |
|
48
|
|
|
public $rowIdField; |
|
49
|
|
|
|
|
50
|
|
|
public $pagerStyle; |
|
51
|
|
|
public $pagerClass; |
|
52
|
|
|
public $pageClass; |
|
53
|
|
|
public $selPageClass; |
|
54
|
|
|
public $noRecordMsg = "No records found."; |
|
55
|
|
|
|
|
56
|
|
|
public $_itemStyle; |
|
57
|
|
|
public $_itemClass; |
|
58
|
|
|
public $_altItemClass; |
|
59
|
|
|
public $_altItemStyle; |
|
60
|
|
|
public $_isDataset; |
|
61
|
|
|
public $_colcount; |
|
62
|
|
|
public $_colnames; |
|
63
|
|
|
public $_colwidths; |
|
64
|
|
|
public $_colaligns; |
|
65
|
|
|
public $_colcolors; |
|
66
|
|
|
public $_coltypes; |
|
67
|
|
|
public $_colwraps; |
|
68
|
|
|
public $_alt; |
|
69
|
|
|
public $_total; |
|
70
|
|
|
public $_fieldnames; |
|
71
|
|
|
/** |
|
72
|
|
|
* @see datagrid modifier in manager/includes/extenders/modifiers.class.inc.php |
|
73
|
|
|
*/ |
|
74
|
|
|
public $cdelim; |
|
75
|
|
|
|
|
76
|
|
|
public static $dataGridCnt; |
|
77
|
|
|
|
|
78
|
|
|
public function __construct($id, $ds, $pageSize = 20, $pageNumber = -1) { |
|
79
|
|
|
// set id |
|
80
|
|
|
self::$dataGridCnt++; |
|
81
|
|
|
$this->id = $this->id ? empty($id) : "dg" . self::$dataGridCnt; |
|
82
|
|
|
|
|
83
|
|
|
// set datasource |
|
84
|
|
|
$this->ds = $ds; |
|
85
|
|
|
|
|
86
|
|
|
// set pager |
|
87
|
|
|
$this->pageSize = $pageSize; |
|
88
|
|
|
$this->pageNumber = $pageNumber; // by setting pager to -1 will cause pager to load it's last page number |
|
89
|
|
|
$this->pagerLocation = 'top-right'; |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
public function setDataSource($ds) { |
|
93
|
|
|
$this->ds = $ds; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
public function render() { |
|
97
|
|
|
$modx = evolutionCMS(); |
|
98
|
|
|
$columnHeaderStyle = ($this->columnHeaderStyle) ? "style='" . $this->columnHeaderStyle . "'" : ''; |
|
99
|
|
|
$columnHeaderClass = ($this->columnHeaderClass) ? "class='" . $this->columnHeaderClass . "'" : ""; |
|
100
|
|
|
$cssStyle = ($this->cssStyle) ? "style='" . $this->cssStyle . "'" : ''; |
|
101
|
|
|
$cssClass = ($this->cssClass) ? "class='" . $this->cssClass . "'" : ''; |
|
102
|
|
|
|
|
103
|
|
|
$pagerClass = ($this->pagerClass) ? "class='" . $this->pagerClass . "'" : ''; |
|
104
|
|
|
$pagerStyle = ($this->pagerStyle) ? "style='" . $this->pagerStyle . "'" : "style='background-color:#ffffff;'"; |
|
105
|
|
|
|
|
106
|
|
|
$this->_itemStyle = ($this->itemStyle) ? "style='" . $this->itemStyle . "'" : ''; |
|
107
|
|
|
$this->_itemClass = ($this->itemClass) ? "class='" . $this->itemClass . "'" : ''; |
|
108
|
|
|
$this->_altItemStyle = ($this->altItemStyle) ? "style='" . $this->altItemStyle . "'" : ''; |
|
109
|
|
|
$this->_altItemClass = ($this->altItemClass) ? "class='" . $this->altItemClass . "'" : ''; |
|
110
|
|
|
|
|
111
|
|
|
$this->_alt = 0; |
|
112
|
|
|
$this->_total = 0; |
|
113
|
|
|
|
|
114
|
|
|
$this->_isDataset = $modx->getDatabase()->isResult($this->ds); // if not dataset then treat as array |
|
115
|
|
|
|
|
116
|
|
|
if(!$cssStyle && !$cssClass) { |
|
117
|
|
|
$cssStyle = "style='width:100%;border:1px solid silver;font-family:verdana,arial; font-size:11px;'"; |
|
118
|
|
|
} |
|
119
|
|
|
if(!$columnHeaderStyle && !$columnHeaderClass) { |
|
120
|
|
|
$columnHeaderStyle = "style='color:black;background-color:silver'"; |
|
121
|
|
|
} |
|
122
|
|
|
if(!$this->_itemStyle && !$this->_itemClass) { |
|
123
|
|
|
$this->_itemStyle = "style='color:black;'"; |
|
124
|
|
|
} |
|
125
|
|
|
if(!$this->_altItemStyle && !$this->_altItemClass) { |
|
126
|
|
|
$this->_altItemStyle = "style='color:black;background-color:#eeeeee'"; |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
if($this->_isDataset && !$this->columns) { |
|
130
|
|
|
$cols = $modx->getDatabase()->numFields($this->ds); |
|
131
|
|
|
for($i = 0; $i < $cols; $i++) $this->columns .= ($i ? "," : "") . $modx->getDatabase()->fieldName($this->ds, $i); |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
// start grid |
|
135
|
|
|
$tblStart = "<table $cssClass $cssStyle cellpadding='" . (isset($this->cellPadding) ? (int) $this->cellPadding : 1) . "' cellspacing='" . (isset($this->cellSpacing) ? (int) $this->cellSpacing : 1) . "'>"; |
|
136
|
|
|
$tblEnd = "</table>"; |
|
137
|
|
|
|
|
138
|
|
|
// build column header |
|
139
|
|
|
$this->_colnames = explode((strstr($this->columns, "||") !== false ? "||" : ","), $this->columns); |
|
140
|
|
|
$this->_colwidths = explode((strstr($this->colWidths, "||") !== false ? "||" : ","), $this->colWidths); |
|
141
|
|
|
$this->_colaligns = explode((strstr($this->colAligns, "||") !== false ? "||" : ","), $this->colAligns); |
|
142
|
|
|
$this->_colwraps = explode((strstr($this->colWraps, "||") !== false ? "||" : ","), $this->colWraps); |
|
143
|
|
|
$this->_colcolors = explode((strstr($this->colColors, "||") !== false ? "||" : ","), $this->colColors); |
|
144
|
|
|
$this->_coltypes = explode((strstr($this->colTypes, "||") !== false ? "||" : ","), $this->colTypes); |
|
145
|
|
|
$this->_colcount = count($this->_colnames); |
|
146
|
|
|
if(!$this->_isDataset) { |
|
147
|
|
|
$this->ds = explode((strstr($this->ds, "||") !== false ? "||" : ","), $this->ds); |
|
148
|
|
|
$this->ds = array_chunk($this->ds, $this->_colcount); |
|
149
|
|
|
} |
|
150
|
|
|
$tblColHdr = "<thead><tr>"; |
|
151
|
|
|
for($c = 0; $c < $this->_colcount; $c++) { |
|
152
|
|
|
$name = $this->_colnames[$c]; |
|
153
|
|
|
$width = $this->_colwidths[$c]; |
|
154
|
|
|
$tblColHdr .= "<td $columnHeaderStyle $columnHeaderClass" . ($width ? " width='$width'" : "") . ">$name</td>"; |
|
155
|
|
|
} |
|
156
|
|
|
$tblColHdr .= "</tr></thead>\n"; |
|
157
|
|
|
|
|
158
|
|
|
// build rows |
|
159
|
|
|
$rowcount = $this->_isDataset ? $modx->getDatabase()->getRecordCount($this->ds) : count($this->ds); |
|
160
|
|
|
$this->_fieldnames = explode(",", $this->fields); |
|
161
|
|
|
if($rowcount == 0) { |
|
162
|
|
|
$tblRows .= "<tr><td " . $this->_itemStyle . " " . $this->_itemClass . " colspan='" . $this->_colcount . "'>" . $this->noRecordMsg . "</td></tr>\n"; |
|
|
|
|
|
|
163
|
|
|
} else { |
|
164
|
|
|
// render grid items |
|
165
|
|
|
if($this->pageSize <= 0) { |
|
166
|
|
|
for($r = 0; $r < $rowcount; $r++) { |
|
167
|
|
|
$row = $this->_isDataset ? $modx->getDatabase()->getRow($this->ds) : $this->ds[$r]; |
|
168
|
|
|
$tblRows .= $this->RenderRowFnc($r + 1, $row); |
|
|
|
|
|
|
169
|
|
|
} |
|
170
|
|
|
} else { |
|
171
|
|
|
if(!$this->pager) { |
|
172
|
|
|
$this->pager = new DataSetPager($this->id, $this->ds, $this->pageSize, $this->pageNumber); |
|
173
|
|
|
$this->pager->setRenderRowFnc($this); // pass this object |
|
174
|
|
|
$this->pager->cssStyle = $pagerStyle; |
|
|
|
|
|
|
175
|
|
|
$this->pager->cssClass = $pagerClass; |
|
|
|
|
|
|
176
|
|
|
} else { |
|
177
|
|
|
$this->pager->pageSize = $this->pageSize; |
|
178
|
|
|
$this->pager->pageNumber = $this->pageNumber; |
|
179
|
|
|
} |
|
180
|
|
|
|
|
181
|
|
|
$this->pager->render(); |
|
182
|
|
|
$tblRows = $this->pager->getRenderedRows(); |
|
183
|
|
|
$tblPager = $this->pager->getRenderedPager(); |
|
184
|
|
|
} |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
// setup header,pager and footer |
|
188
|
|
|
$o = $tblStart; |
|
189
|
|
|
$ptop = (substr($this->pagerLocation, 0, 3) == "top") || (substr($this->pagerLocation, 0, 4) == "both"); |
|
190
|
|
|
$pbot = (substr($this->pagerLocation, 0, 3) == "bot") || (substr($this->pagerLocation, 0, 4) == "both"); |
|
191
|
|
|
if($this->header) { |
|
192
|
|
|
$o .= "<tr><td bgcolor='#ffffff' colspan='" . $this->_colcount . "'>" . $this->header . "</td></tr>"; |
|
193
|
|
|
} |
|
194
|
|
View Code Duplication |
if($tblPager && $ptop) { |
|
195
|
|
|
$o .= "<tr><td align='" . (substr($this->pagerLocation, -4) == "left" ? "left" : "right") . "' $pagerClass $pagerStyle colspan='" . $this->_colcount . "'>" . $tblPager . " </td></tr>"; |
|
|
|
|
|
|
196
|
|
|
} |
|
197
|
|
|
$o .= $tblColHdr . $tblRows; |
|
198
|
|
View Code Duplication |
if($tblPager && $pbot) { |
|
199
|
|
|
$o .= "<tr><td align='" . (substr($this->pagerLocation, -4) == "left" ? "left" : "right") . "' $pagerClass $pagerStyle colspan='" . $this->_colcount . "'>" . $tblPager . " </td></tr>"; |
|
200
|
|
|
} |
|
201
|
|
|
if($this->footer) { |
|
202
|
|
|
$o .= "<tr><td bgcolor='#ffffff' colspan='" . $this->_colcount . "'>" . $this->footer . "</td></tr>"; |
|
203
|
|
|
} |
|
204
|
|
|
$o .= $tblEnd; |
|
205
|
|
|
return $o; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
// format column values |
|
209
|
|
|
|
|
210
|
|
|
public function RenderRowFnc($n, $row) { |
|
|
|
|
|
|
211
|
|
|
if($this->_alt == 0) { |
|
212
|
|
|
$Style = $this->_itemStyle; |
|
213
|
|
|
$Class = $this->_itemClass; |
|
214
|
|
|
$this->_alt = 1; |
|
215
|
|
|
} else { |
|
216
|
|
|
$Style = $this->_altItemStyle; |
|
217
|
|
|
$Class = $this->_altItemClass; |
|
218
|
|
|
$this->_alt = 0; |
|
219
|
|
|
} |
|
220
|
|
|
$o = "<tr>"; |
|
221
|
|
|
for($c = 0; $c < $this->_colcount; $c++) { |
|
222
|
|
|
$colStyle = $Style; |
|
223
|
|
|
$fld = trim($this->_fieldnames[$c]); |
|
224
|
|
|
$width = isset($this->_colwidths[$c]) ? $this->_colwidths[$c] : null; |
|
225
|
|
|
$align = isset($this->_colaligns[$c]) ? $this->_colaligns[$c] : null; |
|
226
|
|
|
$color = isset($this->_colcolors[$c]) ? $this->_colcolors[$c] : null; |
|
227
|
|
|
$type = isset($this->_coltypes[$c]) ? $this->_coltypes[$c] : null; |
|
228
|
|
|
$nowrap = isset($this->_colwraps[$c]) ? $this->_colwraps[$c] : null; |
|
229
|
|
|
$value = $row[($this->_isDataset && $fld ? $fld : $c)]; |
|
230
|
|
|
if($color && $Style) { |
|
231
|
|
|
$colStyle = substr($colStyle, 0, -1) . ";background-color:$color;'"; |
|
232
|
|
|
} |
|
233
|
|
|
$value = $this->formatColumnValue($row, $value, $type, $align); |
|
234
|
|
|
$o .= "<td $colStyle $Class" . ($align ? " align='$align'" : "") . ($color ? " bgcolor='$color'" : "") . ($nowrap ? " nowrap='$nowrap'" : "") . ($width ? " width='$width'" : "") . ">$value</td>"; |
|
235
|
|
|
} |
|
236
|
|
|
$o .= "</tr>\n"; |
|
237
|
|
|
return $o; |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
public function formatColumnValue($row, $value, $type, &$align) { |
|
|
|
|
|
|
241
|
|
|
if(strpos($type, ":") !== false) { |
|
242
|
|
|
list($type, $type_format) = explode(":", $type, 2); |
|
243
|
|
|
} |
|
244
|
|
|
switch(strtolower($type)) { |
|
245
|
|
|
case "integer": |
|
246
|
|
|
if($align == "") { |
|
247
|
|
|
$align = "right"; |
|
248
|
|
|
} |
|
249
|
|
|
$value = number_format($value); |
|
250
|
|
|
break; |
|
251
|
|
|
|
|
252
|
|
View Code Duplication |
case "float": |
|
253
|
|
|
if($align == "") { |
|
254
|
|
|
$align = "right"; |
|
255
|
|
|
} |
|
256
|
|
|
if(!$type_format) { |
|
|
|
|
|
|
257
|
|
|
$type_format = 2; |
|
258
|
|
|
} |
|
259
|
|
|
$value = number_format($value, $type_format); |
|
260
|
|
|
break; |
|
261
|
|
|
|
|
262
|
|
View Code Duplication |
case "currency": |
|
263
|
|
|
if($align == "") { |
|
264
|
|
|
$align = "right"; |
|
265
|
|
|
} |
|
266
|
|
|
if(!$type_format) { |
|
267
|
|
|
$type_format = 2; |
|
268
|
|
|
} |
|
269
|
|
|
$value = "$" . number_format($value, $type_format); |
|
270
|
|
|
break; |
|
271
|
|
|
|
|
272
|
|
|
case "date": |
|
273
|
|
|
if($align == "") { |
|
274
|
|
|
$align = "right"; |
|
275
|
|
|
} |
|
276
|
|
|
if(!is_numeric($value)) { |
|
277
|
|
|
$value = strtotime($value); |
|
278
|
|
|
} |
|
279
|
|
|
if(!$type_format) { |
|
280
|
|
|
$type_format = "%A %d, %B %Y"; |
|
281
|
|
|
} |
|
282
|
|
|
$value = strftime($type_format, $value); |
|
283
|
|
|
break; |
|
284
|
|
|
|
|
285
|
|
|
case "boolean": |
|
286
|
|
|
if($align == '') { |
|
287
|
|
|
$align = "center"; |
|
288
|
|
|
} |
|
289
|
|
|
$value = number_format($value); |
|
290
|
|
|
if($value) { |
|
291
|
|
|
$value = '•'; |
|
292
|
|
|
} else { |
|
293
|
|
|
$value = ' '; |
|
294
|
|
|
} |
|
295
|
|
|
break; |
|
296
|
|
|
|
|
297
|
|
|
case "template": |
|
298
|
|
|
// replace [+value+] first |
|
299
|
|
|
$value = str_replace("[+value+]", $value, $type_format); |
|
300
|
|
|
// replace other [+fields+] |
|
301
|
|
|
if(strpos($value, "[+") !== false) { |
|
302
|
|
|
foreach($row as $k => $v) { |
|
303
|
|
|
$value = str_replace("[+$k+]", $v, $value); |
|
304
|
|
|
} |
|
305
|
|
|
} |
|
306
|
|
|
break; |
|
307
|
|
|
|
|
308
|
|
|
} |
|
309
|
|
|
return $value; |
|
310
|
|
|
} |
|
311
|
|
|
} |
|
312
|
|
|
|
This error can happen if you refactor code and forget to move the variable initialization.
Let’s take a look at a simple example:
The above code is perfectly fine. Now imagine that we re-order the statements:
In that case,
$xwould be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.