1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* XOOPS Kernel Object |
4
|
|
|
* |
5
|
|
|
* You may not change or alter any portion of this comment or credits |
6
|
|
|
* of supporting developers from this source code or any supporting source code |
7
|
|
|
* which is considered copyrighted (c) material of the original comment or credit authors. |
8
|
|
|
* This program is distributed in the hope that it will be useful, |
9
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
10
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace Xoops\Core\Kernel; |
14
|
|
|
|
15
|
|
|
use Xoops\Core\Kernel\Dtype; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Establish Xoops object datatype legacy defines |
19
|
|
|
* New code should use Dtype::TYPE_* constants |
20
|
|
|
* |
21
|
|
|
* These will eventually be removed. See Xoops\Core\Kernel\Dtype for more. |
22
|
|
|
*/ |
23
|
|
|
define('XOBJ_DTYPE_TXTBOX', Dtype::TYPE_TEXT_BOX); |
24
|
|
|
define('XOBJ_DTYPE_TXTAREA', Dtype::TYPE_TEXT_AREA); |
25
|
|
|
define('XOBJ_DTYPE_INT', Dtype::TYPE_INTEGER); |
26
|
|
|
define('XOBJ_DTYPE_URL', Dtype::TYPE_URL); |
27
|
|
|
define('XOBJ_DTYPE_EMAIL', Dtype::TYPE_EMAIL); |
28
|
|
|
define('XOBJ_DTYPE_ARRAY', Dtype::TYPE_ARRAY); |
29
|
|
|
define('XOBJ_DTYPE_OTHER', Dtype::TYPE_OTHER); |
30
|
|
|
define('XOBJ_DTYPE_SOURCE', Dtype::TYPE_SOURCE); |
31
|
|
|
define('XOBJ_DTYPE_STIME', Dtype::TYPE_SHORT_TIME); |
32
|
|
|
define('XOBJ_DTYPE_MTIME', Dtype::TYPE_MEDIUM_TIME); |
33
|
|
|
define('XOBJ_DTYPE_LTIME', Dtype::TYPE_LONG_TIME); |
34
|
|
|
define('XOBJ_DTYPE_FLOAT', Dtype::TYPE_FLOAT); |
35
|
|
|
define('XOBJ_DTYPE_DECIMAL', Dtype::TYPE_DECIMAL); |
36
|
|
|
define('XOBJ_DTYPE_ENUM', Dtype::TYPE_ENUM); |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Base class for all objects in the Xoops kernel (and beyond) |
40
|
|
|
* |
41
|
|
|
* @category Xoops\Core\Kernel\XoopsObject |
42
|
|
|
* @package Xoops\Core\Kernel |
43
|
|
|
* @author Kazumi Ono (AKA onokazu) <http://www.myweb.ne.jp/, http://jp.xoops.org/> |
44
|
|
|
* @author Taiwen Jiang <[email protected]> |
45
|
|
|
* @copyright 2000-2015 XOOPS Project (http://xoops.org) |
46
|
|
|
* @license GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html) |
47
|
|
|
* @link http://xoops.org |
48
|
|
|
* @since 2.0.0 |
49
|
|
|
*/ |
50
|
|
|
abstract class XoopsObject implements \ArrayAccess |
51
|
|
|
{ |
52
|
|
|
/** |
53
|
|
|
* holds all variables(properties) of an object |
54
|
|
|
* |
55
|
|
|
* @var array |
56
|
|
|
*/ |
57
|
|
|
public $vars = array(); |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* variables cleaned for store in DB |
61
|
|
|
* |
62
|
|
|
* @var array |
63
|
|
|
*/ |
64
|
|
|
public $cleanVars = array(); |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* is it a newly created object? |
68
|
|
|
* |
69
|
|
|
* @var bool |
70
|
|
|
*/ |
71
|
|
|
private $isNew = false; |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* has any of the values been modified? |
75
|
|
|
* |
76
|
|
|
* @var bool |
77
|
|
|
*/ |
78
|
|
|
private $isDirty = false; |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* errors |
82
|
|
|
* |
83
|
|
|
* @var array |
84
|
|
|
*/ |
85
|
|
|
private $errors = array(); |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @var string |
89
|
|
|
*/ |
90
|
|
|
public $plugin_path; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* constructor |
94
|
|
|
* |
95
|
|
|
* normally, this is called from child classes only |
96
|
|
|
* |
97
|
|
|
* @access public |
98
|
|
|
*/ |
99
|
22 |
|
public function __construct() |
100
|
|
|
{ |
101
|
22 |
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* used for new/clone objects |
105
|
|
|
* |
106
|
|
|
* @return void |
107
|
|
|
*/ |
108
|
17 |
|
public function setNew() |
109
|
|
|
{ |
110
|
17 |
|
$this->isNew = true; |
111
|
17 |
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* clear new flag |
115
|
|
|
* |
116
|
|
|
* @return void |
117
|
|
|
*/ |
118
|
8 |
|
public function unsetNew() |
119
|
|
|
{ |
120
|
8 |
|
$this->isNew = false; |
121
|
8 |
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* check new flag |
125
|
|
|
* |
126
|
|
|
* @return bool |
127
|
|
|
*/ |
128
|
12 |
|
public function isNew() |
129
|
|
|
{ |
130
|
12 |
|
return $this->isNew; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* mark modified objects as dirty |
135
|
|
|
* |
136
|
|
|
* used for modified objects only |
137
|
|
|
* |
138
|
|
|
* @return void |
139
|
|
|
*/ |
140
|
29 |
|
public function setDirty() |
141
|
|
|
{ |
142
|
29 |
|
$this->isDirty = true; |
143
|
29 |
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* cleaar dirty flag |
147
|
|
|
* |
148
|
|
|
* @return void |
149
|
|
|
*/ |
150
|
14 |
|
public function unsetDirty() |
151
|
|
|
{ |
152
|
14 |
|
$this->isDirty = false; |
153
|
14 |
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* check dirty flag |
157
|
|
|
* |
158
|
|
|
* @return bool |
159
|
|
|
*/ |
160
|
14 |
|
public function isDirty() |
161
|
|
|
{ |
162
|
14 |
|
return $this->isDirty; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* initialize variables for the object |
167
|
|
|
* |
168
|
|
|
* @param string $key key |
169
|
|
|
* @param int $data_type set to one of Dtype::TYPE_XXX constants (set to Dtype::TYPE_OTHER |
170
|
|
|
* if no data type checking nor text sanitizing is required) |
171
|
|
|
* @param mixed $value value |
172
|
|
|
* @param bool $required require html form input? |
173
|
|
|
* @param mixed $maxlength for Dtype::TYPE_TEXT_BOX type only |
174
|
|
|
* @param string $options does this data have any select options? |
175
|
|
|
* |
176
|
|
|
* @return void |
177
|
|
|
*/ |
178
|
286 |
|
public function initVar($key, $data_type, $value = null, $required = false, $maxlength = null, $options = '') |
179
|
|
|
{ |
180
|
286 |
|
$this->vars[$key] = array( |
181
|
286 |
|
'value' => $value, |
182
|
286 |
|
'required' => $required, |
183
|
286 |
|
'data_type' => $data_type, |
184
|
286 |
|
'maxlength' => $maxlength, |
185
|
|
|
'changed' => false, |
186
|
286 |
|
'options' => $options |
187
|
|
|
); |
188
|
286 |
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* assign a value to a variable |
192
|
|
|
* |
193
|
|
|
* @param string $key name of the variable to assign |
194
|
|
|
* @param mixed $value value to assign |
195
|
|
|
* |
196
|
|
|
* @return void |
197
|
|
|
*/ |
198
|
54 |
|
public function assignVar($key, $value) |
199
|
|
|
{ |
200
|
54 |
View Code Duplication |
if (isset($key) && isset($this->vars[$key])) { |
201
|
54 |
|
$this->vars[$key]['value'] = $value; |
202
|
|
|
} |
203
|
54 |
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* assign values to multiple variables in a batch |
207
|
|
|
* |
208
|
|
|
* @param array $var_arr associative array of values to assign |
209
|
|
|
* |
210
|
|
|
* @return void |
211
|
|
|
*/ |
212
|
45 |
|
public function assignVars($var_arr) |
213
|
|
|
{ |
214
|
45 |
|
if (is_array($var_arr)) { |
215
|
45 |
|
foreach ($var_arr as $key => $value) { |
216
|
45 |
|
$this->assignVar($key, $value); |
217
|
|
|
} |
218
|
|
|
} |
219
|
45 |
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* assign a value to a variable |
223
|
|
|
* |
224
|
|
|
* @param string $key name of the variable to assign |
225
|
|
|
* @param mixed $value value to assign |
226
|
|
|
* |
227
|
|
|
* @return void |
228
|
|
|
*/ |
229
|
27 |
|
public function setVar($key, $value) |
230
|
|
|
{ |
231
|
27 |
|
if (!empty($key) && isset($value) && isset($this->vars[$key])) { |
232
|
27 |
|
$this->vars[$key]['value'] = $value; |
233
|
27 |
|
$this->vars[$key]['changed'] = true; |
234
|
27 |
|
$this->setDirty(); |
235
|
|
|
} |
236
|
27 |
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* assign values to multiple variables in a batch |
240
|
|
|
* |
241
|
|
|
* @param array $var_arr associative array of values to assign |
242
|
|
|
* |
243
|
|
|
* @return void |
244
|
|
|
*/ |
245
|
1 |
|
public function setVars($var_arr) |
246
|
|
|
{ |
247
|
1 |
|
if (is_array($var_arr)) { |
248
|
1 |
|
foreach ($var_arr as $key => $value) { |
249
|
1 |
|
$this->setVar($key, $value); |
250
|
|
|
} |
251
|
|
|
} |
252
|
1 |
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* unset variable(s) for the object |
256
|
|
|
* |
257
|
|
|
* @param mixed $var variable(s) |
258
|
|
|
* |
259
|
|
|
* @return bool |
260
|
|
|
*/ |
261
|
1 |
|
public function destroyVars($var) |
262
|
|
|
{ |
263
|
1 |
|
if (empty($var)) { |
264
|
1 |
|
return true; |
265
|
|
|
} |
266
|
|
|
$var = !is_array($var) ? array($var) : $var; |
267
|
|
|
foreach ($var as $key) { |
268
|
|
|
if (!isset($this->vars[$key])) { |
269
|
|
|
continue; |
270
|
|
|
} |
271
|
|
|
$this->vars[$key]['changed'] = null; |
272
|
|
|
} |
273
|
|
|
return true; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* Assign values to multiple variables in a batch |
278
|
|
|
* |
279
|
|
|
* Meant for a CGI context: |
280
|
|
|
* - prefixed CGI args are considered save |
281
|
|
|
* - avoids polluting of namespace with CGI args |
282
|
|
|
* |
283
|
|
|
* @param mixed $var_arr associative array of values to assign |
284
|
|
|
* @param string $pref prefix (only keys starting with the prefix will be set) |
285
|
|
|
* |
286
|
|
|
* @return void |
287
|
|
|
*/ |
288
|
1 |
|
public function setFormVars($var_arr = null, $pref = 'xo_') |
289
|
|
|
{ |
290
|
1 |
|
$len = strlen($pref); |
291
|
1 |
|
if (is_array($var_arr)) { |
292
|
1 |
|
foreach ($var_arr as $key => $value) { |
293
|
1 |
|
if ($pref == substr($key, 0, $len)) { |
294
|
1 |
|
$this->setVar(substr($key, $len), $value); |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
} |
298
|
1 |
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* returns all variables for the object |
302
|
|
|
* |
303
|
|
|
* @return array associative array of key->value pairs |
304
|
|
|
*/ |
305
|
26 |
|
public function getVars() |
306
|
|
|
{ |
307
|
26 |
|
return $this->vars; |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Returns the values of the specified variables |
312
|
|
|
* |
313
|
|
|
* @param mixed $keys An array containing the names of the keys to retrieve, or null to get all of them |
314
|
|
|
* @param string $format Format to use (see getVar) |
315
|
|
|
* @param int $maxDepth Maximum level of recursion to use if some vars are objects themselves |
316
|
|
|
* |
317
|
|
|
* @return array associative array of key->value pairs |
318
|
|
|
*/ |
319
|
3 |
|
public function getValues($keys = null, $format = Dtype::FORMAT_SHOW, $maxDepth = 1) |
320
|
|
|
{ |
321
|
3 |
|
if (!isset($keys)) { |
322
|
3 |
|
$keys = array_keys($this->vars); |
323
|
|
|
} |
324
|
3 |
|
$vars = array(); |
325
|
3 |
|
if (is_array($keys)) { |
326
|
3 |
|
foreach ($keys as $key) { |
327
|
3 |
|
if (isset($this->vars[$key])) { |
328
|
3 |
|
if (is_object($this->vars[$key]) && is_a($this->vars[$key], 'Xoops\Core\Kernel\XoopsObject')) { |
329
|
|
|
if ($maxDepth) { |
330
|
|
|
/* @var $obj XoopsObject */ |
331
|
|
|
$obj = $this->vars[$key]; |
332
|
|
|
$vars[$key] = $obj->getValues(null, $format, $maxDepth - 1); |
333
|
|
|
} |
334
|
|
|
} else { |
335
|
3 |
|
$vars[$key] = $this->getVar($key, $format); |
336
|
|
|
} |
337
|
|
|
} |
338
|
|
|
} |
339
|
|
|
} |
340
|
3 |
|
return $vars; |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* returns a specific variable for the object in a proper format |
345
|
|
|
* |
346
|
|
|
* @param string $key key of the object's variable to be returned |
347
|
|
|
* @param string $format format to use for the output |
348
|
|
|
* |
349
|
|
|
* @return mixed formatted value of the variable |
350
|
|
|
*/ |
351
|
186 |
|
public function getVar($key, $format = Dtype::FORMAT_SHOW) |
352
|
|
|
{ |
353
|
186 |
|
$ret = null; |
354
|
186 |
|
if (!isset($this->vars[$key])) { |
355
|
1 |
|
return $ret; |
356
|
|
|
} |
357
|
186 |
|
$ret = Dtype::getVar($this, $key, $format); |
358
|
186 |
|
return $ret; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* clean values of all variables of the object for storage. |
363
|
|
|
* |
364
|
|
|
* @return bool true if successful |
365
|
|
|
*/ |
366
|
3 |
|
public function cleanVars() |
367
|
|
|
{ |
368
|
3 |
|
$existing_errors = $this->getErrors(); |
369
|
3 |
|
$this->errors = array(); |
370
|
3 |
|
foreach ($this->vars as $k => $v) { |
371
|
3 |
|
if (!$v['changed']) { |
|
|
|
|
372
|
|
|
} else { |
373
|
3 |
|
$this->cleanVars[$k] = Dtype::cleanVar($this, $k); |
374
|
|
|
} |
375
|
|
|
} |
376
|
3 |
|
if (count($this->errors) > 0) { |
377
|
|
|
$this->errors = array_merge($existing_errors, $this->errors); |
378
|
|
|
return false; |
379
|
|
|
} |
380
|
|
|
// $this->_errors = array_merge($existing_errors, $this->_errors); |
381
|
3 |
|
$this->unsetDirty(); |
382
|
3 |
|
return true; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* create a clone(copy) of the current object |
387
|
|
|
* |
388
|
|
|
* @return object clone |
389
|
|
|
*/ |
390
|
1 |
|
public function xoopsClone() |
391
|
|
|
{ |
392
|
1 |
|
$clone = clone $this; |
393
|
1 |
|
return $clone; |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Adjust a newly cloned object |
398
|
|
|
*/ |
399
|
1 |
|
public function __clone() |
400
|
|
|
{ |
401
|
|
|
// need this to notify the handler class that this is a newly created object |
402
|
1 |
|
$this->setNew(); |
403
|
1 |
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* add an error |
407
|
|
|
* |
408
|
|
|
* @param string $err_str to add |
409
|
|
|
* |
410
|
|
|
* @return void |
411
|
|
|
*/ |
412
|
2 |
|
public function setErrors($err_str) |
413
|
|
|
{ |
414
|
2 |
|
if (is_array($err_str)) { |
415
|
1 |
|
$this->errors = array_merge($this->errors, $err_str); |
416
|
|
|
} else { |
417
|
2 |
|
$this->errors[] = trim($err_str); |
418
|
|
|
} |
419
|
2 |
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* return the errors for this object as an array |
423
|
|
|
* |
424
|
|
|
* @return array an array of errors |
425
|
|
|
*/ |
426
|
14 |
|
public function getErrors() |
427
|
|
|
{ |
428
|
14 |
|
return $this->errors; |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
/** |
432
|
|
|
* return the errors for this object as html |
433
|
|
|
* |
434
|
|
|
* @return string html listing the errors |
435
|
|
|
* @todo remove hardcoded HTML strings |
436
|
|
|
*/ |
437
|
1 |
|
public function getHtmlErrors() |
438
|
|
|
{ |
439
|
1 |
|
$ret = '<h4>Errors</h4>'; |
440
|
1 |
|
if (!empty($this->errors)) { |
441
|
1 |
|
foreach ($this->errors as $error) { |
442
|
1 |
|
$ret .= $error . '<br />'; |
443
|
|
|
} |
444
|
|
|
} else { |
445
|
|
|
$ret .= 'None<br />'; |
446
|
|
|
} |
447
|
1 |
|
return $ret; |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Get object variables as an array |
452
|
|
|
* |
453
|
|
|
* @return array of object values |
454
|
|
|
*/ |
455
|
1 |
|
public function toArray() |
456
|
|
|
{ |
457
|
1 |
|
return $this->getValues(); |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* ArrayAccess methods |
462
|
|
|
*/ |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* offsetExists |
466
|
|
|
* |
467
|
|
|
* @param mixed $offset array key |
468
|
|
|
* |
469
|
|
|
* @return bool true if offset exists |
470
|
|
|
*/ |
471
|
2 |
|
public function offsetExists($offset) |
472
|
|
|
{ |
473
|
2 |
|
return isset($this->vars[$offset]); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
/** |
477
|
|
|
* offsetGet |
478
|
|
|
* |
479
|
|
|
* @param mixed $offset array key |
480
|
|
|
* |
481
|
|
|
* @return mixed value |
482
|
|
|
*/ |
483
|
2 |
|
public function offsetGet($offset) |
484
|
|
|
{ |
485
|
2 |
|
return $this->getVar($offset); |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* offsetSet |
490
|
|
|
* |
491
|
|
|
* @param mixed $offset array key |
492
|
|
|
* @param mixed $value |
493
|
|
|
* |
494
|
|
|
* @return void |
495
|
|
|
*/ |
496
|
6 |
|
public function offsetSet($offset, $value) |
497
|
|
|
{ |
498
|
6 |
|
$this->setVar($offset, $value); |
499
|
6 |
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* offsetUnset |
503
|
|
|
* |
504
|
|
|
* @param mixed $offset array key |
505
|
|
|
* |
506
|
|
|
* @return void |
507
|
|
|
*/ |
508
|
1 |
|
public function offsetUnset($offset) |
509
|
|
|
{ |
510
|
1 |
|
$this->vars[$offset]['value'] = null; |
511
|
1 |
|
$this->vars[$offset]['changed'] = true; |
512
|
1 |
|
$this->setDirty(); |
513
|
1 |
|
} |
514
|
|
|
} |
515
|
|
|
|
This check looks for the bodies of
if
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
if
bodies can be removed. If you have an empty if but statements in theelse
branch, consider inverting the condition.could be turned into
This is much more concise to read.