1
|
|
|
<?php |
2
|
|
|
require_once(dirname(__FILE__) . '/fwolflib.php'); |
3
|
|
|
require_once(FWOLFLIB . 'func/request.php'); |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Generate table list |
8
|
|
|
* |
9
|
|
|
* Table head and body are given seperately, but have some relationship, |
10
|
|
|
* you can give head or body contain more data, then limit disp by fit it |
11
|
|
|
* to another part. |
12
|
|
|
* |
13
|
|
|
* Notice: No db query feather in this, data are transferd from outerside. |
14
|
|
|
* |
15
|
|
|
* <code> |
16
|
|
|
* $s = ''; |
17
|
|
|
* // Set <thead> |
18
|
|
|
* $art = array('col1' => 'description_col1', |
19
|
|
|
* 'col2' => 'description_col2', |
20
|
|
|
* ); |
21
|
|
|
* // Set <thead> without col name, only description given. |
22
|
|
|
* //$art = array('description_col1', 'description_col2'); |
23
|
|
|
* |
24
|
|
|
* // Set <tbody> data, 1st dim of ar is row, 2nd dim of ar is col-val pair. |
25
|
|
|
* $ard = array(...); |
26
|
|
|
* |
27
|
|
|
* // Set Config, check manual to see their effect. |
28
|
|
|
* $ar_conf = array( |
29
|
|
|
* 'fit_data_title' => 3, |
30
|
|
|
* ); |
31
|
|
|
* |
32
|
|
|
* // New object |
33
|
|
|
* //$this->oLt = new ListTable($this->oTpl, $ard, $art, '', $ar_conf); |
34
|
|
|
* // Or cal SetXxx func, note that SetCfg MUST before SetData |
35
|
|
|
* $this->oLt->SetCfg($ar_conf); |
36
|
|
|
* $this->oLt->SetData($ar, $art); |
37
|
|
|
* |
38
|
|
|
* // Got output html |
39
|
|
|
* $s = $this->oLt->GetHtml(); |
40
|
|
|
* </code> |
41
|
|
|
* |
42
|
|
|
* @deprecated Use Fwlib\Html\ListTable |
43
|
|
|
* @package fwolflib |
44
|
|
|
* @subpackage class |
45
|
|
|
* @copyright Copyright 2003-2011, Fwolf |
46
|
|
|
* @author Fwolf <[email protected]> |
47
|
|
|
* @since 2003-05-17 12:17:14 |
48
|
|
|
*/ |
49
|
|
|
class ListTable extends Fwolflib { |
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Configuration |
52
|
|
|
* |
53
|
|
|
* <code> |
54
|
|
|
* color_bg_[th/tr_even/tr_odd]: |
55
|
|
|
* Colors of rows. |
56
|
|
|
* color_bg_tr_hover: |
57
|
|
|
* Change to this color when mouseover of row.(Not implement) |
58
|
|
|
* fit_data_title: 0=data fit title, cut data items who's index not |
59
|
|
|
* in title |
60
|
|
|
* 1=title fit data. |
61
|
|
|
* 2=fit to fewest, only items both have allowed. |
62
|
|
|
* 3=fit to mostest, all items in title or data allowed. |
63
|
|
|
* fit_empty: If an value in data is empty, set to this value. |
64
|
|
|
* Title will always set to field name in same situation. |
65
|
|
|
* code_prefix: Prefix auto add before $sId, use to generate html. |
66
|
|
|
* page_cur: Current page no, ONLY USED TO DISP PAGER. |
67
|
|
|
* page_param: Param name of page number in URL, |
68
|
|
|
* Will change if $sId changed. |
69
|
|
|
* page_size: Rows per page, ONLY USED TO DISP PAGER, havn't any |
70
|
|
|
* effect to list data. |
71
|
|
|
* rows_total: Total rows, ONLY USED TO DISP PAGER. |
72
|
|
|
* tpl: Smarty template file to use. |
73
|
|
|
* </code> |
74
|
|
|
* @var array |
75
|
|
|
*/ |
76
|
|
|
public $aCfg = array( |
77
|
|
|
// 浅蓝色配色方案 |
78
|
|
|
// fwolflib-list-table = fl_lt |
79
|
|
|
'code_prefix' => 'fl_lt', // Used in id/class in html and css. |
80
|
|
|
'color_bg_th' => '#d0dcff', // 表头(第0行) |
81
|
|
|
'color_bg_tr_even' => '#fff', // 偶数行 |
82
|
|
|
'color_bg_tr_hover' => '#e3e3de', // 鼠标指向时变色 |
83
|
|
|
'color_bg_tr_odd' => '#eef2ff', // 奇数行,tbody后从0开始算 |
84
|
|
|
'fit_data_title' => 0, |
85
|
|
|
'fit_empty' => ' ', |
86
|
|
|
'orderby' => 0, // 0=off, 1=on |
87
|
|
|
'orderby_dir' => 'asc', |
88
|
|
|
'orderby_idx' => '', // Idx of th ar |
89
|
|
|
'orderby_param' => 'o', |
90
|
|
|
'orderby_text' => '', |
91
|
|
|
// ← = ← ↑ = ↑ → = → ↓ = ↓ |
92
|
|
|
// ∆ = ∆ ∇ = ∇ |
93
|
|
|
'orderby_text_asc' => '↑', |
94
|
|
|
'orderby_text_desc' => '↓', |
95
|
|
|
'page_cur' => 1, |
96
|
|
|
'page_param' => 'p', |
97
|
|
|
'page_size' => 10, |
98
|
|
|
'pager' => false, // Is or not use pager |
99
|
|
|
'pager_bottom' => true, // Is or not use pager bottom, used when pager=true |
100
|
|
|
// This is a message template |
101
|
|
|
// When display, use key append by '_value' |
102
|
|
|
'pager_text_cur' => '共{rows_total}条记录,每页显示{page_size}条,当前为第{page_cur}/{page_max}页', |
103
|
|
|
|
104
|
|
|
'pager_text_first' => '首页', |
105
|
|
|
'pager_text_goto1' => '转到第', |
106
|
|
|
'pager_text_goto2' => '页', |
107
|
|
|
'pager_text_goto3' => '转', |
108
|
|
|
'pager_text_last' => '尾页', |
109
|
|
|
'pager_text_next' => '下一页', |
110
|
|
|
'pager_text_prev' => '上一页', |
111
|
|
|
'pager_text_spacer' => ' | ', // To be between below texts. |
112
|
|
|
'pager_top' => true, // Is or not use pager top, used when pager=true |
113
|
|
|
// 'param' => 'p', // Used in url to set page no. |
114
|
|
|
'rows_total' => 0, |
115
|
|
|
'tpl' => 'list-table.tpl', |
116
|
|
|
|
117
|
|
|
// Add custom string in td/th/tr tag, eg: nowrap="nowrap" |
118
|
|
|
// td/th can use index same with data array index, |
119
|
|
|
// tr can use int index which's value is string too. |
120
|
|
|
// For tr of th row, use th instead. |
121
|
|
|
'td_add' => array(), |
122
|
|
|
'th_add' => array(), |
123
|
|
|
'tr_add' => array(), |
124
|
|
|
); |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* 数组变量,指向要显示数据存放的数组,其格式见类说明 |
128
|
|
|
* @var array |
129
|
|
|
*/ |
130
|
|
|
protected $aData = array(); |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Page url param array. |
134
|
|
|
* @var array |
135
|
|
|
*/ |
136
|
|
|
protected $aParam = array(); |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Title of data, used as table title. |
140
|
|
|
* @var array |
141
|
|
|
*/ |
142
|
|
|
protected $aTitle = array(); |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Array of url, for links to display in tpl |
146
|
|
|
* <code> |
147
|
|
|
* array( |
148
|
|
|
* base => Original page url |
149
|
|
|
* o_cur => Cur orderby link(modified) |
150
|
|
|
* o_other => Other orderby link(modified) |
151
|
|
|
* p_first => First page link |
152
|
|
|
* p_last => Last page link |
153
|
|
|
* p_next => Next page link |
154
|
|
|
* p_prev => Prev page link |
155
|
|
|
* ) |
156
|
|
|
* </code> |
157
|
|
|
* @var array |
158
|
|
|
*/ |
159
|
|
|
protected $aUrl = array( |
160
|
|
|
'base' => '', |
161
|
|
|
'o_cur' => '', |
162
|
|
|
'o_other' => '', |
163
|
|
|
'p_first' => '', |
164
|
|
|
'p_last' => '', |
165
|
|
|
'p_next' => '', |
166
|
|
|
'p_prev' => '', |
167
|
|
|
); |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* 模板变量,指向在构造函数中传入的全局模板变量 |
171
|
|
|
* @var object |
172
|
|
|
*/ |
173
|
|
|
protected $oTpl = null; |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Class of this list in html, used with {@see $sId} |
177
|
|
|
* |
178
|
|
|
* Diff between $sClass and $sId: |
179
|
|
|
* $sClass has no prefix, while $sId has. |
180
|
|
|
* $sClass can be applyed css in project css file, |
181
|
|
|
* while $sId can be applyed css inline in tpl file. |
182
|
|
|
* @var string |
183
|
|
|
*/ |
184
|
|
|
protected $sClass = 'fl_lt'; |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Identify of this list, |
188
|
|
|
* Also used in html, as div id property. |
189
|
|
|
* @var string |
190
|
|
|
*/ |
191
|
|
|
protected $sId = 'fl_lt'; |
192
|
|
|
|
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Construct |
196
|
|
|
* |
197
|
|
|
* $ard, $art can't use referenct because title and data value maybe |
198
|
|
|
* changed in treatment. |
199
|
|
|
* @param object &$tpl Smarty object, will save as {@link $oTpl}. |
200
|
|
|
* @param array $ard Data array, will save as {@link $aData}. |
201
|
|
|
* @param array $art Title of list. |
202
|
|
|
* @param string $id Identify of this list, while multi list |
203
|
|
|
* in page, this is needed. |
204
|
|
|
* Note: will be applyed prefix automatic |
205
|
|
|
* when write to $sId. |
206
|
|
|
* @param array &$conf Configuration. |
207
|
|
|
*/ |
208
|
|
|
public function __construct (&$tpl, $ard = array(), $art = array(), |
209
|
|
|
$id = '', &$conf = array()) { |
210
|
|
|
$this->oTpl = $tpl; |
211
|
|
|
|
212
|
|
|
// Config will effect SetData, so set it first. |
213
|
|
|
$this->SetCfg($conf); |
214
|
|
|
$this->oTpl->assignByRef('lt_config', $this->aCfg); |
215
|
|
|
|
216
|
|
|
$this->SetData($ard, $art); |
217
|
|
|
$this->SetId($id); |
218
|
|
|
} // end of func ListTable |
219
|
|
|
|
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* Fit data and title when their items count diff |
223
|
|
|
* |
224
|
|
|
* <code> |
225
|
|
|
* fit_data_title: 0=data fit title, cut data items who's index not |
226
|
|
|
* in title |
227
|
|
|
* 1=title fit data. |
228
|
|
|
* 2=fit to fewest, only items both have allowed. |
229
|
|
|
* 3=fit to mostest, all items in title or data allowed. |
230
|
|
|
* </code> |
231
|
|
|
* Notice: data have multi row(2 dim), title have only 1 row(1 dim). |
232
|
|
|
* @see $aCfg['fit_data_title'] |
233
|
|
|
*/ |
234
|
|
|
protected function FitDataTitle () { |
235
|
|
|
if (empty($this->aData) || empty($this->aTitle)) |
236
|
|
|
return ; |
237
|
|
|
|
238
|
|
|
// Store result |
239
|
|
|
$ar_title = array(); |
240
|
|
|
$ar_data = array(); |
241
|
|
|
|
242
|
|
|
// Will compare by array keys, data use it's first/current row |
243
|
|
|
// $keys_data = array_keys($this->aData[0]); |
244
|
|
|
$keys_data = array_keys(current($this->aData)); |
245
|
|
|
$keys_title = array_keys($this->aTitle); |
246
|
|
|
|
247
|
|
|
switch ($this->aCfg['fit_data_title']) { |
248
|
|
|
case 0: |
249
|
|
|
// data fit to title |
250
|
|
|
|
251
|
|
|
// Int index and string are difference |
252
|
|
|
// In common, we check only title's index type |
253
|
|
|
// Int index, can only fit by index position |
254
|
|
|
if (0 === $keys_title[0]) { |
255
|
|
|
$ar_title = &$this->aTitle; |
256
|
|
|
foreach ($keys_title as $k => $v) |
257
|
|
|
foreach ($this->aData as $idx => $row) |
258
|
|
|
if (isset($row[$keys_data[$k]])) |
259
|
|
|
$ar_data[$idx][$keys_data[$k]] = &$row[$keys_data[$k]]; |
260
|
|
|
else |
261
|
|
|
$ar_data[$idx][$keys_data[$k]] = $this->aCfg['fit_empty']; |
262
|
|
|
} |
263
|
|
|
else { |
264
|
|
|
$ar_title = &$this->aTitle; |
265
|
|
|
foreach ($keys_title as $k => $v) |
266
|
|
|
foreach ($this->aData as $idx => $row) |
267
|
|
|
if (isset($row[$v])) |
268
|
|
|
$ar_data[$idx][$v] = &$row[$v]; |
269
|
|
|
else |
270
|
|
|
$ar_data[$idx][$v] = $this->aCfg['fit_empty']; |
271
|
|
|
} |
272
|
|
|
break; |
273
|
|
|
case 1: |
274
|
|
|
// title fit to data, inser empty title if havn't |
275
|
|
|
|
276
|
|
|
// Int index, can only fit by index position |
277
|
|
|
if (0 === $keys_title[0]) { |
278
|
|
|
$ar_data = &$this->aData; |
279
|
|
View Code Duplication |
foreach ($keys_data as $k => $v) |
|
|
|
|
280
|
|
|
if (isset($keys_title[$k])) |
281
|
|
|
$ar_title[$k] = &$this->aTitle[$k]; |
282
|
|
|
else |
283
|
|
|
// Use data's index name |
284
|
|
|
$ar_title[$k] = $v; |
285
|
|
|
} |
286
|
|
|
else { |
287
|
|
|
$ar_data = &$this->aData; |
288
|
|
View Code Duplication |
foreach ($keys_data as $k => $v) |
|
|
|
|
289
|
|
|
if (isset($this->aTitle[$v])) |
290
|
|
|
$ar_title[$v] = &$this->aTitle[$v]; |
291
|
|
|
else |
292
|
|
|
$ar_title[$v] = $v; |
293
|
|
|
} |
294
|
|
|
break; |
295
|
|
|
case 2: |
296
|
|
|
// Fit to fewest |
297
|
|
|
// Cut title first, then fit to title |
298
|
|
|
// Cut title: |
299
|
|
|
$ar_title = &$this->aTitle; |
300
|
|
|
if (0 === $keys_title[0]) { |
301
|
|
|
// Int indexed |
302
|
|
|
// Remove title if title has more items than data |
303
|
|
View Code Duplication |
for ($i = count($keys_data); $i < count($keys_title); $i++) |
|
|
|
|
304
|
|
|
unset($ar_title[$i]); |
305
|
|
|
} |
306
|
|
|
else { |
307
|
|
|
// String indexed |
308
|
|
|
// Remove item in title which not in data |
309
|
|
|
foreach ($keys_title as $k => $v) |
310
|
|
|
if (!in_array($v, $keys_data)) |
311
|
|
|
unset($ar_title[$v]); |
312
|
|
|
} |
313
|
|
|
// Then use function itself to fit data to cutted title |
314
|
|
|
$this->aCfg['fit_data_title'] = 0; |
315
|
|
|
$this->FitDataTitle(); |
316
|
|
|
$this->aCfg['fit_data_title'] = 2; |
317
|
|
|
$ar_data = &$this->aData; |
318
|
|
|
$ar_title = &$this->aTitle; |
319
|
|
|
break; |
320
|
|
|
case 3: |
321
|
|
|
// Fit to mostest |
322
|
|
|
// Fill title first, then fit to title |
323
|
|
|
// Fill title: |
324
|
|
|
if (0 === $keys_title[0]) { |
325
|
|
|
// Add as append |
326
|
|
|
$ar_title = &$this->aTitle; |
327
|
|
|
// Int indexed |
328
|
|
|
// Add title if title has fewer items than data |
329
|
|
View Code Duplication |
for ($i = count($keys_title); $i < count($keys_data); $i++) |
|
|
|
|
330
|
|
|
// Can only use field name in data |
331
|
|
|
$ar_title[$i] = $keys_data[$i]; |
332
|
|
|
} |
333
|
|
|
else { |
334
|
|
|
// Add as insert |
335
|
|
|
// need to merge keys first to keep order |
336
|
|
|
$keys_merge = array_merge($keys_title, $keys_data); |
337
|
|
View Code Duplication |
foreach ($keys_merge as $k => $v) |
|
|
|
|
338
|
|
|
if (in_array($v, $keys_title)) |
339
|
|
|
$ar_title[$v] = $this->aTitle[$v]; |
340
|
|
|
else |
341
|
|
|
// Title items is fewer, need to fill |
342
|
|
|
// These infact is keys from data, |
343
|
|
|
// because of merge, so we can use $v directly |
344
|
|
|
$ar_title[$v] = $v; |
345
|
|
|
} |
346
|
|
|
$this->aTitle = &$ar_title; |
347
|
|
|
// Then use function itself to fit data to cutted title |
348
|
|
|
$this->aCfg['fit_data_title'] = 0; |
349
|
|
|
$this->FitDataTitle(); |
350
|
|
|
$this->aCfg['fit_data_title'] = 2; |
351
|
|
|
$ar_data = &$this->aData; |
352
|
|
|
$ar_title = &$this->aTitle; |
353
|
|
|
break; |
354
|
|
|
default: |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
|
358
|
|
|
// Data write back |
359
|
|
|
//var_dump($ar_data); |
360
|
|
|
$this->aData = &$ar_data; |
361
|
|
|
$this->aTitle = &$ar_title; |
362
|
|
|
} // end of func FitDataTitle |
363
|
|
|
|
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* Get full output html |
367
|
|
|
* @return string |
368
|
|
|
*/ |
369
|
|
|
public function GetHtml () { |
370
|
|
|
return $this->oTpl->fetch($this->aCfg['tpl']); |
371
|
|
|
} // end of func GetHtml |
372
|
|
|
|
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* Get http GET param. |
376
|
|
|
* @return array |
377
|
|
|
*/ |
378
|
|
|
public function GetParam() { |
379
|
|
|
$this->aParam = &$_GET; |
380
|
|
|
if (!empty($this->aParam) && !get_magic_quotes_gpc()) { |
381
|
|
|
foreach ($this->aParam as $k=>$v) { |
382
|
|
|
$this->aParam[$k] = addslashes($v); |
383
|
|
|
} |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
// :NOTICE: Will got only url of backend if ProxyPass actived |
387
|
|
|
// Can treat as below before new ListTable obj. |
388
|
|
|
/* |
389
|
|
|
$ar = array('/needless1/', '/needless1/'); |
390
|
|
|
$_SERVER['REQUEST_URI'] = str_replace($ar, '/', $_SERVER['REQUEST_URI']); |
391
|
|
|
$_SERVER['SCRIPT_NAME'] = str_replace($ar, '/', $_SERVER['SCRIPT_NAME']); |
392
|
|
|
*/ |
393
|
|
|
$this->aUrl['base'] = GetSelfUrl(false); |
|
|
|
|
394
|
|
|
|
395
|
|
|
if (isset($this->aParam[$this->aCfg['page_param']])) { |
396
|
|
|
$this->ParsePageCur($this->aParam[$this->aCfg['page_param']]); |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
// Orderby |
400
|
|
|
if (isset($this->aParam[$this->aCfg['orderby_param'] . '_idx'])) |
401
|
|
|
$this->SetOrderby($this->aParam[$this->aCfg['orderby_param'] . '_idx'], $this->aParam[$this->aCfg['orderby_param'] . '_dir']); |
402
|
|
|
|
403
|
|
|
return $this->aParam; |
404
|
|
|
} // end of func GetParam |
405
|
|
|
|
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Get info about some part of query sql |
409
|
|
|
* what can directly use in SqlGenerator, eg: limit, orderby |
410
|
|
|
* |
411
|
|
|
* @return array |
412
|
|
|
* @see SqlGenerator |
413
|
|
|
*/ |
414
|
|
|
public function GetSqlInfo () { |
415
|
|
|
$ar = array(); |
416
|
|
|
|
417
|
|
|
$ar['LIMIT'] = $this->aCfg['page_size'] * ($this->aCfg['page_cur'] - 1) |
418
|
|
|
. ', ' . $this->aCfg['page_size']; |
419
|
|
|
|
420
|
|
|
if (1 == $this->aCfg['orderby']) { |
421
|
|
|
// orderby_idx is column name |
422
|
|
|
$ar['ORDERBY'] = $this->aCfg['orderby_idx'] |
423
|
|
|
. ' ' . $this->aCfg['orderby_dir']; |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
return $ar; |
427
|
|
|
} // end of func GetSqlInfo |
428
|
|
|
|
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Get info about some part of query sql from url $_REQUEST |
432
|
|
|
* what can directly use in SqlGenerator, eg: limit, orderby |
433
|
|
|
* |
434
|
|
|
* @return array |
435
|
|
|
* @see SqlGenerator |
436
|
|
|
*/ |
437
|
|
|
public function GetSqlInfoFromUrl () { |
438
|
|
|
$ar = array(); |
439
|
|
|
|
440
|
|
|
// Limit |
441
|
|
|
$i_page = $this->ParsePageCur(); |
442
|
|
|
$ar['LIMIT'] = ($i_page - 1) * $this->aCfg['page_size'] |
443
|
|
|
. ', ' . $this->aCfg['page_size']; |
444
|
|
|
|
445
|
|
|
// Orderby |
446
|
|
|
$s = $this->aCfg['orderby_param']; |
447
|
|
|
$s_idx = GetRequest($_REQUEST, $s . '_idx'); |
|
|
|
|
448
|
|
|
if (0 < strlen($s_idx)) { |
449
|
|
|
// Orderby enabled |
450
|
|
|
$s_dir = GetRequest($_REQUEST, $s . '_dir', 'asc'); |
|
|
|
|
451
|
|
|
$ar['ORDERBY'] = $s_idx . ' ' . $s_dir; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
return $ar; |
455
|
|
|
} // end of func GetSqlInfoFromUrl |
456
|
|
|
|
457
|
|
|
|
458
|
|
|
/** |
459
|
|
|
* Parse & compute page_cur param |
460
|
|
|
* |
461
|
|
|
* @param int $p Page num param come from outer |
462
|
|
|
* @return int |
463
|
|
|
*/ |
464
|
|
|
protected function ParsePageCur ($p = 0) { |
465
|
|
|
if (0 == $p) { |
466
|
|
|
// Read from GET prarm |
467
|
|
|
$i = GetRequest($_REQUEST, $this->aCfg['page_param']); |
|
|
|
|
468
|
|
|
// Special & dangous setting, use only if 1 LT in page |
469
|
|
|
$i1 = GetRequest($_REQUEST, 'p'); |
|
|
|
|
470
|
|
|
if (!empty($i)) |
471
|
|
|
$page_cur = $i; |
472
|
|
|
elseif (!empty($i1)) |
473
|
|
|
$page_cur = $i1; |
474
|
|
|
else |
475
|
|
|
$page_cur = 1; |
476
|
|
|
} |
477
|
|
|
else |
478
|
|
|
$page_cur = $p; |
479
|
|
|
$page_cur = intval($page_cur); |
480
|
|
|
|
481
|
|
|
// Validate min and max |
482
|
|
|
// Min |
483
|
|
|
if (1 > $page_cur) |
484
|
|
|
$page_cur = 1; |
485
|
|
|
// Max |
486
|
|
|
if (0 < $this->aCfg['rows_total'] |
487
|
|
|
&& 0 < $this->aCfg['page_size']) { |
488
|
|
|
$i = ceil($this->aCfg['rows_total'] |
489
|
|
|
/ $this->aCfg['page_size']); |
490
|
|
|
if ($i < $page_cur) |
491
|
|
|
$page_cur = intval($i); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
// Result |
495
|
|
|
$this->aCfg['page_cur'] = $page_cur; |
496
|
|
|
return $page_cur; |
497
|
|
|
} // end of func ParsePageCur |
498
|
|
|
|
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* Set table data and title to display. |
502
|
|
|
* @param array &$ard Data, will save as {@link $aData}. |
503
|
|
|
* @param array &$art Title of list. |
504
|
|
|
*/ |
505
|
|
|
public function SetData (&$ard = array(), &$art = array()) { |
506
|
|
|
if (!empty($ard)) |
507
|
|
|
$this->aData = $ard; |
508
|
|
|
if (!empty($art)) |
509
|
|
|
$this->aTitle = $art; |
510
|
|
|
|
511
|
|
|
// Same number of items maybe index diff, so always do fit. |
512
|
|
|
$this->FitDataTitle(); |
513
|
|
|
|
514
|
|
|
$this->oTpl->assignByRef('lt_data', $this->aData); |
515
|
|
|
$this->oTpl->assignByRef('lt_title', $this->aTitle); |
516
|
|
|
|
517
|
|
|
return ; |
518
|
|
|
/* obsolete |
519
|
|
|
//$this->aData = &$ar; |
520
|
|
|
// 将输入的数组转换成用数字作为索引的,因为SMARTY不支持ASSOC索引 |
521
|
|
|
$this->aData = array(); |
522
|
|
|
if (empty($ar)) |
523
|
|
|
{ |
524
|
|
|
return(false); |
525
|
|
|
} |
526
|
|
|
foreach ($ar as $key=>$val) |
527
|
|
|
{ |
528
|
|
|
array_push($this->aData, $val); |
529
|
|
|
} |
530
|
|
|
// |
531
|
|
|
$this->mTotalRows = count($this->aData); |
532
|
|
|
*/ |
533
|
|
|
} // end of func SetData |
534
|
|
|
|
535
|
|
|
|
536
|
|
|
/** |
537
|
|
|
* Set identify and class of this list <div> in html |
538
|
|
|
* @param string $id |
539
|
|
|
* @param string $class |
540
|
|
|
* @return string |
541
|
|
|
*/ |
542
|
|
|
public function SetId ($id, $class = '') { |
543
|
|
|
if (empty($id)) |
544
|
|
|
$this->sId = $this->aCfg['code_prefix']; |
545
|
|
|
else |
546
|
|
|
$this->sId = $this->aCfg['code_prefix'] . '_' . $id; |
547
|
|
|
if (!empty($class)) |
548
|
|
|
$this->sClass = $class; |
549
|
|
|
else |
550
|
|
|
// On default, class = id |
551
|
|
|
$this->sClass = $this->sId; |
552
|
|
|
$this->oTpl->assignByRef('lt_id', $this->sId); |
553
|
|
|
$this->oTpl->assignByRef('lt_class', $this->sClass); |
554
|
|
|
|
555
|
|
|
// Change page_param |
556
|
|
|
$this->aCfg['page_param'] = $this->sId . '_p'; |
557
|
|
|
$this->ParsePageCur(); |
558
|
|
|
|
559
|
|
|
// Change orderby param |
560
|
|
|
$this->aCfg['orderby_param'] = $this->sId . '_o'; |
561
|
|
|
|
562
|
|
|
// Find param by new Id |
563
|
|
|
$this->GetParam(); |
564
|
|
|
|
565
|
|
|
return $this->sId; |
566
|
|
|
} // end of func SetId |
567
|
|
|
|
568
|
|
|
|
569
|
|
|
/** |
570
|
|
|
* Set orderby info |
571
|
|
|
* |
572
|
|
|
* Didn't validate $idx to th array. |
573
|
|
|
* @param mixed $idx Idx of th array |
574
|
|
|
* @param string $dir asc/desc, lower letter only |
575
|
|
|
*/ |
576
|
|
|
public function SetOrderby ($idx, $dir = 'asc') { |
577
|
|
|
$this->aCfg['orderby'] = 1; |
578
|
|
|
|
579
|
|
|
// If had got orderby info from url, exit |
580
|
|
|
if (0 < strlen($this->aCfg['orderby_idx'])) |
581
|
|
|
return; |
582
|
|
|
|
583
|
|
|
$this->aCfg['orderby_idx'] = $idx; |
584
|
|
|
$dir = strtolower($dir); |
585
|
|
|
if ('asc' == $dir) { |
586
|
|
|
$dir_rev = 'desc'; |
587
|
|
|
$this->aCfg['orderby_dir'] = 'asc'; |
588
|
|
|
$this->aCfg['orderby_text'] |
589
|
|
|
= $this->aCfg['orderby_text_asc']; |
590
|
|
|
} else { |
591
|
|
|
$dir_rev = 'asc'; |
592
|
|
|
$this->aCfg['orderby_dir'] = 'desc'; |
593
|
|
|
$this->aCfg['orderby_text'] |
594
|
|
|
= $this->aCfg['orderby_text_desc']; |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
// Url param |
598
|
|
|
// Empty idx will fill in tpl |
599
|
|
|
// Keep value of $this->aParam first |
600
|
|
|
$ar = $this->aParam; |
601
|
|
|
$this->aUrl['o_cur'] = $this->SetParam(array($this->aCfg['orderby_param'] . '_dir' => $dir_rev) |
602
|
|
|
, array($this->aCfg['orderby_param'] . '_idx')); |
603
|
|
|
// Same with cur dir, or all new 'asc' |
604
|
|
|
$this->aUrl['o_other'] = $this->SetParam(array($this->aCfg['orderby_param'] . '_dir'=> $this->aCfg['orderby_dir']) |
605
|
|
|
, array($this->aCfg['orderby_param'] . '_idx'));; |
606
|
|
|
// Restore value of $this->aParam |
607
|
|
|
$this->aParam = $ar; |
608
|
|
|
$this->oTpl->assignByRef('lt_url', $this->aUrl); |
609
|
|
|
} // end of func SetOrderby |
610
|
|
|
|
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* Set pager info |
614
|
|
|
* |
615
|
|
|
* Config data will also write to $aCfg, the difference with direct set config |
616
|
|
|
* is this will add more treatment about pager. |
617
|
|
|
* And use after SetCfg() |
618
|
|
|
* @param int $rows_total Total row/record number |
619
|
|
|
* @param int $page_cur Current displayed page, default is get from GET param |
620
|
|
|
* if fail, set to 1. |
621
|
|
|
* @see $aCfg |
622
|
|
|
*/ |
623
|
|
|
public function SetPager ($rows_total= 0, $page_cur = 0) { |
624
|
|
|
// Enable pager disp |
625
|
|
|
$this->aCfg['pager'] = true; |
626
|
|
|
|
627
|
|
|
// Auto compute total rows if not assigned |
628
|
|
|
if (0 == $rows_total) |
629
|
|
|
$rows_total = count($this->aData); |
630
|
|
|
$this->aCfg['rows_total'] = $rows_total; |
631
|
|
|
|
632
|
|
|
// Some param needed |
633
|
|
|
$page_cur = $this->ParsePageCur($page_cur); |
634
|
|
|
$page_size = $this->aCfg['page_size']; |
635
|
|
|
$page_max = ceil($rows_total / $page_size); |
636
|
|
|
|
637
|
|
|
// If data rows exceeds page_size, trim it |
638
|
|
|
if (count($this->aData) > $page_size) { |
639
|
|
|
// If page = 3/5, trim page 1, 2 first |
640
|
|
|
for ($i = 0; $i < ($page_cur - 1) * $page_size; $i ++) |
641
|
|
|
unset($this->aData[$i]); |
642
|
|
|
// Then trim page 4, 5 |
643
|
|
|
for ($i = $page_cur * $page_size; $i < $page_max * $page_size; $i ++) |
644
|
|
|
unset($this->aData[$i]); |
645
|
|
|
} |
646
|
|
|
|
647
|
|
|
$this->aCfg['pager_text_cur_value'] = str_replace( |
648
|
|
|
array('{page_cur}', '{page_max}', '{rows_total}', '{page_size}'), |
649
|
|
|
array($page_cur, $page_max, $rows_total, $page_size), |
650
|
|
|
$this->aCfg['pager_text_cur']); |
651
|
|
|
|
652
|
|
|
// Generate url for pager |
653
|
|
|
//$this->aUrl['base'] = GetSelfUrl(true); // Move to GetParam() |
654
|
|
|
if (1 < $page_cur) { |
655
|
|
|
// Not first page |
656
|
|
|
// $this->aUrl['first'] = $this->aUrl['base'] . '&' . $this->sId |
657
|
|
|
// . '-page_no=' . $page_cur; |
658
|
|
|
// $this->aUrl['prev'] = $this->aUrl['base'] . '&' . $this->sId |
659
|
|
|
// . '-page_no=' . ($page_cur - 1); |
660
|
|
|
$this->aUrl['p_first'] = $this->SetParam($this->aCfg['page_param'], 1); |
661
|
|
|
$this->aUrl['p_prev'] = $this->SetParam($this->aCfg['page_param'], $page_cur - 1); |
662
|
|
|
} else { |
663
|
|
|
$this->aUrl['p_first'] = ''; |
664
|
|
|
$this->aUrl['p_prev'] = ''; |
665
|
|
|
} |
666
|
|
|
if ($page_cur < $page_max) { |
667
|
|
|
// Not last page |
668
|
|
|
// $this->aUrl['next'] = $this->aUrl['base'] . '&' . $this->sId |
669
|
|
|
// . '-page_no=' . ($page_cur + 1); |
670
|
|
|
// $this->aUrl['last'] = $this->aUrl['base'] . '&' . $this->sId |
671
|
|
|
// . '-page_no=' . $page_max; |
672
|
|
|
$this->aUrl['p_next'] = $this->SetParam($this->aCfg['page_param'], $page_cur + 1); |
673
|
|
|
$this->aUrl['p_last'] = $this->SetParam($this->aCfg['page_param'], $page_max); |
674
|
|
|
} else { |
675
|
|
|
$this->aUrl['p_next'] = ''; |
676
|
|
|
$this->aUrl['p_last'] = ''; |
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
// Assign url to tpl |
680
|
|
|
$this->oTpl->assignByRef('lt_url', $this->aUrl); |
681
|
|
|
$this->oTpl->assign('lt_url_form', $this->SetParam(array(), $this->aCfg['page_param'])); |
682
|
|
|
|
683
|
|
|
// Assign hidden input |
684
|
|
|
if (!empty($this->aParam)) { |
685
|
|
|
$s = ''; |
686
|
|
|
foreach ($this->aParam as $k => $v) |
687
|
|
|
{ |
688
|
|
|
$k = filter_var($k, FILTER_SANITIZE_STRING ); |
689
|
|
|
$v = filter_var($v, FILTER_SANITIZE_STRING ); |
690
|
|
|
$s .= "<input type=\"hidden\" name=\"$k\" value=\"$v\" />\n"; |
691
|
|
|
} |
692
|
|
|
/*foreach ($this->aParam as $k => $v) |
693
|
|
|
$s .= "<input type=\"hidden\" name=\"$k\" value=\"$v\" />\n";*/ |
694
|
|
|
$this->oTpl->assign('lt_url_form_hidden', $s); |
695
|
|
|
$this->oTpl->assign('lt_url_form_hidden', $s); |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
// Add page_param deleted in above SetParam |
699
|
|
|
// needed to display right form url in next table in this page |
700
|
|
|
$this->SetParam($this->aCfg['page_param'], $page_cur); |
701
|
|
|
} // end of func SetPager |
702
|
|
|
|
703
|
|
|
|
704
|
|
|
/** |
705
|
|
|
* Set url param, get the url |
706
|
|
|
* |
707
|
|
|
* If $k is string, then $v is string too and means $k=$v. |
708
|
|
|
* if $k is array, then $v is array to, |
709
|
|
|
* and values in $k/$v is added/removed from url param. |
710
|
|
|
* Always 'save' setting and return result url. |
711
|
|
|
* |
712
|
|
|
* @param mixed $k |
713
|
|
|
* @param mixed $v |
714
|
|
|
* @return string |
715
|
|
|
* @see func/request.php::GetParam() |
716
|
|
|
*/ |
717
|
|
|
public function SetParam ($k, $v = '') { |
718
|
|
View Code Duplication |
if (!is_array($k) && !is_array($v)) { |
|
|
|
|
719
|
|
|
$this->aParam[addslashes($k)] = addslashes($v); |
720
|
|
|
} |
721
|
|
|
if (is_array($k)) { |
722
|
|
|
foreach ($k as $key => $val) |
723
|
|
|
$this->aParam[addslashes($key)] = addslashes($val); |
724
|
|
|
if (!is_array($v)) |
725
|
|
|
$v = array($v); |
726
|
|
|
foreach ($v as $val) |
727
|
|
|
if (isset($this->aParam[$val])) |
728
|
|
|
unset($this->aParam[$val]); |
729
|
|
|
} |
730
|
|
|
|
731
|
|
|
// Generate url and return |
732
|
|
|
$s = ''; |
733
|
|
|
foreach ($this->aParam as $k => $v) |
734
|
|
|
$s .= "&$k=$v"; |
735
|
|
|
if (!empty($s)) |
736
|
|
|
$s{0} = '?'; |
737
|
|
|
$s = $this->aUrl['base'] . $s; |
738
|
|
|
return filter_var($s, FILTER_SANITIZE_STRING); |
739
|
|
|
//return $s; |
740
|
|
|
} // end of func SetParam |
741
|
|
|
|
742
|
|
|
|
743
|
|
|
} // end class ListTable |
744
|
|
|
?> |
|
|
|
|
745
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.