Completed
Pull Request — master (#462)
by Richard
15:21
created

XoopsObject::toArray()   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
Metric Value
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']) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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 the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
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 1
    public function toArray()
525
    {
526 1
        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