Issues (407)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/PersistableObjectHandler.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * ****************************************************************************
4
 * myshop - MODULE FOR XOOPS
5
 * Copyright (c) Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
6
 *
7
 * You may not change or alter any portion of this comment or credits
8
 * of supporting developers from this source code or any supporting source code
9
 * which is considered copyrighted (c) material of the original comment or credit authors.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 *
14
 * @copyright       Jan Pedersen
15
 * @copyright       Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
16
 * @license         http://www.fsf.org/copyleft/gpl.html GNU public license
17
 * @package         references
18
 * @author          Jan Pedersen
19
 * @author          Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
20
 *
21
 * ****************************************************************************
22
 */
23
24
defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
25
26
class references_Object extends XoopsObject
27
{
28
    public function toArray($format = 's')
29
    {
30
        $ret = array();
31
        foreach ($this->vars as $k => $v) {
32
            $ret[$k] = $this->getVar($k, $format);
33
        }
34
35
        return $ret;
36
    }
37
38
    // TODO: Rajouter une méthode intsert() et delete()
39
40
    /**
41
     * Permet de valoriser un champ de la table comme si c'était une propriété de la classe
42
     *
43
     * @example $enregistrement->nom_du_champ = 'ma chaine'
44
     *
45
     * @param string $key   Le nom du champ Ă  traiter
46
     * @param mixed  $value La valeur Ă  lui attribuer
47
     * @return void
48
     */
49
    public function __set($key, $value)
50
    {
51
        return $this->setVar($key, $value);
52
    }
53
54
    /**
55
     * Permet d'accéder aux champs de la table comme à des propriétés de la classe
56
     *
57
     * @example echo $enregistrement->nom_du_champ;
58
     *
59
     * @param string $key Le nom du champ que l'on souhaite récupérer
60
     * @return mixed
61
     */
62
    public function __get($key)
63
    {
64
        return $this->getVar($key);
65
    }
66
}
67
68
/**
69
 * Persistable Object Handler class.
70
 * This class is responsible for providing data access mechanisms to the data source
71
 * of derived class objects. Original Author : Mithrandir
72
 *
73
 */
74
class references_XoopsPersistableObjectHandler extends XoopsObjectHandler
75
{
76
    /**#@+
77
     * Information about the class, the handler is managing
78
     *
79
     * @var string
80
     */
81
    public    $table;
82
    public    $keyName;
83
    public    $className;
84
    public    $identifierName;
85
    protected $cacheOptions = array();
86
    /**#@-*/
87
88
    /**
89
     * Constructor - called from child classes
90
     * @param object $db           {@link XoopsDatabase} object
91
     * @param string $tablename    Name of database table
92
     * @param string $classname    Name of Class, this handler is managing
93
     * @param string $keyname      Name of the property, holding the key
94
     * @param string $idenfierName Name of the property, holding the label
95
     * @param array  $cacheOptions Optional, options for the cache
96
     *
97
     */
98
    public function __construct(&$db, $tablename, $classname, $keyname, $idenfierName = '', $cacheOptions = null)
99
    {
100
        parent::__construct($db);
101
        $this->table     = $db->prefix($tablename);
102
        $this->keyName   = $keyname;
103
        $this->className = $classname;
104
        if (trim($idenfierName) != '') {
105
            $this->identifierName = $idenfierName;
106
        }
107
        // To diable cache, add this line after the first one : 'caching' => false,
108
        if (is_null($cacheOptions)) {
109
            $this->setCachingOptions(array('cacheDir' => REFERENCES_CACHE_PATH, 'lifeTime' => null, 'automaticSerialization' => true, 'fileNameProtection' => false));
110
        } else {
111
            $this->setCachingOptions($cacheOptions);
112
        }
113
    }
114
115
    public function setCachingOptions($cacheOptions)
116
    {
117
        $this->cacheOptions = $cacheOptions;
118
    }
119
120
    /**
121
     * Generates a unique ID for a Sql Query
122
     *
123
     * @param  string  $query The SQL query for which we want a unidque ID
124
     * @param  integer $start Which record to start at
125
     * @param  integer $limit Max number of objects to fetch
126
     * @return string  An MD5 of the query
127
     */
128
    protected function _getIdForCache($query, $start, $limit)
129
    {
130
        $id = md5($query . '-' . (string)$start . '-' . (string)$limit);
131
132
        return $id;
133
    }
134
135
    /**
136
     * create a new object
137
     *
138
     * @param bool $isNew Flag the new objects as "new"?
139
     *
140
     * @return object
141
     */
142
    public function &create($isNew = true)
143
    {
144
        $obj = new $this->className();
145
        if ($isNew === true) {
146
            $obj->setNew();
147
        }
148
149
        return $obj;
150
    }
151
152
    /**
153
     * retrieve an object
154
     *
155
     * @param  mixed $id        ID of the object - or array of ids for joint keys. Joint keys MUST be given in the same order as in the constructor
156
     * @param  bool  $as_object whether to return an object or an array
157
     * @return mixed reference to the object, FALSE if failed
158
     */
159
    public function &get($id, $as_object = true)
160
    {
161
        if (is_array($this->keyName)) {
162
            $criteria = new CriteriaCompo();
163
            $vnb      = count($this->keyName);
164
            for ($i = 0; $i < $vnb; ++$i) {
165
                $criteria->add(new Criteria($this->keyName[$i], (int)$id[$i]));
166
            }
167
        } else {
168
            $criteria = new Criteria($this->keyName, (int)$id);
169
        }
170
        $criteria->setLimit(1);
171
        $obj_array = $this->getObjects($criteria, false, $as_object);
172
        if (count($obj_array) != 1) {
173
            $ret = null;
174
        } else {
175
            $ret =& $obj_array[0];
176
        }
177
178
        return $ret;
179
    }
180
181
    /**
182
     * retrieve objects from the database
183
     *
184
     * @param null|CriteriaElement $criteria  {@link CriteriaElement} conditions to be met
185
     * @param bool                 $id_as_key use the ID as key for the array?
186
     * @param bool                 $as_object return an array of objects?
187
     *
188
     * @param string               $fields
189
     * @param bool                 $autoSort
190
     * @return array
191
     */
192
    public function &getObjects(CriteriaElement $criteria = null, $id_as_key = false, $as_object = true, $fields = '*', $autoSort = true)
193
    {
194
        require_once __DIR__ . '/lite.php';
195
        $ret   = array();
196
        $limit = $start = 0;
197
        $sql   = 'SELECT ' . $fields . ' FROM ' . $this->table;
198 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
199
            $sql .= ' ' . $criteria->renderWhere();
200
            if ($criteria->groupby != '') {
201
                $sql .= $criteria->getGroupby();
202
            }
203
            if ($criteria->getSort() != '') {
204
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
205
            } elseif ($this->identifierName != '' && $autoSort) {
206
                $sql .= ' ORDER BY ' . $this->identifierName;
207
            }
208
            $limit = $criteria->getLimit();
209
            $start = $criteria->getStart();
210
        }
211
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
212
        $id         = $this->_getIdForCache($sql, $start, $limit);
213
        $cacheData  = $Cache_Lite->get($id);
214
        if ($cacheData === false) {
215
            $result = $this->db->query($sql, $limit, $start);
216
            if (!$result) {
217
                return $ret;
218
            }
219
            $ret = $this->convertResultSet($result, $id_as_key, $as_object, $fields);
220
            $Cache_Lite->save($ret);
221
222
            return $ret;
223
        } else {
224
            return $cacheData;
225
        }
226
    }
227
228
    /**
229
     * Convert a database resultset to a returnable array
230
     *
231
     * @param object  $result    database resultset
232
     * @param boolean $id_as_key - should NOT be used with joint keys
233
     * @param boolean $as_object
234
     * @param string  $fields    Requested fields from the query
235
     *
236
     * @return array
237
     */
238
    protected function convertResultSet($result, $id_as_key = false, $as_object = true, $fields = '*')
239
    {
240
        $ret = array();
241
        while ($myrow = $this->db->fetchArray($result)) {
242
            $obj =& $this->create(false);
243
            $obj->assignVars($myrow);
244
            if (!$id_as_key) {
245 View Code Duplication
                if ($as_object) {
246
                    $ret[] =& $obj;
247
                } else {
248
                    $row     = array();
249
                    $vars    = $obj->getVars();
250
                    $tbl_tmp = array_keys($vars);
251
                    foreach ($tbl_tmp as $i) {
252
                        $row[$i] = $obj->getVar($i);
253
                    }
254
                    $ret[] = $row;
255
                }
256
            } else {
257
                if ($as_object) {
258
                    if ($fields === '*') {
259
                        $ret[$myrow[$this->keyName]] =& $obj;
260
                    } else {
261
                        $ret[] =& $obj;
262
                    }
263 View Code Duplication
                } else {
264
                    $row     = array();
265
                    $vars    = $obj->getVars();
266
                    $tbl_tmp = array_keys($vars);
267
                    foreach ($tbl_tmp as $i) {
268
                        $row[$i] = $obj->getVar($i);
269
                    }
270
                    $ret[$myrow[$this->keyName]] = $row;
271
                }
272
            }
273
            unset($obj);
274
        }
275
276
        return $ret;
277
    }
278
279
    /**
280
     * get IDs of objects matching a condition
281
     *
282
     * @param  object $criteria {@link CriteriaElement} to match
283
     * @return array  of object IDs
284
     */
285
    public function getIds($criteria = null)
286
    {
287
        require_once __DIR__ . '/lite.php';
288
        $limit = $start = 0;
289
290
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
291
        $sql        = 'SELECT ' . $this->keyName . ' FROM ' . $this->table;
292 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
293
            $sql .= ' ' . $criteria->renderWhere();
294
            if ($criteria->groupby != '') {
295
                $sql .= $criteria->getGroupby();
296
            }
297
            if ($criteria->getSort() != '') {
298
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
299
            } elseif ($this->identifierName != '') {
300
                $sql .= ' ORDER BY ' . $this->identifierName;
301
            }
302
            $limit = $criteria->getLimit();
303
            $start = $criteria->getStart();
304
        }
305
306
        $id        = $this->_getIdForCache($sql, $start, $limit);
307
        $cacheData = $Cache_Lite->get($id);
308
        if ($cacheData === false) {
309
            $result = $this->db->query($sql, $limit, $start);
310
            $ret    = array();
311
            while ($myrow = $this->db->fetchArray($result)) {
312
                $ret[] = $myrow[$this->keyName];
313
            }
314
            $Cache_Lite->save($ret);
315
316
            return $ret;
317
        } else {
318
            return $cacheData;
319
        }
320
    }
321
322
    /**
323
     * Retrieve a list of objects as arrays - DON'T USE WITH JOINT KEYS
324
     *
325
     * @param object $criteria {@link CriteriaElement} conditions to be met
326
     * @return array
327
     */
328
    public function getList($criteria = null)
329
    {
330
        require_once __DIR__ . '/lite.php';
331
        $limit      = $start = 0;
332
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
333
334
        $ret = array();
335
336
        $sql = 'SELECT ' . $this->keyName;
337
        if (!empty($this->identifierName)) {
338
            $sql .= ', ' . $this->identifierName;
339
        }
340
        $sql .= ' FROM ' . $this->table;
341 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
342
            $sql .= ' ' . $criteria->renderWhere();
343
            if ($criteria->groupby != '') {
344
                $sql .= $criteria->getGroupby();
345
            }
346
            if ($criteria->getSort() != '') {
347
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
348
            } elseif ($this->identifierName != '') {
349
                $sql .= ' ORDER BY ' . $this->identifierName;
350
            }
351
            $limit = $criteria->getLimit();
352
            $start = $criteria->getStart();
353
        }
354
355
        $id        = $this->_getIdForCache($sql, $start, $limit);
356
        $cacheData = $Cache_Lite->get($id);
357
        if ($cacheData === false) {
358
            $result = $this->db->query($sql, $limit, $start);
359
            if (!$result) {
360
                $Cache_Lite->save($ret);
361
362
                return $ret;
363
            }
364
365
            $myts = MyTextSanitizer::getInstance();
366
            while ($myrow = $this->db->fetchArray($result)) {
367
                //identifiers should be textboxes, so sanitize them like that
368
                $ret[$myrow[$this->keyName]] = empty($this->identifierName) ? 1 : $myts->htmlSpecialChars($myrow[$this->identifierName]);
369
            }
370
            $Cache_Lite->save($ret);
371
372
            return $ret;
373
        } else {
374
            return $cacheData;
375
        }
376
    }
377
378
    /**
379
     * Retourne des éléments selon leur ID
380
     *
381
     * @param array $ids Les ID des éléments à retrouver
382
     * @param null  $additionnal
383
     * @return array Tableau d'objets
384
     */
385
    public function getItemsFromIds($ids, $additionnal = null)
386
    {
387
        $ret = array();
388
        if (is_array($ids) && count($ids) > 0) {
389
            $criteria = new CriteriaCompo();
390
            $criteria->add(new Criteria($this->keyName, '(' . implode(',', $ids) . ')', 'IN'));
391
            if (!is_null($additionnal)) {
392
                $criteria->add($additionnal);
393
            }
394
            $ret = $this->getObjects($criteria, true);
395
        }
396
397
        return $ret;
398
    }
399
400
    /**
401
     * count objects matching a condition
402
     *
403
     * @param  object $criteria {@link CriteriaElement} to match
404
     * @return int    count of objects
405
     */
406
    public function getCount($criteria = null)
407
    {
408
        $field   = '';
409
        $groupby = false;
410
        $limit   = $start = 0;
411
        require_once __DIR__ . '/lite.php';
412
413
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
414
            if ($criteria->groupby != '') {
415
                $groupby = true;
416
                $field   = $criteria->groupby . ', '; //Not entirely secure unless you KNOW that no criteria's groupby clause is going to be mis-used
417
            }
418
        }
419
        $sql = 'SELECT ' . $field . 'COUNT(*) FROM ' . $this->table;
420 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
421
            $sql .= ' ' . $criteria->renderWhere();
422
            if ($criteria->groupby != '') {
423
                $sql .= $criteria->getGroupby();
424
            }
425
            $limit = $criteria->getLimit();
426
            $start = $criteria->getStart();
427
        }
428
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
429
        $id         = $this->_getIdForCache($sql, $start, $limit);
430
        $cacheData  = $Cache_Lite->get($id);
431
        if ($cacheData === false) {
432
            $result = $this->db->query($sql, $limit, $start);
433
            if (!$result) {
434
                $ret = 0;
435
                $Cache_Lite->save($ret);
436
437
                return $ret;
438
            }
439
            if ($groupby == false) {
440
                list($count) = $this->db->fetchRow($result);
441
                $Cache_Lite->save($count);
442
443
                return $count;
444
            } else {
445
                $ret = array();
446
                while (list($id, $count) = $this->db->fetchRow($result)) {
447
                    $ret[$id] = $count;
448
                }
449
                $Cache_Lite->save($ret);
450
451
                return $ret;
452
            }
453
        } else {
454
            return $cacheData;
455
        }
456
    }
457
458
    /**
459
     * Retourne le total d'un champ
460
     *
461
     * @param  string $field    Le champ dont on veut calculer le total
462
     * @param  object $criteria {@link CriteriaElement} to match
463
     * @return integer le total
464
     */
465
    public function getSum($field, $criteria = null)
466
    {
467
        $limit = $start = 0;
468
        require_once __DIR__ . '/lite.php';
469
470
        $sql = 'SELECT Sum(' . $field . ') as cpt FROM ' . $this->table;
471 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
472
            $sql .= ' ' . $criteria->renderWhere();
473
            if ($criteria->groupby != '') {
474
                $sql .= $criteria->getGroupby();
475
            }
476
            $limit = $criteria->getLimit();
477
            $start = $criteria->getStart();
478
        }
479
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
480
        $id         = $this->_getIdForCache($sql, $start, $limit);
481
        $cacheData  = $Cache_Lite->get($id);
482
        if ($cacheData === false) {
483
            $result = $this->db->query($sql, $limit, $start);
484
            if (!$result) {
485
                $ret = 0;
486
                $Cache_Lite->save($ret);
487
488
                return $ret;
489
            }
490
            $row   = $this->db->fetchArray($result);
491
            $count = $row['cpt'];
492
            $Cache_Lite->save($count);
493
494
            return $count;
495
        } else {
496
            return $cacheData;
497
        }
498
    }
499
500
    /**
501
     * delete an object from the database
502
     *
503
     * @param  XoopsObject $obj reference to the object to delete
504
     * @param  bool        $force
505
     * @return bool   FALSE if failed.
506
     */
507
    public function delete(XoopsObject $obj, $force = false)
508
    {
509
        if (is_array($this->keyName)) {
510
            $clause = array();
511
            $vnb    = count($this->keyName);
512
            for ($i = 0; $i < $vnb; ++$i) {
513
                $clause[] = $this->keyName[$i] . ' = ' . $obj->getVar($this->keyName[$i]);
514
            }
515
            $whereclause = implode(' AND ', $clause);
516
        } else {
517
            $whereclause = $this->keyName . ' = ' . $obj->getVar($this->keyName);
518
        }
519
        $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $whereclause;
520 View Code Duplication
        if (false != $force) {
521
            $result = $this->db->queryF($sql);
522
        } else {
523
            $result = $this->db->query($sql);
524
        }
525
        // Clear cache
526
        $this->forceCacheClean();
527
528
        if (!$result) {
529
            return false;
530
        }
531
532
        return true;
533
    }
534
535
    /**
536
     * Quickly insert a record like this $myobject_handler->quickInsert('field1' => field1value, 'field2' => $field2value)
537
     *
538
     * @param  array $vars  Array containing the fields name and value
539
     * @param  bool  $force whether to force the query execution despite security settings
540
     * @return bool  @link insert's value
541
     */
542
    public function quickInsert($vars = null, $force = true)
543
    {
544
        $object = $this->create(true);
545
        $object->setVars($vars);
546
        $retval =& $this->insert($object, $force);
547
        unset($object);
548
549
        // Clear cache
550
        $this->forceCacheClean();
551
552
        return $retval;
553
    }
554
555
    /**
556
     * insert a new object in the database
557
     *
558
     * @param  XoopsObject $obj         reference to the object
559
     * @param  bool        $force       whether to force the query execution despite security settings
560
     * @param  bool        $checkObject check if the object is dirty and clean the attributes
561
     * @param bool         $ignoreInsert
562
     * @return bool FALSE if failed, TRUE if already present and unchanged or successful
563
     */
564
565
    public function insert(XoopsObject $obj, $force = false, $checkObject = true, $ignoreInsert = false)
566
    {
567
        if ($checkObject != false) {
568
            if (!is_object($obj)) {
569
                trigger_error('Error, not object');
570
571
                return false;
572
            }
573
            /**
574
             * @TODO: Change to if (!(class_exists($this->className) && $obj instanceof $this->className)) when going fully PHP5
575
             */
576
            if (!is_a($obj, $this->className)) {
577
                $obj->setErrors(get_class($obj) . ' Differs from ' . $this->className);
578
579
                return false;
580
            }
581
            if (!$obj->isDirty()) {
582
                $obj->setErrors('Not dirty'); //will usually not be outputted as errors are not displayed when the method returns true, but it can be helpful when troubleshooting code - Mith
583
584
                return true;
585
            }
586
        }
587
        if (!$obj->cleanVars()) {
588
            foreach ($obj->getErrors() as $oneerror) {
589
                trigger_error($oneerror);
590
            }
591
592
            return false;
593
        }
594
        foreach ($obj->cleanVars as $k => $v) {
595
            if ($obj->vars[$k]['data_type'] == XOBJ_DTYPE_INT) {
596
                $cleanvars[$k] = (int)$v;
597
            } elseif (is_array($v)) {
598
                $cleanvars[$k] = $this->db->quoteString(implode(',', $v));
599
            } else {
600
                $cleanvars[$k] = $this->db->quoteString($v);
601
            }
602
        }
603
        if (isset($cleanvars['dohtml'])) {        // Modification Hervďż˝ to be able to use dohtml
604
            unset($cleanvars['dohtml']);
605
        }
606
        if ($obj->isNew()) {
607
            if (!is_array($this->keyName)) {
608
                if ($cleanvars[$this->keyName] < 1) {
609
                    $cleanvars[$this->keyName] = $this->db->genId($this->table . '_' . $this->keyName . '_seq');
610
                }
611
            }
612
            $ignore = '';
613
            if ($ignoreInsert) {
614
                $ignore = 'IGNORE';
615
            }
616
            $sql = "INSERT $ignore INTO " . $this->table . ' (' . implode(',', array_keys($cleanvars)) . ') VALUES (' . implode(',', array_values($cleanvars)) . ')';
617
        } else {
618
            $sql = 'UPDATE ' . $this->table . ' SET';
619
            foreach ($cleanvars as $key => $value) {
620
                if ((!is_array($this->keyName) && $key == $this->keyName) || (is_array($this->keyName) && in_array($key, $this->keyName))) {
621
                    continue;
622
                }
623
                if (isset($notfirst)) {
624
                    $sql .= ',';
625
                }
626
                $sql .= ' ' . $key . ' = ' . $value;
627
                $notfirst = true;
628
            }
629
            if (is_array($this->keyName)) {
630
                $whereclause = '';
631
                $vnb         = count($this->keyName);
632
                for ($i = 0; $i < $vnb; ++$i) {
633
                    if ($i > 0) {
634
                        $whereclause .= ' AND ';
635
                    }
636
                    $whereclause .= $this->keyName[$i] . ' = ' . $obj->getVar($this->keyName[$i]);
637
                }
638
            } else {
639
                $whereclause = $this->keyName . ' = ' . $obj->getVar($this->keyName);
640
            }
641
            $sql .= ' WHERE ' . $whereclause;
642
        }
643
644 View Code Duplication
        if (false != $force) {
645
            $result = $this->db->queryF($sql);
646
        } else {
647
            $result = $this->db->query($sql);
648
        }
649
650
        // Clear cache
651
        $this->forceCacheClean();
652
653
        if (!$result) {
654
            return false;
655
        }
656
        if ($obj->isNew() && !is_array($this->keyName)) {
657
            $obj->assignVar($this->keyName, $this->db->getInsertId());
658
        }
659
660
        return true;
661
    }
662
663
    /**
664
     * Change a value for objects with a certain criteria
665
     *
666
     * @param string $fieldname  Name of the field
667
     * @param string $fieldvalue Value to write
668
     * @param object $criteria   {@link CriteriaElement}
669
     *
670
     * @param bool   $force
671
     * @return bool
672
     */
673
    public function updateAll($fieldname, $fieldvalue, $criteria = null, $force = false)
674
    {
675
        $set_clause = $fieldname . ' = ';
676
        if (is_numeric($fieldvalue)) {
677
            $set_clause .= $fieldvalue;
678
        } elseif (is_array($fieldvalue)) {
679
            $set_clause .= $this->db->quoteString(implode(',', $fieldvalue));
680
        } else {
681
            $set_clause .= $this->db->quoteString($fieldvalue);
682
        }
683
        $sql = 'UPDATE ' . $this->table . ' SET ' . $set_clause;
684
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
685
            $sql .= ' ' . $criteria->renderWhere();
686
        }
687
        if ($force) {
688
            $result = $this->db->queryF($sql);
689
        } else {
690
            $result = $this->db->query($sql);
691
        }
692
693
        // Clear cache
694
        $this->forceCacheClean();
695
696
        if (!$result) {
697
            return false;
698
        }
699
700
        return true;
701
    }
702
703
    //  check if target object is attempting to use duplicated info
704
    public function isDuplicated(&$obj, $field = '', $error = '')
705
    {
706
        if (empty($field)) {
707
            return false;
708
        }
709
        $criteria = new CriteriaCompo();
710
        $criteria->add(new Criteria($field, $obj->getVar($field)));
711
        //  one more condition if target object exisits in database
712
        if (!$obj->isNew()) {
713
            $criteria->add(new Criteria($this->_key, $obj->getVar($this->_key), '!='));
714
        }
715
        if ($this->getCount($criteria)) {
716
            $obj->setErrors($error);
717
718
            return true;
719
        }
720
721
        return false;
722
    }
723
724
    /**
725
     * delete all objects meeting the conditions
726
     *
727
     * @param  object $criteria {@link CriteriaElement} with conditions to meet
728
     * @return bool
729
     */
730
    public function deleteAll($criteria = null)
731
    {
732
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
733
            $sql = 'DELETE FROM ' . $this->table;
734
            $sql .= ' ' . $criteria->renderWhere();
735
            if (!$this->db->queryF($sql)) {
736
                return false;
737
            }
738
            $rows = $this->db->getAffectedRows();
739
740
            // Clear cache
741
            $this->forceCacheClean();
742
743
            return $rows > 0 ? $rows : true;
744
        }
745
746
        return false;
747
    }
748
749
    /**
750
     * Compare two objects and returns, in an array, the differences
751
     *
752
     * @param  XoopsObject $old_object The first object to compare
753
     * @param  XoopsObject $new_object The new object
754
     * @return array       differences  key = fieldname, value = array('old_value', 'new_value')
755
     */
756
    public function compareObjects($old_object, $new_object)
757
    {
758
        $ret       = array();
759
        $vars_name = array_keys($old_object->getVars());
760
        foreach ($vars_name as $one_var) {
761
            if ($old_object->getVar($one_var, 'f') == $new_object->getVar($one_var, 'f')) {
762
            } else {
763
                $ret[$one_var] = array($old_object->getVar($one_var), $new_object->getVar($one_var));
764
            }
765
        }
766
767
        return $ret;
768
    }
769
770
    /**
771
     * Get distincted values of a field in the table
772
     *
773
     * @param  string $field    Field's name
774
     * @param  object $criteria {@link CriteriaElement} conditions to be met
775
     * @param  string $format   Format in wich we want the datas
776
     * @return array  containing the distinct values
777
     */
778
    public function getDistincts($field, $criteria = null, $format = 's')
779
    {
780
        require_once __DIR__ . '/lite.php';
781
        $limit = $start = 0;
782
        $sql   = 'SELECT ' . $this->keyName . ', ' . $field . ' FROM ' . $this->table;
783
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
784
            $sql .= ' ' . $criteria->renderWhere();
785
            $limit = $criteria->getLimit();
786
            $start = $criteria->getStart();
787
        }
788
        $sql .= ' GROUP BY ' . $field . ' ORDER BY ' . $field;
789
790
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
791
        $id         = $this->_getIdForCache($sql, $start, $limit);
792
        $cacheData  = $Cache_Lite->get($id);
793
        if ($cacheData === false) {
794
            $result = $this->db->query($sql, $limit, $start);
795
            $ret    = array();
796
            $obj    = new $this->className();
797
            while ($myrow = $this->db->fetchArray($result)) {
798
                $obj->setVar($field, $myrow[$field]);
799
                $ret[$myrow[$this->keyName]] = $obj->getVar($field, $format);
800
            }
801
            $Cache_Lite->save($ret);
802
803
            return $ret;
804
        } else {
805
            return $cacheData;
806
        }
807
    }
808
809
    /**
810
     * A generic shortcut to getObjects
811
     *
812
     * @author Herve Thouzard - Instant Zero
813
     *
814
     * @param  integer $start   Starting position
815
     * @param  integer $limit   Maximum count of elements to return
816
     * @param  string  $sort    Field to use for the sort
817
     * @param  string  $order   Sort order
818
     * @param  boolean $idAsKey Do we have to return an array whoses keys are the record's ID ?
819
     * @return array   Array of current objects
820
     */
821
    public function getItems($start = 0, $limit = 0, $sort = '', $order = 'ASC', $idAsKey = true)
822
    {
823
        if (trim($order) == '') {
824
            if (isset($this->identifierName) && trim($this->identifierName) != '') {
825
                $order = $this->identifierName;
826
            } else {
827
                $order = $this->keyName;
828
            }
829
        }
830
        $items   = array();
0 ignored issues
show
$items is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
831
        $critere = new Criteria($this->keyName, 0, '<>');
832
        $critere->setLimit($limit);
833
        $critere->setStart($start);
834
        $critere->setSort($sort);
835
        $critere->setOrder($order);
836
        $items = $this->getObjects($critere, $idAsKey);
837
838
        return $items;
839
    }
840
841
    /**
842
     * Forces the cache to be cleaned
843
     */
844
    public function forceCacheClean()
845
    {
846
        require_once __DIR__ . '/lite.php';
847
        $Cache_Lite = new references_Cache_Lite($this->cacheOptions);
848
        $Cache_Lite->clean();
849
    }
850
}
851