PersistableObjectHandler   F
last analyzed

Complexity

Total Complexity 60

Size/Duplication

Total Lines 344
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 144
dl 0
loc 344
rs 3.6
c 0
b 0
f 0
wmc 60

12 Methods

Rating   Name   Duplication   Size   Complexity  
C objectToArray() 0 56 13
A objectToArrayWithoutExternalKey() 0 11 3
A updateCounter() 0 10 2
A getAvg() 0 15 4
A deleteById() 0 22 5
A updateFieldValue() 0 12 5
A _toObject() 0 16 3
B getMax() 0 32 10
B getSum() 0 32 10
A getInsertId() 0 3 1
A create() 0 10 2
A __construct() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like PersistableObjectHandler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PersistableObjectHandler, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace XoopsModules\Extgallery;
4
5
/**
6
 * ExtGallery Class Manager
7
 *
8
 * You may not change or alter any portion of this comment or credits
9
 * of supporting developers from this source code or any supporting source code
10
 * which is considered copyrighted (c) material of the original comment or credit authors.
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 *
15
 * @copyright   {@link https://xoops.org/ XOOPS Project}
16
 * @license     GNU GPL 2 (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
17
 * @author      Zoullou (http://www.zoullou.net)
18
 * @package     ExtGallery
19
 */
20
21
use XoopsModules\Extgallery;
22
23
/**
24
 * Persistable Object Handler class.
25
 * This class is responsible for providing data access mechanisms to the data source
26
 * of derived class objects.
27
 *
28
 * @author    Jan Keller Pedersen <[email protected]> - IDG Danmark A/S <www.idg.dk>
29
 * @copyright copyright (c) 2000-2004 XOOPS.org
30
 * @package   Kernel
31
 */
32
class PersistableObjectHandler extends \XoopsPersistableObjectHandler //XoopsObjectHandler
33
{
34
    /**#@+
35
     * Information about the class, the handler is managing
36
     *
37
     * @var string
38
     */
39
    //    public $table;
40
    //    public $keyName;
41
    //    public $className;
42
    //    public $identifierName;
43
    /**#@-*/
44
45
    /**
46
     * Constructor - called from child classes
47
     *
48
     * @param \XoopsDatabase|null $db        {@link XoopsDatabase}
49
     *                                       object
50
     * @param string              $tablename Name of database table
51
     * @param string              $classname Name of Class, this handler is managing
52
     * @param string              $keyname   Name of the property, holding the key
53
     *
54
     * @param bool                $idenfierName
55
     */
56
    public function __construct(\XoopsDatabase $db, $tablename, $classname, $keyname, $idenfierName = false)
57
    {
58
        parent::__construct($db);
59
        //        $db = \XoopsDatabaseFactory::getDatabaseConnection();
60
        $this->table   = $db->prefix($tablename);
61
        $this->keyName = $keyname;
62
        //        $this->className = '\\XoopsModules\\Extgallery\\' .$classname;
63
        $this->className = $classname;
64
        if (false !== $idenfierName) {
65
            $this->identifierName = $idenfierName;
0 ignored issues
show
Documentation Bug introduced by
The property $identifierName was declared of type string, but $idenfierName is of type true. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
66
        }
67
    }
68
69
    /**
70
     * create a new user
71
     *
72
     * @param bool $isNew Flag the new objects as "new"?
73
     *
74
     * @return \XoopsObject
75
     */
76
    public function create($isNew = true)
77
    {
78
        $temp = '\\XoopsModules\\Extgallery\\' . $this->className;
79
        $obj  = new $temp();
80
81
        if (true === $isNew) {
82
            $obj->setNew();
83
        }
84
85
        return $obj;
86
    }
87
88
    /**
89
     * delete an object from the database
90
     *
91
     * @param mixed $id id of the object to delete
92
     * @param bool  $force
93
     * @return bool        FALSE if failed.
94
     */
95
    public function deleteById($id, $force = false)
96
    {
97
        if (\is_array($this->keyName)) {
0 ignored issues
show
introduced by
The condition is_array($this->keyName) is always false.
Loading history...
98
            $clause = [];
99
            for ($i = 0, $iMax = \count($this->keyName); $i < $iMax; ++$i) {
100
                $clause[] = $this->keyName[$i] . ' = ' . $id[$i];
101
            }
102
            $whereclause = \implode(' AND ', $clause);
103
        } else {
104
            $whereclause = $this->keyName . ' = ' . $id;
105
        }
106
        $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $whereclause;
107
        if (false !== $force) {
108
            $result = $this->db->queryF($sql);
109
        } else {
110
            $result = $this->db->query($sql);
111
        }
112
        if (!$result) {
113
            return false;
114
        }
115
116
        return true;
117
    }
118
119
    /**
120
     * @param      $fieldname
121
     * @param      $fieldvalue
122
     * @param null $criteria
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $criteria is correct as it would always require null to be passed?
Loading history...
123
     * @param bool $force
124
     *
125
     * @return bool
126
     */
127
    public function updateFieldValue($fieldname, $fieldvalue, $criteria = null, $force = true)
128
    {
129
        $sql = 'UPDATE ' . $this->table . ' SET ' . $fieldname . ' = ' . $fieldvalue;
130
        if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
131
            $sql .= ' ' . $criteria->renderWhere();
132
        }
133
        $result = false !== $force ? $this->db->queryF($sql) : $this->db->query($sql);
134
        if (!$result) {
135
            return false;
136
        }
137
138
        return true;
139
    }
140
141
    /**
142
     * @param $data
143
     *
144
     * @return array
145
     */
146
    public function _toObject($data)
147
    {
148
        if (\is_array($data)) {
149
            $ret = [];
150
            foreach ($data as $v) {
151
                $object = new $this->className();
152
                $object->assignVars($v);
153
                $ret[] = $object;
154
            }
155
156
            return $ret;
157
        }
158
        $object = new $this->className();
159
        $object->assignVars($v);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v seems to be never defined.
Loading history...
160
161
        return $object;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $object returns the type object which is incompatible with the documented return type array.
Loading history...
162
    }
163
164
    /**
165
     * @param        $objects
166
     * @param array  $externalKeys
167
     * @param string $format
168
     *
169
     * @return array
170
     */
171
    public function objectToArray($objects, $externalKeys = [], $format = 's')
172
    {
173
        static $cached;
174
175
        $ret = [];
176
        if (\is_array($objects)) {
177
            $i = 0;
178
            foreach ($objects as $object) {
179
                $vars = $object->getVars();
180
                foreach ($vars as $k => $v) {
181
                    $ret[$i][$k] = $object->getVar($k, $format);
182
                }
183
                foreach ($externalKeys as $key) {
184
                    // Replace external key by corresponding object
185
                    $externalKey = $object->getExternalKey($key);
186
                    if (0 != $ret[$i][$key]) {
187
                        // Retriving data if isn't cached
188
                        if (!isset($cached[$externalKey['keyName']][$ret[$i][$key]])) {
189
                            if ($externalKey['core']) {
190
                                $handler = \xoops_getHandler($externalKey['className']);
191
                            } else {
192
                                $handler = Extgallery\Helper::getInstance()->getHandler($externalKey['className']);
193
                            }
194
                            $cached[$externalKey['keyName']][$ret[$i][$key]] = $this->objectToArrayWithoutExternalKey($handler->{$externalKey['getMethodeName']}($ret[$i][$key]), $format);
195
                        }
196
                        $ret[$i][$externalKey['keyName']] = $cached[$externalKey['keyName']][$ret[$i][$key]];
197
                    }
198
                    unset($ret[$i][$key]);
199
                }
200
                ++$i;
201
            }
202
        } else {
203
            $vars = $objects->getVars();
204
            foreach ($vars as $k => $v) {
205
                $ret[$k] = $objects->getVar($k, $format);
206
            }
207
            foreach ($externalKeys as $key) {
208
                // Replace external key by corresponding object
209
                $externalKey = $objects->getExternalKey($key);
210
                if (0 != $ret[$key]) {
211
                    // Retriving data if isn't cached
212
                    if (!isset($cached[$externalKey['keyName']][$ret[$key]])) {
213
                        if ($externalKey['core']) {
214
                            $handler = \xoops_getHandler($externalKey['className']);
215
                        } else {
216
                            $handler = Extgallery\Helper::getInstance()->getHandler($externalKey['className']);
217
                        }
218
                        $cached[$externalKey['keyName']][$ret[$key]] = $this->objectToArrayWithoutExternalKey($handler->{$externalKey['getMethodeName']}($ret[$key]), $format);
219
                    }
220
                    $ret[$externalKey['keyName']] = $cached[$externalKey['keyName']][$ret[$key]];
221
                }
222
                unset($ret[$key]);
223
            }
224
        }
225
226
        return $ret;
227
    }
228
229
    /**
230
     * @param        $object
231
     * @param string $format
232
     *
233
     * @return array
234
     */
235
    public function objectToArrayWithoutExternalKey($object, $format = 's')
236
    {
237
        $ret = [];
238
        if (null !== $object) {
239
            $vars = $object->getVars();
240
            foreach ($vars as $k => $v) {
241
                $ret[$k] = $object->getVar($k, $format);
242
            }
243
        }
244
245
        return $ret;
246
    }
247
248
    /**
249
     * @param        $fieldname
250
     * @param        $criteria
251
     * @param string $op
252
     *
253
     * @return bool
254
     */
255
    public function updateCounter($fieldname, $criteria, $op = '+')
256
    {
257
        $sql    = 'UPDATE ' . $this->table . ' SET ' . $fieldname . ' = ' . $fieldname . $op . '1';
258
        $sql    .= ' ' . $criteria->renderWhere();
259
        $result = $this->db->queryF($sql);
260
        if (!$result) {
261
            return false;
262
        }
263
264
        return true;
265
    }
266
267
    /**
268
     * @param null|\CriteriaElement $criteria
269
     * @param string                $sum
270
     *
271
     * @return array|int|string
272
     */
273
    public function getSum(\CriteriaElement $criteria = null, $sum = '*')
274
    {
275
        $field   = '';
276
        $groupby = false;
277
        if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
278
            if ('' != $criteria->groupby) {
279
                $groupby = true;
280
                $field   = $criteria->groupby . ', '; //Not entirely secure unless you KNOW that no criteria's groupby clause is going to be mis-used
281
            }
282
        }
283
        $sql = 'SELECT ' . $field . "SUM($sum) FROM " . $this->table;
284
        if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
285
            $sql .= ' ' . $criteria->renderWhere();
0 ignored issues
show
Bug introduced by
The method renderWhere() does not exist on CriteriaElement. Did you maybe mean render()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

285
            $sql .= ' ' . $criteria->/** @scrutinizer ignore-call */ renderWhere();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
286
            if ('' != $criteria->groupby) {
287
                $sql .= $criteria->getGroupby();
288
            }
289
        }
290
        $result = $this->db->query($sql);
291
        if (!$result) {
292
            return 0;
293
        }
294
        if (false === $groupby) {
295
            [$sum] = $this->db->fetchRow($result);
296
297
            return $sum;
298
        }
299
        $ret = [];
300
        while (list($id, $sum) = $this->db->fetchRow($result)) {
301
            $ret[$id] = $sum;
302
        }
303
304
        return $ret;
305
    }
306
307
    /**
308
     * @param \CriteriaElement $criteria
309
     * @param string           $max
310
     *
311
     * @return array|int|string
312
     */
313
    public function getMax(\CriteriaElement $criteria = null, $max = '*')
314
    {
315
        $field   = '';
316
        $groupby = false;
317
        if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
318
            if ('' != $criteria->groupby) {
319
                $groupby = true;
320
                $field   = $criteria->groupby . ', '; //Not entirely secure unless you KNOW that no criteria's groupby clause is going to be mis-used
321
            }
322
        }
323
        $sql = 'SELECT ' . $field . "MAX($max) FROM " . $this->table;
324
        if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
325
            $sql .= ' ' . $criteria->renderWhere();
326
            if ('' != $criteria->groupby) {
327
                $sql .= $criteria->getGroupby();
328
            }
329
        }
330
        $result = $this->db->query($sql);
331
        if (!$result) {
332
            return 0;
333
        }
334
        if (false === $groupby) {
335
            [$max] = $this->db->fetchRow($result);
336
337
            return $max;
338
        }
339
        $ret = [];
340
        while (list($id, $max) = $this->db->fetchRow($result)) {
341
            $ret[$id] = $max;
342
        }
343
344
        return $ret;
345
    }
346
347
    /**
348
     * @param \CriteriaElement $criteria
349
     * @param string           $avg
350
     *
351
     * @return int
352
     */
353
    public function getAvg(\CriteriaElement $criteria = null, $avg = '*')
354
    {
355
        $field = '';
356
357
        $sql = 'SELECT ' . $field . "AVG($avg) FROM " . $this->table;
358
        if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
359
            $sql .= ' ' . $criteria->renderWhere();
360
        }
361
        $result = $this->db->query($sql);
362
        if (!$result) {
363
            return 0;
364
        }
365
        [$sum] = $this->db->fetchRow($result);
366
367
        return $sum;
368
    }
369
370
    /**
371
     * @return mixed
372
     */
373
    public function getInsertId()
374
    {
375
        return $this->db->getInsertId();
376
    }
377
}
378