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.

Faq::getTopTen()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 1
dl 0
loc 34
rs 9.0648
c 0
b 0
f 0
1
<?php
2
3
namespace phpMyFAQ;
4
5
/**
6
 * The main FAQ class.
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 Matteo Scaramuccia <[email protected]>
15
 * @author Georgi Korchev <[email protected]>
16
 * @author Adrianna Musiol <[email protected]>
17
 * @author Peter Caesar <[email protected]>
18
 * @copyright 2005-2019 phpMyFAQ Team
19
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
20
 * @link https://www.phpmyfaq.de
21
 * @since 2005-12-20
22
 */
23
24
use phpMyFAQ\Attachment\Factory;
25
use phpMyFAQ\Helper\FaqHelper as HelperFaq;
26
use phpMyFAQ\Instance\Elasticsearch;
27
use phpMyFAQ\Language\Plurals;
28
29
if (!defined('IS_VALID_PHPMYFAQ')) {
30
    exit();
31
}
32
33
/*
34
 * SQL constants definitions
35
 */
36
define('FAQ_SQL_ACTIVE_YES', 'yes');
37
define('FAQ_SQL_ACTIVE_NO', 'no');
38
39
/*
40
 * Query type definitions
41
 */
42
define('FAQ_QUERY_TYPE_DEFAULT', 'faq_default');
43
define('FAQ_QUERY_TYPE_APPROVAL', 'faq_approval');
44
define('FAQ_QUERY_TYPE_EXPORT_PDF', 'faq_export_pdf');
45
define('FAQ_QUERY_TYPE_EXPORT_XHTML', 'faq_export_xhtml');
46
define('FAQ_QUERY_TYPE_EXPORT_XML', 'faq_export_xml');
47
define('FAQ_QUERY_TYPE_RSS_LATEST', 'faq_rss_latest');
48
49
/*
50
 * Sorting type definitions
51
 */
52
define('FAQ_SORTING_TYPE_NONE', 0);
53
define('FAQ_SORTING_TYPE_CATID_FAQID', 1);
54
define('FAQ_SORTING_TYPE_FAQTITLE_FAQID', 2);
55
define('FAQ_SORTING_TYPE_DATE_FAQID', 3);
56
define('FAQ_SORTING_TYPE_FAQID', 4);
57
58
/**
59
 * The main FAQ class - 3K LOC of funny things for phpMyFAQ.
60
 *
61
 * @package phpMyFAQ
62
 * @author Thorsten Rinne <[email protected]>
63
 * @author Matteo Scaramuccia <[email protected]>
64
 * @author Georgi Korchev <[email protected]>
65
 * @author Adrianna Musiol <[email protected]>
66
 * @author Peter Caesar <[email protected]>
67
 * @copyright 2005-2019 phpMyFAQ Team
68
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
69
 * @link https://www.phpmyfaq.de
70
 * @since 2005-12-20
71
 */
72
class Faq
73
{
74
    /**
75
     * The current FAQ record.
76
     * @var array
77
     */
78
    public $faqRecord = [];
79
80
    /**
81
     * All current FAQ records in an array.
82
     * @var array
83
     */
84
    public $faqRecords = [];
85
86
    /**
87
     * @var Configuration
88
     */
89
    private $config;
90
91
    /**
92
     * Language strings.
93
     * @var string
94
     */
95
    private $translation;
96
97
    /**
98
     * Plural form support.
99
     * @var Plurals
100
     */
101
    private $plurals;
102
103
    /**
104
     * Users.
105
     * @var int
106
     */
107
    private $user = -1;
108
109
    /**
110
     * Groups.
111
     * @var array
112
     */
113
    private $groups = [-1];
114
115
    /**
116
     * Flag for Group support.
117
     * @var bool
118
     */
119
    private $groupSupport = false;
120
121
    /**
122
     * Constructor.
123
     * @param Configuration $config
124
     */
125
    public function __construct(Configuration $config)
126
    {
127
        global $PMF_LANG, $plr;
128
129
        $this->config = $config;
130
        $this->translation = $PMF_LANG;
131
        $this->plurals = $plr;
132
133
        if ($this->config->get('security.permLevel') == 'medium') {
134
            $this->groupSupport = true;
135
        }
136
    }
137
138
    /**
139
     * @param int $userId
140
     */
141
    public function setUser($userId = -1)
142
    {
143
        $this->user = $userId;
144
    }
145
146
    /**
147
     * @param array $groups
148
     */
149
    public function setGroups(Array $groups)
150
    {
151
        $this->groups = $groups;
152
    }
153
154
    /**
155
     * This function returns all not expired records from one category.
156
     *
157
     * @param int $categoryId Entity ID
158
     * @param string $orderBy Order by
159
     * @param string $sortBy Sort by
160
     *
161
     * @return array
162
     */
163
    public function getAllRecordPerCategory($categoryId, $orderBy = 'id', $sortBy = 'ASC')
164
    {
165
        global $sids;
166
167
        $faqData = [];
168
169
        if ($orderBy == 'visits') {
170
            $currentTable = 'fv';
171
        } else {
172
            $currentTable = 'fd';
173
        }
174
175
        $now = date('YmdHis');
176
        $query = sprintf("
177
            SELECT
178
                fd.id AS id,
179
                fd.lang AS lang,
180
                fd.thema AS thema,
181
                fd.content AS record_content,
182
                fd.updated AS updated,
183
                fcr.category_id AS category_id,
184
                fv.visits AS visits,
185
                fd.created AS created
186
            FROM
187
                %sfaqdata AS fd
188
            LEFT JOIN
189
                %sfaqcategoryrelations AS fcr
190
            ON
191
                fd.id = fcr.record_id
192
            AND
193
                fd.lang = fcr.record_lang
194
            LEFT JOIN
195
                %sfaqvisits AS fv
196
            ON
197
                fd.id = fv.id
198
            AND
199
                fv.lang = fd.lang
200
            LEFT JOIN
201
                %sfaqdata_group AS fdg
202
            ON
203
                fd.id = fdg.record_id
204
            LEFT JOIN
205
                %sfaqdata_user AS fdu
206
            ON
207
                fd.id = fdu.record_id
208
            WHERE
209
                fd.date_start <= '%s'
210
            AND
211
                fd.date_end   >= '%s'
212
            AND
213
                fd.active = 'yes'
214
            AND
215
                fcr.category_id = %d
216
            AND
217
                fd.lang = '%s'
218
                %s
219
            ORDER BY
220
                %s.%s %s",
221
            Db::getTablePrefix(),
222
            Db::getTablePrefix(),
223
            Db::getTablePrefix(),
224
            Db::getTablePrefix(),
225
            Db::getTablePrefix(),
226
            $now,
227
            $now,
228
            $categoryId,
229
            $this->config->getLanguage()->getLanguage(),
230
            $this->queryPermission($this->groupSupport),
231
            $currentTable,
232
            $this->config->getDb()->escape($orderBy),
233
            $this->config->getDb()->escape($sortBy)
234
        );
235
236
        $result = $this->config->getDb()->query($query);
237
        $num = $this->config->getDb()->numRows($result);
238
239
        if ($num > 0) {
240
            $faqHelper = new HelperFaq($this->config);
241
            while (($row = $this->config->getDb()->fetchObject($result))) {
242
                if (empty($row->visits)) {
243
                    $visits = 0;
244
                } else {
245
                    $visits = $row->visits;
246
                }
247
248
                $url = sprintf(
249
                    '%sindex.php?%saction=faq&cat=%d&id=%d&artlang=%s',
250
                    $this->config->getDefaultUrl(),
251
                    $sids,
252
                    $row->category_id,
253
                    $row->id,
254
                    $row->lang
255
                );
256
                $oLink = new Link($url, $this->config);
257
                $oLink->itemTitle = $oLink->text = $oLink->tooltip = $row->thema;
258
259
                $faqData[] = array(
260
                    'record_id' => $row->id,
261
                    'record_lang' => $row->lang,
262
                    'category_id' => $row->category_id,
263
                    'record_title' => $row->thema,
264
                    'record_preview' => $faqHelper->renderAnswerPreview($row->record_content, 25),
265
                    'record_link' => $oLink->toString(),
266
                    'record_updated' => $row->updated,
267
                    'visits' => $visits,
268
                    'record_created' => $row->created,
269
                );
270
            }
271
        } else {
272
            return $faqData;
273
        }
274
275
        return $faqData;
276
    }
277
278
    /**
279
     * Returns a part of a query to check permissions.
280
     *
281
     * @param bool $hasGroupSupport
282
     *
283
     * @return string
284
     */
285
    protected function queryPermission($hasGroupSupport = false)
286
    {
287
        if ($hasGroupSupport) {
288
            if (-1 === $this->user) {
289
                return sprintf(
290
                    'AND fdg.group_id IN (%s)',
291
                    implode(', ', $this->groups),
292
                    $this->user,
293
                    implode(', ', $this->groups));
294 View Code Duplication
            } else {
295
                return sprintf(
296
                    'AND ( fdg.group_id IN (%s) OR (fdu.user_id = %d OR fdg.group_id IN (%s)) )',
297
                    implode(', ', $this->groups),
298
                    $this->user,
299
                    implode(', ', $this->groups)
300
                );
301
            }
302
        } else {
303
            if (-1 !== $this->user) {
304
                return sprintf(
305
                    'AND ( fdu.user_id = %d OR fdu.user_id = -1 )',
306
                    $this->user
307
                );
308
            } else {
309
                return sprintf(
310
                    'AND fdu.user_id = -1',
311
                    $this->user
312
                );
313
            }
314
        }
315
    }
316
317
    /**
318
     * This function returns all not expired records from one category.
319
     *
320
     * @param int $categoryId Entity ID
321
     * @param string $orderBy Order by
322
     * @param string $sortBy Sort by
323
     *
324
     * @return string
325
     */
326
    public function renderRecordsByCategoryId($categoryId, $orderBy = 'id', $sortBy = 'ASC')
327
    {
328
        global $sids;
329
330
        $numPerPage = $this->config->get('records.numberOfRecordsPerPage');
331
        $page = Filter::filterInput(INPUT_GET, 'seite', FILTER_VALIDATE_INT, 1);
332
        $output = '';
333
        $title = '';
334
335
        if ($orderBy == 'visits') {
336
            $currentTable = 'fv';
337
        } else {
338
            $currentTable = 'fd';
339
        }
340
341
        // If random FAQs are activated, we don't need an order
342
        if (true === $this->config->get('records.randomSort')) {
343
            $order = '';
344
        } else {
345
            $order = sprintf(
346
                'ORDER BY fd.sticky DESC, %s.%s %s',
347
                $currentTable,
348
                $this->config->getDb()->escape($orderBy),
349
                $this->config->getDb()->escape($sortBy)
350
            );
351
        }
352
353
        $now = date('YmdHis');
354
        $query = sprintf("
355
            SELECT
356
                fd.id AS id,
357
                fd.lang AS lang,
358
                fd.sticky AS sticky,
359
                fd.thema AS thema,
360
                fcr.category_id AS category_id,
361
                fv.visits AS visits
362
            FROM
363
                %sfaqdata AS fd
364
            LEFT JOIN
365
                %sfaqcategoryrelations AS fcr
366
            ON
367
                fd.id = fcr.record_id
368
            AND
369
                fd.lang = fcr.record_lang
370
            LEFT JOIN
371
                %sfaqvisits AS fv
372
            ON
373
                fd.id = fv.id
374
            AND
375
                fv.lang = fd.lang
376
            LEFT JOIN
377
                %sfaqdata_group AS fdg
378
            ON
379
                fd.id = fdg.record_id
380
            LEFT JOIN
381
                %sfaqdata_user AS fdu
382
            ON
383
                fd.id = fdu.record_id
384
            WHERE
385
                fd.date_start <= '%s'
386
            AND
387
                fd.date_end   >= '%s'
388
            AND
389
                fd.active = 'yes'
390
            AND
391
                fcr.category_id = %d
392
            AND
393
                fd.lang = '%s'
394
            %s
395
            %s",
396
            Db::getTablePrefix(),
397
            Db::getTablePrefix(),
398
            Db::getTablePrefix(),
399
            Db::getTablePrefix(),
400
            Db::getTablePrefix(),
401
            $now,
402
            $now,
403
            $categoryId,
404
            $this->config->getLanguage()->getLanguage(),
405
            $this->queryPermission($this->groupSupport),
406
            $order
407
        );
408
409
        $result = $this->config->getDb()->query($query);
410
        $num = $this->config->getDb()->numRows($result);
411
        $pages = (int)ceil($num/$numPerPage);
412
413
        if ($page == 1) {
414
            $first = 0;
415
        } else {
416
            $first = $page*$numPerPage - $numPerPage;
417
        }
418
419
        if ($num > 0) {
420 View Code Duplication
            if ($pages > 1) {
421
                $output .= sprintf('<p><strong>%s %s %s</strong></p>',
422
                    $this->translation['msgPage'].$page,
423
                    $this->translation['msgVoteFrom'],
424
                    $pages.$this->translation['msgPages']);
425
            }
426
            $output .= '<ul class="phpmyfaq_ul">';
427
428
            $counter = 0;
429
            $displayedCounter = 0;
430
            $renderedItems = [];
431
            while (($row = $this->config->getDb()->fetchObject($result)) && $displayedCounter < $numPerPage) {
432
                ++$counter;
433
                if ($counter <= $first) {
434
                    continue;
435
                }
436
                ++$displayedCounter;
437
438
                if (empty($row->visits)) {
439
                    $visits = 0;
440
                } else {
441
                    $visits = $row->visits;
442
                }
443
444
                $title = $row->thema;
445
                $url = sprintf(
446
                    '%s?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
447
                    Link::getSystemRelativeUri(),
448
                    $sids,
449
                    $row->category_id,
450
                    $row->id,
451
                    $row->lang
452
                );
453
454
                $oLink = new Link($url, $this->config);
455
                $oLink->itemTitle = $oLink->text = $oLink->tooltip = $title;
456
457
                // If random FAQs are activated, we don't need sticky FAQs
458
                if (true === $this->config->get('records.randomSort')) {
459
                    $row->sticky = 0;
460
                }
461
462
                $renderedItems[$row->id] = sprintf(
463
                    '<li%s>%s<span id="viewsPerRecord"><br /><small>(%s)</small></span></li>',
464
                    ($row->sticky == 1) ? ' class="sticky-faqs"' : '',
465
                    $oLink->toHtmlAnchor(),
466
                    $this->plurals->GetMsg('plmsgViews', $visits)
467
                );
468
            }
469
470
            // If random FAQs are activated, shuffle the FAQs :-)
471
            if (true === $this->config->get('records.randomSort')) {
472
                shuffle($renderedItems);
473
            }
474
475
            $output .= implode("\n", $renderedItems);
476
            $output .= '</ul>';
477
        } else {
478
            return false;
479
        }
480
481
        if ($pages > 1) {
482
            // Set rewrite URL, if needed
483
            if ($this->config->get('main.enableRewriteRules')) {
484
                $link = new Link(Link::getSystemRelativeUri('index.php'), $this->config);
485
                $useRewrite = true;
486
                $rewriteUrl = sprintf(
487
                    '%scategory/%d/%%d/%s.html',
488
                    Link::getSystemRelativeUri('index.php'),
489
                    $categoryId,
490
                    $link->getSEOItemTitle($title)
491
                );
492
            } else {
493
                $useRewrite = false;
494
                $rewriteUrl = '';
495
            }
496
            $baseUrl = sprintf(
497
                '%s?%saction=show&amp;cat=%d&amp;seite=%d',
498
                Link::getSystemRelativeUri(),
499
                (empty($sids) ? '' : $sids),
500
                $categoryId,
501
                $page
502
            );
503
504
            $options = array(
505
                'baseUrl' => $baseUrl,
506
                'total' => $num,
507
                'perPage' => $this->config->get('records.numberOfRecordsPerPage'),
508
                'useRewrite' => $useRewrite,
509
                'rewriteUrl' => $rewriteUrl,
510
                'pageParamName' => 'seite',
511
            );
512
513
            $pagination = new Pagination($this->config, $options);
514
            $output .= $pagination->render();
515
        }
516
517
        return $output;
518
    }
519
520
    /**
521
     * This function returns all not expired records from the given record ids.
522
     *
523
     * @param array $recordIds Array of record ids
524
     * @param string $orderBy Order by
525
     * @param string $sortBy Sort by
526
     *
527
     * @return string
528
     */
529
    public function renderRecordsByFaqIds(Array $recordIds, $orderBy = 'fd.id', $sortBy = 'ASC')
530
    {
531
        global $sids;
532
533
        $records = implode(', ', $recordIds);
534
        $page = Filter::filterInput(INPUT_GET, 'seite', FILTER_VALIDATE_INT, 1);
535
        $taggingId = Filter::filterInput(INPUT_GET, 'tagging_id', FILTER_DEFAULT);
536
        $output = '';
537
538
        $now = date('YmdHis');
539
        $query = sprintf("
540
            SELECT
541
                fd.id AS id,
542
                fd.lang AS lang,
543
                fd.thema AS thema,
544
                fcr.category_id AS category_id,
545
                fv.visits AS visits
546
            FROM
547
                %sfaqdata AS fd
548
            LEFT JOIN
549
                %sfaqcategoryrelations AS fcr
550
            ON
551
                fd.id = fcr.record_id
552
            AND
553
                fd.lang = fcr.record_lang
554
            LEFT JOIN
555
                %sfaqvisits AS fv
556
            ON
557
                fd.id = fv.id
558
            AND
559
                fv.lang = fd.lang
560
            LEFT JOIN
561
                %sfaqdata_group AS fdg
562
            ON
563
                fd.id = fdg.record_id
564
            LEFT JOIN
565
                %sfaqdata_user AS fdu
566
            ON
567
                fd.id = fdu.record_id
568
            WHERE
569
                fd.date_start <= '%s'
570
            AND
571
                fd.date_end   >= '%s'
572
            AND
573
                fd.active = 'yes'
574
            AND
575
                fd.id IN (%s)
576
            AND
577
                fd.lang = '%s'
578
                %s
579
            ORDER BY
580
                %s %s",
581
            Db::getTablePrefix(),
582
            Db::getTablePrefix(),
583
            Db::getTablePrefix(),
584
            Db::getTablePrefix(),
585
            Db::getTablePrefix(),
586
            $now,
587
            $now,
588
            $records,
589
            $this->config->getLanguage()->getLanguage(),
590
            $this->queryPermission($this->groupSupport),
591
            $this->config->getDb()->escape($orderBy),
592
            $this->config->getDb()->escape($sortBy));
593
594
        $result = $this->config->getDb()->query($query);
595
596
        $num = $this->config->getDb()->numRows($result);
597
        $pages = ceil($num/$this->config->get('records.numberOfRecordsPerPage'));
598
599
        if ($page == 1) {
600
            $first = 0;
601
        } else {
602
            $first = ($page*$this->config->get('records.numberOfRecordsPerPage')) - $this->config->get('records.numberOfRecordsPerPage');
603
        }
604
605
        if ($num > 0) {
606 View Code Duplication
            if ($pages > 1) {
607
                $output .= sprintf('<p><strong>%s %s %s</strong></p>',
608
                    $this->translation['msgPage'].$page,
609
                    $this->translation['msgVoteFrom'],
610
                    $pages.$this->translation['msgPages']);
611
            }
612
            $output .= '<ul class="phpmyfaq_ul">';
613
            $counter = 0;
614
            $displayedCounter = 0;
615
616
            $lastFaqId = 0;
617
            while (($row = $this->config->getDb()->fetchObject($result)) && $displayedCounter < $this->config->get('records.numberOfRecordsPerPage')) {
618
                ++$counter;
619
                if ($counter <= $first) {
620
                    continue;
621
                }
622
                ++$displayedCounter;
623
624
                if ($lastFaqId == $row->id) {
625
                    continue; // Don't show multiple FAQs
626
                }
627
628
                if (empty($row->visits)) {
629
                    $visits = 0;
630
                } else {
631
                    $visits = $row->visits;
632
                }
633
634
                $title = $row->thema;
635
                $url = sprintf(
636
                    '%s?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
637
                    Link::getSystemRelativeUri(),
638
                    $sids,
639
                    $row->category_id,
640
                    $row->id,
641
                    $row->lang
642
                );
643
                $oLink = new Link($url, $this->config);
644
                $oLink->itemTitle = $row->thema;
645
                $oLink->text = $title;
646
                $oLink->tooltip = $title;
647
                $listItem = sprintf(
648
                    '<li>%s<br /><small>(%s)</small></li>',
649
                    $oLink->toHtmlAnchor(),
650
                    $this->plurals->GetMsg('plmsgViews', $visits)
651
                );
652
653
                $output .= $listItem;
654
655
                $lastFaqId = $row->id;
656
            }
657
            $output .= '</ul><span id="totFaqRecords" style="display: none;">'.$num.'</span>';
658
        } else {
659
            return false;
660
        }
661
662
        if ($num > $this->config->get('records.numberOfRecordsPerPage')) {
663
            $output .= '<p class="text-center"><strong>';
664
            if (!isset($page)) {
665
                $page = 1;
666
            }
667
            $vor = $page - 1;
668
            $next = $page + 1;
669 View Code Duplication
            if ($vor != 0) {
670
                $url = $sids.'&amp;action=search&amp;tagging_id='.$taggingId.'&amp;seite='.$vor;
671
                $oLink = new Link(Link::getSystemRelativeUri().'?'.$url, $this->config);
672
                $oLink->itemTitle = 'tag';
673
                $oLink->text = $this->translation['msgPrevious'];
674
                $oLink->tooltip = $this->translation['msgPrevious'];
675
                $output .= '[ '.$oLink->toHtmlAnchor().' ]';
676
            }
677
            $output .= ' ';
678 View Code Duplication
            if ($next <= $pages) {
679
                $url = $sids.'&amp;action=search&amp;tagging_id='.$taggingId.'&amp;seite='.$next;
680
                $oLink = new Link(Link::getSystemRelativeUri().'?'.$url, $this->config);
681
                $oLink->itemTitle = 'tag';
682
                $oLink->text = $this->translation['msgNext'];
683
                $oLink->tooltip = $this->translation['msgNext'];
684
                $output .= '[ '.$oLink->toHtmlAnchor().' ]';
685
            }
686
            $output .= '</strong></p>';
687
        }
688
689
        return $output;
690
    }
691
692
    /**
693
     * Returns an array with all data from a FAQ record.
694
     *
695
     * @param int $faqId FAQ ID
696
     * @param int $faqRevisionId Revision ID
697
     * @param bool $isAdmin Must be true if it is called by an admin/author context
698
     */
699
    public function getRecord($faqId, $faqRevisionId = null, $isAdmin = false)
700
    {
701
        global $PMF_LANG;
702
703
        $currentLanguage = $this->config->getLanguage()->getLanguage();
704
        $defaultLanguage = $this->config->getDefaultLanguage();
705
706
        $result = $this->getRecordResult($faqId, $currentLanguage, $faqRevisionId, $isAdmin);
707
708
        if (0 === $this->config->getDb()->numRows($result)) {
709
            $result = $this->getRecordResult($faqId, $defaultLanguage, $faqRevisionId, $isAdmin);
710
        }
711
712
        if ($row = $this->config->getDb()->fetchObject($result)) {
713
            $question = nl2br($row->thema);
714
            $answer = $row->content;
715
            $active = ('yes' === $row->active);
716
            $expired = (date('YmdHis') > $row->date_end);
717
718
            if (!$isAdmin) {
719
                if (!$active) {
720
                    $answer = $this->translation['err_inactiveArticle'];
721
                }
722
                if ($expired) {
723
                    $answer = $this->translation['err_expiredArticle'];
724
                }
725
            }
726
727
            $this->faqRecord = [
728
                'id' => $row->id,
729
                'lang' => $row->lang,
730
                'solution_id' => $row->solution_id,
731
                'revision_id' => $row->revision_id,
732
                'active' => $row->active,
733
                'sticky' => $row->sticky,
734
                'keywords' => $row->keywords,
735
                'title' => $question,
736
                'content' => $answer,
737
                'author' => $row->author,
738
                'email' => $row->email,
739
                'comment' => $row->comment,
740
                'date' => Date::createIsoDate($row->updated),
741
                'dateStart' => $row->date_start,
742
                'dateEnd' => $row->date_end,
743
                'linkState' => $row->links_state,
744
                'linkCheckDate' => $row->links_check_date,
745
                'notes' => $row->notes,
746
                'created' => $row->created,
747
            ];
748
        } else {
749
            $this->faqRecord = [
750
                'id' => $faqId,
751
                'lang' => $currentLanguage,
752
                'solution_id' => 42,
753
                'revision_id' => $faqRevisionId,
754
                'active' => 'no',
755
                'sticky' => 0,
756
                'keywords' => '',
757
                'title' => '',
758
                'content' => $PMF_LANG['msgAccessDenied'],
759
                'author' => '',
760
                'email' => '',
761
                'comment' => '',
762
                'date' => Date::createIsoDate(date('YmdHis')),
763
                'dateStart' => '',
764
                'dateEnd' => '',
765
                'linkState' => '',
766
                'linkCheckDate' => '',
767
                'notes' => '',
768
                'created' => date('c'),
769
            ];
770
        }
771
    }
772
773
    /**
774
     * Executes a query to retrieve a single FAQ.
775
     *
776
     * @param int $faqId
777
     * @param string $faqLanguage
778
     * @param int $faqRevisionId
779
     * @param bool $isAdmin
780
     *
781
     * @return mixed
782
     */
783
    public function getRecordResult($faqId, $faqLanguage, $faqRevisionId = null, $isAdmin = false)
784
    {
785
        $query = sprintf(
786
            "SELECT
787
                 id, lang, solution_id, revision_id, active, sticky, keywords,
788
                 thema, content, author, email, comment, updated, links_state,
789
                 links_check_date, date_start, date_end, created, notes
790
            FROM
791
                %s%s fd
792
            LEFT JOIN
793
                %sfaqdata_group fdg
794
            ON
795
                fd.id = fdg.record_id
796
            LEFT JOIN
797
                %sfaqdata_user fdu
798
            ON
799
                fd.id = fdu.record_id
800
            WHERE
801
                fd.id = %d
802
            %s
803
            AND
804
                fd.lang = '%s'
805
                %s",
806
            Db::getTablePrefix(),
807
            isset($faqRevisionId) ? 'faqdata_revisions' : 'faqdata',
808
            Db::getTablePrefix(),
809
            Db::getTablePrefix(),
810
            $faqId,
811
            isset($faqRevisionId) ? 'AND revision_id = '.$faqRevisionId : '',
812
            $faqLanguage,
813
            ($isAdmin) ? 'AND 1=1' : $this->queryPermission($this->groupSupport)
814
        );
815
816
        return $this->config->getDb()->query($query);
817
    }
818
819
    /**
820
     * Return records from given IDs
821
     *
822
     * @param array $faqIds
823
     *
824
     * @return array
825
     */
826
    public function getRecordsByIds(Array $faqIds)
827
    {
828
        $faqRecords = [];
829
830
        $query = sprintf(
831
            "SELECT
832
                 fd.id AS id,
833
                 fd.lang AS lang,
834
                 fd.thema AS question,
835
                 fd.content AS answer,
836
                 fd.updated AS updated,
837
                 fd.created AS created,
838
                 fcr.category_id AS category_id,
839
                 fv.visits AS visits
840
            FROM
841
                %sfaqdata fd
842
            LEFT JOIN
843
                %sfaqcategoryrelations fcr
844
            ON
845
                fd.id = fcr.record_id
846
            AND
847
                fd.lang = fcr.record_lang
848
            LEFT JOIN
849
                %sfaqdata_group fdg
850
            ON
851
                fd.id = fdg.record_id
852
            LEFT JOIN
853
                %sfaqvisits AS fv
854
            ON
855
                fd.id = fv.id
856
            AND
857
                fv.lang = fd.lang
858
            LEFT JOIN
859
                %sfaqdata_user fdu
860
            ON
861
                fd.id = fdu.record_id
862
            WHERE
863
                fd.id IN (%s)
864
            AND
865
                fd.lang = '%s'
866
                %s",
867
            Db::getTablePrefix(),
868
            Db::getTablePrefix(),
869
            Db::getTablePrefix(),
870
            Db::getTablePrefix(),
871
            Db::getTablePrefix(),
872
            implode(',', $faqIds),
873
            $this->config->getLanguage()->getLanguage(),
874
            $this->queryPermission($this->groupSupport)
875
        );
876
877
        $result = $this->config->getDb()->query($query);
878
879
        $faqHelper = new HelperFaq($this->config);
880
        while ($row = $this->config->getDb()->fetchObject($result)) {
881
            if (empty($row->visits)) {
882
                $visits = 0;
883
            } else {
884
                $visits = $row->visits;
885
            }
886
887
            $url = sprintf(
888
                '%sindex.php?action=faq&cat=%d&id=%d&artlang=%s',
889
                $this->config->getDefaultUrl(),
890
                $row->category_id,
891
                $row->id,
892
                $row->lang
893
            );
894
            $oLink = new Link($url, $this->config);
895
            $oLink->itemTitle = $oLink->text = $oLink->tooltip = $row->question;
896
897
            $faqRecords[] = [
898
                'record_id' => (int)$row->id,
899
                'record_lang' => $row->lang,
900
                'category_id' => (int)$row->category_id,
901
                'record_title' => $row->question,
902
                'record_preview' => $faqHelper->renderAnswerPreview($row->answer, 25),
903
                'record_link' => $oLink->toString(),
904
                'record_updated' => Date::createIsoDate($row->updated).':00',
905
                'visits' => (int)$visits,
906
                'record_created' => $row->created
907
            ];
908
        }
909
910
        return $faqRecords;
911
    }
912
913
    /**
914
     * Adds a new record.
915
     *
916
     * @param array $data Array of FAQ data
917
     * @param bool $newRecord Do not create a new ID if false
918
     *
919
     * @return int
920
     */
921
    public function addRecord(Array $data, $newRecord = true)
922
    {
923
        if ($newRecord) {
924
            $recordId = $this->config->getDb()->nextId(Db::getTablePrefix().'faqdata', 'id');
925
        } else {
926
            $recordId = $data['id'];
927
        }
928
929
        // Add new entry
930
        $query = sprintf("
931
            INSERT INTO
932
                %sfaqdata
933
            VALUES
934
                (%d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s')",
935
            Db::getTablePrefix(),
936
            $recordId,
937
            $data['lang'],
938
            $this->getSolutionId(),
939
            0,
940
            $data['active'],
941
            $data['sticky'],
942
            $this->config->getDb()->escape($data['keywords']),
943
            $this->config->getDb()->escape($data['thema']),
944
            $this->config->getDb()->escape($data['content']),
945
            $this->config->getDb()->escape($data['author']),
946
            $data['email'],
947
            $data['comment'],
948
            $data['date'],
949
            $data['linkState'],
950
            $data['linkDateCheck'],
951
            $data['dateStart'],
952
            $data['dateEnd'],
953
            date('Y-m-d H:i:s'),
954
            $data['notes']
955
        );
956
957
        $this->config->getDb()->query($query);
958
959
        return $recordId;
960
    }
961
962
    /**
963
     * Gets the latest solution id for a FAQ record.
964
     *
965
     * @return int
966
     */
967
    public function getSolutionId()
968
    {
969
        $latestId = 0;
970
971
        $query = sprintf('
972
            SELECT
973
                MAX(solution_id) AS solution_id
974
            FROM
975
                %sfaqdata',
976
            Db::getTablePrefix()
977
        );
978
979
        $result = $this->config->getDb()->query($query);
980
981
        if ($result && $row = $this->config->getDb()->fetchObject($result)) {
982
            $latestId = $row->solution_id;
983
        }
984
985
        if ($latestId < PMF_SOLUTION_ID_START_VALUE) {
986
            $nextSolutionId = PMF_SOLUTION_ID_START_VALUE;
987
        } else {
988
            $nextSolutionId = $latestId + PMF_SOLUTION_ID_INCREMENT_VALUE;
989
        }
990
991
        return $nextSolutionId;
992
    }
993
994
    /**
995
     * Updates a record.
996
     *
997
     * @param array $data Array of FAQ data
998
     *
999
     * @return bool
1000
     */
1001
    public function updateRecord(Array $data)
1002
    {
1003
        // Update entry
1004
        $query = sprintf("
1005
            UPDATE
1006
                %sfaqdata
1007
            SET
1008
                revision_id = %d,
1009
                active = '%s',
1010
                sticky = %d,
1011
                keywords = '%s',
1012
                thema = '%s',
1013
                content = '%s',
1014
                author = '%s',
1015
                email = '%s',
1016
                comment = '%s',
1017
                updated = '%s',
1018
                links_state = '%s',
1019
                links_check_date = %d,
1020
                date_start = '%s',
1021
                date_end = '%s',
1022
                notes = '%s'
1023
            WHERE
1024
                id = %d
1025
            AND
1026
                lang = '%s'",
1027
            Db::getTablePrefix(),
1028
            $data['revision_id'],
1029
            $data['active'],
1030
            $data['sticky'],
1031
            $this->config->getDb()->escape($data['keywords']),
1032
            $this->config->getDb()->escape($data['thema']),
1033
            $this->config->getDb()->escape($data['content']),
1034
            $this->config->getDb()->escape($data['author']),
1035
            $data['email'],
1036
            $data['comment'],
1037
            $data['date'],
1038
            $data['linkState'],
1039
            $data['linkDateCheck'],
1040
            $data['dateStart'],
1041
            $data['dateEnd'],
1042
            $data['notes'],
1043
            $data['id'],
1044
            $data['lang']
1045
        );
1046
1047
        $this->config->getDb()->query($query);
1048
1049
        return true;
1050
    }
1051
1052
    /**
1053
     * Deletes a record and all the dependencies.
1054
     *
1055
     * @param int $recordId Record id
1056
     * @param string $recordLang Record language
1057
     *
1058
     * @return bool
1059
     */
1060
    public function deleteRecord($recordId, $recordLang)
1061
    {
1062
        $solutionId = $this->getSolutionIdFromId($recordId, $recordLang);
1063
1064
        $queries = array(
1065
            sprintf(
1066
                "DELETE FROM %sfaqchanges WHERE beitrag = %d AND lang = '%s'",
1067
                Db::getTablePrefix(),
1068
                $recordId,
1069
                $recordLang
1070
            ),
1071
            sprintf(
1072
                "DELETE FROM %sfaqcategoryrelations WHERE record_id = %d AND record_lang = '%s'",
1073
                Db::getTablePrefix(),
1074
                $recordId,
1075
                $recordLang
1076
            ),
1077
            sprintf(
1078
                "DELETE FROM %sfaqdata WHERE id = %d AND lang = '%s'",
1079
                Db::getTablePrefix(),
1080
                $recordId,
1081
                $recordLang
1082
            ),
1083
            sprintf(
1084
                "DELETE FROM %sfaqdata_revisions WHERE id = %d AND lang = '%s'",
1085
                Db::getTablePrefix(),
1086
                $recordId,
1087
                $recordLang
1088
            ),
1089
            sprintf(
1090
                "DELETE FROM %sfaqvisits WHERE id = %d AND lang = '%s'",
1091
                Db::getTablePrefix(),
1092
                $recordId,
1093
                $recordLang
1094
            ),
1095
            sprintf(
1096
                'DELETE FROM %sfaqdata_user WHERE record_id = %d',
1097
                Db::getTablePrefix(),
1098
                $recordId,
1099
                $recordLang
1100
            ),
1101
            sprintf(
1102
                'DELETE FROM %sfaqdata_group WHERE record_id = %d',
1103
                Db::getTablePrefix(),
1104
                $recordId,
1105
                $recordLang
1106
            ),
1107
            sprintf(
1108
                'DELETE FROM %sfaqdata_tags WHERE record_id = %d',
1109
                Db::getTablePrefix(),
1110
                $recordId
1111
            ),
1112
            sprintf(
1113
                'DELETE FROM %sfaqdata_tags WHERE %sfaqdata_tags.record_id NOT IN (SELECT %sfaqdata.id FROM %sfaqdata)',
1114
                Db::getTablePrefix(),
1115
                Db::getTablePrefix(),
1116
                Db::getTablePrefix(),
1117
                Db::getTablePrefix()
1118
            ),
1119
            sprintf(
1120
                'DELETE FROM %sfaqcomments WHERE id = %d',
1121
                Db::getTablePrefix(),
1122
                $recordId
1123
            ),
1124
            sprintf(
1125
                'DELETE FROM %sfaqvoting WHERE artikel = %d',
1126
                Db::getTablePrefix(),
1127
                $recordId
1128
            ),
1129
        );
1130
1131
        foreach ($queries as $query) {
1132
            $this->config->getDb()->query($query);
1133
        }
1134
1135
        // Delete possible attachments
1136
        $attId = Factory::fetchByRecordId($this->config, $recordId);
1137
        $attachment = Factory::create($attId);
0 ignored issues
show
Documentation introduced by
$attId is of type array, but the function expects a integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1138
        $attachment->delete();
1139
1140
        // Delete possible Elasticsearch documents
1141
        if ($this->config->get('search.enableElasticsearch')) {
1142
            $esInstance = new Elasticsearch($this->config);
1143
            $esInstance->delete($solutionId);
1144
        }
1145
1146
        return true;
1147
    }
1148
1149
    /**
1150
     * Returns the solution ID from a given ID and language
1151
     *
1152
     * @param integer $faqId
1153
     * @param string $faqLang
1154
     *
1155
     * @return int
1156
     */
1157
    public function getSolutionIdFromId($faqId, $faqLang)
1158
    {
1159
        $query = sprintf("
1160
            SELECT
1161
                solution_id
1162
            FROM
1163
                %sfaqdata
1164
            WHERE
1165
                id = %d
1166
                AND
1167
                lang = '%s'",
1168
            Db::getTablePrefix(),
1169
            (int)$faqId,
1170
            $this->config->getDb()->escape($faqLang)
1171
        );
1172
1173
        $result = $this->config->getDb()->query($query);
1174
1175
        if ($row = $this->config->getDb()->fetchObject($result)) {
1176
            return $row->solution_id;
1177
        }
1178
1179
        return $this->getSolutionId();
1180
    }
1181
1182
    /**
1183
     * Checks if a record is already translated.
1184
     *
1185
     * @param int $recordId Record id
1186
     * @param string $recordLang Record language
1187
     *
1188
     * @return bool
1189
     */
1190
    public function hasTranslation($recordId, $recordLang)
1191
    {
1192
        $query = sprintf("
1193
            SELECT
1194
                id, lang
1195
            FROM
1196
                %sfaqdata
1197
            WHERE
1198
                id = %d
1199
            AND
1200
                lang = '%s'",
1201
            Db::getTablePrefix(),
1202
            $recordId,
1203
            $recordLang);
1204
1205
        $result = $this->config->getDb()->query($query);
1206
1207
        if ($this->config->getDb()->numRows($result)) {
1208
            return true;
1209
        }
1210
1211
        return false;
1212
    }
1213
1214
    /**
1215
     * Checks, if comments are disabled for the FAQ record.
1216
     *
1217
     * @param int $recordId Id of FAQ or news entry
1218
     * @param string $recordLang Language
1219
     * @param string $commentType Type of comment: faq or news
1220
     *
1221
     * @return bool true, if comments are disabled
1222
     */
1223
    public function commentDisabled($recordId, $recordLang, $commentType = 'faq')
1224
    {
1225
        if ('news' == $commentType) {
1226
            $table = 'faqnews';
1227
        } else {
1228
            $table = 'faqdata';
1229
        }
1230
1231
        $query = sprintf("
1232
            SELECT
1233
                comment
1234
            FROM
1235
                %s%s
1236
            WHERE
1237
                id = %d
1238
            AND
1239
                lang = '%s'",
1240
            Db::getTablePrefix(),
1241
            $table,
1242
            $recordId,
1243
            $recordLang
1244
        );
1245
1246
        $result = $this->config->getDb()->query($query);
1247
1248
        if ($row = $this->config->getDb()->fetchObject($result)) {
1249
            return ($row->comment === 'y') ? false : true;
1250
        } else {
1251
            return true;
1252
        }
1253
    }
1254
1255
    /**
1256
     * Adds new category relation to a record.
1257
     *
1258
     * @param mixed $category Entity or array of categories
1259
     * @param int $recordId Record id
1260
     * @param string $language Language
1261
     *
1262
     * @return bool
1263
     */
1264
    public function addCategoryFaqRelation($category, $recordId, $language)
1265
    {
1266
        // Just a fallback when (wrong case) $category is an array
1267
        if (is_array($category)) {
1268
            $this->addCategoryRelations($category, $recordId, $language);
1269
        }
1270
        $categories[] = $category;
1271
1272
        return $this->addCategoryRelations($categories, $recordId, $language);
1273
    }
1274
1275
    /**
1276
     * Adds new category relations to a record.
1277
     *
1278
     * @param array $categories Array of categories
1279
     * @param int $recordId Record id
1280
     * @param string $language Language
1281
     *
1282
     * @return boolean
1283
     */
1284
    public function addCategoryRelations(Array $categories, $recordId, $language)
1285
    {
1286
        if (!is_array($categories)) {
1287
            return false;
1288
        }
1289
1290
        foreach ($categories as $_category) {
1291
            $this->config->getDb()->query(sprintf(
1292
                "INSERT INTO
1293
                    %sfaqcategoryrelations
1294
                VALUES
1295
                    (%d, '%s', %d, '%s')",
1296
                Db::getTablePrefix(),
1297
                $_category,
1298
                $language,
1299
                $recordId,
1300
                $language)
1301
            );
1302
        }
1303
1304
        return true;
1305
    }
1306
1307
    /**
1308
     * Deletes category relations to a record.
1309
     *
1310
     * @param int $recordId Record id
1311
     * @param string $recordLang Language
1312
     *
1313
     * @return bool
1314
     */
1315 View Code Duplication
    public function deleteCategoryRelations($recordId, $recordLang)
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...
1316
    {
1317
        $query = sprintf("
1318
            DELETE FROM
1319
                %sfaqcategoryrelations
1320
            WHERE
1321
                record_id = %d
1322
            AND
1323
                record_lang = '%s'",
1324
            Db::getTablePrefix(),
1325
            $recordId,
1326
            $recordLang
1327
        );
1328
        $this->config->getDb()->query($query);
1329
1330
        return true;
1331
    }
1332
1333
    /**
1334
     * Returns an array with all data from a FAQ record.
1335
     *
1336
     * @param int $solutionId Solution ID
1337
     */
1338
    public function getRecordBySolutionId($solutionId)
1339
    {
1340
        $query = sprintf(
1341
            'SELECT
1342
                *
1343
            FROM
1344
                %sfaqdata fd
1345
            LEFT JOIN
1346
                %sfaqdata_group fdg
1347
            ON
1348
                fd.id = fdg.record_id
1349
            LEFT JOIN
1350
                %sfaqdata_user fdu
1351
            ON
1352
                fd.id = fdu.record_id
1353
            WHERE
1354
                fd.solution_id = %d
1355
                %s',
1356
            Db::getTablePrefix(),
1357
            Db::getTablePrefix(),
1358
            Db::getTablePrefix(),
1359
            $solutionId,
1360
            $this->queryPermission($this->groupSupport)
1361
        );
1362
1363
        $result = $this->config->getDb()->query($query);
1364
1365
        if ($row = $this->config->getDb()->fetchObject($result)) {
1366
            $question = nl2br($row->thema);
1367
            $content = $row->content;
1368
            $active = ('yes' == $row->active);
1369
            $expired = (date('YmdHis') > $row->date_end);
1370
1371
            if (!$active) {
1372
                $content = $this->translation['err_inactiveArticle'];
1373
            }
1374
            if ($expired) {
1375
                $content = $this->translation['err_expiredArticle'];
1376
            }
1377
1378
            $this->faqRecord = array(
1379
                'id' => $row->id,
1380
                'lang' => $row->lang,
1381
                'solution_id' => $row->solution_id,
1382
                'revision_id' => $row->revision_id,
1383
                'active' => $row->active,
1384
                'sticky' => $row->sticky,
1385
                'keywords' => $row->keywords,
1386
                'title' => $question,
1387
                'content' => $content,
1388
                'author' => $row->author,
1389
                'email' => $row->email,
1390
                'comment' => $row->comment,
1391
                'date' => Date::createIsoDate($row->updated),
1392
                'dateStart' => $row->date_start,
1393
                'dateEnd' => $row->date_end,
1394
                'linkState' => $row->links_state,
1395
                'linkCheckDate' => $row->links_check_date,
1396
                'notes' => $row->notes
1397
            );
1398
        }
1399
    }
1400
1401
    /**
1402
     * Gets the record ID from a given solution ID.
1403
     *
1404
     * @param int $solutionId Solution ID
1405
     *
1406
     * @return array
1407
     */
1408
    public function getIdFromSolutionId($solutionId)
1409
    {
1410
        $query = sprintf('
1411
            SELECT
1412
                fd.id,
1413
                fd.lang,
1414
                fd.thema AS question,
1415
                fd.content,
1416
                fcr.category_id AS category_id
1417
            FROM
1418
                %sfaqdata fd
1419
            LEFT JOIN
1420
                %sfaqcategoryrelations fcr
1421
            ON
1422
                fd.id = fcr.record_id
1423
            AND
1424
                fd.lang = fcr.record_lang
1425
            WHERE
1426
                fd.solution_id = %d',
1427
            Db::getTablePrefix(),
1428
            Db::getTablePrefix(),
1429
            $solutionId
1430
        );
1431
1432
        $result = $this->config->getDb()->query($query);
1433
1434
        if ($row = $this->config->getDb()->fetchObject($result)) {
1435
            return [
1436
                'id' => $row->id,
1437
                'lang' => $row->lang,
1438
                'question' => $row->question,
1439
                'content' => $row->content,
1440
                'category_id' => $row->category_id
1441
            ];
1442
        }
1443
1444
        return [];
1445
    }
1446
1447
    /**
1448
     * Returns an array with all data from all FAQ records.
1449
     *
1450
     * @param int $sortType Sorting type
1451
     * @param array $condition Condition
1452
     * @param string $sortOrder Sorting order
1453
     */
1454
    public function getAllRecords($sortType = FAQ_SORTING_TYPE_CATID_FAQID, Array $condition = null, $sortOrder = 'ASC')
1455
    {
1456
        $where = '';
1457
        if (!is_null($condition)) {
1458
            $num = count($condition);
1459
            $where = 'WHERE ';
1460
            foreach ($condition as $field => $data) {
1461
                --$num;
1462
                $where .= $field;
1463
                if (is_array($data)) {
1464
                    $where .= ' IN (';
1465
                    $separator = '';
1466
                    foreach ($data as $value) {
1467
                        $where .= $separator."'".$this->config->getDb()->escape($value)."'";
1468
                        $separator = ', ';
1469
                    }
1470
                    $where .= ')';
1471
                } else {
1472
                    $where .= " = '".$this->config->getDb()->escape($data)."'";
1473
                }
1474
                if ($num > 0) {
1475
                    $where .= ' AND ';
1476
                }
1477
            }
1478
        }
1479
1480
        switch ($sortType) {
1481
1482
            case FAQ_SORTING_TYPE_CATID_FAQID:
1483
                $orderBy = sprintf('
1484
            ORDER BY
1485
                fcr.category_id,
1486
                fd.id %s',
1487
                    $sortOrder);
1488
                break;
1489
1490
            case FAQ_SORTING_TYPE_FAQID:
1491
                $orderBy = sprintf('
1492
            ORDER BY
1493
                fd.id %s',
1494
                    $sortOrder);
1495
                break;
1496
1497
            case FAQ_SORTING_TYPE_FAQTITLE_FAQID:
1498
                $orderBy = sprintf('
1499
            ORDER BY
1500
                fcr.category_id,
1501
                fd.thema %s',
1502
                    $sortOrder);
1503
                break;
1504
1505
            case FAQ_SORTING_TYPE_DATE_FAQID:
1506
                $orderBy = sprintf('
1507
            ORDER BY
1508
                fcr.category_id,
1509
                fd.updated %s',
1510
                    $sortOrder);
1511
                break;
1512
1513
            default:
1514
                $orderBy = '';
1515
                break;
1516
        }
1517
1518
        // prevents multiple display of FAQ incase it is tagged under multiple groups.
1519
        $group_by = ' group by fd.id, fcr.category_id,fd.solution_id,fd.revision_id,fd.active,fd.sticky,fd.keywords,fd.thema,fd.content,fd.author,fd.email,fd.comment,fd.updated,fd.links_state,fd.links_check_date,fd.date_start,fd.date_end,fd.sticky,fd.created,fd.notes,fd.lang ';
1520
        $query = sprintf('
1521
            SELECT
1522
                fd.id AS id,
1523
                fd.lang AS lang,
1524
                fcr.category_id AS category_id,
1525
                fd.solution_id AS solution_id,
1526
                fd.revision_id AS revision_id,
1527
                fd.active AS active,
1528
                fd.sticky AS sticky,
1529
                fd.keywords AS keywords,
1530
                fd.thema AS thema,
1531
                fd.content AS content,
1532
                fd.author AS author,
1533
                fd.email AS email,
1534
                fd.comment AS comment,
1535
                fd.updated AS updated,
1536
                fd.links_state AS links_state,
1537
                fd.links_check_date AS links_check_date,
1538
                fd.date_start AS date_start,
1539
                fd.date_end AS date_end,
1540
                fd.sticky AS sticky,
1541
                fd.created AS created,
1542
                fd.notes AS notes
1543
            FROM
1544
                %sfaqdata fd
1545
            LEFT JOIN
1546
                %sfaqcategoryrelations fcr
1547
            ON
1548
                fd.id = fcr.record_id
1549
            AND
1550
                fd.lang = fcr.record_lang
1551
            LEFT JOIN
1552
                %sfaqdata_group AS fdg
1553
            ON
1554
                fd.id = fdg.record_id
1555
            LEFT JOIN
1556
                %sfaqdata_user AS fdu
1557
            ON
1558
                fd.id = fdu.record_id
1559
            %s
1560
            %s
1561
            %s
1562
            %s',
1563
            Db::getTablePrefix(),
1564
            Db::getTablePrefix(),
1565
            Db::getTablePrefix(),
1566
            Db::getTablePrefix(),
1567
            $where,
1568
            $this->queryPermission($this->groupSupport),
1569
            $group_by,
1570
            $orderBy
1571
        );
1572
1573
        $result = $this->config->getDb()->query($query);
1574
1575
        while ($row = $this->config->getDb()->fetchObject($result)) {
1576
            $content = $row->content;
1577
            $active = ('yes' == $row->active);
1578
            $expired = (date('YmdHis') > $row->date_end);
1579
1580
            if (!$active) {
1581
                $content = $this->translation['err_inactiveArticle'];
1582
            }
1583
            if ($expired) {
1584
                $content = $this->translation['err_expiredArticle'];
1585
            }
1586
1587
            $this->faqRecords[] = [
1588
                'id' => $row->id,
1589
                'category_id' => $row->category_id,
1590
                'lang' => $row->lang,
1591
                'solution_id' => $row->solution_id,
1592
                'revision_id' => $row->revision_id,
1593
                'active' => $row->active,
1594
                'sticky' => $row->sticky,
1595
                'keywords' => $row->keywords,
1596
                'title' => $row->thema,
1597
                'content' => $content,
1598
                'author' => $row->author,
1599
                'email' => $row->email,
1600
                'comment' => $row->comment,
1601
                'updated' => Date::createIsoDate($row->updated, 'Y-m-d H:i:s'),
1602
                'dateStart' => $row->date_start,
1603
                'dateEnd' => $row->date_end,
1604
                'created' => $row->created,
1605
                'notes' => $row->notes
1606
            ];
1607
        }
1608
    }
1609
1610
    /**
1611
     * Returns the FAQ record title from the ID and language.
1612
     *
1613
     * @param int $id Record id
1614
     *
1615
     * @return string
1616
     */
1617
    public function getRecordTitle($id)
1618
    {
1619
        if (isset($this->faqRecord['id']) && ($this->faqRecord['id'] == $id)) {
1620
            return $this->faqRecord['title'];
1621
        }
1622
1623
        $question = '';
1624
1625
        $query = sprintf(
1626
            "SELECT
1627
                thema AS question
1628
            FROM
1629
                %sfaqdata
1630
            WHERE
1631
                id = %d AND lang = '%s'",
1632
            Db::getTablePrefix(),
1633
            $id,
1634
            $this->config->getLanguage()->getLanguage()
1635
        );
1636
        $result = $this->config->getDb()->query($query);
1637
1638
        if ($this->config->getDb()->numRows($result) > 0) {
1639
            while ($row = $this->config->getDb()->fetchObject($result)) {
1640
                $question = Strings::htmlspecialchars($row->question);
1641
            }
1642
        } else {
1643
            $question = $this->translation['no_cats'];
1644
        }
1645
1646
        return $question;
1647
    }
1648
1649
    /**
1650
     * Gets all revisions from a given record ID.
1651
     *
1652
     * @param int $recordId Record id
1653
     * @param string $recordLang Record language
1654
     *
1655
     * @return array
1656
     */
1657
    public function getRevisionIds($recordId, $recordLang)
1658
    {
1659
        $revisionData = [];
1660
1661
        $query = sprintf("
1662
            SELECT
1663
                revision_id, updated, author
1664
            FROM
1665
                %sfaqdata_revisions
1666
            WHERE
1667
                id = %d
1668
            AND
1669
                lang = '%s'
1670
            ORDER BY
1671
                revision_id",
1672
            Db::getTablePrefix(),
1673
            $recordId,
1674
            $recordLang
1675
        );
1676
1677
        $result = $this->config->getDb()->query($query);
1678
1679
        if ($this->config->getDb()->numRows($result) > 0) {
1680
            while ($row = $this->config->getDb()->fetchObject($result)) {
1681
                $revisionData[] = [
1682
                    'revision_id' => $row->revision_id,
1683
                    'updated' => $row->updated,
1684
                    'author' => $row->author,
1685
                ];
1686
            }
1687
        }
1688
1689
        return $revisionData;
1690
    }
1691
1692
    /**
1693
     * Adds a new revision from a given record ID.
1694
     *
1695
     * @param int $recordId Record id
1696
     * @param string $recordLang Record language
1697
     *
1698
     * @return bool
1699
     */
1700 View Code Duplication
    public function addNewRevision($recordId, $recordLang)
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...
1701
    {
1702
        $query = sprintf("
1703
            INSERT INTO
1704
                %sfaqdata_revisions
1705
            SELECT * FROM
1706
                %sfaqdata
1707
            WHERE
1708
                id = %d
1709
            AND
1710
                lang = '%s'",
1711
            Db::getTablePrefix(),
1712
            Db::getTablePrefix(),
1713
            $recordId,
1714
            $recordLang);
1715
        $this->config->getDb()->query($query);
1716
1717
        return true;
1718
    }
1719
1720
    /**
1721
     * Returns the keywords of a FAQ record from the ID and language.
1722
     *
1723
     * @param int $id record id
1724
     *
1725
     * @return string
1726
     */
1727
    public function getRecordKeywords($id)
1728
    {
1729
        if (isset($this->faqRecord['id']) && ($this->faqRecord['id'] == $id)) {
1730
            return $this->faqRecord['keywords'];
1731
        }
1732
1733
        $query = sprintf(
1734
            "SELECT
1735
                keywords
1736
            FROM
1737
                %sfaqdata
1738
            WHERE id = %d AND lang = '%s'",
1739
            Db::getTablePrefix(),
1740
            $id,
1741
            $this->config->getLanguage()->getLanguage());
1742
1743
        $result = $this->config->getDb()->query($query);
1744
1745
        if ($this->config->getDb()->numRows($result) > 0) {
1746
            $row = $this->config->getDb()->fetchObject($result);
1747
1748
            return Strings::htmlspecialchars($row->keywords, ENT_QUOTES, 'utf-8');
1749
        } else {
1750
            return '';
1751
        }
1752
    }
1753
1754
    /**
1755
     * Returns a answer preview of the FAQ record.
1756
     *
1757
     * @param int $recordId FAQ record ID
1758
     * @param int $wordCount Number of words, default: 12
1759
     *
1760
     * @return string
1761
     */
1762
    public function getRecordPreview($recordId, $wordCount = 12)
1763
    {
1764
        if (isset($this->faqRecord['id']) && ((int)$this->faqRecord['id'] === (int)$recordId)) {
1765
            $answerPreview = $this->faqRecord['content'];
1766
1767
            return Utils::makeShorterText($answerPreview, $wordCount);
1768
        }
1769
1770
        $query = sprintf("
1771
            SELECT
1772
                content as answer
1773
            FROM
1774
                %sfaqdata
1775
            WHERE 
1776
                id = %d 
1777
            AND 
1778
                lang = '%s'",
1779
            Db::getTablePrefix(),
1780
            $recordId,
1781
            $this->config->getLanguage()->getLanguage()
1782
        );
1783
1784
        $result = $this->config->getDb()->query($query);
1785
1786
        if ($this->config->getDb()->numRows($result) > 0) {
1787
            $row = $this->config->getDb()->fetchObject($result);
1788
            $answerPreview = strip_tags($row->answer);
1789
        } else {
1790
            $answerPreview = $this->config->get('main.metaDescription');
1791
        }
1792
1793
        return Utils::makeShorterText($answerPreview, $wordCount);
1794
    }
1795
1796
    /**
1797
     * Returns the number of activated and not expired records, optionally
1798
     * not limited to the current language.
1799
     *
1800
     * @param string $language Language
1801
     *
1802
     * @return int
1803
     */
1804
    public function getNumberOfRecords($language = null)
1805
    {
1806
        $now = date('YmdHis');
1807
1808
        $query = sprintf("
1809
            SELECT
1810
                id
1811
            FROM
1812
                %sfaqdata
1813
            WHERE
1814
                active = 'yes'
1815
            %s
1816
            AND
1817
                date_start <= '%s'
1818
            AND
1819
                date_end >= '%s'",
1820
            Db::getTablePrefix(),
1821
            null == $language ? '' : "AND lang = '".$language."'",
1822
            $now,
1823
            $now
1824
        );
1825
1826
        $num = $this->config->getDb()->numRows($this->config->getDb()->query($query));
1827
1828
        if ($num > 0) {
1829
            return $num;
1830
        } else {
1831
            return 0;
1832
        }
1833
    }
1834
1835
    /**
1836
     * This function generates a list with the most voted or most visited records.
1837
     *
1838
     * @param string $type Type definition visits/voted
1839
     *
1840
     * @since  2009-11-03
1841
     *
1842
     * @author Max Köhler <[email protected]>
1843
     *
1844
     * @return array
1845
     */
1846
    public function getTopTen($type = 'visits')
1847
    {
1848
        if ('visits' == $type) {
1849
            $result = $this->getTopTenData(PMF_NUMBER_RECORDS_TOPTEN, 0, $this->config->getLanguage()->getLanguage());
1850
        } else {
1851
            $result = $this->getTopVotedData(PMF_NUMBER_RECORDS_TOPTEN, $this->config->getLanguage()->getLanguage());
1852
        }
1853
        $output = [];
1854
1855
        if (count($result) > 0) {
1856
            foreach ($result as $row) {
1857
                if ('visits' == $type) {
1858
                    $output['title'][] = Utils::makeShorterText($row['question'], 8);
1859
                    $output['preview'][] = $row['question'];
1860
                    $output['url'][] = $row['url'];
1861
                    $output['visits'][] = $this->plurals->GetMsg('plmsgViews', $row['visits']);
1862
                } else {
1863
                    $output['title'][] = Utils::makeShorterText($row['question'], 8);
1864
                    $output['preview'][] = $row['question'];
1865
                    $output['url'][] = $row['url'];
1866
                    $output['voted'][] = sprintf(
1867
                        '%s %s 5 - %s',
1868
                        round($row['avg'], 2),
1869
                        $this->translation['msgVoteFrom'],
1870
                        $this->plurals->GetMsg('plmsgVotes', $row['user'])
1871
                    );
1872
                }
1873
            }
1874
        } else {
1875
            $output['error'] = $this->translation['err_noTopTen'];
1876
        }
1877
1878
        return $output;
1879
    }
1880
1881
    /**
1882
     * This function generates the Top Ten data with the mosted viewed records.
1883
     *
1884
     * @param int $count Number of records
1885
     * @param int $categoryId Entity ID
1886
     * @param string $language Language
1887
     *
1888
     * @return array
1889
     */
1890
    public function getTopTenData($count = PMF_NUMBER_RECORDS_TOPTEN, $categoryId = 0, $language = null)
1891
    {
1892
        global $sids;
1893
1894
        $now = date('YmdHis');
1895
        $query =
1896
            '            SELECT
1897
                fd.id AS id,
1898
                fd.lang AS lang,
1899
                fd.thema AS question,
1900
                fd.content AS answer,
1901
                fd.updated AS updated,
1902
                fcr.category_id AS category_id,
1903
                fv.visits AS visits,
1904
                fv.last_visit AS last_visit,
1905
                fdg.group_id AS group_id,
1906
                fdu.user_id AS user_id
1907
            FROM
1908
                ' . Db::getTablePrefix().'faqvisits fv,
1909
                ' . Db::getTablePrefix().'faqdata fd
1910
            LEFT JOIN
1911
                ' . Db::getTablePrefix().'faqcategoryrelations fcr
1912
            ON
1913
                fd.id = fcr.record_id
1914
            AND
1915
                fd.lang = fcr.record_lang
1916
            LEFT JOIN
1917
                ' . Db::getTablePrefix().'faqdata_group AS fdg
1918
            ON
1919
                fd.id = fdg.record_id
1920
            LEFT JOIN
1921
                ' . Db::getTablePrefix().'faqdata_user AS fdu
1922
            ON
1923
                fd.id = fdu.record_id
1924
            WHERE
1925
                    fd.date_start <= \'' . $now.'\'
1926
                AND fd.date_end   >= \'' . $now.'\'
1927
                AND fd.id = fv.id
1928
                AND fd.lang = fv.lang
1929
                AND fd.active = \'yes\'';
1930
1931 View Code Duplication
        if (isset($categoryId) && is_numeric($categoryId) && ($categoryId != 0)) {
1932
            $query .= '
1933
            AND
1934
                fcr.category_id = \'' . $categoryId.'\'';
1935
        }
1936
        if (isset($language) && Language::isASupportedLanguage($language)) {
1937
            $query .= '
1938
            AND
1939
                fd.lang = \'' . $language.'\'';
1940
        }
1941
        $query .= '
1942
                ' . $this->queryPermission($this->groupSupport).'
1943
1944
            GROUP BY
1945
                fd.id,fd.lang,fcr.category_id,fv.visits,fv.last_visit,fdg.group_id,fdu.user_id
1946
            ORDER BY
1947
                fv.visits DESC';
1948
1949
        $result = $this->config->getDb()->query($query);
1950
        $topTen = [];
1951
        $data = [];
1952
1953
        if ($result) {
1954
            while ($row = $this->config->getDb()->fetchObject($result)) {
1955 View Code Duplication
                if ($this->groupSupport) {
1956
                    if (!in_array($row->user_id, array(-1, $this->user)) || !in_array($row->group_id, $this->groups)) {
1957
                        continue;
1958
                    }
1959
                } else {
1960
                    if (!in_array($row->user_id, array(-1, $this->user))) {
1961
                        continue;
1962
                    }
1963
                }
1964
1965
                $data['visits'] = (int)$row->visits;
1966
                $data['question'] = $row->question;
1967
                $data['answer'] = $row->answer;
1968
                $data['date'] = Date::createIsoDate($row->updated, DATE_ISO8601, true);
1969
                $data['last_visit'] = date('c', $row->last_visit);
1970
1971
                $title = $row->question;
1972
                $url = sprintf(
1973
                    '%sindex.php?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
1974
                    $this->config->getDefaultUrl(),
1975
                    $sids,
1976
                    $row->category_id,
1977
                    $row->id,
1978
                    $row->lang
1979
                );
1980
                $oLink = new Link($url, $this->config);
1981
                $oLink->itemTitle = $row->question;
1982
                $oLink->tooltip = $title;
1983
                $data['url'] = $oLink->toString();
1984
1985
                $topTen[$row->id] = $data;
1986
1987
                if (count($topTen) === $count) {
1988
                    break;
1989
                }
1990
            }
1991
1992
            array_multisort($topTen, SORT_DESC);
1993
        }
1994
1995
        return $topTen;
1996
    }
1997
1998
    /**
1999
     * This function generates a data-set with the most voted FAQs.
2000
     *
2001
     * @param int $count Number of records
2002
     * @param string $language Language
2003
     *
2004
     * @return array
2005
     */
2006
    public function getTopVotedData($count = PMF_NUMBER_RECORDS_TOPTEN, $language = null)
2007
    {
2008
        global $sids;
2009
2010
        $topten = $data = [];
2011
2012
        $now = date('YmdHis');
2013
        $query =
2014
            '            SELECT
2015
                fd.id AS id,
2016
                fd.lang AS lang,
2017
                fd.thema AS thema,
2018
                fd.updated AS updated,
2019
                fcr.category_id AS category_id,
2020
                (fv.vote/fv.usr) AS avg,
2021
                fv.usr AS user
2022
            FROM
2023
                ' . Db::getTablePrefix().'faqvoting fv,
2024
                ' . Db::getTablePrefix().'faqdata fd
2025
            LEFT JOIN
2026
                ' . Db::getTablePrefix().'faqcategoryrelations fcr
2027
            ON
2028
                fd.id = fcr.record_id
2029
            AND
2030
                fd.lang = fcr.record_lang
2031
            LEFT JOIN
2032
                ' . Db::getTablePrefix().'faqdata_group AS fdg
2033
            ON
2034
                fd.id = fdg.record_id
2035
            LEFT JOIN
2036
                ' . Db::getTablePrefix().'faqdata_user AS fdu
2037
            ON
2038
                fd.id = fdu.record_id
2039
            WHERE
2040
                    fd.date_start <= \'' . $now.'\'
2041
                AND fd.date_end   >= \'' . $now.'\'
2042
                AND fd.id = fv.artikel
2043
                AND fd.active = \'yes\'';
2044
2045 View Code Duplication
        if (isset($categoryId) && is_numeric($categoryId) && ($categoryId != 0)) {
0 ignored issues
show
Bug introduced by
The variable $categoryId seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
2046
            $query .= '
2047
            AND
2048
                fcr.category_id = \'' . $categoryId.'\'';
2049
        }
2050
        if (isset($language) && Language::isASupportedLanguage($language)) {
2051
            $query .= '
2052
            AND
2053
                fd.lang = \'' . $language.'\'';
2054
        }
2055
        $query .= '
2056
                ' . $this->queryPermission($this->groupSupport).'
2057
            ORDER BY
2058
                avg DESC';
2059
2060
        $result = $this->config->getDb()->query($query);
2061
2062
        $i = 1;
2063
        $oldId = 0;
2064
        while (($row = $this->config->getDb()->fetchObject($result)) && $i <= $count) {
2065
            if ($oldId != $row->id) {
2066
                $data['avg'] = $row->avg;
2067
                $data['question'] = $row->thema;
2068
                $data['date'] = $row->updated;
2069
                $data['user'] = $row->user;
2070
2071
                $title = $row->thema;
2072
                $url = sprintf(
2073
                    '%s?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
2074
                    Link::getSystemRelativeUri(),
2075
                    $sids,
2076
                    $row->category_id,
2077
                    $row->id,
2078
                    $row->lang
2079
                );
2080
                $oLink = new Link($url, $this->config);
2081
                $oLink->itemTitle = $row->thema;
2082
                $oLink->tooltip = $title;
2083
                $data['url'] = $oLink->toString();
2084
2085
                $topten[] = $data;
2086
                ++$i;
2087
            }
2088
            $oldId = $row->id;
2089
        }
2090
2091
        return $topten;
2092
    }
2093
2094
    /**
2095
     * This function generates the list with the latest published records.
2096
     *
2097
     * @return array
2098
     */
2099
    public function getLatest()
2100
    {
2101
        $date = new Date($this->config);
2102
        $result = $this->getLatestData(PMF_NUMBER_RECORDS_LATEST, $this->config->getLanguage()->getLanguage());
2103
        $output = [];
2104
2105
        if (count($result) > 0) {
2106
            foreach ($result as $row) {
2107
                $output['url'][] = $row['url'];
2108
                $output['title'][] = Utils::makeShorterText($row['question'], 8);
2109
                $output['preview'][] = $row['question'];
2110
                $output['date'][] = $date->format($row['date']);
2111
            }
2112
        } else {
2113
            $output['error'] = $this->translation['err_noArticles'];
2114
        }
2115
2116
        return $output;
2117
    }
2118
2119
    /**
2120
     * This function generates an array with a specified number of most recent
2121
     * published records.
2122
     *
2123
     * @param int $count Number of records
2124
     * @param string $language Language
2125
     *
2126
     * @return array
2127
     */
2128
    public function getLatestData($count = PMF_NUMBER_RECORDS_LATEST, $language = null)
2129
    {
2130
        global $sids;
2131
2132
        $now = date('YmdHis');
2133
        $query =
2134
            '            SELECT
2135
                fd.id AS id,
2136
                fd.lang AS lang,
2137
                fcr.category_id AS category_id,
2138
                fd.thema AS question,
2139
                fd.content AS content,
2140
                fd.updated AS updated,
2141
                fv.visits AS visits,
2142
                fdg.group_id AS group_id,
2143
                fdu.user_id AS user_id
2144
            FROM
2145
                ' . Db::getTablePrefix().'faqvisits fv,
2146
                ' . Db::getTablePrefix().'faqdata fd
2147
            LEFT JOIN
2148
                ' . Db::getTablePrefix().'faqcategoryrelations fcr
2149
            ON
2150
                fd.id = fcr.record_id
2151
            AND
2152
                fd.lang = fcr.record_lang
2153
            LEFT JOIN
2154
                ' . Db::getTablePrefix().'faqdata_group AS fdg
2155
            ON
2156
                fd.id = fdg.record_id
2157
            LEFT JOIN
2158
                ' . Db::getTablePrefix().'faqdata_user AS fdu
2159
            ON
2160
                fd.id = fdu.record_id
2161
            WHERE
2162
                    fd.date_start <= \'' . $now.'\'
2163
                AND fd.date_end   >= \'' . $now.'\'
2164
                AND fd.id = fv.id
2165
                AND fd.lang = fv.lang
2166
                AND fd.active = \'yes\'';
2167
2168
        if (isset($language) && Language::isASupportedLanguage($language)) {
2169
            $query .= '
2170
            AND
2171
                fd.lang = \'' . $language.'\'';
2172
        }
2173
        $query .= '
2174
                ' . $this->queryPermission($this->groupSupport).'
2175
            GROUP BY
2176
                fd.id,fd.lang,fcr.category_id,fv.visits,fdg.group_id,fdu.user_id
2177
            ORDER BY
2178
                fd.updated DESC';
2179
2180
        $result = $this->config->getDb()->query($query);
2181
        $latest = [];
2182
        $data = [];
2183
2184
        if ($result) {
2185
            while (($row = $this->config->getDb()->fetchObject($result))) {
2186 View Code Duplication
                if ($this->groupSupport) {
2187
                    if (!in_array($row->user_id, array(-1, $this->user)) || !in_array($row->group_id, $this->groups)) {
2188
                        continue;
2189
                    }
2190
                } else {
2191
                    if (!in_array($row->user_id, array(-1, $this->user))) {
2192
                        continue;
2193
                    }
2194
                }
2195
2196
                $data['date'] = Date::createIsoDate($row->updated, DATE_ISO8601, true);
2197
                $data['question'] = $row->question;
2198
                $data['answer'] = $row->content;
2199
                $data['visits'] = (int)$row->visits;
2200
2201
                $title = $row->question;
2202
                $url = sprintf(
2203
                    '%sindex.php?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
2204
                    $this->config->getDefaultUrl(),
2205
                    $sids,
2206
                    $row->category_id,
2207
                    $row->id,
2208
                    $row->lang
2209
                );
2210
                $oLink = new Link($url, $this->config);
2211
                $oLink->itemTitle = $row->question;
2212
                $oLink->tooltip = $title;
2213
                $data['url'] = $oLink->toString();
2214
2215
                $latest[$row->id] = $data;
2216
2217
                if (count($latest) === $count) {
2218
                    break;
2219
                }
2220
            }
2221
        }
2222
2223
        return $latest;
2224
    }
2225
2226
    /**
2227
     * Deletes a question for the table faqquestions.
2228
     *
2229
     * @param int $questionId
2230
     *
2231
     * @return bool
2232
     */
2233 View Code Duplication
    public function deleteQuestion($questionId)
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...
2234
    {
2235
        $delete = sprintf("
2236
            DELETE FROM
2237
                %sfaqquestions
2238
            WHERE
2239
                id = %d
2240
            AND
2241
                lang = '%s'",
2242
            Db::getTablePrefix(),
2243
            $questionId,
2244
            $this->config->getLanguage()->getLanguage()
2245
        );
2246
2247
        $this->config->getDb()->query($delete);
2248
2249
        return true;
2250
    }
2251
2252
    /**
2253
     * Returns the visibility of a question.
2254
     *
2255
     * @param   int $questionId
2256
     *
2257
     * @return  string
2258
     */
2259 View Code Duplication
    public function getVisibilityOfQuestion($questionId)
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...
2260
    {
2261
        $query = sprintf("
2262
            SELECT
2263
                is_visible
2264
            FROM
2265
                %sfaqquestions
2266
            WHERE
2267
                id = %d
2268
            AND
2269
                lang = '%s'",
2270
            Db::getTablePrefix(),
2271
            $questionId,
2272
            $this->config->getLanguage()->getLanguage()
2273
        );
2274
2275
        $result = $this->config->getDb()->query($query);
2276
        if ($this->config->getDb()->numRows($result) > 0) {
2277
            $row = $this->config->getDb()->fetchObject($result);
2278
2279
            return $row->is_visible;
2280
        }
2281
2282
        return;
2283
    }
2284
2285
    /**
2286
     * Sets the visibility of a question.
2287
     *
2288
     * @param int $questionId
2289
     * @param string $isVisible
2290
     *
2291
     * @return bool
2292
     */
2293 View Code Duplication
    public function setVisibilityOfQuestion($questionId, $isVisible)
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...
2294
    {
2295
        $query = sprintf("
2296
            UPDATE
2297
                %sfaqquestions
2298
            SET
2299
                is_visible = '%s'
2300
            WHERE
2301
                id = %d
2302
            AND
2303
                lang = '%s'",
2304
            Db::getTablePrefix(),
2305
            $isVisible,
2306
            $questionId,
2307
            $this->config->getLanguage()->getLanguage()
2308
        );
2309
2310
        $this->config->getDb()->query($query);
2311
2312
        return true;
2313
    }
2314
2315
2316
    /**
2317
     * Adds a new question.
2318
     *
2319
     * @param array $questionData
2320
     *
2321
     * @return bool
2322
     */
2323
    public function addQuestion(Array $questionData)
2324
    {
2325
        $query = sprintf("
2326
            INSERT INTO
2327
                %sfaqquestions
2328
            (id, lang, username, email, category_id, question, created, is_visible, answer_id)
2329
                VALUES
2330
            (%d, '%s', '%s', '%s', %d, '%s', '%s', '%s', %d)",
2331
            Db::getTablePrefix(),
2332
            $this->config->getDb()->nextId(Db::getTablePrefix().'faqquestions', 'id'),
2333
            $this->config->getLanguage()->getLanguage(),
2334
            $this->config->getDb()->escape($questionData['username']),
2335
            $this->config->getDb()->escape($questionData['email']),
2336
            $questionData['category_id'],
2337
            $this->config->getDb()->escape($questionData['question']),
2338
            date('YmdHis'),
2339
            $questionData['is_visible'],
2340
            0
2341
        );
2342
        $this->config->getDb()->query($query);
2343
2344
        return true;
2345
    }
2346
2347
    /**
2348
     * Returns a new question.
2349
     *
2350
     * @param int $questionId
2351
     *
2352
     * @return array
2353
     */
2354
    public function getQuestion($questionId)
2355
    {
2356
        $question = [
2357
            'id' => 0,
2358
            'lang' => '',
2359
            'username' => '',
2360
            'email' => '',
2361
            'category_id' => '',
2362
            'question' => '',
2363
            'created' => '',
2364
            'is_visible' => '',
2365
        ];
2366
2367
        if (!is_int($questionId)) {
2368
            return $question;
2369
        }
2370
2371
        $question = [];
2372
2373
        $query = sprintf("
2374
            SELECT
2375
                 id, lang, username, email, category_id, question, created, is_visible
2376
            FROM
2377
                %sfaqquestions
2378
            WHERE
2379
                id = %d
2380
            AND
2381
                lang = '%s'",
2382
            Db::getTablePrefix(),
2383
            $questionId,
2384
            $this->config->getLanguage()->getLanguage()
2385
        );
2386
2387 View Code Duplication
        if ($result = $this->config->getDb()->query($query)) {
2388
            if ($row = $this->config->getDb()->fetchObject($result)) {
2389
                $question = array(
2390
                    'id' => $row->id,
2391
                    'lang' => $row->lang,
2392
                    'username' => $row->username,
2393
                    'email' => $row->email,
2394
                    'category_id' => $row->category_id,
2395
                    'question' => $row->question,
2396
                    'created' => $row->created,
2397
                    'is_visible' => $row->is_visible,
2398
                );
2399
            }
2400
        }
2401
2402
        return $question;
2403
    }
2404
2405
    /**
2406
     * Returns all open questions.
2407
     *
2408
     * @param boolean $all If true, then return visible and non-visible
2409
     *                     questions; otherwise only visible ones
2410
     *
2411
     * @return array
2412
     */
2413
    public function getAllOpenQuestions($all = true)
2414
    {
2415
        $questions = [];
2416
2417
        $query = sprintf("
2418
            SELECT
2419
                id, lang, username, email, category_id, question, created, answer_id, is_visible
2420
            FROM
2421
                %sfaqquestions
2422
            WHERE
2423
                lang = '%s'
2424
                %s
2425
            ORDER BY 
2426
                created ASC",
2427
            Db::getTablePrefix(),
2428
            $this->config->getLanguage()->getLanguage(),
2429
            ($all === false ? " AND is_visible = 'Y'" : '')
2430
        );
2431
2432 View Code Duplication
        if ($result = $this->config->getDb()->query($query)) {
2433
            while ($row = $this->config->getDb()->fetchObject($result)) {
2434
                $questions[] = array(
2435
                    'id' => $row->id,
2436
                    'lang' => $row->lang,
2437
                    'username' => $row->username,
2438
                    'email' => $row->email,
2439
                    'category_id' => $row->category_id,
2440
                    'question' => $row->question,
2441
                    'created' => $row->created,
2442
                    'answer_id' => $row->answer_id,
2443
                    'is_visible' => $row->is_visible,
2444
                );
2445
            }
2446
        }
2447
2448
        return $questions;
2449
    }
2450
2451
    /**
2452
     * Adds a new changelog entry in the table faqchanges.
2453
     *
2454
     * @param int $id
2455
     * @param int $userId
2456
     * @param string $text
2457
     * @param string $lang
2458
     * @param int $revision_id
2459
     *
2460
     * @return bool
2461
     */
2462
    public function createChangeEntry($id, $userId, $text, $lang, $revision_id = 0)
2463
    {
2464
        if (!is_numeric($id)
2465
            && !is_numeric($userId)
2466
            && !is_string($text)
2467
            && !is_string($lang)
2468
        ) {
2469
            return false;
2470
        }
2471
2472
        $query = sprintf(
2473
            "INSERT INTO
2474
                %sfaqchanges
2475
            (id, beitrag, lang, revision_id, usr, datum, what)
2476
                VALUES
2477
            (%d, %d, '%s', %d, %d, %d, '%s')",
2478
            Db::getTablePrefix(),
2479
            $this->config->getDb()->nextId(Db::getTablePrefix().'faqchanges', 'id'),
2480
            $id,
2481
            $lang,
2482
            $revision_id,
2483
            $userId,
2484
            $_SERVER['REQUEST_TIME'],
2485
            $text);
2486
2487
        $this->config->getDb()->query($query);
2488
2489
        return true;
2490
    }
2491
2492
    /**
2493
     * Returns the changelog of a FAQ record.
2494
     *
2495
     * @param int $recordId
2496
     *
2497
     * @return array
2498
     */
2499 View Code Duplication
    public function getChangeEntries($recordId)
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...
2500
    {
2501
        $entries = [];
2502
2503
        $query = sprintf('
2504
            SELECT
2505
                DISTINCT revision_id, usr, datum, what
2506
            FROM
2507
                %sfaqchanges
2508
            WHERE
2509
                beitrag = %d
2510
            ORDER BY revision_id, datum DESC',
2511
            Db::getTablePrefix(),
2512
            $recordId
2513
        );
2514
2515
        if ($result = $this->config->getDb()->query($query)) {
2516
            while ($row = $this->config->getDb()->fetchObject($result)) {
2517
                $entries[] = array(
2518
                    'revision_id' => $row->revision_id,
2519
                    'user' => $row->usr,
2520
                    'date' => $row->datum,
2521
                    'changelog' => $row->what,
2522
                );
2523
            }
2524
        }
2525
2526
        return $entries;
2527
    }
2528
2529
    /**
2530
     * Retrieve faq records according to the constraints provided.
2531
     *
2532
     * @param string $queryType
2533
     * @param int $nCatid
2534
     * @param bool $bDownwards
2535
     * @param string $lang
2536
     * @param string $date
2537
     *
2538
     * @return array
2539
     */
2540
    public function get($queryType = FAQ_QUERY_TYPE_DEFAULT, $nCatid = 0, $bDownwards = true, $lang = '', $date = '')
2541
    {
2542
        $faqs = [];
2543
2544
        $result = $this->config->getDb()->query($this->getSQLQuery($queryType, $nCatid, $bDownwards, $lang, $date));
2545
2546
        if ($this->config->getDb()->numRows($result) > 0) {
2547
            $i = 0;
2548
            while ($row = $this->config->getDb()->fetchObject($result)) {
2549
                $faq = [];
2550
                $faq['id'] = $row->id;
2551
                $faq['solution_id'] = $row->solution_id;
2552
                $faq['revision_id'] = $row->revision_id;
2553
                $faq['lang'] = $row->lang;
2554
                $faq['category_id'] = $row->category_id;
2555
                $faq['active'] = $row->active;
2556
                $faq['sticky'] = $row->sticky;
2557
                $faq['keywords'] = $row->keywords;
2558
                $faq['topic'] = $row->thema;
2559
                $faq['content'] = $row->content;
2560
                $faq['author_name'] = $row->author;
2561
                $faq['author_email'] = $row->email;
2562
                $faq['comment_enable'] = $row->comment;
2563
                $faq['lastmodified'] = $row->updated;
2564
                $faq['hits'] = $row->visits;
2565
                $faq['hits_last'] = $row->last_visit;
2566
                $faq['notes'] = $row->notes;
2567
                $faqs[$i] = $faq;
2568
                ++$i;
2569
            }
2570
        }
2571
2572
        return $faqs;
2573
    }
2574
2575
    /**
2576
     * Build the SQL query for retrieving faq records according to the constraints provided.
2577
     *
2578
     * @param string $queryType
2579
     * @param integer $categoryId
2580
     * @param boolean $bDownwards
2581
     * @param string $lang
2582
     * @param string $date
2583
     * @param $faqId
2584
     *
2585
     * @return string
2586
     */
2587
    private function getSQLQuery($queryType, $categoryId, $bDownwards, $lang, $date, $faqId = 0)
2588
    {
2589
        $now = date('YmdHis');
2590
        $query = sprintf("
2591
            SELECT
2592
                fd.id AS id,
2593
                fd.solution_id AS solution_id,
2594
                fd.revision_id AS revision_id,
2595
                fd.lang AS lang,
2596
                fcr.category_id AS category_id,
2597
                fd.active AS active,
2598
                fd.sticky AS sticky,
2599
                fd.keywords AS keywords,
2600
                fd.thema AS thema,
2601
                fd.content AS content,
2602
                fd.author AS author,
2603
                fd.email AS email,
2604
                fd.comment AS comment,
2605
                fd.updated AS updated,
2606
                fd.notes AS notes,
2607
                fv.visits AS visits,
2608
                fv.last_visit AS last_visit
2609
            FROM
2610
                %sfaqdata fd,
2611
                %sfaqvisits fv,
2612
                %sfaqcategoryrelations fcr
2613
            WHERE
2614
                fd.id = fcr.record_id
2615
            AND
2616
                fd.lang = fcr.record_lang
2617
            AND
2618
                fd.date_start <= '%s'
2619
            AND
2620
                fd.date_end   >= '%s'
2621
            AND ",
2622
            Db::getTablePrefix(),
2623
            Db::getTablePrefix(),
2624
            Db::getTablePrefix(),
2625
            $now,
2626
            $now);
2627
        // faqvisits data selection
2628
        if (!empty($faqId)) {
2629
            // Select ONLY the faq with the provided $faqid
2630
            $query .= "fd.id = '".$faqId."' AND ";
2631
        }
2632
        $query .= 'fd.id = fv.id
2633
            AND
2634
                fd.lang = fv.lang';
2635
        $needAndOp = true;
2636
        if ((!empty($categoryId)) && is_int($categoryId) && $categoryId > 0) {
2637
            if ($needAndOp) {
2638
                $query .= ' AND';
2639
            }
2640
            $query .= ' (fcr.category_id = '.$categoryId;
2641
            if ($bDownwards) {
2642
                $query .= $this->getCatidWhereSequence($categoryId, 'OR');
2643
            }
2644
            $query .= ')';
2645
            $needAndOp = true;
2646
        }
2647 View Code Duplication
        if ((!empty($date)) && Utils::isLikeOnPMFDate($date)) {
2648
            if ($needAndOp) {
2649
                $query .= ' AND';
2650
            }
2651
            $query .= " fd.updated LIKE '".$date."'";
2652
            $needAndOp = true;
2653
        }
2654 View Code Duplication
        if ((!empty($lang)) && Utils::isLanguage($lang)) {
2655
            if ($needAndOp) {
2656
                $query .= ' AND';
2657
            }
2658
            $query .= " fd.lang = '".$lang."'";
2659
            $needAndOp = true;
2660
        }
2661
        switch ($queryType) {
2662
            case FAQ_QUERY_TYPE_APPROVAL:
2663
                if ($needAndOp) {
2664
                    $query .= ' AND';
2665
                }
2666
                $query .= " fd.active = '".FAQ_SQL_ACTIVE_NO."'";
2667
                break;
2668
            case FAQ_QUERY_TYPE_EXPORT_PDF:
2669
            case FAQ_QUERY_TYPE_EXPORT_XHTML:
2670
            case FAQ_QUERY_TYPE_EXPORT_XML:
2671
                if ($needAndOp) {
2672
                    $query .= ' AND';
2673
                }
2674
                $query .= " fd.active = '".FAQ_SQL_ACTIVE_YES."'";
2675
                break;
2676
            default:
2677
                if ($needAndOp) {
2678
                    $query .= ' AND';
2679
                }
2680
                $query .= " fd.active = '".FAQ_SQL_ACTIVE_YES."'";
2681
                break;
2682
        }
2683
        // Sort criteria
2684
        switch ($queryType) {
2685
            case FAQ_QUERY_TYPE_EXPORT_PDF:
2686
            case FAQ_QUERY_TYPE_EXPORT_XHTML:
2687
            case FAQ_QUERY_TYPE_EXPORT_XML:
2688
                $query .= "\nORDER BY fcr.category_id, fd.id";
2689
                break;
2690
            case FAQ_QUERY_TYPE_RSS_LATEST:
2691
                $query .= "\nORDER BY fd.updated DESC";
2692
                break;
2693
            default:
2694
                // Normal ordering
2695
                $query .= "\nORDER BY fcr.category_id, fd.id";
2696
                break;
2697
        }
2698
2699
        return $query;
2700
    }
2701
2702
    /**
2703
     * Build a logic sequence, for a WHERE statement, of those category IDs
2704
     * children of the provided category ID, if any.
2705
     *
2706
     * @param   integer $nCatid
2707
     * @param   $logicOp
2708
     * @param   $oCat
2709
     *
2710
     * @return string
2711
     */
2712
    private function getCatidWhereSequence($nCatid, $logicOp = 'OR', $oCat = null)
2713
    {
2714
        $sqlWhereFilter = '';
2715
2716
        if (!isset($oCat)) {
2717
            $oCat = new Category($this->config);
2718
        }
2719
        $aChildren = array_values($oCat->getChildren($nCatid));
2720
2721
        foreach ($aChildren as $catid) {
2722
            $sqlWhereFilter .= ' '.$logicOp.' fcr.category_id = '.$catid;
2723
            $sqlWhereFilter .= $this->getCatidWhereSequence($catid, 'OR', $oCat);
2724
        }
2725
2726
        return $sqlWhereFilter;
2727
    }
2728
2729
    /**
2730
     * Adds the record permissions for users and groups.
2731
     *
2732
     * @param string $mode 'group' or 'user'
2733
     * @param int $recordId ID of the current record
2734
     * @param array $ids Array of group or user IDs
2735
     *
2736
     * @return bool
2737
     */
2738
    public function addPermission($mode, $recordId, $ids)
2739
    {
2740
        if ('user' !== $mode && 'group' !== $mode) {
2741
            return false;
2742
        }
2743
2744
        foreach ($ids as $id) {
2745
            $query = sprintf('
2746
            INSERT INTO
2747
                %sfaqdata_%s
2748
            (record_id, %s_id)
2749
                VALUES
2750
            (%d, %d)',
2751
                Db::getTablePrefix(),
2752
                $mode,
2753
                $mode,
2754
                $recordId,
2755
                $id
2756
            );
2757
2758
            $this->config->getDb()->query($query);
2759
        }
2760
2761
        return true;
2762
    }
2763
2764
    /**
2765
     * Deletes the record permissions for users and groups.
2766
     *
2767
     * @param string $mode 'group' or 'user'
2768
     * @param int $record_id ID of the current record
2769
     *
2770
     * @return bool
2771
     *
2772
     * @author  Thorsten Rinne <[email protected]>
2773
     */
2774 View Code Duplication
    public function deletePermission($mode, $record_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...
2775
    {
2776
        if (!($mode == 'user' || $mode == 'group')) {
2777
            return false;
2778
        }
2779
        if (!is_int($record_id)) {
2780
            return false;
2781
        }
2782
2783
        $query = sprintf('
2784
            DELETE FROM
2785
                %sfaqdata_%s
2786
            WHERE
2787
                record_id = %d',
2788
            Db::getTablePrefix(),
2789
            $mode,
2790
            $record_id);
2791
        $this->config->getDb()->query($query);
2792
2793
        return true;
2794
    }
2795
2796
    /**
2797
     * Returns the record permissions for users and groups.
2798
     *
2799
     * @param string $mode 'group' or 'user'
2800
     * @param int $recordId
2801
     *
2802
     * @return array
2803
     */
2804
    public function getPermission($mode, $recordId)
2805
    {
2806
        $permissions = [];
2807
2808
        if (!($mode == 'user' || $mode == 'group')) {
2809
            return $permissions;
2810
        }
2811
2812
        $query = sprintf('
2813
            SELECT
2814
                %s_id AS permission
2815
            FROM
2816
                %sfaqdata_%s
2817
            WHERE
2818
                record_id = %d',
2819
            $mode,
2820
            Db::getTablePrefix(),
2821
            $mode,
2822
            (int)$recordId);
2823
2824
        $result = $this->config->getDb()->query($query);
2825
2826
        if ($this->config->getDb()->numRows($result) > 0) {
2827
            while (($row = $this->config->getDb()->fetchObject($result))) {
2828
                $permissions[] = (int)$row->permission;
2829
            }
2830
        }
2831
2832
        return $permissions;
2833
    }
2834
2835
    /**
2836
     * Returns all records of one category.
2837
     *
2838
     * @param int $categoryId
2839
     *
2840
     * @return string
2841
     */
2842
    public function getRecordsWithoutPagingByCategoryId(int $categoryId): string
2843
    {
2844
        global $sids;
2845
2846
        $output = '';
2847
        $now = date('YmdHis');
2848
        $query = sprintf("
2849
            SELECT
2850
                fd.id AS id,
2851
                fd.lang AS lang,
2852
                fd.thema AS thema,
2853
                fcr.category_id AS category_id,
2854
                fv.visits AS visits
2855
            FROM
2856
                %sfaqdata fd
2857
            LEFT JOIN
2858
                %sfaqcategoryrelations fcr
2859
            ON
2860
                fd.id = fcr.record_id
2861
            AND
2862
                fd.lang = fcr.record_lang
2863
            LEFT JOIN
2864
                %sfaqvisits fv
2865
            ON
2866
                fd.id = fv.id
2867
            AND
2868
                fv.lang = fd.lang
2869
            LEFT JOIN
2870
                %sfaqdata_group fdg
2871
            ON
2872
                fd.id = fdg.record_id
2873
            LEFT JOIN
2874
                %sfaqdata_user fdu
2875
            ON
2876
                fd.id = fdu.record_id
2877
            WHERE
2878
                fd.date_start <= '%s'
2879
            AND
2880
                fd.date_end   >= '%s'
2881
            AND
2882
                fd.active = 'yes'
2883
            AND
2884
                fcr.category_id = %d
2885
            AND
2886
                fd.lang = '%s'
2887
                %s
2888
            GROUP BY
2889
                fd.id,fd.lang,fcr.category_id,fv.visits
2890
            ORDER BY
2891
                %s %s",
2892
            Db::getTablePrefix(),
2893
            Db::getTablePrefix(),
2894
            Db::getTablePrefix(),
2895
            Db::getTablePrefix(),
2896
            Db::getTablePrefix(),
2897
            $now,
2898
            $now,
2899
            $categoryId,
2900
            $this->config->getLanguage()->getLanguage(),
2901
            $this->queryPermission($this->groupSupport),
2902
            $this->config->get('records.orderby'),
2903
            $this->config->get('records.sortby')
2904
        );
2905
2906
        $result = $this->config->getDb()->query($query);
2907
2908
        if ($result) {
2909
            $output = '<ul>';
2910
            while (($row = $this->config->getDb()->fetchObject($result))) {
2911
                $title = $row->thema;
2912
                $url = sprintf(
2913
                    '%s?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
2914
                    Link::getSystemRelativeUri(),
2915
                    $sids,
2916
                    $row->category_id,
2917
                    $row->id,
2918
                    $row->lang
2919
                );
2920
2921
                $oLink = new Link($url, $this->config);
2922
                $oLink->itemTitle = $row->thema;
2923
                $oLink->text = $title;
2924
                $oLink->tooltip = $title;
2925
                $listItem = '<li>'.$oLink->toHtmlAnchor().'</li>';
2926
2927
                $output .= $listItem;
2928
            }
2929
            $output .= '</ul>';
2930
        }
2931
2932
        return $output;
2933
    }
2934
2935
    /**
2936
     * Prints the open questions as a XHTML table.
2937
     *
2938
     * @return string
2939
     */
2940
    public function renderOpenQuestions(): string
2941
    {
2942
        global $sids, $category;
2943
2944
        $date = new Date($this->config);
2945
        $mail = new Mail($this->config);
2946
2947
        $query = sprintf("
2948
            SELECT
2949
                COUNT(id) AS num
2950
            FROM
2951
                %sfaqquestions
2952
            WHERE
2953
                lang = '%s'
2954
            AND
2955
                is_visible != 'Y'",
2956
            Db::getTablePrefix(),
2957
            $this->config->getLanguage()->getLanguage()
2958
        );
2959
2960
        $result = $this->config->getDb()->query($query);
2961
        $row = $this->config->getDb()->fetchObject($result);
2962
        $numOfInvisibles = $row->num;
2963
2964
        if ($numOfInvisibles > 0) {
2965
            $extraout = sprintf(
2966
                '<tr><td colspan="3"><small>%s %s</small></td></tr>',
2967
                $this->translation['msgQuestionsWaiting'],
2968
                $numOfInvisibles
2969
            );
2970
        } else {
2971
            $extraout = '';
2972
        }
2973
2974
        $query = sprintf("
2975
            SELECT
2976
                *
2977
            FROM
2978
                %sfaqquestions
2979
            WHERE
2980
                lang = '%s'
2981
            AND
2982
                is_visible = 'Y'
2983
            ORDER BY
2984
                created ASC",
2985
            Db::getTablePrefix(),
2986
            $this->config->getLanguage()->getLanguage()
2987
        );
2988
2989
        $result = $this->config->getDb()->query($query);
2990
        $output = '';
2991
2992
        if ($result && $this->config->getDb()->numRows($result) > 0) {
2993
            while ($row = $this->config->getDb()->fetchObject($result)) {
2994
                $output .= '<tr class="openquestions">';
2995
                $output .= sprintf(
2996
                    '<td><small>%s</small><br /><a href="mailto:%s">%s</a></td>',
2997
                    $date->format(Date::createIsoDate($row->created)),
2998
                    $mail->safeEmail($row->email),
2999
                    $row->username
3000
                );
3001
                $output .= sprintf(
3002
                    '<td><strong>%s:</strong><br />%s</td>',
3003
                    isset($category->categoryName[$row->category_id]['name']) ? $category->categoryName[$row->category_id]['name'] : '',
3004
                    strip_tags($row->question)
3005
                );
3006
                if ($this->config->get('records.enableCloseQuestion') && $row->answer_id) {
3007
                    $output .= sprintf(
3008
                        '<td><a id="PMF_openQuestionAnswered" href="?%saction=faq&amp;cat=%d&amp;id=%d">%s</a></td>',
3009
                        $sids,
3010
                        $row->category_id,
3011
                        $row->answer_id,
3012
                        $this->translation['msg2answerFAQ']
3013
                    );
3014
                } else {
3015
                    $output .= sprintf(
3016
                        '<td><a class="btn btn-primary" href="?%saction=add&amp;question=%d&amp;cat=%d">%s</a></td>',
3017
                        $sids,
3018
                        $row->id,
3019
                        $row->category_id,
3020
                        $this->translation['msg2answer']
3021
                    );
3022
                }
3023
                $output .= '</tr>';
3024
            }
3025
        } else {
3026
            $output = sprintf(
3027
                '<tr><td colspan="3">%s</td></tr>',
3028
                $this->translation['msgNoQuestionsAvailable']
3029
            );
3030
        }
3031
3032
        return $output.$extraout;
3033
    }
3034
3035
    /**
3036
     * Set or unset a faq item flag.
3037
     *
3038
     * @param int $id Record id
3039
     * @param string $lang language code which is valid with Language::isASupportedLanguage
3040
     * @param bool $flag record is set to sticky or not
3041
     * @param string $type type of the flag to set, use the column name
3042
     *
3043
     * @return bool
3044
     */
3045
    public function updateRecordFlag($id, $lang, $flag, $type)
3046
    {
3047
        $retval = false;
3048
3049
        switch ($type) {
3050
            case 'sticky':
3051
                $flag = ($flag === 'checked' ? 1 : 0);
3052
                break;
3053
3054
            case 'active':
3055
                $flag = ($flag === 'checked' ? "'yes'" : "'no'");
3056
                break;
3057
3058
            default:
3059
                // This is because we would run into unknown db column
3060
                $flag = null;
3061
                break;
3062
        }
3063
3064
        if (null !== $flag) {
3065
            $update = sprintf("
3066
                UPDATE 
3067
                    %sfaqdata 
3068
                SET 
3069
                    %s = %s 
3070
                WHERE 
3071
                    id = %d 
3072
                AND 
3073
                    lang = '%s'",
3074
                Db::getTablePrefix(),
3075
                $type,
3076
                $flag,
3077
                $id,
3078
                $lang
3079
            );
3080
3081
            $retval = (bool)$this->config->getDb()->query($update);
3082
        }
3083
3084
        return $retval;
3085
    }
3086
3087
    /**
3088
     * Prepares and returns the sticky records for the frontend.
3089
     *
3090
     * @return array
3091
     */
3092
    public function getStickyRecords()
3093
    {
3094
        $result = $this->getStickyRecordsData();
3095
        $output = [];
3096
3097
        if (count($result) > 0) {
3098
            foreach ($result as $row) {
3099
                $output['title'][] = Utils::makeShorterText($row['thema'], 8);
3100
                $output['preview'][] = $row['thema'];
3101
                $output['url'][] = $row['url'];
3102
            }
3103
        } else {
3104
            $output['error'] = sprintf('<li>%s</li>', $this->translation['err_noTopTen']);
3105
        }
3106
3107
        return $output;
3108
    }
3109
3110
    /**
3111
     * Returns the sticky records with URL and Title.
3112
     *
3113
     * @return array
3114
     */
3115
    private function getStickyRecordsData()
3116
    {
3117
        global $sids;
3118
3119
        $now = date('YmdHis');
3120
        $query = sprintf("
3121
            SELECT
3122
                fd.id AS id,
3123
                fd.lang AS lang,
3124
                fd.thema AS thema,
3125
                fcr.category_id AS category_id,
3126
                fv.visits AS visits
3127
            FROM
3128
                %sfaqvisits fv,
3129
                %sfaqdata fd
3130
            LEFT JOIN
3131
                %sfaqcategoryrelations fcr
3132
            ON
3133
                fd.id = fcr.record_id
3134
            AND
3135
                fd.lang = fcr.record_lang
3136
            LEFT JOIN
3137
                %sfaqdata_group AS fdg
3138
            ON
3139
                fd.id = fdg.record_id
3140
            LEFT JOIN
3141
                %sfaqdata_user AS fdu
3142
            ON
3143
                fd.id = fdu.record_id
3144
            WHERE
3145
                fd.lang = '%s'
3146
            AND 
3147
                fd.date_start <= '%s'
3148
            AND 
3149
                fd.date_end   >= '%s'
3150
            AND 
3151
                fd.active = 'yes'
3152
            AND 
3153
                fd.sticky = 1
3154
            AND
3155
                fd.id = fv.id
3156
            AND 
3157
                fd.lang = fv.lang
3158
            %s
3159
            GROUP BY
3160
                fd.id, fd.lang, fd.thema, fcr.category_id, fv.visits
3161
            ORDER BY
3162
                fv.visits DESC",
3163
            Db::getTablePrefix(),
3164
            Db::getTablePrefix(),
3165
            Db::getTablePrefix(),
3166
            Db::getTablePrefix(),
3167
            Db::getTablePrefix(),
3168
            $this->config->getLanguage()->getLanguage(),
3169
            $now,
3170
            $now,
3171
            $this->queryPermission($this->groupSupport)
3172
        );
3173
3174
        $result = $this->config->getDb()->query($query);
3175
        $sticky = [];
3176
        $data = [];
3177
3178
        $oldId = 0;
3179
        while (($row = $this->config->getDb()->fetchObject($result))) {
3180
            if ($oldId != $row->id) {
3181
                $data['thema'] = $row->thema;
3182
3183
                $title = $row->thema;
3184
                $url = sprintf(
3185
                    '%s?%saction=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s',
3186
                    Link::getSystemRelativeUri(),
3187
                    $sids,
3188
                    $row->category_id,
3189
                    $row->id,
3190
                    $row->lang
3191
                );
3192
                $oLink = new Link($url, $this->config);
3193
                $oLink->itemTitle = $row->thema;
3194
                $oLink->tooltip = $title;
3195
                $data['url'] = $oLink->toString();
3196
3197
                $sticky[] = $data;
3198
            }
3199
            $oldId = $row->id;
3200
        }
3201
3202
        return $sticky;
3203
    }
3204
3205
    /**
3206
     * Returns the inactive records with admin URL to edit the FAQ and title.
3207
     *
3208
     * @return array
3209
     */
3210
    public function getInactiveFaqsData()
3211
    {
3212
        $query = sprintf("
3213
            SELECT
3214
                fd.id AS id,
3215
                fd.lang AS lang,
3216
                fd.thema AS thema
3217
            FROM
3218
                %sfaqdata fd
3219
            WHERE
3220
                fd.lang = '%s'
3221
            AND 
3222
                fd.active = 'no'
3223
            GROUP BY
3224
                fd.id, fd.lang, fd.thema
3225
            ORDER BY
3226
                fd.id DESC",
3227
            Db::getTablePrefix(),
3228
            $this->config->getLanguage()->getLanguage()
3229
        );
3230
3231
        $result = $this->config->getDb()->query($query);
3232
        $inactive = [];
3233
        $data = [];
3234
3235
        $oldId = 0;
3236
        while (($row = $this->config->getDb()->fetchObject($result))) {
3237
            if ($oldId != $row->id) {
3238
                $data['question'] = $row->thema;
3239
                $data['url'] = sprintf(
3240
                    '%s?action=editentry&id=%d&lang=%s',
3241
                    Link::getSystemRelativeUri(),
3242
                    $row->id,
3243
                    $row->lang
3244
                );
3245
                $inactive[] = $data;
3246
            }
3247
            $oldId = $row->id;
3248
        }
3249
3250
        return $inactive;
3251
    }
3252
3253
    /**
3254
     * Updates field answer_id in faqquestion.
3255
     *
3256
     * @param int $openQuestionId
3257
     * @param int $faqId
3258
     * @param int $categoryId
3259
     *
3260
     * @return bool
3261
     */
3262 View Code Duplication
    public function updateQuestionAnswer($openQuestionId, $faqId, $categoryId)
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...
3263
    {
3264
        $query = sprintf(
3265
            'UPDATE %sfaqquestions SET answer_id = %d, category_id= %d WHERE id= %d',
3266
            Db::getTablePrefix(),
3267
            $faqId,
3268
            $categoryId,
3269
            $openQuestionId
3270
        );
3271
3272
        return $this->config->getDb()->query($query);
3273
    }
3274
}
3275