Completed
Push — master ( 1db5db...8743f5 )
by Michael
06:44
created

__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
c 1
b 0
f 0
nc 2
nop 5
dl 0
loc 10
rs 9.4285
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 32 and the first side effect is on line 27.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
//  ------------------------------------------------------------------------ //
3
//                      BOOKSHOP - MODULE FOR XOOPS 2                        //
4
//                  Copyright (c) 2007, 2008 Instant Zero                    //
5
//                     <http://www.instant-zero.com/>                        //
6
// ------------------------------------------------------------------------- //
7
//  This program is free software; you can redistribute it and/or modify     //
8
//  it under the terms of the GNU General Public License as published by     //
9
//  the Free Software Foundation; either version 2 of the License, or        //
10
//  (at your option) any later version.                                      //
11
//                                                                           //
12
//  You may not change or alter any portion of this comment or credits       //
13
//  of supporting developers from this source code or any supporting         //
14
//  source code which is considered copyrighted (c) material of the          //
15
//  original comment or credit authors.                                      //
16
//                                                                           //
17
//  This program is distributed in the hope that it will be useful,          //
18
//  but WITHOUT ANY WARRANTY; without even the implied warranty of           //
19
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
20
//  GNU General Public License for more details.                             //
21
//                                                                           //
22
//  You should have received a copy of the GNU General Public License        //
23
//  along with this program; if not, write to the Free Software              //
24
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
25
//  ------------------------------------------------------------------------ //
26
27
defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
28
29
/**
30
 * Class Bookshop_Object
31
 */
32
class Bookshop_Object extends XoopsObject
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
33
{
34
    /**
35
     * @param string $format
36
     *
37
     * @return array
38
     */
39
    public function toArray($format = 's')
40
    {
41
        $ret = array();
42
        foreach ($this->vars as $k => $v) {
43
            $ret[$k] = $this->getVar($k, $format);
44
        }
45
46
        return $ret;
47
    }
48
}
49
50
/**
51
 * Persistable Object Handler class.
52
 * This class is responsible for providing data access mechanisms to the data source
53
 * of derived class objects. Original Author : Mithrandir
54
 *
55
 */
56
class Bookshop_XoopsPersistableObjectHandler extends XoopsObjectHandler
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
57
{
58
    /**#@+
59
     * Information about the class, the handler is managing
60
     *
61
     * @var string
62
     */
63
    public    $table;
64
    protected $keyName;
65
    protected $className;
66
    protected $identifierName;
67
    protected $cacheOptions = array();
68
    /**#@-*/
69
70
    /**
71
     * Constructor - called from child classes
72
     *
73
     * @param object $db        {@link XoopsDatabase} object
74
     * @param string $tablename Name of database table
75
     * @param string $classname Name of Class, this handler is managing
76
     * @param string $keyname   Name of the property, holding the key
77
     *
78
     * @param bool   $idenfierName
79
     *
80
     */
81
    public function __construct($db, $tablename, $classname, $keyname, $idenfierName = false)
82
    {
83
        parent::__construct($db);
84
        $this->table     = $db->prefix($tablename);
85
        $this->keyName   = $keyname;
86
        $this->className = $classname;
87
        if ($idenfierName != false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
88
            $this->identifierName = $idenfierName;
89
        }
90
    }
91
92
    /**
93
     * create a new object
94
     *
95
     * @param bool $isNew Flag the new objects as "new"?
96
     *
97
     * @return object
98
     */
99
    public function create($isNew = true)
100
    {
101
        $obj = new $this->className();
102
        if ($isNew === true) {
103
            $obj->setNew();
104
        }
105
106
        return $obj;
107
    }
108
109
    /**
110
     * retrieve an object
111
     *
112
     * @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
113
     * @param  bool  $as_object whether to return an object or an array
114
     * @return mixed reference to the object, FALSE if failed
115
     */
116
    public function &get($id, $as_object = true)
117
    {
118
        if (is_array($this->keyName)) {
119
            $criteria = new CriteriaCompo();
120
            $vnb      = count($this->keyName);
121
            for ($i = 0; $i < $vnb; ++$i) {
122
                $criteria->add(new Criteria($this->keyName[$i], (int)$id[$i]));
123
            }
124
        } else {
125
            $criteria = new Criteria($this->keyName, (int)$id);
126
        }
127
        $criteria->setLimit(1);
128
        $obj_array =& $this->getObjects($criteria, false, $as_object);
129
        if (count($obj_array) != 1) {
130
            $ret = null;
131
        } else {
132
            $ret =& $obj_array[0];
133
        }
134
135
        return $ret;
136
    }
137
138
    /**
139
     * retrieve objects from the database
140
     *
141
     * @param null|CriteriaElement $criteria  {@link CriteriaElement} conditions to be met
142
     * @param bool                 $id_as_key use the ID as key for the array?
143
     * @param bool                 $as_object return an array of objects?
144
     *
145
     * @return array
146
     */
147
    public function &getObjects(CriteriaElement $criteria = null, $id_as_key = false, $as_object = true)
148
    {
149
        $ret   = array();
150
        $limit = $start = 0;
151
        $sql   = 'SELECT * FROM ' . $this->table;
152 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
153
            $sql .= ' ' . $criteria->renderWhere();
154
            if ($criteria->getSort() != '') {
155
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
156
            }
157
            $limit = $criteria->getLimit();
158
            $start = $criteria->getStart();
159
        }
160
        $result = $this->db->query($sql, $limit, $start);
161
        if (!$result) {
162
            return $ret;
163
        }
164
165
        $ret = $this->convertResultSet($result, $id_as_key, $as_object);
166
167
        return $ret;
168
    }
169
170
    /**
171
     * Convert a database resultset to a returnable array
172
     *
173
     * @param object $result    database resultset
174
     * @param bool   $id_as_key - should NOT be used with joint keys
175
     * @param bool   $as_object
176
     *
177
     * @return array
178
     */
179
    public function convertResultSet($result, $id_as_key = false, $as_object = true)
180
    {
181
        $ret = array();
182
        while ($myrow = $this->db->fetchArray($result)) {
183
            $obj = $this->create(false);
184
            $obj->assignVars($myrow);
185
            if (!$id_as_key) {
186 View Code Duplication
                if ($as_object) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
187
                    $ret[] =& $obj;
188
                } else {
189
                    $row     = array();
190
                    $vars    = $obj->getVars();
191
                    $tbl_tmp = array_keys($vars);
192
                    foreach ($tbl_tmp as $i) {
193
                        $row[$i] = $obj->getVar($i);
194
                    }
195
                    $ret[] = $row;
196
                }
197
            } else {
198
                if ($as_object) {
199
                    $ret[$myrow[$this->keyName]] =& $obj;
200 View Code Duplication
                } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
                    $row     = array();
202
                    $vars    = $obj->getVars();
203
                    $tbl_tmp = array_keys($vars);
204
                    foreach ($tbl_tmp as $i) {
205
                        $row[$i] = $obj->getVar($i);
206
                    }
207
                    $ret[$myrow[$this->keyName]] = $row;
208
                }
209
            }
210
            unset($obj);
211
        }
212
213
        return $ret;
214
    }
215
216
    /**
217
     * get IDs of objects matching a condition
218
     *
219
     * @param  object $criteria {@link CriteriaElement} to match
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
220
     * @return array  of object IDs
221
     */
222
    public function getIds($criteria = null)
223
    {
224
        $sql = 'SELECT ' . $this->keyName . ' FROM ' . $this->table;
225
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
226
            $sql .= ' ' . $criteria->renderWhere();
227
        }
228
        $result = $this->db->query($sql);
229
        $ret    = array();
230
        while ($myrow = $this->db->fetchArray($result)) {
231
            $ret[] = $myrow[$this->keyName];
232
        }
233
234
        return $ret;
235
    }
236
237
    /**
238
     * Retrieve a list of objects as arrays - DON'T USE WITH JOINT KEYS
239
     *
240
     * @param object $criteria {@link CriteriaElement} conditions to be met
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
241
     * @param int    $limit    Max number of objects to fetch
242
     * @param int    $start    Which record to start at
243
     *
244
     * @return array
245
     */
246
    public function getList($criteria = null, $limit = 0, $start = 0)
247
    {
248
        $ret = array();
249
        if ($criteria == null) {
250
            $criteria = new CriteriaCompo();
251
        }
252
253
        if ($criteria->getSort() == '') {
254
            $criteria->setSort($this->identifierName);
255
        }
256
257
        $sql = 'SELECT ' . $this->keyName;
258
        if (!empty($this->identifierName)) {
259
            $sql .= ', ' . $this->identifierName;
260
        }
261
        $sql .= ' FROM ' . $this->table;
262 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
            $sql .= ' ' . $criteria->renderWhere();
264
            if ($criteria->getSort() != '') {
265
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
266
            }
267
            $limit = $criteria->getLimit();
268
            $start = $criteria->getStart();
269
        }
270
        $result = $this->db->query($sql, $limit, $start);
271
        if (!$result) {
272
            return $ret;
273
        }
274
275
        $myts = MyTextSanitizer::getInstance();
276
        while ($myrow = $this->db->fetchArray($result)) {
277
            //identifiers should be textboxes, so sanitize them like that
278
            $ret[$myrow[$this->keyName]] = empty($this->identifierName) ? 1 : $myts->htmlSpecialChars($myrow[$this->identifierName]);
279
        }
280
281
        return $ret;
282
    }
283
284
    /**
285
     * count objects matching a condition
286
     *
287
     * @param  object $criteria {@link CriteriaElement} to match
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
288
     * @return int    count of objects
289
     */
290
    public function getCount($criteria = null)
291
    {
292
        $field   = '';
293
        $groupby = false;
294
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
295
            if ($criteria->groupby != '') {
296
                $groupby = true;
297
                $field   = $criteria->groupby . ', '; //Not entirely secure unless you KNOW that no criteria's groupby clause is going to be mis-used
298
            }
299
        }
300
        $sql = 'SELECT ' . $field . 'COUNT(*) FROM ' . $this->table;
301
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
302
            $sql .= ' ' . $criteria->renderWhere();
303
            if ($criteria->groupby != '') {
304
                $sql .= $criteria->getGroupby();
305
            }
306
        }
307
        $result = $this->db->query($sql);
308
        if (!$result) {
309
            return 0;
310
        }
311
        if ($groupby == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
312
            list($count) = $this->db->fetchRow($result);
313
314
            return $count;
315
        } else {
316
            $ret = array();
317
            while (list($id, $count) = $this->db->fetchRow($result)) {
318
                $ret[$id] = $count;
319
            }
320
321
            return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $ret; (array) is incompatible with the return type documented by Bookshop_XoopsPersistableObjectHandler::getCount of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
322
        }
323
    }
324
325
    /**
326
     * delete an object from the database
327
     *
328
     * @param  XoopsObject $obj reference to the object to delete
329
     * @param  bool        $force
330
     * @return bool   FALSE if failed.
331
     */
332
    public function delete(XoopsObject $obj, $force = false)
333
    {
334
        if (is_array($this->keyName)) {
335
            $clause = array();
336
            $vnb    = count($this->keyName);
337
            for ($i = 0; $i < $vnb; ++$i) {
338
                $clause[] = $this->keyName[$i] . ' = ' . $obj->getVar($this->keyName[$i]);
339
            }
340
            $whereclause = implode(' AND ', $clause);
341
        } else {
342
            $whereclause = $this->keyName . ' = ' . $obj->getVar($this->keyName);
343
        }
344
        $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $whereclause;
345 View Code Duplication
        if (false != $force) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
346
            $result = $this->db->queryF($sql);
347
        } else {
348
            $result = $this->db->query($sql);
349
        }
350
        if (!$result) {
351
            return false;
352
        }
353
354
        return true;
355
    }
356
357
    /**
358
     * Quickly insert a record like this $myobject_handler->quickInsert('field1' => field1value, 'field2' => $field2value)
359
     *
360
     * @param  array $vars  Array containing the fields name and value
0 ignored issues
show
Documentation introduced by
Should the type for parameter $vars not be array|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
361
     * @param  bool  $force whether to force the query execution despite security settings
362
     * @return bool  @link insert's value
363
     */
364
    public function quickInsert($vars = null, $force = false)
365
    {
366
        $object = $this->create(true);
367
        $object->setVars($vars);
368
        $retval = $this->insert($object, $force);
369
        unset($object);
370
371
        return $retval;
372
    }
373
374
    /**
375
     * insert a new object in the database
376
     *
377
     * @param  XoopsObject $obj         reference to the object
378
     * @param  bool        $force       whether to force the query execution despite security settings
379
     * @param  bool        $checkObject check if the object is dirty and clean the attributes
380
     * @return bool   FALSE if failed, TRUE if already present and unchanged or successful
381
     */
382
383
    public function insert(XoopsObject $obj, $force = false, $checkObject = true)
384
    {
385
        if ($checkObject != false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
386
            if (!is_object($obj)) {
387
                echo '<br><h1>Error, not object</h1>';
388
389
                return false;
390
            }
391
            /**
392
             * @TODO: Change to if (!(class_exists($this->className) && $obj instanceof $this->className)) when going fully PHP5
393
             */
394
//            if (!is_a($obj, $this->className)) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
395
//                $obj->setErrors(get_class($obj) . ' Differs from ' . $this->className);
396
397
                if (!(class_exists($this->className) && $obj instanceof $this->className)) {
398
                    $obj->setErrors(get_class($obj) . ' Differs from ' . $this->className);
399
400
                return false;
401
            }
402
            if (!$obj->isDirty()) {
403
                $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
404
405
                return true;
406
            }
407
        }
408
        if (!$obj->cleanVars()) {
409
            foreach ($obj->getErrors() as $oneerror) {
410
                echo '<br><h2>' . $oneerror . '</h2>';
411
            }
412
413
            return false;
414
        }
415
        foreach ($obj->cleanVars as $k => $v) {
416
            if ($obj->vars[$k]['data_type'] == XOBJ_DTYPE_INT) {
417
                $cleanvars[$k] = (int)$v;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$cleanvars was never initialized. Although not strictly required by PHP, it is generally a good practice to add $cleanvars = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
418
            } elseif (is_array($v)) {
419
                $cleanvars[$k] = $this->db->quoteString(implode(',', $v));
0 ignored issues
show
Bug introduced by
The variable $cleanvars does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
420
            } else {
421
                $cleanvars[$k] = $this->db->quoteString($v);
422
            }
423
        }
424
        if (isset($cleanvars['dohtml'])) {        // Modification Herv� to be able to use dohtml
425
            unset($cleanvars['dohtml']);
426
        }
427
        if ($obj->isNew()) {
428
            if (!is_array($this->keyName)) {
429
                if ($cleanvars[$this->keyName] < 1) {
430
                    $cleanvars[$this->keyName] = $this->db->genId($this->table . '_' . $this->keyName . '_seq');
431
                }
432
            }
433
            $sql = 'INSERT INTO ' . $this->table . ' (' . implode(',', array_keys($cleanvars)) . ') VALUES (' . implode(',', array_values($cleanvars)) . ')';
434
        } else {
435
            $sql = 'UPDATE ' . $this->table . ' SET';
436
            foreach ($cleanvars as $key => $value) {
437
                if ((!is_array($this->keyName) && $key == $this->keyName) || (is_array($this->keyName) && in_array($key, $this->keyName))) {
438
                    continue;
439
                }
440
                if (isset($notfirst)) {
441
                    $sql .= ',';
442
                }
443
                $sql .= ' ' . $key . ' = ' . $value;
444
                $notfirst = true;
445
            }
446
            if (is_array($this->keyName)) {
447
                $whereclause = '';
448
                $vnb         = count($this->keyName);
449
                for ($i = 0; $i < $vnb; ++$i) {
450
                    if ($i > 0) {
451
                        $whereclause .= ' AND ';
452
                    }
453
                    $whereclause .= $this->keyName[$i] . ' = ' . $obj->getVar($this->keyName[$i]);
454
                }
455
            } else {
456
                $whereclause = $this->keyName . ' = ' . $obj->getVar($this->keyName);
457
            }
458
            $sql .= ' WHERE ' . $whereclause;
459
        }
460
461 View Code Duplication
        if (false != $force) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
462
            $result = $this->db->queryF($sql);
463
        } else {
464
            $result = $this->db->query($sql);
465
        }
466
        if (!$result) {
467
            return false;
468
        }
469
        if ($obj->isNew() && !is_array($this->keyName)) {
470
            $obj->assignVar($this->keyName, $this->db->getInsertId());
471
        }
472
473
        return true;
474
    }
475
476
    /**
477
     * Change a value for objects with a certain criteria
478
     *
479
     * @param string $fieldname  Name of the field
480
     * @param string $fieldvalue Value to write
481
     * @param object $criteria   {@link CriteriaElement}
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
482
     *
483
     * @param bool   $force
484
     *
485
     * @return bool
486
     */
487
    public function updateAll($fieldname, $fieldvalue, $criteria = null, $force = false)
488
    {
489
        $set_clause = $fieldname . ' = ';
490
        if (is_numeric($fieldvalue)) {
491
            $set_clause .= $fieldvalue;
492
        } elseif (is_array($fieldvalue)) {
493
            $set_clause .= $this->db->quoteString(implode(',', $fieldvalue));
494
        } else {
495
            $set_clause .= $this->db->quoteString($fieldvalue);
496
        }
497
        $sql = 'UPDATE ' . $this->table . ' SET ' . $set_clause;
498
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
499
            $sql .= ' ' . $criteria->renderWhere();
500
        }
501 View Code Duplication
        if (false != $force) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
502
            $result = $this->db->queryF($sql);
503
        } else {
504
            $result = $this->db->query($sql);
505
        }
506
        if (!$result) {
507
            return false;
508
        }
509
510
        return true;
511
    }
512
513
    /**
514
     * delete all objects meeting the conditions
515
     *
516
     * @param  object $criteria {@link CriteriaElement} with conditions to meet
517
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
518
     */
519
520
    public function deleteAll($criteria = null)
521
    {
522
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
523
            $sql = 'DELETE FROM ' . $this->table;
524
            $sql .= ' ' . $criteria->renderWhere();
525
            if (!$this->db->queryF($sql)) {
526
                return false;
527
            }
528
            $rows = $this->db->getAffectedRows();
529
530
            return $rows > 0 ? $rows : true;
531
        }
532
533
        return false;
534
    }
535
536
    /**
537
     * Compare two objects and returns, in an array, the differences
538
     *
539
     * @param  XoopsObject $old_object The first object to compare
540
     * @param  XoopsObject $new_object The new object
541
     * @return array       differences  key = fieldname, value = array('old_value', 'new_value')
542
     */
543
    public function compareObjects($old_object, $new_object)
544
    {
545
        $ret       = array();
546
        $vars_name = array_keys($old_object->getVars());
547
        foreach ($vars_name as $one_var) {
548
            if ($old_object->getVar($one_var, 'f') == $new_object->getVar($one_var, 'f')) {
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...
549
            } else {
550
                $ret[$one_var] = array($old_object->getVar($one_var), $new_object->getVar($one_var));
551
            }
552
        }
553
554
        return $ret;
555
    }
556
557
    /**
558
     * Get distincted values of a field in the table
559
     *
560
     * @param  string $field  Field's name
561
     * @param  string $format Format in wich we want the datas
562
     * @return array  containing the distinct values
563
     */
564
    public function getDistincts($field, $format = 's')
565
    {
566
        $sql    = 'SELECT ' . $this->keyName . ', ' . $field . ' FROM ' . $this->table . ' GROUP BY ' . $field . ' ORDER BY ' . $field;
567
        $result = $this->db->query($sql);
568
        $ret    = array();
569
        $obj    = new $this->className();
570
        while ($myrow = $this->db->fetchArray($result)) {
571
            $obj->setVar($field, $myrow[$field]);
572
            $ret[$myrow[$this->keyName]] = $obj->getVar($field, $format);
573
        }
574
575
        return $ret;
576
    }
577
}
578