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.
Completed
Pull Request — master (#1192)
by
unknown
14:48
created

PMF_Category::viewTree()   F

Complexity

Conditions 21
Paths 792

Size

Total Lines 128
Code Lines 77

Duplication

Lines 21
Ratio 16.41 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 21
loc 128
rs 2.3015
c 1
b 0
f 0
cc 21
eloc 77
nc 792
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * The main category class
4
 *
5
 * PHP Version 5.4
6
 *
7
 * This Source Code Form is subject to the terms of the Mozilla Public License,
8
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
9
 * obtain one at http://mozilla.org/MPL/2.0/.
10
 *
11
 * @category  phpMyFAQ
12
 * @package   Category
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-2014 phpMyFAQ Team
18
 * @license   http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
19
 * @link      http://www.phpmyfaq.de
20
 * @since     2004-02-16
21
 */
22
23
if (!defined('IS_VALID_PHPMYFAQ')) {
24
    exit();
25
}
26
27
/**
28
 * Category
29
 *
30
 * @category  phpMyFAQ
31
 * @package   Category
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-2014 phpMyFAQ Team
37
 * @license   http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
38
 * @link      http://www.phpmyfaq.de
39
 * @since     2004-02-16
40
 */
41
class PMF_Category
42
{
43
    /**
44
     * @var PMF_Configuration
45
     */
46
    private $_config = null;
47
48
    /**
49
     * User ID
50
     *
51
     * @var integer
52
     */
53
    private $user = -1;
54
55
    /**
56
     * Groupd
57
     *
58
     * @var array
59
     */
60
    private $groups = array(-1);
61
62
    /**
63
     *
64
     * The categories as an array.
65
     *
66
     * @var  array
67
     */
68
    public $categories = [];
69
70
    /**
71
     * The category names as an array.
72
     *
73
     * @var  array
74
     */
75
    public $categoryName = [];
76
77
    /**
78
     * The category tree
79
     *
80
     * @var  array
81
     */
82
    public $catTree = [];
83
84
    /**
85
     * The children nodes
86
     *
87
     * @var  array
88
     */
89
    private $children = [];
90
91
    /**
92
     * The current language
93
     *
94
     * @var  string
95
     */
96
    private $language = null;
97
98
    /**
99
     * The lines of tabs
100
     *
101
     * @var  array
102
     */
103
    private $lineTab = [];
104
105
    /**
106
     * The tree with the tabs
107
     *
108
     * @var  array
109
     */
110
    public $treeTab = [];
111
112
    /**
113
     * Symbol for each item
114
     * NOTE: We do not use this currently
115
     *
116
     * @var  array
117
     */
118
    private $symbols = array(
119
        'vertical' => '|',
120
        'plus'     => '+',
121
        'minus'    => '-',
122
        'space'    => '&nbsp;',
123
        'angle'    => '-',
124
        'medium'   => '|-');
125
126
    /**
127
     * Constructor
128
     *
129
     * @param PMF_Configuration $config   Configuration object
130
     * @param array             $groups   Array with group IDs
131
     * @param boolean           $withperm With or without permission check
132
     *
133
     * @return PMF_Category
134
     */
135
    public function __construct(PMF_Configuration $config, $groups = [], $withperm = true)
136
    {
137
        $this->_config = $config;
138
139
        $this->setGroups($groups);
140
        $this->setLanguage($this->_config->getLanguage()->getLanguage());
141
142
        $this->lineTab = $this->getOrderedCategories($withperm);
143
        for ($i = 0; $i < count($this->lineTab); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
144
            $this->lineTab[$i]['level'] = $this->levelOf($this->lineTab[$i]['id']);
145
        }
146
    }
147
148
    /**
149
     * @param integer $userId
150
     */
151
    public function setUser($userId = -1)
152
    {
153
        $this->user = $userId;
154
    }
155
156
    /**
157
     * @param array $groups
158
     */
159
    public function setGroups(Array $groups)
160
    {
161
        if (0 === count($groups)) {
162
            $groups = array(-1);
163
        }
164
        $this->groups = $groups;
165
    }
166
167
    /**
168
     * Returns all categories with ordered category IDs according to the user
169
     * and group permissions
170
     *
171
     * @param  boolean $withperm With or without permission check
172
     * @return array
173
     */
174
    private function getOrderedCategories($withperm = true)
175
    {
176
        $where = '';
177
178 View Code Duplication
        if ($withperm) {
179
            $where = sprintf("
180
                WHERE
181
                    ( fg.group_id IN (%s)
182
                OR
183
                    (fu.user_id = %d AND fg.group_id IN (%s)))",
184
                implode(', ', $this->groups),
185
                $this->user,
186
                implode(', ', $this->groups)
187
            );
188
        }
189
190
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
191
            $where .= empty($where) ? '
192
            WHERE' : '
193
            AND';
194
            $where .= "
195
                fc.lang = '".$this->language."'";
196
        }
197
198
        $query = sprintf("
199
            SELECT
200
                fc.id AS id,
201
                fc.lang AS lang,
202
                fc.parent_id AS parent_id,
203
                fc.name AS name,
204
                fc.description AS description,
205
                fc.user_id AS user_id
206
            FROM
207
                %sfaqcategories fc
208
            LEFT JOIN
209
                %sfaqcategory_group fg
210
            ON
211
                fc.id = fg.category_id
212
            LEFT JOIN
213
                %sfaqcategory_user fu
214
            ON
215
                fc.id = fu.category_id%s
216
            GROUP BY
217
                fc.id, fc.lang, fc.parent_id, fc.name, fc.description, fc.user_id
218
            ORDER BY
219
                fc.id",
220
            PMF_Db::getTablePrefix(),
221
            PMF_Db::getTablePrefix(),
222
            PMF_Db::getTablePrefix(),
223
            $where
224
        );
225
226
        $result = $this->_config->getDb()->query($query);
227
228 View Code Duplication
        while ($row = $this->_config->getDb()->fetchArray($result)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
229
            $this->categoryName[$row['id']] = $row;
230
            $this->categories[] =& $this->categoryName[$row['id']];
231
            $this->children[$row['parent_id']][$row['id']] =& $this->categoryName[$row['id']];
232
        }
233
234
        return $this->categories;
235
    }
236
237
    /**
238
     * Gets the main categories and write them in an array
239
     *
240
     * @param  string  $categories Array of parent category ids
241
     * @param  boolean $parent_id  Only top level categories?
242
     *
243
     * @return array
244
     */
245
    public function getCategories($categories, $parent_id = true)
246
    {
247
        $_query = '';
248
        $query  = sprintf('
249
            SELECT
250
                id, lang, parent_id, name, description, user_id
251
            FROM
252
                %sfaqcategories
253
            WHERE ',
254
            PMF_Db::getTablePrefix());
255
256
        if (true == $parent_id) {
257
            $query .= 'parent_id = 0';
258
        }
259
        foreach (explode(',', $categories) as $cats) {
260
            $_query .= ' OR parent_id = '.$cats;
261
        }
262
        if (false == $parent_id && 0 < PMF_String::strlen($_query)) {
263
            $query .= PMF_String::substr($_query, 4);
264
        }
265 View Code Duplication
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
266
            $query .= " AND lang = '".$this->language."'";
267
        }
268
        $query .= " ORDER BY id";
269
        $result = $this->_config->getDb()->query($query);
270 View Code Duplication
        while ($row = $this->_config->getDb()->fetchArray($result)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
271
            $this->categories[$row['id']] = $row;
272
        }
273
        return $this->categories;
274
    }
275
276
    /**
277
     * Gets all categories and write them in an array
278
     *
279
     * @return array
280
     */
281
    public function getAllCategories()
282
    {
283
        $query = sprintf("
284
            SELECT
285
                id, lang, parent_id, name, description, user_id
286
            FROM
287
                %sfaqcategories",
288
            PMF_Db::getTablePrefix());
289 View Code Duplication
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
290
            $query .= " WHERE lang = '".$this->language."'";
291
        }
292
        $result = $this->_config->getDb()->query($query);
293 View Code Duplication
        while ($row = $this->_config->getDb()->fetchArray($result)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
294
            $this->categories[$row["id"]] = $row;
295
        }
296
        return $this->categories;
297
    }
298
299
    /**
300
     * Builds the category tree
301
     *
302
     * @param  integer $id_parent Parent id
303
     * @param  integer $indent    Indention
304
     * @return void
305
     */
306
    public function buildTree($id_parent = 0, $indent = 0)
307
    {
308
        $tt = [];
309
        $x = 0;
310
        $loop = 0;
311
312
        foreach ($this->categories as $n) {
313
            if (isset($n['parent_id']) && $n['parent_id'] == $id_parent) {
314
                $tt[$x++] = $loop;
315
            }
316
            $loop++;
317
        }
318
319
        if ($x != 0) {
320
            foreach ($tt as $d) {
321
                $tmp = [];
322
                if (isset($this->categories[$d])) {
323
                    foreach ($this->categories[$d] as $key => $value) {
324
                        $tmp[$key] = $value;
325
                    }
326
                    $tmp['indent'] = $indent;
327
                    $this->catTree[] = $tmp;
328
                    $this->buildTree($tmp["id"], $indent + 1);
329
                }
330
            }
331
        }
332
    }
333
334
    /**
335
     * Get the level of the item id
336
     *
337
     * @param  integer $id Category id
338
     * @return integer
339
     */
340
    private function levelOf($id)
341
    {
342
        $alreadies = array($id);
343
        $ret       = 0;
344
        while ((isset($this->categoryName[$id]['parent_id'])) && ($this->categoryName[$id]['parent_id'] != 0)) {
345
            $ret++;
346
            $id = $this->categoryName[$id]['parent_id'];
347
348
            if (in_array($id, $alreadies)) {
349
                break;
350
            } else {
351
                array_push($alreadies, $id);
352
            }
353
        }
354
        return $ret;
355
    }
356
357
    /**
358
     * Get the line number where to find the node $id
359
     *
360
     * @param  integer $id Category id
361
     * @return integer
362
     */
363
    private function getLine($id)
364
    {
365
        for ($i = 0; $i < count($this->lineTab); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
366
            if ($this->lineTab[$i]['id'] == $id) {
367
                return $i;
368
            }
369
        }
370
    }
371
372
    /**
373
     * Transforms the linear array in a 1D array in the order of the tree, with
374
     * the info
375
     *
376
     * @param  integer $id Category id
377
     * @return void
378
     */
379
    public function transform($id)
380
    {
381
        $thisParent_id = 0;
382
        $tree          = [];
383
        $tabs          = isset($this->children[$id]) ? array_keys($this->children[$id]) : [];
384
        $num           = count($tabs);
385
386
        if ($id > 0) {
387
            $thisLevel       = $this->categoryName[$id]['level'];
388
            $thisParent_id   = $this->categoryName[$id]['parent_id'];
389
            $thisName        = $this->categoryName[$id]['name'];
390
            $thisdescription = $this->categoryName[$id]['description'];
391
        }
392
393
        if ($num > 0) {
394
            $symbol = 'minus';
395
        } else {
396
            $temp = isset($this->children[$thisParent_id]) ? array_keys($this->children[$thisParent_id]) : [];
397
            if (isset($temp[count($temp)-1])) {
398
                $symbol = ($id == $temp[count($temp)-1]) ? 'angle' : 'medium';
399
            }
400
        }
401
402
        $ascendants     = $this->getNodes($id);
403
        $num_ascendants = count($ascendants);
404
405
        if ($id > 0) {
406
            for ($i = 0; $i < $num_ascendants; $i++) {
407
                $brothers = $this->getBrothers($ascendants[$i]);
408
                $tree[$i] = ($ascendants[$i] == $brothers[count($brothers) - 1]) ? 'space' : 'vertical';
409
            }
410
        }
411
412
        if ($id > 0) {
413
            $this->treeTab[] = array(
414
                'id'          => $id,
415
                'symbol'      => $symbol,
416
                'name'        => $thisName,
417
                'numChilds'   => count($tabs),
418
                'level'       => $thisLevel,
419
                'parent_id'   => $thisParent_id,
420
                'childs'      => $tabs,
421
                'tree'        => $tree,
422
                'description' => $thisdescription
423
            );
424
        }
425
426
        foreach ($tabs as $i) {
427
            $this->transform($i);
428
        }
429
    }
430
431
    /**
432
     * Get the line number where to find the node $id in the category tree
433
     *
434
     * @param  integer $id Category id
435
     * @return integer
436
     */
437
    private function getLineCategory($id)
438
    {
439
        for ($i = 0; $i < count($this->treeTab); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
440
            if (isset($this->treeTab[$i]['id']) && $this->treeTab[$i]['id'] == $id) {
441
                return $i;
442
            }
443
        }
444
    }
445
446
    //
447
    /**
448
     * List in a array of the $id of the child
449
     *
450
     * @param  integer $id Category id
451
     * @return array
452
     * @access public
453
     * @author Thorsten Rinne <[email protected]>
454
     */
455
    public function getChildren($id)
456
    {
457
        return isset($this->children[$id]) ? array_keys($this->children[$id]) : [];
458
    }
459
460
    /**
461
     * list in a array of the $id of the child
462
     *
463
     * @param  integer $id Category id
464
     * @return array
465
     */
466
    public function getChildNodes($id)
467
    {
468
        $childs = [];
469
470
        if (isset($this->children[$id])) {
471
            foreach(array_keys($this->children[$id]) as $childId) {
472
                $childs = array_merge($childs, array($childId));
473
                $childs = array_merge($childs, $this->getChildNodes($childId));
474
            }
475
        }
476
477
        return $childs;
478
    }
479
480
    /**
481
     * number of childs of the $id
482
     *
483
     * @param  integer $id Category id
484
     * @return integer
485
     */
486
    private function numChilds($id)
487
    {
488
        return count($this->getNodes($id));
489
    }
490
491
    /**
492
     * List in array the root, super-root, ... of the $id
493
     *
494
     * @param  integer $id Category id
495
     * @return array
496
     */
497
    private function getNodes($id)
498
    {
499
        if (($id > 0) && (isset($this->categoryName[$id]['level']))) {
500
            $thisLevel = $this->categoryName[$id]['level'];
501
            $temp = [];
502
            for ($i = $thisLevel; $i > 0; $i--) {
503
                $id = $this->categoryName[$id]['parent_id'];
504
                array_unshift($temp, $id);
505
            }
506
            return $temp;
507
        }
508
    }
509
510
    /**
511
     * Collapse the complete category tree
512
     *
513
     * @return void
514
     */
515 View Code Duplication
    public function collapseAll()
516
    {
517
        for ($i = 0; $i < count($this->treeTab); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
518
            if ($this->treeTab[$i]["symbol"] == "minus") {
519
                $this->treeTab[$i]["symbol"] = "plus";
520
            }
521
        }
522
    }
523
524
    /**
525
     * expand the node $id
526
     *
527
     * @param  integer $id Category id
528
     * @return void
529
     */
530
    public function expand($id)
531
    {
532
        $this->treeTab[$this->getLineCategory($id)]["symbol"] = "minus";
533
    }
534
535
    // try to expand from the parent_id to the node $id
536
    public function expandTo($id)
537
    {
538
        $this->collapseAll();
539
        $ascendants = $this->getNodes($id);
540
        $ascendants[] = $id;
541
        for ($i = 0; $i < count($ascendants); $i++) {
542
            $numChilds = 0;
543
            if (isset($this->treeTab[$this->getLineCategory($ascendants[$i])]["numChilds"])) {
544
                $numChilds = $this->treeTab[$this->getLineCategory($ascendants[$i])]["numChilds"];
545
                if ($numChilds > 0) {
546
                    $this->expand($ascendants[$i]);
547
                } else {
548
                    $i = count($ascendants);
549
                }
550
            }
551
        }
552
    }
553
554
    /**
555
     * expand the entire tree
556
     *
557
     * @return void
558
     */
559 View Code Duplication
    public function expandAll()
560
    {
561
        for ($i = 0; $i < count($this->treeTab); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
562
            if ($this->treeTab[$i]["symbol"] == "plus") {
563
                $this->treeTab[$i]["symbol"] = "minus";
564
            }
565
        }
566
    }
567
568
    /**
569
     * Total height of the expanded tree
570
     *
571
     * @return integer
572
     */
573
    public function height()
574
    {
575
        return count($this->treeTab);
576
    }
577
578
    /**
579
    * print the static tree with the number of records
580
    *
581
    * @return string
582
    */
583
    public function viewTree()
584
    {
585
        global $sids, $plr;
586
587
        $totFaqRecords = 0;
588
        $number = [];
589
590
        $query = sprintf("
591
            SELECT
592
                fcr.category_id AS category_id,
593
                count(fcr.category_id) AS number
594
            FROM
595
                %sfaqcategoryrelations fcr,
596
                %sfaqdata fd
597
            WHERE
598
                fcr.record_id = fd.id
599
            AND
600
                fcr.record_lang = fd.lang",
601
            PMF_Db::getTablePrefix(),
602
            PMF_Db::getTablePrefix());
603
604
        if (strlen($this->language) > 0) {
605
            $query .= sprintf(" AND fd.lang = '%s'",
606
                $this->language);
607
        }
608
609
        $query .= sprintf("
610
            AND
611
                fd.active = 'yes'
612
            GROUP BY
613
                fcr.category_id",
614
            PMF_Db::getTablePrefix(),
615
            PMF_Db::getTablePrefix());
616
        $result = $this->_config->getDb()->query($query);
617
618
        if ($this->_config->getDb()->numRows($result) > 0) {
619
            while ($row = $this->_config->getDb()->fetchObject($result)) {
620
                $number[$row->category_id] = $row->number;
621
            }
622
        }
623
624
        $output = "<ul>\n";
625
        $open   = 0;
626
        $this->expandAll();
627
628
        for ($y = 0 ;$y < $this->height(); $y = $this->getNextLineTree($y)) {
629
630
            list($hasChild, $categoryName, $parent, $description) = $this->getLineDisplay($y);
631
            $level     = $this->treeTab[$y]['level'];
632
            $leveldiff = $open - $level;
633
634
            if (!isset($number[$parent])) {
635
                $number[$parent] = 0;
636
            }
637
638 View Code Duplication
            if ($this->_config->get('records.hideEmptyCategories') && 0 === $number[$parent] && '-' === $hasChild) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
639
                continue;
640
            }
641
642 View Code Duplication
            if ($leveldiff > 1) {
643
                $output .= '</li>';
644
                for ($i = $leveldiff; $i > 1; $i--) {
645
                    $output .= sprintf("\n%s</ul>\n%s</li>\n",
646
                        str_repeat("\t", $level + $i + 1),
647
                        str_repeat("\t", $level + $i));
648
                }
649
            }
650
651 View Code Duplication
            if ($level < $open) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
652
                if (($level - $open) == -1) {
653
                    $output .= '</li>';
654
                }
655
                $output .= sprintf("\n%s</ul>\n%s</li>\n",
656
                    str_repeat("\t", $level + 2),
657
                    str_repeat("\t", $level + 1));
658
            } elseif ($level == $open && $y != 0) {
659
                $output .= "</li>\n";
660
            }
661
662
            if ($level > $open) {
663
                $output .= sprintf("\n%s<ul>\n%s<li>",
664
                    str_repeat("\t", $level + 1),
665
                    str_repeat("\t", $level + 1));
666
            } else {
667
                $output .= str_repeat("\t", $level + 1)."<li>";
668
            }
669
670
            if (0 === $number[$parent] && 0 === $level) {
671
                $numFaqs = '';
672
            } else {
673
                $totFaqRecords += $number[$parent];
674
                $numFaqs = '<span class="rssCategoryLink"> (' . $plr->GetMsg('plmsgEntries', $number[$parent]);
675
                if ($this->_config->get('main.enableRssFeeds')) {
676
                    $numFaqs .= sprintf(
677
                        ' <a href="feed/category/rss.php?category_id=%d&category_lang=%s" target="_blank"><i class="fa fa-rss"></i></a>',
678
                        $parent,
679
                        $this->language,
680
                        $parent
681
                    );
682
                }
683
                $numFaqs .= ')</span>';
684
            }
685
686
            $url = sprintf(
687
                '%s?%saction=show&amp;cat=%d',
688
                PMF_Link::getSystemRelativeUri(),
689
                $sids,
690
                $parent
691
            );
692
            $oLink            = new PMF_Link($url, $this->_config);
693
            $oLink->itemTitle = $categoryName;
694
            $oLink->text      = $categoryName;
695
            $oLink->tooltip   = $description;
696
697
            $output .= $oLink->toHtmlAnchor() . $numFaqs;
698
            $open    = $level;
699
        }
700
701
        if (isset($level) && $level > 0) {
702
            $output .= str_repeat("</li>\n\t</ul>\n\t", $level);
703
        }
704
705
        $output .= "\t</li>\n";
706
        $output .= "\t</ul>\n";
707
        $output .= '<span id="totFaqRecords" style="display: none;">'.$totFaqRecords."</span>\n";
708
709
        return $output;
710
    }
711
712
    /**
713
     * Returns the three parts of a line to display: last part of tree,
714
     * category name, and id of the root node
715
     *
716
     * @param  integer $y ID
717
     * @return array
718
     */
719
    public function getLineDisplay($y)
720
    {
721
        $ret[0] = $this->symbols[$this->treeTab[$y]["symbol"]];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ret was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ret = array(); before regardless.

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
722
        $ret[1] = $this->treeTab[$y]["name"];
723
        $ret[2] = $this->treeTab[$y]["id"];
724
        $ret[3] = $this->treeTab[$y]["description"];
725
        return $ret;
726
    }
727
728
    /**
729
     * Gets the next line in the array treeTab, depending of the
730
     * collapse/expand node
731
     *
732
     * @param  integer $l Current line
733
     * @return integer
734
     */
735
    public function getNextLineTree($l)
736
    {
737
        if ($this->treeTab[$l]["symbol"] != "plus") {
738
            return $l + 1;
739
        } else {
740
            for ($i = $l + 1; $i < $this->height(); $i++) {
741
                if ($this->treeTab[$i]["level"]<=$this->treeTab[$l]["level"]) {
742
                    return $i;
743
                }
744
            }
745
        }
746
        return $this->height();
747
    }
748
749
    /**
750
     * Gets the list of the brothers of $id (include $id)
751
     *
752
     * @param  integer $id Brothers
753
     * @return array
754
     */
755
    private function getBrothers($id)
756
    {
757
        return $this->getChildren($this->categoryName[$id]['parent_id']);
758
    }
759
760
    /**
761
     * Creates a category link
762
     *
763
     * @param  string  $sids         Session id
764
     * @param  integer $categoryId   Parent category
765
     * @param  string  $categoryName Category name
766
     * @param  string  $description  Description
767
     * @param  boolean $hasChildren  Child categories available
768
     * @param  boolean $isActive     Sets a link active via CSS
769
     * @return  string
770
     */
771
    public function addCategoryLink($sids, $categoryId, $categoryName, $description, $hasChildren = false, $isActive = false)
772
    {
773
        $url = sprintf(
774
            '%s?%saction=show&amp;cat=%d',
775
            PMF_Link::getSystemRelativeUri(),
776
            $sids,
777
            $categoryId
778
        );
779
780
        $oLink            = new PMF_Link($url, $this->_config);
781
        $oLink->id        = 'category_' . $categoryId;
782
        $oLink->itemTitle = $categoryName;
783
        $oLink->text      = $categoryName;
784
785
        if ($hasChildren) {
786
            $oLink->text .= sprintf(
787
                ' <img src="assets/img/more.gif" width="11" height="11" alt="%s" style="border: none; vertical-align: middle;" />',
788
                $categoryName);
789
        }
790
791
        if ($isActive) {
792
            $oLink->class = 'active';
793
        }
794
795
        $oLink->tooltip = $description;
796
797
        return $oLink->toHtmlAnchor();
798
    }
799
800
    /**
801
     * Gets the path from root to child as breadcrumbs
802
     *
803
     * @param integer $id                Category ID
804
     * @param string  $separator         Path separator
805
     * @param boolean $renderAsMicroData Renders breadcrumbs as HTML5 microdata
806
     * @param string  $useCssClass       Use CSS class "breadcrumb"
807
     * @return string
808
     */
809
    public function getPath($id, $separator = ' / ', $renderAsMicroData = false, $useCssClass = 'breadcrumb')
810
    {
811
        global $sids;
812
813
        $ids = $this->getNodes($id);
814
        $num = count($ids);
815
816
        $temp = $catid = $desc = $breadcrumb = [];
817
818
        for ($i = 0; $i < $num; $i++) {
819
            $t = $this->getLineCategory($ids[$i]);
820
            if (array_key_exists($t, $this->treeTab)) {
821
                $temp[]  = $this->treeTab[$this->getLineCategory($ids[$i])]['name'];
822
                $catid[] = $this->treeTab[$this->getLineCategory($ids[$i])]['id'];
823
                $desc[]  = $this->treeTab[$this->getLineCategory($ids[$i])]['description'];
824
            }
825
        }
826
        if (isset($this->treeTab[$this->getLineCategory($id)]['name'])) {
827
            $temp[]  = $this->treeTab[$this->getLineCategory($id)]['name'];
828
            $catid[] = $this->treeTab[$this->getLineCategory($id)]['id'];
829
            $desc[]  = $this->treeTab[$this->getLineCategory($id)]['description'];
830
        }
831
832
        // @todo Maybe this should be done somewhere else ...
833
        if ($renderAsMicroData) {
834
835
            foreach ($temp as $k => $category) {
836
                $url = sprintf(
837
                    '%s?%saction=show&amp;cat=%d',
838
                    PMF_Link::getSystemRelativeUri(),
839
                    $sids,
840
                    $catid[$k]
841
                );
842
                $oLink            = new PMF_Link($url, $this->_config);
843
                $oLink->text      = sprintf('<span itemprop="title">%s</span>', $category);
844
                $oLink->itemTitle = $category;
845
                $oLink->tooltip   = $desc[$k];
846
                $oLink->setItemProperty('url');
847
                if (0 == $k) {
848
                    $oLink->setRelation('index');
849
                }
850
851
                $breadcrumb[] = sprintf(
852
                    '<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb">%s</li>',
853
                    $oLink->toHtmlAnchor()
854
                );
855
            }
856
857
            $temp = $breadcrumb;
858
859
            return sprintf(
860
                '<ul class="%s">%s</ul>',
861
                $useCssClass,
862
                implode('', $temp)
863
            );
864
        } else {
865
            return implode($separator, $temp);
866
        }
867
    }
868
869
    /**
870
     * Returns the categories from a record id and language
871
     *
872
     * @param  integer $record_id   record id
873
     * @param  integer $record_lang record language
874
     * @return array
875
     */
876 View Code Duplication
    public function getCategoryRelationsFromArticle($record_id, $record_lang)
877
    {
878
        $categories = [];
879
880
        $query = sprintf("
881
            SELECT
882
                category_id, category_lang
883
            FROM
884
                %sfaqcategoryrelations
885
            WHERE
886
                record_id = %d
887
            AND
888
                record_lang = '%s'",
889
            PMF_Db::getTablePrefix(),
890
            $record_id,
891
            $record_lang);
892
893
        $result = $this->_config->getDb()->query($query);
894
        while ($row = $this->_config->getDb()->fetchObject($result)) {
895
            $categories[] = array(
896
                'category_id'   => $row->category_id,
897
                'category_lang' => $row->category_lang);
898
        }
899
900
        return $categories;
901
    }
902
903
    /**
904
     * Returns all categories that are related to the given article-id and
905
     * the current language $this->language in an unsorted array which consists
906
     * of associative arrays with the keys 'name', 'id', 'lang',
907
     * 'parent_id' and 'description'.
908
     *
909
     * @param integer $article_id Record id
0 ignored issues
show
Bug introduced by
There is no parameter named $article_id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
910
     *
911
     * @return  array
912
     */
913
    public function getCategoriesFromArticle($articleId)
914
    {
915
        $query = sprintf("
916
            SELECT
917
                fc.id AS id,
918
                fc.lang AS lang,
919
                fc.parent_id AS parent_id,
920
                fc.name AS name,
921
                fc.description AS description
922
            FROM
923
                %sfaqcategoryrelations fcr,
924
                %sfaqcategories fc
925
            WHERE
926
                fc.id = fcr.category_id
927
            AND
928
                fcr.record_id = %d
929
            AND
930
                fcr.category_lang = '%s'
931
            AND
932
                fc.lang = '%s'",
933
            PMF_Db::getTablePrefix(),
934
            PMF_Db::getTablePrefix(),
935
            $articleId,
936
            $this->language,
937
            $this->language);
938
939
        $result = $this->_config->getDb()->query($query);
940
        $num    = $this->_config->getDb()->numRows($result);
941
        $this->categories = [];
942
        if ($num > 0) {
943
            while ($row = $this->_config->getDb()->fetchArray($result)) {
944
                $this->categories[] = $row;
945
            }
946
        }
947
        return $this->categories;
948
    }
949
950
    /**
951
     * Returns the ID of a category that associated with the given article.
952
     *
953
     * @param  integer $article_id Record id
954
     * @return integer
955
     */
956
    public function getCategoryIdFromArticle($article_id)
957
    {
958
        $cats = $this->getCategoryIdsFromArticle($article_id);
959
        if (isset($cats[0])) {
960
            return $cats[0];
961
        } else {
962
            return 0;
963
        }
964
    }
965
966
    /**
967
     * Returns an array with the IDs of all categories that are associated with
968
     * the given article.
969
     *
970
     * @param  integer $article_id Record id
971
     * @return array
972
     */
973
    public function getCategoryIdsFromArticle($article_id)
974
    {
975
        $cats = $this->getCategoriesFromArticle($article_id);
976
        $arr  = [];
977
        foreach ($cats as $cat) {
978
            $arr[] = $cat['id'];
979
        }
980
        return $arr;
981
    }
982
983
    /**
984
     * Returns the admin user of the selected category
985
     *
986
     * @param   integer $category_id Category id
987
     * @return  integer
988
     * @todo    Return the name, not the ID
989
     */
990
    public function getCategoryUser($category_id)
991
    {
992
        return $this->categoryName[$category_id]['user_id'];
993
    }
994
995
    /**
996
     * Adds a new category entry
997
     *
998
     * @param array   $categoryData Array of category data
999
     * @param integer $parentId     Parent id
1000
     * @param integer $id            Category id
1001
     *
1002
     * @return integer
1003
     */
1004
    public function addCategory(Array $categoryData, $parentId = 0, $id = null)
1005
    {
1006
        // If we only need a new language, we don't need a new category id
1007
        if (is_null($id)) {
1008
            $id = $this->_config->getDb()->nextId(PMF_Db::getTablePrefix().'faqcategories', 'id');
1009
        }
1010
1011
        $query = sprintf("
1012
            INSERT INTO
1013
                %sfaqcategories
1014
            (id, lang, parent_id, name, description, user_id)
1015
                VALUES
1016
            (%d, '%s', %d, '%s', '%s', %d)",
1017
            PMF_Db::getTablePrefix(),
1018
            $id,
1019
            $categoryData['lang'],
1020
            $parentId,
1021
            $categoryData['name'],
1022
            $categoryData['description'],
1023
            $categoryData['user_id']
1024
        );
1025
        $this->_config->getDb()->query($query);
1026
1027
        return $id;
1028
    }
1029
1030
    /**
1031
     * Updates an existent category entry
1032
     *
1033
     * @param  array   $category_data Array of category data
1034
     * @return boolean
1035
     */
1036 View Code Duplication
    public function updateCategory(Array $category_data)
1037
    {
1038
        if (!is_array($category_data)) {
1039
            return false;
1040
        }
1041
1042
        $query = sprintf("
1043
            UPDATE
1044
                %sfaqcategories
1045
            SET
1046
                name = '%s',
1047
                description = '%s',
1048
                user_id = %d
1049
            WHERE
1050
                id = %d
1051
            AND
1052
                lang = '%s'",
1053
            PMF_Db::getTablePrefix(),
1054
            $category_data['name'],
1055
            $category_data['description'],
1056
            $category_data['user_id'],
1057
            $category_data['id'],
1058
            $category_data['lang']);
1059
        $this->_config->getDb()->query($query);
1060
1061
        return true;
1062
    }
1063
1064
    /**
1065
     * Move the categories ownership, if any.
1066
     *
1067
     * @param  integer $from Old user id
1068
     * @param  integer $to   New user id
1069
     * @return boolean
1070
     */
1071
    public function moveOwnership($from, $to)
1072
    {
1073
        if (!is_numeric($from) || !is_numeric($to)) {
1074
            return false;
1075
        }
1076
1077
        $query = sprintf("
1078
            UPDATE
1079
                %sfaqcategories
1080
            SET
1081
                user_id = %d
1082
            WHERE
1083
                user_id = %d",
1084
            PMF_Db::getTablePrefix(),
1085
            $to,
1086
            $from
1087
            );
1088
        $this->_config->getDb()->query($query);
1089
1090
        return true;
1091
    }
1092
1093
    /**
1094
     * Checks wether a language is already defined for a category id
1095
     *
1096
     * @param  integer $category_id   Category id
1097
     * @param  string  $category_lang Category language
1098
     * @return boolean
1099
     */
1100
    public function checkLanguage($category_id, $category_lang)
1101
    {
1102
        $query = sprintf("
1103
            SELECT
1104
                lang
1105
            FROM
1106
                %sfaqcategories
1107
            WHERE
1108
                id = %d
1109
            AND
1110
                lang = '%s'",
1111
            PMF_Db::getTablePrefix(),
1112
            $category_id,
1113
            $category_lang);
1114
1115
        $result = $this->_config->getDb()->query($query);
1116
        return $this->_config->getDb()->numRows($result);
1117
    }
1118
1119
    /**
1120
     * Swaps two categories
1121
     *
1122
     * @param  integer $category_id_1 First category
1123
     * @param  integer $category_id_2 Second category
1124
     * @return boolean
1125
     */
1126
    public function swapCategories($category_id_1, $category_id_2)
1127
    {
1128
        $temp_cat = rand(200000, 400000);
1129
1130
        $tables = array(
1131
            array('faqcategories'        => 'id'),
1132
            array('faqcategories'        => 'parent_id'),
1133
            array('faqcategoryrelations' => 'category_id'),
1134
            array('faqcategory_group'    => 'category_id'),
1135
            array('faqcategory_user'     => 'category_id'));
1136
1137
        $result = true;
1138 View Code Duplication
        foreach ($tables as $pair) {
1139
            foreach ($pair as $_table => $_field) {
1140
                $result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = %d WHERE %s = %d",
1141
                    PMF_Db::getTablePrefix().$_table,
1142
                    $_field,
1143
                    $temp_cat,
1144
                    $_field,
1145
                    $category_id_2));
1146
                $result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = %d WHERE %s = %d",
1147
                    PMF_Db::getTablePrefix().$_table,
1148
                    $_field,
1149
                    $category_id_2,
1150
                    $_field,
1151
                    $category_id_1));
1152
                $result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = %d WHERE %s = %d",
1153
                    PMF_Db::getTablePrefix().$_table,
1154
                    $_field,
1155
                    $category_id_1,
1156
                    $_field,
1157
                    $temp_cat));
1158
            }
1159
        }
1160
1161
        $tables2 = array(array('faqquestions' => 'category_id'));
1162
1163 View Code Duplication
        foreach ($tables2 as $pair) {
1164
            foreach ($pair as $_table => $_field) {
1165
                $result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'",
1166
                    PMF_Db::getTablePrefix().$_table,
1167
                    $_field,
1168
                    $temp_cat,
1169
                    $_field,
1170
                    $category_id_2));
1171
                $result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'",
1172
                    PMF_Db::getTablePrefix().$_table,
1173
                    $_field,
1174
                    $category_id_2,
1175
                    $_field,
1176
                    $category_id_1));
1177
                $result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'",
1178
                    PMF_Db::getTablePrefix().$_table,
1179
                    $_field,
1180
                    $category_id_1,
1181
                    $_field,
1182
                    $temp_cat));
1183
            }
1184
        }
1185
1186
        return $result;
1187
    }
1188
1189
    /**
1190
     * Updates the parent category
1191
     *
1192
     * @param  integer $category_id Category id
1193
     * @param  integer $parent_id   Parent category id
1194
     * @return boolean
1195
     */
1196
    public function updateParentCategory($category_id, $parent_id)
1197
    {
1198
        if ((!is_numeric($category_id) || !is_numeric($parent_id)) && $category_id != $parent_id) {
1199
            return false;
1200
        }
1201
1202
        $query = sprintf("
1203
            UPDATE
1204
                %sfaqcategories
1205
            SET
1206
                parent_id = %d
1207
            WHERE
1208
                id = %d",
1209
            PMF_Db::getTablePrefix(),
1210
            $parent_id,
1211
            $category_id);
1212
        $this->_config->getDb()->query($query);
1213
1214
        return true;
1215
    }
1216
1217
    /**
1218
     * Deletes a category
1219
     *
1220
     * @param  integer $category_id   Category id
1221
     * @param  string  $category_lang Categiry language
1222
     * @param  boolean $delete_all    Delete all languages?
1223
     * @return boolean
1224
     */
1225 View Code Duplication
    public function deleteCategory($category_id, $category_lang, $delete_all = false)
1226
    {
1227
        $query = sprintf("
1228
            DELETE FROM
1229
                %sfaqcategories
1230
            WHERE
1231
                id = %d",
1232
            PMF_Db::getTablePrefix(),
1233
            $category_id);
1234
        if (!$delete_all) {
1235
           $query .= " AND lang = '".$category_lang."'";
1236
        }
1237
        $this->_config->getDb()->query($query);
1238
1239
        return true;
1240
    }
1241
    /**
1242
     * Deletes a category relation
1243
     *
1244
     * @param  integer $category_id   Category id
1245
     * @param  string  $category_lang Categiry language
1246
     * @param  boolean $delete_all    Delete all languages?
1247
     * @return boolean
1248
     */
1249 View Code Duplication
    public function deleteCategoryRelation($category_id, $category_lang, $delete_all = false)
1250
    {
1251
        $query = sprintf("
1252
            DELETE FROM
1253
                %sfaqcategoryrelations
1254
            WHERE
1255
                category_id = %d",
1256
            PMF_Db::getTablePrefix(),
1257
            $category_id);
1258
        if (!$delete_all) {
1259
           $query .= " AND category_lang = '".$category_lang."'";
1260
        }
1261
        $this->_config->getDb()->query($query);
1262
1263
        return true;
1264
    }
1265
1266
    /**
1267
     * Create array with translated categories
1268
     *
1269
     * @param   integer  $category_id
1270
     * @return  array
1271
     * @access  public
1272
     * @since   2006-09-10
1273
     * @author  Rudi Ferrari <[email protected]>
1274
     */
1275
    public function getCategoryLanguagesTranslated($category_id)
1276
    {
1277
        global $languageCodes;
1278
1279
        $existcatlang = $this->_config->getLanguage()->languageAvailable($category_id, 'faqcategories');
1280
        $translated   = [];
1281
1282
        foreach ($existcatlang as $language) {
1283
           $query = sprintf("
1284
               SELECT
1285
                  name, description
1286
               FROM
1287
                   %sfaqcategories
1288
               WHERE
1289
                   id = %d
1290
               AND
1291
                   lang = '%s'",
1292
               PMF_Db::getTablePrefix(),
1293
               $category_id,
1294
               $language);
1295
           $result = $this->_config->getDb()->query($query);
1296
           if ($row = $this->_config->getDb()->fetchArray($result)) {
1297
              $translated[$languageCodes[strtoupper($language)]] = $row['name'].('' == $row['description'] ? '' : '  ('.$row['description'].')');
1298
           }
1299
        }
1300
        ksort($translated);
1301
1302
        return $translated;
1303
    }
1304
1305
    /**
1306
     * Create all languagess which can be used for translation as <option>
1307
     *
1308
     * @param  integer $category_id   Category id
1309
     * @param  string  $selected_lang Selected language
1310
     *
1311
     * @return string
1312
     */
1313
    public function getCategoryLanguagesToTranslate($category_id, $selected_lang)
1314
    {
1315
        $output       = '';
1316
        $existcatlang = $this->_config->getLanguage()->languageAvailable($category_id, 'faqcategories');
1317
1318
        foreach (PMF_Language::getAvailableLanguages() as $lang => $langname) {
1319
            if (!in_array(strtolower($lang), $existcatlang)) {
1320
                $output .= "\t<option value=\"".strtolower($lang)."\"";
1321
                if ($lang == $selected_lang) {
1322
                    $output .= " selected=\"selected\"";
1323
                }
1324
                $output .=  ">".$langname."</option>\n";
1325
            }
1326
        }
1327
1328
        return $output;
1329
    }
1330
1331
    /**
1332
     * Gets all categories which are not translated in actual language
1333
     * to add in this->categories (used in admin section)
1334
     *
1335
     * @return void
1336
     */
1337
    public function getMissingCategories()
1338
    {
1339
        $query = sprintf("
1340
            SELECT
1341
                id, lang, parent_id, name, description, user_id
1342
            FROM
1343
                %sfaqcategories",
1344
            PMF_Db::getTablePrefix());
1345 View Code Duplication
        if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1346
            $query .= " WHERE lang != '".$this->language."'";
1347
        }
1348
        $query .= ' ORDER BY id';
1349
        $result = $this->_config->getDb()->query($query);
1350 View Code Duplication
        while ($row = $this->_config->getDb()->fetchArray($result)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1351
            if (!array_key_exists($row['id'],$this->categoryName)) {
1352
               $this->categoryName[$row['id']] = $row;
1353
               $this->categories[] =& $this->categoryName[$row['id']];
1354
               $this->children[$row['parent_id']][$row['id']] =& $this->categoryName[$row['id']];
1355
            }
1356
        }
1357
    }
1358
1359
    /**
1360
     * Get number of nodes at the same parent_id level
1361
     *
1362
     * @param  integer $parent_id Parent id
1363
     * @return integer
1364
     */
1365
    public function numParent($parent_id)
1366
    {
1367
        $query = sprintf("
1368
            SELECT distinct
1369
                id
1370
            FROM
1371
                %sfaqcategories
1372
            WHERE
1373
                parent_id = %d",
1374
            PMF_Db::getTablePrefix(),
1375
            $parent_id);
1376
        $result = $this->_config->getDb()->query($query);
1377
1378
        return $this->_config->getDb()->numRows($result);
1379
    }
1380
1381
    /**
1382
     * Adds the category permissions for users and groups
1383
     *
1384
     * @param string $mode       'group' or 'user'
1385
     * @param array  $categories ID of the current category
1386
     * @param array  $ids        Array of group or user IDs
1387
     *
1388
     * @return boolean
1389
     */
1390
    public function addPermission($mode, Array $categories, Array $ids)
1391
    {
1392
        if ('user' !== $mode && 'group' !== $mode) {
1393
            return false;
1394
        }
1395
1396
        foreach ($categories as $categoryId) {
1397
            foreach ($ids as $id) {
1398
                $query = sprintf(
1399
                    "SELECT * FROM %sfaqcategory_%s WHERE category_id = %d AND %s_id = %d",
1400
                    PMF_Db::getTablePrefix(),
1401
                    $mode,
1402
                    $categoryId,
1403
                    $mode,
1404
                    $id
1405
                );
1406
1407
                if ($this->_config->getDb()->numRows($this->_config->getDb()->query($query))) {
1408
                    continue;
1409
                }
1410
1411
                $query = sprintf(
1412
                    'INSERT INTO %sfaqcategory_%s (category_id, %s_id) VALUES (%d, %d)',
1413
                    PMF_Db::getTablePrefix(),
1414
                    $mode,
1415
                    $mode,
1416
                    $categoryId,
1417
                    $id
1418
                );
1419
1420
                $this->_config->getDb()->query($query);
1421
            }
1422
        }
1423
1424
        return true;
1425
    }
1426
1427
    /**
1428
     * Deletes the category permissions for users and groups
1429
     *
1430
     * @param  string $mode       'group' or 'user'
1431
     * @param  array  $categories ID of the current category
1432
     * @return boolean
1433
     */
1434 View Code Duplication
    public function deletePermission($mode, $categories)
1435
    {
1436
        if (!($mode == "user" || $mode == "group")) {
1437
            return false;
1438
        }
1439
        if (!is_array($categories)) {
1440
            return false;
1441
        }
1442
1443
        foreach ($categories as $category_id) {
1444
            $query = sprintf("
1445
                DELETE FROM
1446
                    %sfaqcategory_%s
1447
                WHERE
1448
                    category_id = %d",
1449
                PMF_Db::getTablePrefix(),
1450
                $mode,
1451
                $category_id);
1452
            $this->_config->getDb()->query($query);
1453
        }
1454
1455
        return true;
1456
    }
1457
1458
    /**
1459
     * Returns the category permissions for users and groups
1460
     *
1461
     * @param   string $mode       'group' or 'user'
1462
     * @param   array  $categories Array of category ids
1463
     * @return  array
1464
     */
1465
    public function getPermissions($mode, Array $categories)
1466
    {
1467
        $permissions = [];
1468
        if (!($mode == "user" || $mode == "group")) {
1469
            return false;
1470
        }
1471
        if (!is_array($categories)) {
1472
            return false;
1473
        }
1474
1475
        $query = sprintf("
1476
            SELECT
1477
                %s_id AS permission
1478
            FROM
1479
                %sfaqcategory_%s
1480
            WHERE
1481
                category_id IN (%s)",
1482
            $mode,
1483
            PMF_Db::getTablePrefix(),
1484
            $mode,
1485
            implode(', ', $categories));
1486
1487
        $result = $this->_config->getDb()->query($query);
1488
        while ($row = $this->_config->getDb()->fetchObject($result)) {
1489
            $permissions[] = $row->permission;
1490
        }
1491
        return $permissions;
1492
    }
1493
1494
    /**
1495
     * Returns the number of records in each category
1496
     *
1497
     * @return array
1498
     */
1499
    public function getNumberOfRecordsOfCategory()
1500
    {
1501
        $numRecordsByCat = [];
1502
1503
        $query = sprintf("
1504
            SELECT
1505
                fcr.category_id AS category_id,
1506
                COUNT(fcr.record_id) AS number
1507
            FROM
1508
                %sfaqcategoryrelations fcr, %sfaqdata fd
1509
            WHERE
1510
                fcr.record_id = fd.id
1511
            AND
1512
                fcr.record_lang = fd.lang
1513
            GROUP BY fcr.category_id",
1514
            PMF_Db::getTablePrefix(),
1515
            PMF_Db::getTablePrefix());
1516
1517
        $result = $this->_config->getDb()->query($query);
1518
1519
        if ($this->_config->getDb()->numRows($result) > 0) {
1520
            while ($row = $this->_config->getDb()->fetchObject($result)) {
1521
                $numRecordsByCat[$row->category_id] = $row->number;
1522
            }
1523
        }
1524
1525
        return $numRecordsByCat;
1526
    }
1527
1528
    /**
1529
     * Create a matrix for representing categories and faq records
1530
     *
1531
     * @return array
1532
     */
1533
    public function getCategoryRecordsMatrix()
1534
    {
1535
        $matrix = [];
1536
1537
        $query = sprintf('
1538
            SELECT
1539
                fcr.category_id AS id_cat,
1540
                fd.id AS id
1541
            FROM
1542
                %sfaqdata fd
1543
            INNER JOIN
1544
                %sfaqcategoryrelations fcr
1545
            ON
1546
                fd.id = fcr.record_id
1547
            AND
1548
                fd.lang = fcr.category_lang
1549
            ORDER BY
1550
                fcr.category_id, fd.id',
1551
             PMF_Db::getTablePrefix(),
1552
             PMF_Db::getTablePrefix());
1553
        $result = $this->_config->getDb()->query($query);
1554
1555
        if ($this->_config->getDb()->numRows($result) > 0) {
1556
            while ($row = $this->_config->getDb()->fetchObject($result)) {
1557
                $matrix[$row->id_cat][$row->id] = true;
1558
            }
1559
        }
1560
1561
        return $matrix;
1562
    }
1563
1564
    /**
1565
     * Sets language
1566
     *
1567
     * @param string $language
1568
     */
1569
    public function setLanguage($language)
1570
    {
1571
        $this->language = $language;
1572
    }
1573
}
1574