Completed
Push — stdsmarty ( b2664a...5d7a52 )
by Richard
06:30
created

XoopsObject::getErrors()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
ccs 2
cts 2
cp 1
cc 1
eloc 2
nc 1
nop 0
crap 1
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
     * additional filters registered dynamically by a child class object
89
     *
90
     * @var array
91
     */
92
    private $filters = array();
93
94
    /**
95
     * @var string
96
     */
97
    public $plugin_path;
98
99
    /**
100
     * used for new/clone objects
101
     *
102
     * @return void
103
     */
104 13
    public function setNew()
105
    {
106 13
        $this->isNew = true;
107 13
    }
108
109
    /**
110
     * clear new flag
111
     *
112
     * @return void
113
     */
114 8
    public function unsetNew()
115
    {
116 8
        $this->isNew = false;
117 8
    }
118
119
    /**
120
     * check new flag
121
     *
122
     * @return bool
123
     */
124 12
    public function isNew()
125
    {
126 12
        return $this->isNew;
127
    }
128
129
    /**
130
     * mark modified objects as dirty
131
     *
132
     * used for modified objects only
133
     *
134
     * @return void
135
     */
136 29
    public function setDirty()
137
    {
138 29
        $this->isDirty = true;
139 29
    }
140
141
    /**
142
     * cleaar dirty flag
143
     *
144
     * @return void
145
     */
146 14
    public function unsetDirty()
147
    {
148 14
        $this->isDirty = false;
149 14
    }
150
151
    /**
152
     * check dirty flag
153
     *
154
     * @return bool
155
     */
156 14
    public function isDirty()
157
    {
158 14
        return $this->isDirty;
159
    }
160
161
    /**
162
     * initialize variables for the object
163
     *
164
     * @param string $key       key
165
     * @param int    $data_type set to one of Dtype::TYPE_XXX constants (set to Dtype::TYPE_OTHER
166
     *                           if no data type checking nor text sanitizing is required)
167
     * @param mixed  $value     value
168
     * @param bool   $required  require html form input?
169
     * @param mixed  $maxlength for Dtype::TYPE_TEXT_BOX type only
170
     * @param string $options   does this data have any select options?
171
     *
172
     * @return void
173
     */
174 273
    public function initVar($key, $data_type, $value = null, $required = false, $maxlength = null, $options = '')
175
    {
176 273
        $this->vars[$key] = array(
177 273
            'value' => $value,
178 273
            'required' => $required,
179 273
            'data_type' => $data_type,
180 273
            'maxlength' => $maxlength,
181 273
            'changed' => false,
182
            'options' => $options
183 273
        );
184 273
    }
185
186
    /**
187
     * assign a value to a variable
188
     *
189
     * @param string $key   name of the variable to assign
190
     * @param mixed  $value value to assign
191
     *
192
     * @return void
193
     */
194 49
    public function assignVar($key, $value)
195
    {
196 49 View Code Duplication
        if (isset($key) && isset($this->vars[$key])) {
197 49
            $this->vars[$key]['value'] = $value;
198 49
        }
199 49
    }
200
201
    /**
202
     * assign values to multiple variables in a batch
203
     *
204
     * @param array $var_arr associative array of values to assign
205
     *
206
     * @return void
207
     */
208 40
    public function assignVars($var_arr)
209
    {
210 40
        if (is_array($var_arr)) {
211 40
            foreach ($var_arr as $key => $value) {
212 40
                $this->assignVar($key, $value);
213 40
            }
214 40
        }
215 40
    }
216
217
    /**
218
     * assign a value to a variable
219
     *
220
     * @param string $key     name of the variable to assign
221
     * @param mixed  $value   value to assign
222
     *
223
     * @return void
224
     */
225 27
    public function setVar($key, $value)
226
    {
227 27
        if (!empty($key) && isset($value) && isset($this->vars[$key])) {
228 27
            $this->vars[$key]['value'] = $value;
229 27
            $this->vars[$key]['changed'] = true;
230 27
            $this->setDirty();
231 27
        }
232 27
    }
233
234
    /**
235
     * assign values to multiple variables in a batch
236
     *
237
     * @param array $var_arr associative array of values to assign
238
     *
239
     * @return void
240
     */
241 1
    public function setVars($var_arr)
242
    {
243 1
        if (is_array($var_arr)) {
244 1
            foreach ($var_arr as $key => $value) {
245 1
                $this->setVar($key, $value);
246 1
            }
247 1
        }
248 1
    }
249
250
    /**
251
     * unset variable(s) for the object
252
     *
253
     * @param mixed $var variable(s)
254
     *
255
     * @return bool
256
     */
257 1
    public function destroyVars($var)
258
    {
259 1
        if (empty($var)) {
260 1
            return true;
261
        }
262
        $var = !is_array($var) ? array($var) : $var;
263
        foreach ($var as $key) {
264
            if (!isset($this->vars[$key])) {
265
                continue;
266
            }
267
            $this->vars[$key]['changed'] = null;
268
        }
269
        return true;
270
    }
271
272
    /**
273
     * Assign values to multiple variables in a batch
274
     *
275
     * Meant for a CGI context:
276
     * - prefixed CGI args are considered save
277
     * - avoids polluting of namespace with CGI args
278
     *
279
     * @param mixed  $var_arr associative array of values to assign
280
     * @param string $pref    prefix (only keys starting with the prefix will be set)
281
     *
282
     * @return void
283
     */
284 1
    public function setFormVars($var_arr = null, $pref = 'xo_')
285
    {
286 1
        $len = strlen($pref);
287 1
        if (is_array($var_arr)) {
288 1
            foreach ($var_arr as $key => $value) {
289 1
                if ($pref == substr($key, 0, $len)) {
290 1
                    $this->setVar(substr($key, $len), $value);
291 1
                }
292 1
            }
293 1
        }
294 1
    }
295
296
    /**
297
     * returns all variables for the object
298
     *
299
     * @return array associative array of key->value pairs
300
     */
301 26
    public function getVars()
302
    {
303 26
        return $this->vars;
304
    }
305
306
    /**
307
     * Returns the values of the specified variables
308
     *
309
     * @param mixed  $keys     An array containing the names of the keys to retrieve, or null to get all of them
310
     * @param string $format   Format to use (see getVar)
311
     * @param int    $maxDepth Maximum level of recursion to use if some vars are objects themselves
312
     *
313
     * @return array associative array of key->value pairs
314
     */
315 3
    public function getValues($keys = null, $format = Dtype::FORMAT_SHOW, $maxDepth = 1)
316
    {
317 3
        if (!isset($keys)) {
318 3
            $keys = array_keys($this->vars);
319 3
        }
320 3
        $vars = array();
321 3
        if (is_array($keys)) {
322 3
            foreach ($keys as $key) {
323 3
                if (isset($this->vars[$key])) {
324 3
                    if (is_object($this->vars[$key]) && is_a($this->vars[$key], 'Xoops\Core\Kernel\XoopsObject')) {
325
                        if ($maxDepth) {
326
                            /* @var $obj XoopsObject */
327
                            $obj = $this->vars[$key];
328
                            $vars[$key] = $obj->getValues(null, $format, $maxDepth - 1);
329
                        }
330
                    } else {
331 3
                        $vars[$key] = $this->getVar($key, $format);
332
                    }
333 3
                }
334 3
            }
335 3
        }
336 3
        return $vars;
337
    }
338
339
    /**
340
     * returns a specific variable for the object in a proper format
341
     *
342
     * @param string $key    key of the object's variable to be returned
343
     * @param string $format format to use for the output
344
     *
345
     * @return mixed formatted value of the variable
346
     */
347 181
    public function getVar($key, $format = Dtype::FORMAT_SHOW)
348
    {
349 181
        $ret = null;
350 181
        if (!isset($this->vars[$key])) {
351 1
            return $ret;
352
        }
353 181
        $ret = Dtype::getVar($this, $key, $format);
354 181
        return $ret;
355
    }
356
357
    /**
358
     * clean values of all variables of the object for storage.
359
     *
360
     * @return bool true if successful
361
     */
362 3
    public function cleanVars()
363
    {
364 3
        $existing_errors = $this->getErrors();
365 3
        $this->errors = array();
366 3
        foreach ($this->vars as $k => $v) {
367 3
            if (!$v['changed']) {
368 1
            } else {
369 3
                $this->cleanVars[$k] = Dtype::cleanVar($this, $k);
370
            }
371 3
        }
372 3
        if (count($this->errors) > 0) {
373
            $this->errors = array_merge($existing_errors, $this->errors);
374
            return false;
375
        }
376
        // $this->_errors = array_merge($existing_errors, $this->_errors);
377 3
        $this->unsetDirty();
378 3
        return true;
379
    }
380
381
    /**
382
     * dynamically register additional filter for the object
383
     *
384
     * @param string $filtername name of the filter
385
     *
386
     * @return void
387
     */
388
    public function registerFilter($filtername)
389
    {
390
        $this->filters[] = $filtername;
391
    }
392
393
    /**
394
     * load all additional filters that have been registered to the object
395
     *
396
     * @return void
397
     */
398
    private function internalLoadFilters()
399
    {
400
        static $loaded;
401
        if (isset($loaded)) {
402
            return;
403
        }
404
        $loaded = 1;
405
406
        $path = empty($this->plugin_path) ? __DIR__ . '/filters' : $this->plugin_path;
407
        if (\XoopsLoad::fileExists($file = $path . '/filter.php')) {
408
            include_once $file;
409
            if (is_array($this->filters)) {
410
                foreach ($this->filters as $f) {
411
                    if (\XoopsLoad::fileExists($file = $path . '/' . strtolower($f) . 'php')) {
412
                        include_once $file;
413
                    }
414
                }
415
            }
416
        }
417
    }
418
419
    /**
420
     * load all local filters for the object
421
     *
422
     * Filter distribution:
423
     * In each module folder there is a folder "filter" containing filter files with,
424
     * filename: [name_of_target_class][.][function/action_name][.php];
425
     * function name: [dirname][_][name_of_target_class][_][function/action_name];
426
     * parameter: the target object
427
     *
428
     * @param string $method function or action name
429
     *
430
     * @return void
431
     */
432
    public function loadFilters($method)
433
    {
434
        $this->internalLoadFilters();
435
436
        $class = get_class($this);
437
        $modules_active = \Xoops::getInstance()->getActiveModules();
438
        if (is_array($modules_active)) {
439
            foreach ($modules_active as $dirname) {
440
                $file = \XoopsBaseConfig::get('root-path') . '/modules/'
441
                    . $dirname . '/filter/' . $class . '.' . $method . '.php';
442
                if (\XoopsLoad::fileExists($file)) {
443
                    include_once $file;
444
                    $function = $dirname . '_' . $class . '_' . $method;
445
                    if (function_exists($function)) {
446
                        call_user_func_array($function, array(&$this));
447
                    }
448
                }
449
            }
450
        }
451
    }
452
453
    /**
454
     * create a clone(copy) of the current object
455
     *
456
     * @return object clone
457
     */
458 1
    public function xoopsClone()
459
    {
460 1
        $clone = clone $this;
461 1
        return $clone;
462
    }
463
464
    /**
465
     * Adjust a newly cloned object
466
     */
467 1
    public function __clone()
468
    {
469
        // need this to notify the handler class that this is a newly created object
470 1
        $this->setNew();
471 1
    }
472
473
    /**
474
     * add an error
475
     *
476
     * @param string $err_str to add
477
     *
478
     * @return void
479
     */
480 2
    public function setErrors($err_str)
481
    {
482 2
        if (is_array($err_str)) {
483 1
            $this->errors = array_merge($this->errors, $err_str);
484 1
        } else {
485 2
            $this->errors[] = trim($err_str);
486
        }
487 2
    }
488
489
    /**
490
     * return the errors for this object as an array
491
     *
492
     * @return array an array of errors
493
     */
494 14
    public function getErrors()
495
    {
496 14
        return $this->errors;
497
    }
498
499
    /**
500
     * return the errors for this object as html
501
     *
502
     * @return string html listing the errors
503
     * @todo remove hardcoded HTML strings
504
     */
505 1
    public function getHtmlErrors()
506
    {
507 1
        $ret = '<h4>Errors</h4>';
508 1
        if (!empty($this->errors)) {
509 1
            foreach ($this->errors as $error) {
510 1
                $ret .= $error . '<br />';
511 1
            }
512 1
        } else {
513
            $ret .= 'None<br />';
514
        }
515 1
        return $ret;
516
    }
517
518
    /**
519
     * toArray
520
     *
521
     * @deprecated
522
     * @return array
523
     */
524
    public function toArray()
525
    {
526
        return $this->getValues();
527
    }
528
529
    /**
530
     * ArrayAccess methods
531
     */
532
533
    /**
534
     * offsetExists
535
     *
536
     * @param mixed $offset array key
537
     *
538
     * @return bool true if offset exists
539
     */
540 2
    public function offsetExists($offset)
541
    {
542 2
        return isset($this->vars[$offset]);
543
    }
544
545
    /**
546
     * offsetGet
547
     *
548
     * @param mixed $offset array key
549
     *
550
     * @return mixed value
551
     */
552 2
    public function offsetGet($offset)
553
    {
554 2
        return $this->getVar($offset);
555
    }
556
557
    /**
558
     * offsetSet
559
     *
560
     * @param mixed $offset array key
561
     * @param mixed $value
562
     *
563
     * @return void
564
     */
565 6
    public function offsetSet($offset, $value)
566
    {
567 6
        $this->setVar($offset, $value);
568 6
    }
569
570
    /**
571
     * offsetUnset
572
     *
573
     * @param mixed $offset array key
574
     *
575
     * @return void
576
     */
577 1
    public function offsetUnset($offset)
578
    {
579 1
        $this->vars[$offset]['value'] = null;
580 1
        $this->vars[$offset]['changed'] = true;
581 1
        $this->setDirty();
582 1
    }
583
}
584