Passed
Push — master ( fb46c9...e4f11c )
by Michael
17:52 queued 15:44
created

TagHandler   F

Complexity

Total Complexity 100

Size/Duplication

Total Lines 597
Duplicated Lines 0 %

Importance

Changes 10
Bugs 0 Features 0
Metric Value
eloc 282
c 10
b 0
f 0
dl 0
loc 597
rs 2
wmc 100

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
F updateByItem() 0 91 24
A getItemCount() 0 28 6
F getByLimit() 0 61 19
C update_stats() 0 104 13
B getByItem() 0 25 9
C getItems() 0 51 12
A getCount() 0 29 4
A delete() 0 40 1
A cleanOrphan() 0 6 1
B getTagData() 0 39 10

How to fix   Complexity   

Complex Class

Complex classes like TagHandler 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 TagHandler, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace XoopsModules\Tag;
4
5
/*
6
 You may not change or alter any portion of this comment or credits
7
 of supporting developers from this source code or any supporting source code
8
 which is considered copyrighted (c) material of the original comment or credit authors.
9
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
15
/**
16
 * XOOPS tag management module
17
 *
18
 * @package         XoopsModules\Tag
19
 * @copyright       {@link http://sourceforge.net/projects/xoops/ The XOOPS Project}
20
 * @license         {@link http://www.fsf.org/copyleft/gpl.html GNU public license}
21
 * @author          Taiwen Jiang <[email protected]>
22
 * @since           1.00
23
 */
24
\defined('XOOPS_ROOT_PATH') || exit('Restricted access');
25
26
use XoopsModules\Tag\Utility;
27
28
/**
29
 * Class TagHandler
30
 */
31
class TagHandler extends \XoopsPersistableObjectHandler
32
{
33
    public $table_link;
34
    public $table_stats;
35
36
    /**
37
     * Constructor
38
     *
39
     * @param \XoopsDatabase|null $db reference to the object {@link XoopsDatabase}
40
     */
41
    public function __construct(\XoopsDatabase $db = null)
42
    {
43
        parent::__construct($db, 'tag_tag', Tag::class, 'tag_id', 'tag_term');
44
        $this->table_link  = $this->db->prefix('tag_link');
45
        $this->table_stats = $this->db->prefix('tag_stats');
46
    }
47
48
    /**
49
     * Get tags linked to an item
50
     *
51
     * @access public
52
     * @param int $itemid item ID
53
     * @param int $modid  module ID, optional
54
     * @param int $catid  id of corresponding category, optional
55
     * @return array associative array of tags (id, term)
56
     */
57
    public function getByItem($itemid, $modid = 0, $catid = 0)
58
    {
59
        $ret = [];
60
61
        $itemid = (int)$itemid;
62
        $modid  = (empty($modid) && \is_object($GLOBALS['xoopsModule'])
63
                   && 'tag' !== $GLOBALS['xoopsModule']->getVar('dirname')) ? $GLOBALS['xoopsModule']->getVar('mid') : (int)$modid;
64
        if (empty($itemid) || empty($modid)) {
65
            return $ret;
66
        }
67
68
        $sql = 'SELECT o.tag_id, o.tag_term'
69
               . " FROM {$this->table_link} AS l "
70
               . " LEFT JOIN {$this->table} AS o ON o.{$this->keyName} = l.{$this->keyName} "
71
               . " WHERE  l.tag_itemid = {$itemid} AND l.tag_modid = {$modid}"
72
               . (empty($catid) ? '' : (' AND l.tag_catid=' . (int)$catid))
73
               . ' ORDER BY o.tag_count DESC';
74
75
        $result = $this->db->query($sql);
76
        if ($result instanceof \mysqli_result) {
77
            while (false !== ($myrow = $this->db->fetchArray($result))) {
78
                $ret[$myrow[$this->keyName]] = $myrow['tag_term'];
79
            }
80
        }
81
        return $ret;
82
    }
83
84
    /**
85
     * Update tags linked to an item
86
     *
87
     * @access   public
88
     * @param array|string $tags   array of $tags or a single tag
89
     * @param int          $itemid item ID
90
     * @param int|string   $modid  module ID or module dirname, optional
91
     * @param int          $catid  id of corresponding category, optional
92
     * @return bool
93
     */
94
    public function updateByItem($tags, $itemid, $modid = '', $catid = 0)
95
    {
96
        $catid  = (int)$catid;
97
        $itemid = (int)$itemid;
98
99
        if (!empty($modid) && !\is_numeric($modid)) {
100
            if (($GLOBALS['xoopsModule'] instanceof \XoopsModule)
101
                && ($modid == $GLOBALS['xoopsModule']->getVar('dirname'))) {
102
                $modid = $GLOBALS['xoopsModule']->getVar('mid');
103
            } else {
104
                /** @var \XoopsModuleHandler $moduleHandler */
105
                $moduleHandler = \xoops_getHandler('module');
106
                $modid         = ($module_obj = $moduleHandler->getByDirname($modid)) ? $module_obj->getVar('mid') : 0;
107
            }
108
        } elseif ($GLOBALS['xoopsModule'] instanceof \XoopsModule) {
109
            $modid = $GLOBALS['xoopsModule']->getVar('mid');
110
        }
111
112
        if (empty($itemid) || empty($modid)) {
113
            return false;
114
        }
115
116
        if (empty($tags)) {
117
            $tags = [];
118
        } elseif (!\is_array($tags)) {
119
            //require_once $GLOBALS['xoops']->path('/modules/tag/include/functions.php');
120
            $tags = Utility::tag_parse_tag(\addslashes(\stripslashes($tags)));
121
        }
122
123
        $tags_existing = $this->getByItem($itemid, $modid, $catid);
124
        $tags_delete   = \array_diff(\array_values($tags_existing), $tags);
125
        $tags_add      = \array_diff($tags, \array_values($tags_existing));
126
        $tags_update   = [];
127
128
        if (0 < \count($tags_delete)) {
129
            $tags_delete = \array_map([$this->db, 'quoteString'], $tags_delete);
130
            $tags_id     = &$this->getIds(new \Criteria('tag_term', '(' . \implode(', ', $tags_delete) . ')', 'IN'));
131
            if ($tags_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tags_id of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
132
                $sql = "DELETE FROM {$this->table_link}" . ' WHERE ' . "     {$this->keyName} IN (" . \implode(', ', $tags_id) . ')' . "     AND tag_modid = {$modid} AND tag_catid = {$catid} AND tag_itemid = {$itemid}";
133
                if (false === ($result = $this->db->queryF($sql))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
134
                    //@todo: decide if we should do something here on failure
135
                }
136
                $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . '    tag_count < 2 AND ' . "     {$this->keyName} IN (" . \implode(', ', $tags_id) . ')';
137
                if (false === ($result = $this->db->queryF($sql))) {
138
                    //xoops_error($this->db->error());
139
                }
140
141
                $sql = 'UPDATE ' . $this->table . ' SET tag_count = tag_count - 1' . ' WHERE ' . "     {$this->keyName} IN (" . \implode(', ', $tags_id) . ')';
142
                if (false === ($result = $this->db->queryF($sql))) {
143
                    //xoops_error($this->db->error());
144
                }
145
                $tags_update = $tags_id;
146
            }
147
        }
148
149
        if (!empty($tags_add)) {
150
            $tag_link  = [];
151
            $tag_count = [];
152
            foreach ($tags_add as $tag) {
153
                $tags_id = &$this->getIds(new \Criteria('tag_term', $tag));
154
                if ($tags_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tags_id of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
155
                    $tag_id      = $tags_id[0];
156
                    $tag_count[] = $tag_id;
157
                } else {
158
                    $tag_obj = $this->create();
159
                    $tag_obj->setVars(['tag_term' => $tag, 'tag_count' => 1]);
160
                    $this->insert($tag_obj);
161
                    $tag_id = $tag_obj->getVar('tag_id');
162
                    unset($tag_obj);
163
                }
164
                $tag_link[]    = "({$tag_id}, {$itemid}, {$catid}, {$modid}, " . \time() . ')';
165
                $tags_update[] = $tag_id;
166
            }
167
            $sql = "INSERT INTO {$this->table_link}" . ' (tag_id, tag_itemid, tag_catid, tag_modid, tag_time) ' . ' VALUES ' . \implode(', ', $tag_link);
168
            if (false === ($result = $this->db->queryF($sql))) {
169
                //xoops_error($this->db->error());
170
            }
171
            if (!empty($tag_count)) {
172
                $sql = 'UPDATE ' . $this->table . ' SET tag_count = tag_count+1' . ' WHERE ' . "     {$this->keyName} IN (" . \implode(', ', $tag_count) . ')';
173
                if (false === ($result = $this->db->queryF($sql))) {
174
                    //xoops_error($this->db->error());
175
                }
176
            }
177
        }
178
        if (\is_array($tags_update)) {
179
            foreach ($tags_update as $tag_id) {
180
                $this->update_stats($tag_id, $modid, $catid);
181
            }
182
        }
183
184
        return true;
185
    }
186
187
    /**
188
     * Update count stats or tag
189
     *
190
     * @access public
191
     * @param int $tag_id
192
     * @param int $modid
193
     * @param int $catid
194
     * @return bool
195
     */
196
    public function update_stats($tag_id, $modid = 0, $catid = 0)
197
    {
198
        $tag_id = (int)$tag_id;
199
        if (0 === $tag_id) {
200
            return true;
201
        }
202
203
        $tag_count = [];
204
        $modid     = (int)$modid;
205
        $catid     = (0 === $modid) ? -1 : (int)$catid;
206
207
        /** @var \XoopsModules\Tag\LinkHandler $linkHandler */
208
        $linkHandler = \XoopsModules\Tag\Helper::getInstance()->getHandler('Link');
209
        $criteria    = new \CriteriaCompo(new \Criteria('tag_id', $tag_id));
210
        if (0 !== $modid) {
211
            $criteria->add(new \Criteria('tag_modid', $modid), 'ADD');
212
        }
213
        if (0 < $catid) {
214
            $criteria->add(new \Criteria('tag_catid', $catid), 'ADD');
215
        }
216
        $count = $linkHandler->getCount($criteria);
217
        /*
218
        $sql   = 'SELECT COUNT(*) ' . " FROM {$this->table_link}" . " WHERE tag_id = {$tag_id}" . (empty($modid) ? '' : " AND tag_modid = {$modid}") . (($catid < 0) ? '' : " AND tag_catid = {$catid}");
219
220
        $result = $this->db->query($sql);
221
        if ($result) {
222
            list($count) = $this->db->fetchRow($result);
223
        }
224
        */
225
        if (0 === $modid) {
226
            $tag_obj = $this->get($tag_id);
227
            if ($tag_obj instanceof \XoopsModules\Tag\Tag) {
228
                if (0 === $count) {
229
                    $this->delete($tag_obj);
230
                } else {
231
                    $tag_obj->setVar('tag_count', $count);
232
                    $this->insert($tag_obj, true);
233
                }
234
            }
235
        } else {
236
            $statsHandler = \XoopsModules\Tag\Helper::getInstance()->getHandler('Stats');
237
            if (empty($count)) {
238
                $criteria = new \CriteriaCompo(new \Criteria($this->keyName, $tag_id));
239
                $criteria->add(new \Criteria('tag_modid, $modid'), 'AND');
240
                $criteria->add(new \Criteria('tag_catid', $catid), 'AND');
241
                $status = $statsHandler->deleteAll($criteria);
242
                if (!$status) {
243
                    //@todo determine what should happen here on failure.
244
                }
245
                /*
246
                $sql = "DELETE FROM {$this->table_stats}" . ' WHERE ' . " {$this->keyName} = {$tag_id}" . " AND tag_modid = {$modid}" . " AND tag_catid = {$catid}";
247
248
                if (false === $result = $this->db->queryF($sql)) {
249
                    //xoops_error($this->db->error());
250
                }
251
                */
252
            } else {
253
                $ts_id    = null;
254
                $criteria = new \CriteriaCompo(new \Criteria($this->keyName, $tag_id));
255
                $criteria->add(new \Criteria('tag_modid', $modid), 'AND');
256
                $criteria->add(new \Criteria('tag_catid', $catid), 'AND');
257
                $criteria->setLimit(1);
258
                $tsCountObjs = $statsHandler->getAll($criteria);
259
                if (\count($tsCountObjs) > 0) {
260
                    $tsCountObj = \array_pop($tsCountObjs); // get 1st (only) item
261
                    $ts_id      = $tsCountObj->getVar('ts_id');
262
                    $tag_count  = $tsCountObj->getVar('tag_count');
263
                }
264
                /*
265
                $sql   = 'SELECT ts_id, tag_count ' . " FROM {$this->table_stats}" . " WHERE {$this->keyName} = {$tag_id}" . " AND tag_modid = {$modid}" . " AND tag_catid = {$catid}";
266
                $result = $this->db->query($sql);
267
                if ($result) {
268
                    list($ts_id, $tag_count) = $this->db->fetchRow($result);
269
                }
270
                */
271
                $sql = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $sql is dead and can be removed.
Loading history...
272
                if ($ts_id) {
273
                    if ($tag_count != $count) {
274
                        $tsCountObj->setVar('tag_count', $count);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tsCountObj does not seem to be defined for all execution paths leading up to this point.
Loading history...
275
                        $statsHandler->insert($tsCountObj);
276
                        //$sql = "UPDATE {$this->table_stats}" . " SET tag_count = {$count}" . ' WHERE ' . "     ts_id = {$ts_id}";
277
                    }
278
                } else {
279
                    $newTsObj = $statsHandler->create();
280
                    $newTsObj->setVars(
281
                        [
282
                            'tag_id'    => $tag_id,
283
                            'tag_modid' => $modid,
284
                            'tag_catid' => $catid,
285
                            'tag_count' => $count,
286
                        ]
287
                    );
288
                    $statsHandler->insert($newTsObj);
289
                    //$sql = "INSERT INTO {$this->table_stats}" . ' (tag_id, tag_modid, tag_catid, tag_count)' . " VALUES ({$tag_id}, {$modid}, {$catid}, {$count})";
290
                }
291
                /*
292
                if (!empty($sql) && false === ($result = $this->db->queryF($sql))) {
293
                    //xoops_error($this->db->error());
294
                }
295
                */
296
            }
297
        }
298
299
        return true;
300
    }
301
302
    /**
303
     * Get tags with item count
304
     *
305
     * @access         public
306
     * @param int                                  $limit
307
     * @param int                                  $start
308
     * @param null|\CriteriaElement|\CriteriaCompo $criteria  {@link Criteria}
309
     * @param null                                 $fields
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fields is correct as it would always require null to be passed?
Loading history...
310
     * @param bool                                 $fromStats fetch from tag-stats table
311
     * @return array associative array of tags (id, term, status, count)
312
     */
313
    public function &getByLimit(
314
        $limit = Constants::UNLIMITED,
315
        $start = Constants::BEGINNING,
316
        \CriteriaElement $criteria = null,
317
        $fields = null,
318
        $fromStats = true
319
    )//&getByLimit($criteria = null, $fromStats = true)
320
    {
321
        $ret = [];
322
        if ($fromStats) {
323
            $sql = "SELECT DISTINCT(o.{$this->keyName}), o.tag_term, o.tag_status, SUM(l.tag_count) AS count" . " FROM {$this->table} AS o LEFT JOIN {$this->table_stats} AS l ON l.{$this->keyName} = o.{$this->keyName}";
324
        } else {
325
            $sql = "SELECT DISTINCT(o.{$this->keyName}), o.tag_term, o.tag_status, COUNT(l.tl_id) AS count" . " FROM {$this->table} AS o LEFT JOIN {$this->table_link} AS l ON l.{$this->keyName} = o.{$this->keyName}";
326
        }
327
328
        $limit = \is_int($limit) && ($limit >= 0) ? $limit : Constants::UNLIMITED;
329
        $start = \is_int($start) && ($start >= 0) ? $start : Constants::BEGINNING;
330
        $sort  = '';
331
        $order = '';
332
        if (($criteria instanceof \CriteriaCompo) || ($criteria instanceof \Criteria)) {
333
            $sql   .= ' ' . $criteria->renderWhere();
334
            $sort  = $criteria->getSort();
335
            $order = $criteria->getOrder();
336
            $limit = $limit >= 0 ? $limit : $criteria->getLimit(); // non-zero arg passed to method overrides $criteria setting
337
            $start = $start >= 0 ? $start : $criteria->getStart(); // non-zero arg passed to method overrides $criteria setting
338
        }
339
        $sql .= " GROUP BY o.{$this->keyName}, o.tag_term, o.tag_status, l.tag_modid";
340
341
        $order = ('ASC' !== \mb_strtoupper($order)) ? 'DESC' : 'ASC';
342
        $sort  = \mb_strtolower($sort);
343
        switch ($sort) {
344
            case 'a':
345
            case 'alphabet':
346
                $sql .= " ORDER BY o.tag_term {$order}";
347
                break;
348
            case 'id':
349
            case 'time':
350
                $sql .= " ORDER BY o.{$this->keyName} {$order}";
351
                break;
352
            case 'c':
353
            case 'count':
354
            default:
355
                $sql .= " ORDER BY count {$order}";
356
                break;
357
        }
358
359
        if (false === ($result = $this->db->query($sql, $limit, $start))) {
360
            //xoops_error($this->db->error());
361
            $ret = null;
362
        } else {
363
            while (false !== ($myrow = $this->db->fetchArray($result))) {
364
                $ret[$myrow[$this->keyName]] = [
365
                    'id'     => $myrow[$this->keyName],
366
                    'term'   => \htmlspecialchars($myrow['tag_term'], \ENT_QUOTES | \ENT_HTML5),
367
                    'status' => $myrow['tag_status'],
368
                    'count'  => (int)$myrow['count'],
369
                ];
370
            }
371
        }
372
373
        return $ret;
374
    }
375
376
    /**
377
     * Get count of tags
378
     *
379
     * @access public
380
     * @param null|\CriteriaElement|\CriteriaCompo $criteria {@link Criteria)
381
     * @return int count
382
     */
383
    public function getCount(\CriteriaElement $criteria = null)
384
    {
385
        /*
386
        $catid    = (int)($catid);
387
        $modid    = (int)($modid);
388
        */
389
        $sql = "SELECT COUNT(DISTINCT o.{$this->keyName})" . "    FROM {$this->table} AS o LEFT JOIN {$this->table_link} AS l ON l.{$this->keyName} = o.{$this->keyName}";
390
        if (($criteria instanceof \CriteriaCompo) || ($criteria instanceof \Criteria)) {
391
            $sql .= ' ' . $criteria->renderWhere();
392
        }
393
        /*
394
        $sql_where    = "    WHERE 1 = 1";
395
        if (!empty($modid)) {
396
            $sql_where    .= " AND l.tag_modid = {$modid}";
397
        }
398
        if (empty($catid) || $catid > 0) {
399
            $sql_where    .= " AND l.tag_catid = {$catid}";
400
        }
401
402
        $sql =     $sql_select . " " . $sql_from . " " . $sql_where;
403
        */
404
        if (false === ($result = $this->db->query($sql))) {
405
            //xoops_error($this->db->error());
406
            $ret = 0;
407
        } else {
408
            [$ret] = $this->db->fetchRow($result);
409
        }
410
411
        return $ret;
412
    }
413
414
    /**
415
     * Get items linked with a tag
416
     *
417
     * @access public
418
     * @param \CriteriaElement|null $criteria {@link Criteria}
419
     * @return array associative array of items[] => (id, modid, catid, time)
420
     */
421
    public function getItems(\CriteriaElement $criteria = null)
422
    {
423
        $ret = [];
424
        $sql = '    SELECT o.tl_id, o.tag_itemid, o.tag_modid, o.tag_catid, o.tag_time';
425
        $sql .= "    FROM {$this->table_link} AS o LEFT JOIN {$this->table} AS l ON l.{$this->keyName} = o.{$this->keyName}";
426
427
        $limit = Constants::UNLIMITED;
428
        $start = Constants::BEGINNING;
429
        $sort  = '';
430
        $order = '';
431
        if (($criteria instanceof \CriteriaCompo) || ($criteria instanceof \Criteria)) {
432
            $sql   .= ' ' . $criteria->renderWhere();
433
            $sort  = $criteria->getSort();
434
            $order = $criteria->getOrder();
435
            $limit = $criteria->getLimit();
436
            $start = $criteria->getStart();
437
        }
438
439
        $order = ('ASC' !== \mb_strtoupper($order)) ? 'DESC' : 'ASC';
440
        $sort  = \mb_strtolower($sort);
441
        switch ($sort) {
442
            case 'i':
443
            case 'item':
444
                $sql .= "    ORDER BY o.tag_itemid {$order}, o.tl_id DESC";
445
                break;
446
            case 'm':
447
            case 'module':
448
                $sql .= "    ORDER BY o.tag_modid {$order}, o.tl_id DESC";
449
                break;
450
            case 't':
451
            case 'time':
452
            default:
453
                $sql .= "    ORDER BY o.tl_id {$order}";
454
                break;
455
        }
456
457
        if (false === ($result = $this->db->query($sql, $limit, $start))) {
458
            //xoops_error($this->db->error());
459
            $ret = [];
460
        } else {
461
            while (false !== ($myrow = $this->db->fetchArray($result))) {
462
                $ret[$myrow['tl_id']] = [
463
                    'itemid' => $myrow['tag_itemid'],
464
                    'modid'  => $myrow['tag_modid'],
465
                    'catid'  => $myrow['tag_catid'],
466
                    'time'   => $myrow['tag_time'],
467
                ];
468
            }
469
        }
470
471
        return $ret;
472
    }
473
474
    /**
475
     * Get count of items linked with a tag
476
     *
477
     * @access public
478
     * @param int $tag_id
479
     * @param int $modid id of corresponding module, optional: 0 for all; >1 for a specific module
480
     * @param int $catid id of corresponding category, optional
481
     * @return int count
482
     */
483
    public function getItemCount($tag_id, $modid = 0, $catid = 0)
484
    {
485
        if (!$tag_id = (int)$tag_id) {
486
            $ret = 0;
487
        } else {
488
            $catid = (int)$catid;
489
            $modid = (int)$modid;
490
491
            $sql_select = '    SELECT COUNT(DISTINCT o.tl_id)';
492
            $sql_from   = "    FROM {$this->table_link} AS o LEFT JOIN {$this->table} AS l ON l.{$this->keyName} = o.{$this->keyName}";
493
            $sql_where  = "    WHERE o.tag_id = {$tag_id}";
494
            if (!empty($modid)) {
495
                $sql_where .= " AND o.tag_modid = {$modid}";
496
            }
497
            if (empty($catid) || $catid > 0) {
498
                $sql_where .= " AND o.tag_catid = {$catid}";
499
            }
500
501
            $sql = $sql_select . ' ' . $sql_from . ' ' . $sql_where;
502
            if (false === ($result = $this->db->query($sql))) {
503
                //xoops_error($this->db->error());
504
                $ret = 0;
505
            } else {
506
                [$ret] = $this->db->fetchRow($result);
507
            }
508
        }
509
510
        return $ret;
511
    }
512
513
    /**
514
     * Get detailed data (and font) for a tag
515
     *
516
     * @access public
517
     * @param array $tags_array associative array of tags (id, term, status, count)
518
     * @param int   $font_max
519
     * @param int   $font_min
520
     * @return array tag data values for display
521
     */
522
    public function getTagData($tags_array, $font_max = 0, $font_min = 0)
523
    {
524
        $tags_data_array = [];
525
        if (\is_array($tags_array) && !empty($tags_array)) {
526
            // set min and max tag count
527
            $count_array = \array_column($tags_array, 'count', 'id');
528
            $count_min   = \count($count_array) > 0 ? \min($count_array) : 0;
529
            $count_min   = max($count_min, 0);
530
            $count_max   = \count($count_array) > 0 ? \max($count_array) : 0;
531
            $count_max   = max($count_max, 0);
532
            if ($count_max > 0) {
533
                $term_array      = \array_column($tags_array, 'term', 'id');
534
                $tags_term_array = \array_map('\mb_strtolower', $term_array);
535
                \array_multisort($tags_term_array, \SORT_ASC, $tags_array);
0 ignored issues
show
Bug introduced by
SORT_ASC cannot be passed to array_multisort() as the parameter $rest expects a reference. ( Ignorable by Annotation )

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

535
                \array_multisort($tags_term_array, /** @scrutinizer ignore-type */ \SORT_ASC, $tags_array);
Loading history...
536
                $count_interval = $count_max - $count_min;
537
                $level_limit    = 5;
538
539
                $font_ratio = $count_interval ? ($font_max - $font_min) / $count_interval : 1;
540
541
                foreach ($tags_array as $tag) {
542
                    /*
543
                     * Font-size = ((tag.count - count.min) * (font.max - font.min) / (count.max - count.min) ) * 100%
544
                     */
545
                    $font_sz           = \floor(($tag['count'] - $count_min) * $font_ratio) + $font_min;
546
                    $level_sz          = \floor(($tag['count'] - $count_min) * $level_limit / $count_max);
547
                    $tags_data_array[] = [
548
                        'id'    => $tag['id'],
549
                        'font'  => empty($count_interval) ? 100 : (int)$font_sz,
550
                        'level' => empty($count_max) ? 0 : (int)$level_sz,
551
                        'term'  => \urlencode($tag['term']),
552
                        'title' => \htmlspecialchars($tag['term'], \ENT_QUOTES | \ENT_HTML5),
553
                        'count' => $tag['count'],
554
                    ];
555
                }
556
            }
557
        }
558
559
560
        return $tags_data_array;
561
    }
562
563
    /**
564
     * Delete an object as well as links relying on it
565
     *
566
     * @access public
567
     * @param \XoopsObject $object $object {@link Tag}
568
     * @param bool         $force  flag to force the query execution despite security settings
569
     * @return bool
570
     */
571
    public function delete(\XoopsObject $object, $force = true)
572
    {
573
        /* {@internal - this isn't needed if we type hint Tag object }}
574
        if (!is_object($object) || !$object->getVar($this->keyName)) {
575
            return false;
576
        }
577
        */
578
        //$queryFunc = empty($force) ? 'query' : 'queryF';
579
580
        /*
581
         * Remove item-tag links
582
         */
583
        $helper = \XoopsModules\Tag\Helper::getInstance();
584
585
        /** @var \XoopsModules\Tag\LinkHandler $linkHandler */
586
        $linkHandler = $helper->getHandler('Link');
587
        $criteria    = new \Criteria($this->keyName, $object->getVar($this->keyName));
0 ignored issues
show
Bug introduced by
It seems like $object->getVar($this->keyName) can also be of type array and array; however, parameter $value of Criteria::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

587
        $criteria    = new \Criteria($this->keyName, /** @scrutinizer ignore-type */ $object->getVar($this->keyName));
Loading history...
588
        $linkHandler->deleteAll($criteria, $force);
589
        //$sql = 'DELETE' . " FROM {$this->table_link}" . " WHERE  {$this->keyName} = " . $object->getVar($this->keyName);
590
        /*
591
                if (false ===  ($result = $this->db->{$queryFunc}($sql))) {
592
                   // xoops_error($this->db->error());
593
                }
594
        */
595
        /*
596
         * Remove stats-tag links
597
         */
598
        /** @var \XoopsModules\Tag\StatsHandler $statsHandler */
599
        $statsHandler = $helper->getHandler('Stats');
600
        $criteria     = new \Criteria($this->keyName, $object->getVar($this->keyName));
601
        $statsHandler->deleteAll($criteria, $force);
602
        //$sql = 'DELETE' . " FROM {$this->table_stats}" . " WHERE  {$this->keyName} = " . $object->getVar($this->keyName);
603
604
        /*
605
                if (false === ($result = $this->db->{$queryFunc}($sql))) {
606
                   // xoops_error($this->db->error());
607
                }
608
        */
609
610
        return parent::delete($object, $force);
611
    }
612
613
    /**
614
     * clean orphan links from database
615
     *
616
     * @access public
617
     * @param string $table_link
618
     * @param string $field_link
619
     * @param string $field_object
620
     * @return bool true on success
621
     */
622
    public function cleanOrphan($table_link = '', $field_link = '', $field_object = '')
623
    {
624
        require_once $GLOBALS['xoops']->path('/modules/tag/functions.recon.php');
625
626
        //mod_loadFunctions("recon");
627
        return \tag_cleanOrphan();
628
    }
629
}
630