GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Category::deleteCategoryRelation()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 16
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 3
dl 16
loc 16
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
namespace phpMyFAQ;
4
5
/**
6
 * The main category class. Yes, it's huge.
7
 *
8
 * This Source Code Form is subject to the terms of the Mozilla Public License,
9
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
10
 * obtain one at http://mozilla.org/MPL/2.0/.
11
 *
12
 * @package phpMyFAQ
13
 * @author Thorsten Rinne <[email protected]>
14
 * @author Lars Tiedemann <[email protected]>
15
 * @author Matteo Scaramuccia <[email protected]>
16
 * @author Rudi Ferrari <[email protected]>
17
 * @copyright 2004-2019 phpMyFAQ Team
18
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
19
 * @link https://www.phpmyfaq.de
20
 * @since 2004-02-16
21
 */
22
23
use phpMyFAQ\Category\Entity;
24
25
if (!defined('IS_VALID_PHPMYFAQ')) {
26
    exit();
27
}
28
29
/**
30
 * Class Category
31
 * @package phpMyFAQ
32
 * @author Thorsten Rinne <[email protected]>
33
 * @author Lars Tiedemann <[email protected]>
34
 * @author Matteo Scaramuccia <[email protected]>
35
 * @author Rudi Ferrari <[email protected]>
36
 * @copyright 2004-2019 phpMyFAQ Team
37
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
38
 * @link https://www.phpmyfaq.de
39
 * @since 2004-02-16
40
 */
41
class Category
42
{
43
    /**
44
     * The categories as an array.
45
     *
46
     * @var array
47
     */
48
    public $categories = [];
49
50
    /**
51
     * The category names as an array.
52
     *
53
     * @var array
54
     */
55
    public $categoryName = [];
56
57
    /**
58
     * The image as an array.
59
     *
60
     * @var array
61
     */
62
    public $image = [];
63
64
    /**
65
     * The category tree.
66
     * @var array
67
     */
68
    private $catTree = [];
69
70
    /**
71
     * The tree with the tabs.
72
     *
73
     * @var array
74
     */
75
    public $treeTab = [];
76
77
    /**
78
     * @var Configuration
79
     */
80
    private $config = null;
81
82
    /**
83
     * User ID.
84
     *
85
     * @var int
86
     */
87
    private $user = -1;
88
89
    /**
90
     * Groupd.
91
     *
92
     * @var array
93
     */
94
    private $groups = [-1];
95
96
    /**
97
     * The children nodes.
98
     *
99
     * @var array
100
     */
101
    private $children = [];
102
    /**
103
     * The current language.
104
     *
105
     * @var string
106
     */
107
    private $language = null;
108
109
    /**
110
     * The lines of tabs.
111
     *
112
     * @var array
113
     */
114
    private $lineTab = [];
115
116
    /**
117
     * Entity owners
118
     *
119
     * @var array
120
     */
121
    private $owner = [];
122
123
    /**
124
     * Entity moderators
125
     *
126
     * @var array
127
     */
128
    private $moderators = [];
129
130
    /**
131
     * Symbol for each item
132
     * NOTE: We do not use this currently.
133
     *
134
     * @var array
135
     */
136
    private $symbols = [
137
        'vertical' => '|',
138
        'plus' => '+',
139
        'minus' => '-',
140
        'space' => '&nbsp;',
141
        'angle' => '-',
142
        'medium' => '|-'
143
    ];
144
145
    /**
146
     * Constructor.
147
     *
148
     * @param Configuration $config Configuration object
149
     * @param array $groups Array with group IDs
150
     * @param bool $withPerm With or without permission check
151
     */
152
    public function __construct(Configuration $config, $groups = [], $withPerm = true)
153
    {
154
        $this->config = $config;
155
156
        $this->setGroups($groups);
157
        $this->setLanguage($this->config->getLanguage()->getLanguage());
158
159
        $this->lineTab = $this->getOrderedCategories($withPerm);
160
        foreach (array_keys($this->lineTab) as $i) {
161
            $this->lineTab[$i]['level'] = $this->levelOf($this->lineTab[$i]['id']);
162
        }
163
    }
164
165
    /**
166
     * @param array $groups
167
     */
168
    public function setGroups(Array $groups)
169
    {
170
        if (0 === count($groups)) {
171
            $groups = array(-1);
172
        }
173
        $this->groups = $groups;
174
    }
175
176
    /**
177
     * Sets language.
178
     *
179
     * @param string $language
180
     */
181
    public function setLanguage($language)
182
    {
183
        $this->language = $language;
184
    }
185
186
    /**
187
     * Returns all categories with ordered category IDs according to the user
188
     * and group permissions.
189
     *
190
     * @param bool $withPermission With or without permission check
191
     *
192
     * @return array
193
     */
194
    private function getOrderedCategories($withPermission = true)
195
    {
196
        $where = '';
197
198 View Code Duplication
        if ($withPermission) {
199
            $where = sprintf('
200
                WHERE
201
                    ( fg.group_id IN (%s)
202
                OR
203
                    (fu.user_id = %d AND fg.group_id IN (%s)))
204
                AND
205
                    fc.active = 1',
206
                implode(', ', $this->groups),
207
                $this->user,
208
                implode(', ', $this->groups)
209
            );
210
        }
211
212
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
213
            $where .= empty($where) ? '
214
            WHERE' : '
215
            AND';
216
            $where .= "
217
                fc.lang = '" . $this->language."'";
218
        }
219
220
        $query = sprintf('
221
            SELECT
222
                fc.id AS id,
223
                fc.lang AS lang,
224
                fc.parent_id AS parent_id,
225
                fc.name AS name,
226
                fc.description AS description,
227
                fc.user_id AS user_id,
228
                fc.group_id AS group_id,
229
                fc.active AS active,
230
                fc.image AS image,
231
                fc.show_home AS show_home
232
            FROM
233
                %sfaqcategories fc
234
            LEFT JOIN
235
                %sfaqcategory_group fg
236
            ON
237
                fc.id = fg.category_id
238
            LEFT JOIN
239
                %sfaqcategory_user fu
240
            ON
241
                fc.id = fu.category_id
242
            %s
243
            GROUP BY
244
                fc.id, fc.lang, fc.parent_id, fc.name, fc.description, fc.user_id, fc.group_id, fc.active, fc.image, fc.show_home
245
            ORDER BY
246
                fc.parent_id, fc.id',
247
            Db::getTablePrefix(),
248
            Db::getTablePrefix(),
249
            Db::getTablePrefix(),
250
            $where
251
        );
252
253
        $result = $this->config->getDb()->query($query);
254
255
        if ($result) {
256
            while ($row = $this->config->getDb()->fetchArray($result)) {
257
                $this->categoryName[$row['id']] = $row;
258
                $this->categories[] = & $this->categoryName[$row['id']];
259
                $this->children[$row['parent_id']][$row['id']] = & $this->categoryName[$row['id']];
260
                $this->owner[$row['id']] = & $row['user_id'];
261
                $this->moderators[$row['id']] = & $row['group_id'];
262
            }
263
        }
264
265
        return $this->categories;
266
    }
267
268
    /**
269
     * Get the level of the item id.
270
     *
271
     * @param int $id Entity id
272
     *
273
     * @return int
274
     */
275
    private function levelOf($id)
276
    {
277
        $alreadies = array($id);
278
        $ret = 0;
279
        while ((isset($this->categoryName[$id]['parent_id'])) && ($this->categoryName[$id]['parent_id'] != 0)) {
280
            ++$ret;
281
            $id = $this->categoryName[$id]['parent_id'];
282
283
            if (in_array($id, $alreadies)) {
284
                break;
285
            } else {
286
                array_push($alreadies, $id);
287
            }
288
        }
289
290
        return $ret;
291
    }
292
293
    /**
294
     * @param int $userId
295
     */
296
    public function setUser($userId = -1)
297
    {
298
        $this->user = $userId;
299
    }
300
301
    /**
302
     * Gets the main categories and write them in an array.
303
     *
304
     * @param string $categories Array of parent category ids
305
     * @param bool $parentId Only top level categories?
306
     *
307
     * @return array
308
     */
309
    public function getCategories($categories, $parentId = true)
310
    {
311
        $_query = '';
312
        $query = sprintf('
313
            SELECT
314
                id, lang, parent_id, name, description, user_id, group_id, active, image, show_home
315
            FROM
316
                %sfaqcategories
317
            WHERE ',
318
            Db::getTablePrefix());
319
320
        if (true === $parentId) {
321
            $query .= 'parent_id = 0';
322
        }
323
        foreach (explode(',', $categories) as $cats) {
324
            $_query .= ' OR parent_id = '.$cats;
325
        }
326
        if (false === $parentId && 0 < Strings::strlen($_query)) {
327
            $query .= Strings::substr($_query, 4);
328
        }
329
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
330
            $query .= " AND lang = '".$this->language."'";
331
        }
332
        $query .= ' ORDER BY id';
333
        $result = $this->config->getDb()->query($query);
334 View Code Duplication
        while ($row = $this->config->getDb()->fetchArray($result)) {
335
            $this->categories[$row['id']] = $row;
336
        }
337
338
        return $this->categories;
339
    }
340
341
    /**
342
     * Gets all categories and write them in an array.
343
     *
344
     * @return array
345
     */
346 View Code Duplication
    public function getAllCategories()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
347
    {
348
        $categories = [];
349
        $query = sprintf('
350
            SELECT
351
                id, lang, parent_id, name, description, user_id, group_id, active, show_home, image
352
            FROM
353
                %sfaqcategories',
354
            Db::getTablePrefix()
355
        );
356
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
357
            $query .= " WHERE lang = '".$this->language."'";
358
        }
359
        $result = $this->config->getDb()->query($query);
360
        while ($row = $this->config->getDb()->fetchArray($result)) {
361
            $categories[(int)$row['id']] = [
362
                'id' => (int)$row['id'],
363
                'lang' => $row['lang'],
364
                'parent_id' => (int)$row['parent_id'],
365
                'name' => $row['name'],
366
                'description' => $row['description'],
367
                'user_id' => (int)$row['user_id'],
368
                'group_id' => (int)$row['group_id'],
369
                'active' => (int)$row['active'],
370
                'show_home' => (int)$row['show_home'],
371
                'image' => $row['image'],
372
                'level' => (int)$this->levelOf($row['id'])
373
            ];
374
        }
375
376
        return $categories;
377
    }
378
379
    /**
380
     * Get top level categories and returns them in an array.
381
     *
382
     * @return array
383
     */
384 View Code Duplication
    public function getTopLevelCategories()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
385
    {
386
        $categories = [];
387
        $query = sprintf('
388
            SELECT
389
                id, lang, parent_id, name, description, user_id, group_id, active, show_home, image
390
            FROM
391
                %sfaqcategories
392
            WHERE 
393
                parent_id = 0',
394
            Db::getTablePrefix()
395
        );
396
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
397
            $query .= " AND lang = '".$this->language."'";
398
        }
399
        $result = $this->config->getDb()->query($query);
400
401
        while ($row = $this->config->getDb()->fetchArray($result)) {
402
            $categories[(int)$row['id']] = [
403
                'id' => (int)$row['id'],
404
                'lang' => $row['lang'],
405
                'parent_id' => (int)$row['parent_id'],
406
                'name' => $row['name'],
407
                'description' => $row['description'],
408
                'user_id' => (int)$row['user_id'],
409
                'group_id' => (int)$row['group_id'],
410
                'active' => (int)$row['active'],
411
                'show_home' => (int)$row['show_home'],
412
                'image' => $row['image'],
413
                'level' => (int)$this->levelOf($row['id'])
414
            ];
415
        }
416
417
        return $categories;
418
    }
419
420
    /**
421
     * Gets all categories and write them in an array.
422
     *
423
     * @return array
424
     */
425
    public function getHomeCategories()
426
    {
427
        $categories = [];
428
        $query = sprintf('
429
            SELECT
430
                id, lang, parent_id, name, description, user_id, group_id, active, show_home, image
431
            FROM
432
                %sfaqcategories
433
            WHERE 
434
                show_home = 1',
435
            Db::getTablePrefix()
436
        );
437
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
438
            $query .= " AND lang = '".$this->language."'";
439
        }
440
        $result = $this->config->getDb()->query($query);
441
        while ($row = $this->config->getDb()->fetchArray($result)) {
442
            $url = sprintf('%s?action=show&amp;cat=%d', Link::getSystemRelativeUri(), $row['id']);
443
            $link = new Link($url, $this->config);
444
            $link->itemTitle = $row['name'];
445
            $categories['url'][] = $link->toString();
446
            $categories['name'][] = $row['name'];
447
            $categories['description'][] = $row['description'];
448
            $categories['image'][] = $row['image'];
449
        }
450
451
        return $categories;
452
    }
453
454
    /**
455
     * Gets all category IDs
456
     *
457
     * @return array
458
     */
459
    public function getAllCategoryIds()
460
    {
461
        $categories = [];
462
463
        $query = sprintf('
464
            SELECT
465
                id
466
            FROM
467
                %sfaqcategories',
468
            Db::getTablePrefix()
469
        );
470
471
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
472
            $query .= sprintf(" WHERE lang = '%s'", $this->language);
473
        }
474
475
        $result = $this->config->getDb()->query($query);
476
477
        while ($row = $this->config->getDb()->fetchArray($result)) {
478
            $categories[] = (int)$row['id'];
479
        }
480
481
        return $categories;
482
    }
483
484
    /**
485
     * Builds the category tree.
486
     *
487
     * @param int $id_parent Parent id
488
     * @param int $indent Indention
489
     */
490
    public function buildTree($id_parent = 0, $indent = 0)
491
    {
492
        $tt = [];
493
        $x = 0;
494
495
        foreach ($this->categories as $categoryId => $n) {
496
            if (isset($n['parent_id']) && $n['parent_id'] == $id_parent) {
497
                $tt[$x++] = $categoryId;
498
            }
499
        }
500
501
        if ($x != 0) {
502
            foreach ($tt as $d) {
503
                $tmp = [];
504
                if (isset($this->categories[$d])) {
505
                    foreach ($this->categories[$d] as $key => $value) {
506
                        $tmp[$key] = $value;
507
                    }
508
                    $tmp['indent'] = $indent;
509
                    $this->catTree[] = $tmp;
510
                    $this->buildTree($tmp['id'], $indent + 1);
511
                }
512
            }
513
        }
514
    }
515
516
    /**
517
     * Transforms the linear array in a 1D array in the order of the tree, with
518
     * the info.
519
     *
520
     * @param int $id Entity id
521
     */
522
    public function transform($id)
523
    {
524
        $parentId = $level = $showHome = 0;
525
        $tree = [];
526
        $tabs = isset($this->children[$id]) ? array_keys($this->children[$id]) : [];
527
        $num = count($tabs);
528
        $symbol = 'minus';
529
        $name = $description = '';
530
        $active = true;
531
        $image = '';
532
533
        if ($id > 0) {
534
            $active = $this->categoryName[$id]['active'];
535
            $description = $this->categoryName[$id]['description'];
536
            $level = $this->categoryName[$id]['level'];
537
            $name = $this->categoryName[$id]['name'];
538
            $parentId = $this->categoryName[$id]['parent_id'];
539
            $image = $this->categoryName[$id]['image'];
540
            $showHome = $this->categoryName[$id]['show_home'];
541
        }
542
543
        if ($num < 0) {
544
            $temp = isset($this->children[$parentId]) ? array_keys($this->children[$parentId]) : [];
545
            if (isset($temp[count($temp) - 1])) {
546
                $symbol = ($id == $temp[count($temp) - 1]) ? 'angle' : 'medium';
547
            }
548
        }
549
550
        $ascendants = $this->getNodes($id);
551
        $numAscendants = count($ascendants);
552
553
        if ($id > 0) {
554
            for ($i = 0; $i < $numAscendants; ++$i) {
555
                $brothers = $this->getBrothers($ascendants[$i]);
556
                $tree[$i] = ($ascendants[$i] == $brothers[count($brothers) - 1]) ? 'space' : 'vertical';
557
            }
558
        }
559
560
        if ($id > 0) {
561
            $this->treeTab[] = array(
562
                'id' => $id,
563
                'symbol' => $symbol,
564
                'name' => $name,
565
                'numChilds' => count($tabs),
566
                'level' => $level,
567
                'parent_id' => $parentId,
568
                'childs' => $tabs,
569
                'tree' => $tree,
570
                'description' => $description,
571
                'active' => $active,
572
                'image' => $image,
573
                'show_home' => $showHome
574
            );
575
        }
576
577
        foreach ($tabs as $i) {
578
            $this->transform($i);
579
        }
580
    }
581
582
    //
583
584
    /**
585
     * List in array the root, super-root, ... of the $id.
586
     *
587
     * @param $id
588
     * @return array
589
     */
590
    private function getNodes($id)
591
    {
592
        if (($id > 0) && (isset($this->categoryName[$id]['level']))) {
593
            $thisLevel = $this->categoryName[$id]['level'];
594
            $temp = [];
595
            for ($i = $thisLevel; $i > 0; --$i) {
596
                $id = $this->categoryName[$id]['parent_id'];
597
                array_unshift($temp, $id);
598
            }
599
600
            return $temp;
601
        }
602
603
        return [];
604
    }
605
606
    /**
607
     * Gets the list of the brothers of $id (include $id).
608
     *
609
     * @param int $id Brothers
610
     *
611
     * @return array
612
     */
613
    private function getBrothers($id)
614
    {
615
        return $this->getChildren($this->categoryName[$id]['parent_id']);
616
    }
617
618
    /**
619
     * List in a array of the $id of the child.
620
     *
621
     * @param integer $categoryId
622
     *
623
     * @return array
624
     */
625
    public function getChildren($categoryId)
626
    {
627
        return isset($this->children[$categoryId]) ? array_keys($this->children[$categoryId]) : [];
628
    }
629
630
    /**
631
     * list in a array of the $id of the child.
632
     *
633
     * @param int $id Entity id
634
     *
635
     * @return array
636
     */
637
    public function getChildNodes($id)
638
    {
639
        $children = [];
640
641
        if (isset($this->children[$id])) {
642
            foreach (array_keys($this->children[$id]) as $childId) {
643
                $children = array_merge($children, array($childId));
644
                $children = array_merge($children, $this->getChildNodes($childId));
645
            }
646
        }
647
648
        return $children;
649
    }
650
651
    /**
652
     * Try to expand from the parent_id to the node $id
653
     *
654
     * @param int $id
655
     *
656
     * @return void
657
     */
658
    public function expandTo($id)
659
    {
660
        $this->collapseAll();
661
        $ascendants = $this->getNodes($id);
662
        $ascendants[] = $id;
663
        $numAscendants = count($ascendants);
664
        for ($i = 0; $i < $numAscendants; ++$i) {
665
            if (isset($this->treeTab[$this->getLineCategory($ascendants[$i])]['numChilds'])) {
666
                $numChilds = $this->treeTab[$this->getLineCategory($ascendants[$i])]['numChilds'];
667
                if ($numChilds > 0) {
668
                    $this->expand($ascendants[$i]);
669
                } else {
670
                    $i = count($ascendants);
671
                }
672
            }
673
        }
674
    }
675
676
    /**
677
     * Collapse the complete category tree.
678
     */
679 View Code Duplication
    public function collapseAll()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
680
    {
681
        $numTreeTab = count($this->treeTab);
682
        for ($i = 0; $i < $numTreeTab; ++$i) {
683
            if ($this->treeTab[$i]['symbol'] == 'minus') {
684
                $this->treeTab[$i]['symbol'] = 'plus';
685
            }
686
        }
687
    }
688
689
    /**
690
     * Get the line number where to find the node $id in the category tree.
691
     *
692
     * @param int $id Entity id
693
     *
694
     * @return int
695
     */
696
    private function getLineCategory($id)
697
    {
698
        $num = count($this->treeTab);
699
        for ($i = 0; $i < $num; ++$i) {
700
            if (isset($this->treeTab[$i]['id']) && $this->treeTab[$i]['id'] == $id) {
701
                return $i;
702
            }
703
        }
704
    }
705
706
    /**
707
     * expand the node $id.
708
     *
709
     * @param int $id Entity id
710
     */
711
    public function expand($id)
712
    {
713
        $this->treeTab[$this->getLineCategory($id)]['symbol'] = 'minus';
714
    }
715
716
    /**
717
     * print the static tree with the number of records.
718
     *
719
     * @return string
720
     */
721
    public function viewTree()
722
    {
723
        global $sids, $plr;
724
725
        $number = [];
726
727
        $query = sprintf('
728
            SELECT
729
                fcr.category_id AS category_id,
730
                count(fcr.category_id) AS number
731
            FROM
732
                %sfaqcategoryrelations fcr,
733
                %sfaqdata fd
734
            WHERE
735
                fcr.record_id = fd.id
736
            AND
737
                fcr.record_lang = fd.lang',
738
            Db::getTablePrefix(),
739
            Db::getTablePrefix());
740
741
        if (strlen($this->language) > 0) {
742
            $query .= sprintf(" AND fd.lang = '%s'",
743
                $this->language);
744
        }
745
746
        $query .= sprintf("
747
            AND
748
                fd.active = 'yes'
749
            GROUP BY
750
                fcr.category_id",
751
            Db::getTablePrefix(),
752
            Db::getTablePrefix());
753
        $result = $this->config->getDb()->query($query);
754
        if ($this->config->getDb()->numRows($result) > 0) {
755
            while ($row = $this->config->getDb()->fetchObject($result)) {
756
                $number[$row->category_id] = $row->number;
757
            }
758
        }
759
        $output = '<ul class="pmf-category-overview">';
760
        $open = 0;
761
        $this->expandAll();
762
763
        for ($y = 0; $y < $this->height(); $y = $this->getNextLineTree($y)) {
764
            list($hasChild, $categoryName, $parent, $description) = $this->getLineDisplay($y);
765
            $level = $this->treeTab[$y]['level'];
766
            $levelDiff = $open - $level;
767
            if (!isset($number[$parent])) {
768
                $number[$parent] = 0;
769
            }
770
771 View Code Duplication
            if ($this->config->get('records.hideEmptyCategories') && 0 === $number[$parent] && '-' === $hasChild) {
772
                continue;
773
            }
774
775
            if ($levelDiff > 1) {
776
                $output .= '</li>';
777
                for ($i = $levelDiff; $i > 1; --$i) {
778
                    $output .= '</ul></li>';
779
                }
780
            }
781
782
            if ($level < $open) {
783
                if (($level - $open) == -1) {
784
                    $output .= '</li>';
785
                }
786
                $output .= '</ul></li>';
787
            } elseif ($level == $open && $y != 0) {
788
                $output .= '</li>';
789
            }
790
791
            if ($level > $open) {
792
                $output .= sprintf(
793
                    '<ul><li data-category-id="%d" data-category-level="%d">',
794
                    $parent,
795
                    $level
796
                );
797
            } else {
798
                $output .= sprintf(
799
                    '<li data-category-id="%d" data-category-level="%d">',
800
                    $parent,
801
                    $level
802
                );
803
            }
804
805
            if (0 === $number[$parent] && 0 === $level) {
806
                $numFaqs = '';
807
            } else {
808
                $numFaqs = '<span class="rssCategoryLink"> ('.$plr->GetMsg('plmsgEntries', $number[$parent]);
809
                if ($this->config->get('main.enableRssFeeds')) {
810
                    $numFaqs .= sprintf(
811
                        ' <a href="feed/category/rss.php?category_id=%d&category_lang=%s" target="_blank"><i aria-hidden="true" class="fas fa-rss"></i></a>',
812
                        $parent,
813
                        $this->language,
814
                        $parent
815
                    );
816
                }
817
                $numFaqs .= ')</span>';
818
            }
819
820
            $url = sprintf(
821
                '%s?%saction=show&amp;cat=%d',
822
                Link::getSystemRelativeUri(),
823
                $sids,
824
                $parent
825
            );
826
            $oLink = new Link($url, $this->config);
827
            $oLink->itemTitle = $categoryName;
828
            $oLink->text = $categoryName;
829
            $oLink->tooltip = $description;
830
831
            $output .= $oLink->toHtmlAnchor().$numFaqs;
832
            $open = $level;
833
        }
834
835
        if (isset($level) && $level > 0) {
836
            $output .= str_repeat('</li></ul>', $level);
837
        }
838
839
        $output .= '</li></ul>';
840
841
        return $output;
842
    }
843
844
    /**
845
     * Expand the entire tree
846
     *
847
     * @return void
848
     */
849 View Code Duplication
    public function expandAll()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
850
    {
851
        $numTreeTab = count($this->treeTab);
852
        for ($i = 0; $i < $numTreeTab; ++$i) {
853
            if ($this->treeTab[$i]['symbol'] == 'plus') {
854
                $this->treeTab[$i]['symbol'] = 'minus';
855
            }
856
        }
857
    }
858
859
    /**
860
     * Total height of the expanded tree.
861
     *
862
     * @return int
863
     */
864
    public function height()
865
    {
866
        return count($this->treeTab);
867
    }
868
869
    /**
870
     * Gets the next line in the array treeTab, depending of the
871
     * collapse/expand node.
872
     *
873
     * @param int $line Current line
874
     *
875
     * @return int
876
     */
877
    public function getNextLineTree($line)
878
    {
879
        if ($this->treeTab[$line]['symbol'] !== 'plus') {
880
            return $line + 1;
881
        } else {
882
            for ($i = $line + 1; $i < $this->height(); ++$i) {
883
                if ($this->treeTab[$i]['level'] <= $this->treeTab[$line]['level']) {
884
                    return $i;
885
                }
886
            }
887
        }
888
889
        return $this->height();
890
    }
891
892
    /**
893
     * Returns the four parts of a line to display: category name, the ID of
894
     * the root node, the description and if the category is active
895
     *
896
     * @param integer $node
897
     *
898
     * @return array
899
     */
900
    public function getLineDisplay($node)
901
    {
902
        return [
903
            $this->symbols[$this->treeTab[$node]['symbol']],
904
            $this->treeTab[$node]['name'],
905
            $this->treeTab[$node]['id'],
906
            $this->treeTab[$node]['description'],
907
            $this->treeTab[$node]['active'],
908
            $this->treeTab[$node]['image']
909
        ];
910
    }
911
912
    /**
913
     * Creates a category link.
914
     *
915
     * @param string $sids Session id
916
     * @param int $categoryId Parent category
917
     * @param string $categoryName Entity name
918
     * @param string $description Description
919
     * @param bool $hasChildren Child categories available
920
     * @param bool $isActive Sets a link active via CSS
921
     *
922
     * @return string
923
     */
924
    public function addCategoryLink(
925
        $sids,
926
        $categoryId,
927
        $categoryName,
928
        $description,
929
        $hasChildren = false,
930
        $isActive = false
931
    ) {
932
        $url = sprintf(
933
            '%s?%saction=show&amp;cat=%d',
934
            Link::getSystemRelativeUri(),
935
            $sids,
936
            $categoryId
937
        );
938
939
        $oLink = new Link($url, $this->config);
940
        $oLink->id = 'category_'.$categoryId;
941
        $oLink->itemTitle = $categoryName;
942
        $oLink->text = $categoryName;
943
944
        if ($hasChildren) {
945
            $oLink->text .= sprintf(
946
                '<i aria-hidden="true" class="fas fa-caret-right"></i>',
947
                $categoryName);
948
        }
949
950
        if ($isActive) {
951
            $oLink->class = 'active';
952
        }
953
954
        $oLink->tooltip = $description;
955
956
        return $oLink->toHtmlAnchor();
957
    }
958
959
    /*
960
     * Generate HTML for Categories each level
961
     *
962
     * @param array $categories
963
     * @param integer $level
964
     * @return string
965
     */
966
967
    /**
968
     * Get Entity Data for the next level
969
     *
970
     * @param array $ids category id
971
     * @param $parentId parent category
972
     *
973
     * @return array
974
     */
975
    public function getCategoriesDataNextLevel(Array $ids, $parentId)
976
    {
977
        $result = [];
978
        foreach ($ids as $catId) {
979
            $category = $this->getCategoryData($catId);
980
            if ($parentId == $category->getParentId()) {
981
                array_push($result, $this->getCategoryData($catId));
982
            }
983
        }
984
985
        return $result;
986
    }
987
988
    /**
989
     * Returns the data of the given category.
990
     *
991
     * @param int $categoryId
992
     *
993
     * @return Entity
994
     */
995
    public function getCategoryData($categoryId)
996
    {
997
        $entity = new Entity();
998
999
        $query = sprintf(
1000
            "SELECT * FROM %sfaqcategories WHERE id = %d AND lang = '%s'",
1001
            Db::getTablePrefix(),
1002
            $categoryId,
1003
            $this->language
1004
        );
1005
1006
        $result = $this->config->getDb()->query($query);
1007
1008
        if ($row = $this->config->getDb()->fetchObject($result)) {
1009
            $entity
1010
                ->setId($row->id)
1011
                ->setLang($row->lang)
1012
                ->setParentId($row->parent_id)
1013
                ->setName($row->name)
1014
                ->setDescription($row->description)
1015
                ->setUserId($row->user_id)
1016
                ->setGroupId($row->group_id)
1017
                ->setActive($row->active)
1018
                ->setShowHome($row->show_home)
1019
                ->setImage($row->image);
1020
        }
1021
1022
        return $entity;
1023
    }
1024
1025
    public function generateCategoriesList(array $categories, $level)
1026
    {
1027
        $output = '<div class="pmf-categories pmf-slider-categories-'.$level.'" ><ul id="categories_'.$level.'">';
1028
        if (count($categories) > 0) {
1029
            foreach ($categories as $category) {
1030
                $output .= '<li class="slide_category_2" id="'.$category->getId().'" >';
1031
                $output .= '<span class="info">'.$category->getName().'</span>';
1032
                if ('' != $category->getImage()) {
1033
                    $output .= '<img src="'.'/images/'.$category->getImage().'" alt="'.$category->getName().'">';
1034
                } else {
1035
                    $output .= '<img src="/images/no_picture.png" alt="'.$category->getName().'">';
1036
                }
1037
                $output .= '</li>';
1038
            }
1039
            $output .= '</ul></div>';
1040
        }
1041
        return $output;
1042
    }
1043
1044
    /**
1045
     * Gets the path from root to child as breadcrumbs.
1046
     *
1047
     * @param int $id Entity ID
1048
     * @param string $separator Path separator
1049
     * @param bool $renderAsMicroData Renders breadcrumbs as HTML5 microdata
1050
     * @param string $useCssClass Use CSS class "breadcrumb"
1051
     *
1052
     * @return string
1053
     */
1054
    public function getPath($id, $separator = ' / ', $renderAsMicroData = false, $useCssClass = 'breadcrumb')
1055
    {
1056
        global $sids;
1057
1058
        $ids = $this->getNodes($id);
1059
        $num = count($ids);
1060
1061
        $temp = $catid = $desc = $breadcrumb = [];
1062
1063
        for ($i = 0; $i < $num; ++$i) {
1064
            $t = $this->getLineCategory($ids[$i]);
1065
            if (array_key_exists($t, $this->treeTab)) {
1066
                $temp[] = $this->treeTab[$this->getLineCategory($ids[$i])]['name'];
1067
                $catid[] = $this->treeTab[$this->getLineCategory($ids[$i])]['id'];
1068
                $desc[] = $this->treeTab[$this->getLineCategory($ids[$i])]['description'];
1069
            }
1070
        }
1071
        if (isset($this->treeTab[$this->getLineCategory($id)]['name'])) {
1072
            $temp[] = $this->treeTab[$this->getLineCategory($id)]['name'];
1073
            $catid[] = $this->treeTab[$this->getLineCategory($id)]['id'];
1074
            $desc[] = $this->treeTab[$this->getLineCategory($id)]['description'];
1075
        }
1076
1077
        // @todo Maybe this should be done somewhere else ...
1078
        if ($renderAsMicroData) {
1079
            foreach ($temp as $k => $category) {
1080
                $url = sprintf(
1081
                    '%s?%saction=show&amp;cat=%d',
1082
                    Link::getSystemRelativeUri(),
1083
                    $sids,
1084
                    $catid[$k]
1085
                );
1086
                $oLink = new Link($url, $this->config);
1087
                $oLink->text = sprintf('<span itemprop="title">%s</span>', $category);
1088
                $oLink->itemTitle = $category;
1089
                $oLink->tooltip = $desc[$k];
1090
                $oLink->setItemProperty('url');
1091
                if (0 == $k) {
1092
                    $oLink->setRelation('index');
1093
                }
1094
1095
                $breadcrumb[] = sprintf(
1096
                    '<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb">%s</li>',
1097
                    $oLink->toHtmlAnchor()
1098
                );
1099
            }
1100
1101
            $temp = $breadcrumb;
1102
1103
            return sprintf(
1104
                '<ul class="%s">%s</ul>',
1105
                $useCssClass,
1106
                implode('', $temp)
1107
            );
1108
        } else {
1109
            return implode($separator, $temp);
1110
        }
1111
    }
1112
1113
    /**
1114
     * Returns the categories from a record id and language.
1115
     *
1116
     * @param int $record_id record id
1117
     * @param int $record_lang record language
1118
     *
1119
     * @return array
1120
     */
1121 View Code Duplication
    public function getCategoryRelationsFromArticle($record_id, $record_lang)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1122
    {
1123
        $categories = [];
1124
1125
        $query = sprintf("
1126
            SELECT
1127
                category_id, category_lang
1128
            FROM
1129
                %sfaqcategoryrelations
1130
            WHERE
1131
                record_id = %d
1132
            AND
1133
                record_lang = '%s'",
1134
            Db::getTablePrefix(),
1135
            $record_id,
1136
            $record_lang);
1137
1138
        $result = $this->config->getDb()->query($query);
1139
        while ($row = $this->config->getDb()->fetchObject($result)) {
1140
            $categories[$row->category_id] = array(
1141
                'category_id' => $row->category_id,
1142
                'category_lang' => $row->category_lang,
1143
            );
1144
        }
1145
1146
        return $categories;
1147
    }
1148
1149
    /**
1150
     * Returns the ID of a category that associated with the given article.
1151
     *
1152
     * @param int $faqId FAQ id
1153
     *
1154
     * @return int
1155
     */
1156
    public function getCategoryIdFromFaq($faqId)
1157
    {
1158
        $cats = $this->getCategoryIdsFromFaq($faqId);
1159
        if (isset($cats[0])) {
1160
            return $cats[0];
1161
        } else {
1162
            return 0;
1163
        }
1164
    }
1165
1166
    /**
1167
     * Returns an array with the IDs of all categories that are associated with
1168
     * the given article.
1169
     *
1170
     * @param int $faqId Record id
1171
     *
1172
     * @return array
1173
     */
1174
    public function getCategoryIdsFromFaq($faqId)
1175
    {
1176
        $categories = $this->getCategoriesFromFaq($faqId);
1177
        $result = [];
1178
        foreach ($categories as $category) {
1179
            $result[] = $category['id'];
1180
        }
1181
1182
        return $result;
1183
    }
1184
1185
    /**
1186
     * Returns all categories that are related to the given article-id and
1187
     * the current language $this->language in an unsorted array which consists
1188
     * of associative arrays with the keys 'name', 'id', 'lang',
1189
     * 'parent_id' and 'description'.
1190
     *
1191
     * @param int $faqId Record id
1192
     *
1193
     * @return array
1194
     */
1195
    public function getCategoriesFromFaq($faqId)
1196
    {
1197
        $query = sprintf("
1198
            SELECT
1199
                fc.id AS id,
1200
                fc.lang AS lang,
1201
                fc.parent_id AS parent_id,
1202
                fc.name AS name,
1203
                fc.description AS description
1204
            FROM
1205
                %sfaqcategoryrelations fcr,
1206
                %sfaqcategories fc
1207
            WHERE
1208
                fc.id = fcr.category_id
1209
            AND
1210
                fcr.record_id = %d
1211
            AND
1212
                fcr.category_lang = '%s'
1213
            AND
1214
                fc.lang = '%s'",
1215
            Db::getTablePrefix(),
1216
            Db::getTablePrefix(),
1217
            $faqId,
1218
            $this->language,
1219
            $this->language
1220
        );
1221
1222
        $result = $this->config->getDb()->query($query);
1223
        $num = $this->config->getDb()->numRows($result);
1224
        $this->categories = [];
1225
        if ($num > 0) {
1226 View Code Duplication
            while ($row = $this->config->getDb()->fetchArray($result)) {
1227
                $this->categories[intval($row['id'])] = $row;
1228
            }
1229
        }
1230
1231
        return $this->categories;
1232
    }
1233
1234
    /**
1235
     * Given FAQ ID and category ID are connected or not.
1236
     * @param $faqId
1237
     * @param $categoryId
1238
     * @return bool
1239
     */
1240
    public function categoryHasLinkToFaq($faqId, $categoryId)
1241
    {
1242
        $categories = $this->getCategoriesFromFaq($faqId);
1243
        foreach ($categories as $category) {
1244
            if ((int)$category['id'] === (int)$categoryId) {
1245
                return true;
1246
            }
1247
        }
1248
1249
        return false;
1250
    }
1251
1252
    /**
1253
     * Returns the admin user of the given category.
1254
     *
1255
     * @param int $categoryId
1256
     *
1257
     * @return int
1258
     */
1259
    public function getCategoryUser($categoryId)
1260
    {
1261
        if (isset($this->categories[$categoryId]['user_id'])) {
1262
            return $this->categories[$categoryId]['user_id'];
1263
        } else {
1264
            return 1;
1265
        }
1266
    }
1267
1268
    /**
1269
     * Returns the category tree as array.
1270
     * @return array
1271
     */
1272
    public function getCategoryTree(): array
1273
    {
1274
        return $this->catTree;
1275
    }
1276
1277
    /**
1278
     * Returns the moderator group ID of the given category.
1279
     *
1280
     * @param int $categoryId
1281
     *
1282
     * @return int
1283
     */
1284
    public function getModeratorGroupId($categoryId)
1285
    {
1286
        return $this->moderators[$categoryId];
1287
    }
1288
1289
    /**
1290
     * Adds a new category entry.
1291
     *
1292
     * @param array $categoryData Array of category data
1293
     * @param int $parentId Parent id
1294
     * @param int $id Entity id
1295
     *
1296
     * @return int
1297
     */
1298
    public function addCategory(Array $categoryData, $parentId = 0, $id = null)
1299
    {
1300
        // If we only need a new language, we don't need a new category id
1301
        if (is_null($id)) {
1302
            $id = $this->config->getDb()->nextId(Db::getTablePrefix().'faqcategories', 'id');
1303
        }
1304
1305
        $query = sprintf("
1306
            INSERT INTO
1307
                %sfaqcategories
1308
            (id, lang, parent_id, name, description, user_id, group_id, active, image, show_home)
1309
                VALUES
1310
            (%d, '%s', %d, '%s', '%s', %d, %d, %d, '%s', %d)",
1311
            Db::getTablePrefix(),
1312
            $id,
1313
            $categoryData['lang'],
1314
            $parentId,
1315
            $categoryData['name'],
1316
            $categoryData['description'],
1317
            $categoryData['user_id'],
1318
            $categoryData['group_id'],
1319
            $categoryData['active'],
1320
            $categoryData['image'],
1321
            $categoryData['show_home']
1322
        );
1323
        $this->config->getDb()->query($query);
1324
1325
        return $id;
1326
    }
1327
1328
    /**
1329
     * Updates an existent category entry.
1330
     *
1331
     * @param array $categoryData Array of category data
1332
     *
1333
     * @return bool
1334
     */
1335
    public function updateCategory(Array $categoryData)
1336
    {
1337
        $query = sprintf("
1338
            UPDATE
1339
                %sfaqcategories
1340
            SET
1341
                name = '%s',
1342
                description = '%s',
1343
                user_id = %d,
1344
                group_id = %d,
1345
                active = %d,
1346
                show_home = %d,
1347
                image = '%s'
1348
            WHERE
1349
                id = %d
1350
            AND
1351
                lang = '%s'",
1352
            Db::getTablePrefix(),
1353
            $categoryData['name'],
1354
            $categoryData['description'],
1355
            $categoryData['user_id'],
1356
            $categoryData['group_id'],
1357
            $categoryData['active'],
1358
            $categoryData['show_home'],
1359
            $categoryData['image'],
1360
            $categoryData['id'],
1361
            $categoryData['lang']
1362
        );
1363
1364
        return $this->config->getDb()->query($query);
1365
    }
1366
1367
    /**
1368
     * Move the categories ownership for users.
1369
     *
1370
     * @param int $from Old user id
1371
     * @param int $to New user id
1372
     *
1373
     * @return bool
1374
     */
1375
    public function moveOwnership($from, $to)
1376
    {
1377
        if (!is_numeric($from) || !is_numeric($to)) {
1378
            return false;
1379
        }
1380
1381
        $query = sprintf('
1382
            UPDATE
1383
                %sfaqcategories
1384
            SET
1385
                user_id = %d
1386
            WHERE
1387
                user_id = %d',
1388
            Db::getTablePrefix(),
1389
            $to,
1390
            $from
1391
        );
1392
        $this->config->getDb()->query($query);
1393
1394
        return true;
1395
    }
1396
1397
    /**
1398
     * Checks if a language is already defined for a category id.
1399
     *
1400
     * @param int $category_id Entity id
1401
     * @param string $category_lang Entity language
1402
     *
1403
     * @return bool
1404
     */
1405
    public function checkLanguage($category_id, $category_lang)
1406
    {
1407
        $query = sprintf("
1408
            SELECT
1409
                lang
1410
            FROM
1411
                %sfaqcategories
1412
            WHERE
1413
                id = %d
1414
            AND
1415
                lang = '%s'",
1416
            Db::getTablePrefix(),
1417
            $category_id,
1418
            $category_lang);
1419
1420
        $result = $this->config->getDb()->query($query);
1421
1422
        return $this->config->getDb()->numRows($result);
1423
    }
1424
1425
    /**
1426
     * Swaps two categories.
1427
     *
1428
     * @param int $category_id_1 First category
1429
     * @param int $category_id_2 Second category
1430
     *
1431
     * @return bool
1432
     */
1433
    public function swapCategories($category_id_1, $category_id_2)
1434
    {
1435
        $temp_cat = rand(200000, 400000);
1436
1437
        $tables = array(
1438
            array('faqcategories' => 'id'),
1439
            array('faqcategories' => 'parent_id'),
1440
            array('faqcategoryrelations' => 'category_id'),
1441
            array('faqcategory_group' => 'category_id'),
1442
            array('faqcategory_user' => 'category_id'),
1443
        );
1444
1445
        $result = true;
1446 View Code Duplication
        foreach ($tables as $pair) {
1447
            foreach ($pair as $_table => $_field) {
1448
                $result = $result && $this->config->getDb()->query(sprintf('UPDATE %s SET %s = %d WHERE %s = %d',
1449
                        Db::getTablePrefix().$_table,
1450
                        $_field,
1451
                        $temp_cat,
1452
                        $_field,
1453
                        $category_id_2));
1454
                $result = $result && $this->config->getDb()->query(sprintf('UPDATE %s SET %s = %d WHERE %s = %d',
1455
                        Db::getTablePrefix().$_table,
1456
                        $_field,
1457
                        $category_id_2,
1458
                        $_field,
1459
                        $category_id_1));
1460
                $result = $result && $this->config->getDb()->query(sprintf('UPDATE %s SET %s = %d WHERE %s = %d',
1461
                        Db::getTablePrefix().$_table,
1462
                        $_field,
1463
                        $category_id_1,
1464
                        $_field,
1465
                        $temp_cat));
1466
            }
1467
        }
1468
1469
        $tables2 = array(array('faqquestions' => 'category_id'));
1470
1471 View Code Duplication
        foreach ($tables2 as $pair) {
1472
            foreach ($pair as $_table => $_field) {
1473
                $result = $result && $this->config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'",
1474
                        Db::getTablePrefix().$_table,
1475
                        $_field,
1476
                        $temp_cat,
1477
                        $_field,
1478
                        $category_id_2));
1479
                $result = $result && $this->config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'",
1480
                        Db::getTablePrefix().$_table,
1481
                        $_field,
1482
                        $category_id_2,
1483
                        $_field,
1484
                        $category_id_1));
1485
                $result = $result && $this->config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'",
1486
                        Db::getTablePrefix().$_table,
1487
                        $_field,
1488
                        $category_id_1,
1489
                        $_field,
1490
                        $temp_cat));
1491
            }
1492
        }
1493
1494
        return $result;
1495
    }
1496
1497
    /**
1498
     * Updates the parent category.
1499
     *
1500
     * @param int $category_id Entity id
1501
     * @param int $parent_id Parent category id
1502
     *
1503
     * @return bool
1504
     */
1505
    public function updateParentCategory($category_id, $parent_id)
1506
    {
1507
        if ((!is_numeric($category_id) || !is_numeric($parent_id)) && $category_id != $parent_id) {
1508
            return false;
1509
        }
1510
1511
        $query = sprintf('
1512
            UPDATE
1513
                %sfaqcategories
1514
            SET
1515
                parent_id = %d
1516
            WHERE
1517
                id = %d',
1518
            Db::getTablePrefix(),
1519
            $parent_id,
1520
            $category_id);
1521
        $this->config->getDb()->query($query);
1522
1523
        return true;
1524
    }
1525
1526
    /**
1527
     * Deletes a category.
1528
     *
1529
     * @param int $category_id Entity id
1530
     * @param string $category_lang Categiry language
1531
     * @param bool $delete_all Delete all languages?
1532
     *
1533
     * @return bool
1534
     */
1535 View Code Duplication
    public function deleteCategory($category_id, $category_lang, $delete_all = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1536
    {
1537
        $query = sprintf('
1538
            DELETE FROM
1539
                %sfaqcategories
1540
            WHERE
1541
                id = %d',
1542
            Db::getTablePrefix(),
1543
            $category_id);
1544
        if (!$delete_all) {
1545
            $query .= " AND lang = '".$category_lang."'";
1546
        }
1547
        $this->config->getDb()->query($query);
1548
1549
        return true;
1550
    }
1551
1552
    /**
1553
     * Deletes a category relation.
1554
     *
1555
     * @param int $category_id Entity id
1556
     * @param string $category_lang Categiry language
1557
     * @param bool $delete_all Delete all languages?
1558
     *
1559
     * @return bool
1560
     */
1561 View Code Duplication
    public function deleteCategoryRelation($category_id, $category_lang, $delete_all = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1562
    {
1563
        $query = sprintf('
1564
            DELETE FROM
1565
                %sfaqcategoryrelations
1566
            WHERE
1567
                category_id = %d',
1568
            Db::getTablePrefix(),
1569
            $category_id);
1570
        if (!$delete_all) {
1571
            $query .= " AND category_lang = '".$category_lang."'";
1572
        }
1573
        $this->config->getDb()->query($query);
1574
1575
        return true;
1576
    }
1577
1578
    /**
1579
     * Create array with translated categories.
1580
     *
1581
     * @param int $category_id
1582
     *
1583
     * @return array
1584
     */
1585
    public function getCategoryLanguagesTranslated($category_id)
1586
    {
1587
        global $languageCodes;
1588
1589
        $existcatlang = $this->config->getLanguage()->languageAvailable($category_id, 'faqcategories');
1590
        $translated = [];
1591
1592
        foreach ($existcatlang as $language) {
1593
            $query = sprintf("
1594
               SELECT
1595
                  name, description
1596
               FROM
1597
                   %sfaqcategories
1598
               WHERE
1599
                   id = %d
1600
               AND
1601
                   lang = '%s'",
1602
                Db::getTablePrefix(),
1603
                $category_id,
1604
                $language);
1605
            $result = $this->config->getDb()->query($query);
1606
            if ($row = $this->config->getDb()->fetchArray($result)) {
1607
                $translated[$languageCodes[strtoupper($language)]] = $row['name'].('' == $row['description'] ? '' : '  ('.$row['description'].')');
1608
            }
1609
        }
1610
        ksort($translated);
1611
1612
        return $translated;
1613
    }
1614
1615
    /**
1616
     * Create all languages which can be used for translation as <option>.
1617
     *
1618
     * @param int $category_id Entity id
1619
     * @param string $selected_lang Selected language
1620
     *
1621
     * @return string
1622
     */
1623
    public function getCategoryLanguagesToTranslate($category_id, $selected_lang)
1624
    {
1625
        $output = '';
1626
        $existcatlang = $this->config->getLanguage()->languageAvailable($category_id, 'faqcategories');
1627
1628
        foreach (Language::getAvailableLanguages() as $lang => $langname) {
1629
            if (!in_array(strtolower($lang), $existcatlang)) {
1630
                $output .= "\t<option value=\"".strtolower($lang).'"';
1631
                if ($lang == $selected_lang) {
1632
                    $output .= ' selected="selected"';
1633
                }
1634
                $output .= '>'.$langname."</option>\n";
1635
            }
1636
        }
1637
1638
        return $output;
1639
    }
1640
1641
    /**
1642
     * Gets all categories which are not translated in actual language
1643
     * to add in this->categories (used in admin section).
1644
     */
1645
    public function getMissingCategories()
1646
    {
1647
        $query = sprintf('
1648
            SELECT
1649
                id, lang, parent_id, name, description, user_id
1650
            FROM
1651
                %sfaqcategories',
1652
            Db::getTablePrefix());
1653
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
1654
            $query .= " WHERE lang != '".$this->language."'";
1655
        }
1656
        $query .= ' ORDER BY id';
1657
        $result = $this->config->getDb()->query($query);
1658
        while ($row = $this->config->getDb()->fetchArray($result)) {
1659
            if (!array_key_exists($row['id'], $this->categoryName)) {
1660
                $this->categoryName[$row['id']] = $row;
1661
                $this->categories[$row['id']] = &$this->categoryName[$row['id']];
1662
                $this->children[$row['parent_id']][$row['id']] = &$this->categoryName[$row['id']];
1663
            }
1664
        }
1665
    }
1666
1667
    /**
1668
     * Get number of nodes at the same parent_id level.
1669
     *
1670
     * @param int $parent_id Parent id
1671
     *
1672
     * @return int
1673
     */
1674 View Code Duplication
    public function numParent($parent_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1675
    {
1676
        $query = sprintf('
1677
            SELECT distinct
1678
                id
1679
            FROM
1680
                %sfaqcategories
1681
            WHERE
1682
                parent_id = %d',
1683
            Db::getTablePrefix(),
1684
            $parent_id);
1685
        $result = $this->config->getDb()->query($query);
1686
1687
        return $this->config->getDb()->numRows($result);
1688
    }
1689
1690
    /**
1691
     * Adds the category permissions for users and groups.
1692
     *
1693
     * @param string $mode 'group' or 'user'
1694
     * @param array $categories ID of the current category
1695
     * @param array $ids Array of group or user IDs
1696
     *
1697
     * @return bool
1698
     */
1699
    public function addPermission($mode, Array $categories, Array $ids)
1700
    {
1701
        if ('user' !== $mode && 'group' !== $mode) {
1702
            return false;
1703
        }
1704
1705
        foreach ($categories as $categoryId) {
1706
            foreach ($ids as $id) {
1707
                $query = sprintf(
1708
                    'SELECT * FROM %sfaqcategory_%s WHERE category_id = %d AND %s_id = %d',
1709
                    Db::getTablePrefix(),
1710
                    $mode,
1711
                    $categoryId,
1712
                    $mode,
1713
                    $id
1714
                );
1715
1716
                if ($this->config->getDb()->numRows($this->config->getDb()->query($query))) {
1717
                    continue;
1718
                }
1719
1720
                $query = sprintf(
1721
                    'INSERT INTO %sfaqcategory_%s (category_id, %s_id) VALUES (%d, %d)',
1722
                    Db::getTablePrefix(),
1723
                    $mode,
1724
                    $mode,
1725
                    $categoryId,
1726
                    $id
1727
                );
1728
1729
                $this->config->getDb()->query($query);
1730
            }
1731
        }
1732
1733
        return true;
1734
    }
1735
1736
    /**
1737
     * Deletes the category permissions for users and groups.
1738
     *
1739
     * @param string $mode 'group' or 'user'
1740
     * @param array $categories ID of the current category
1741
     *
1742
     * @return bool
1743
     */
1744 View Code Duplication
    public function deletePermission($mode, $categories)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1745
    {
1746
        if (!($mode == 'user' || $mode == 'group')) {
1747
            return false;
1748
        }
1749
        if (!is_array($categories)) {
1750
            return false;
1751
        }
1752
1753
        foreach ($categories as $category_id) {
1754
            $query = sprintf('
1755
                DELETE FROM
1756
                    %sfaqcategory_%s
1757
                WHERE
1758
                    category_id = %d',
1759
                Db::getTablePrefix(),
1760
                $mode,
1761
                $category_id);
1762
            $this->config->getDb()->query($query);
1763
        }
1764
1765
        return true;
1766
    }
1767
1768
    /**
1769
     * Returns the category permissions for users and groups.
1770
     *
1771
     * @param string $mode 'group' or 'user'
1772
     * @param array $categories Array of category ids
1773
     *
1774
     * @return array
1775
     */
1776
    public function getPermissions($mode, Array $categories)
1777
    {
1778
        $permissions = [];
1779
        if (!($mode === 'user' || $mode === 'group')) {
1780
            return $permissions;
1781
        }
1782
        if (!is_array($categories)) {
1783
            return $permissions;
1784
        }
1785
1786
        $query = sprintf('
1787
            SELECT
1788
                %s_id AS permission
1789
            FROM
1790
                %sfaqcategory_%s
1791
            WHERE
1792
                category_id IN (%s)',
1793
            $mode,
1794
            Db::getTablePrefix(),
1795
            $mode,
1796
            implode(', ', $categories));
1797
1798
        $result = $this->config->getDb()->query($query);
1799
        while ($row = $this->config->getDb()->fetchObject($result)) {
1800
            $permissions[] = $row->permission;
1801
        }
1802
1803
        return $permissions;
1804
    }
1805
1806
    /**
1807
     * Returns the number of records in each category.
1808
     *
1809
     * @param bool $categoryRestriction
1810
     *
1811
     * @return array
1812
     */
1813
    public function getNumberOfRecordsOfCategory($categoryRestriction = false)
1814
    {
1815
        $numRecordsByCat = [];
1816
        if ($categoryRestriction) {
1817
            $query = sprintf('
1818
                SELECT
1819
                    fcr.category_id AS category_id,
1820
                    COUNT(fcr.record_id) AS number
1821
                FROM
1822
                    %sfaqcategoryrelations fcr
1823
                LEFT JOIN
1824
                    %sfaqdata fd on fcr.record_id = fd.id
1825
                LEFT JOIN
1826
                    %sfaqdata_group fdg on fdg.record_id = fcr.record_id
1827
                WHERE
1828
                    fdg.group_id = %s
1829
                AND
1830
                    fcr.record_lang = fd.lang
1831
                GROUP BY fcr.category_id',
1832
                Db::getTablePrefix(),
1833
                Db::getTablePrefix(),
1834
                Db::getTablePrefix(),
1835
                $this->groups[0]);
1836
        } else {
1837
            $query = sprintf('
1838
                SELECT
1839
                    fcr.category_id AS category_id,
1840
                    COUNT(fcr.record_id) AS number
1841
                FROM
1842
                    %sfaqcategoryrelations fcr, %sfaqdata fd
1843
                WHERE
1844
                    fcr.record_id = fd.id
1845
                AND
1846
                    fcr.record_lang = fd.lang
1847
                GROUP BY fcr.category_id',
1848
                Db::getTablePrefix(),
1849
                Db::getTablePrefix());
1850
        }
1851
        $result = $this->config->getDb()->query($query);
1852
1853
        if ($this->config->getDb()->numRows($result) > 0) {
1854
            while ($row = $this->config->getDb()->fetchObject($result)) {
1855
                $numRecordsByCat[$row->category_id] = $row->number;
1856
            }
1857
        }
1858
1859
        return $numRecordsByCat;
1860
    }
1861
1862
    /**
1863
     * Create a matrix for representing categories and faq records.
1864
     *
1865
     * @return array
1866
     */
1867
    public function getCategoryRecordsMatrix()
1868
    {
1869
        $matrix = [];
1870
1871
        $query = sprintf('
1872
            SELECT
1873
                fcr.category_id AS id_cat,
1874
                fd.id AS id
1875
            FROM
1876
                %sfaqdata fd
1877
            INNER JOIN
1878
                %sfaqcategoryrelations fcr
1879
            ON
1880
                fd.id = fcr.record_id
1881
            AND
1882
                fd.lang = fcr.category_lang
1883
            ORDER BY
1884
                fcr.category_id, fd.id',
1885
            Db::getTablePrefix(),
1886
            Db::getTablePrefix());
1887
        $result = $this->config->getDb()->query($query);
1888
1889
        if ($this->config->getDb()->numRows($result) > 0) {
1890
            while ($row = $this->config->getDb()->fetchObject($result)) {
1891
                $matrix[$row->id_cat][$row->id] = true;
1892
            }
1893
        }
1894
1895
        return $matrix;
1896
    }
1897
1898
    /**
1899
     * Returns the user id of the category owner
1900
     * @param integer $categoryId
1901
     * @return int
1902
     */
1903
    public function getOwner(int $categoryId): int
1904
    {
1905
        return isset($this->owner[$categoryId]) ? (int)$this->owner[$categoryId] : 1;
1906
    }
1907
}
1908