Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.33% covered (success)
83.33%
25 / 30
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
PdfController
83.33% covered (success)
83.33%
25 / 30
50.00% covered (danger)
50.00%
1 / 2
7.23
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
82.76% covered (success)
82.76%
24 / 29
0.00% covered (danger)
0.00%
0 / 1
6.18
1<?php
2
3declare(strict_types=1);
4
5/**
6 * PDF Controller
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 https://mozilla.org/MPL/2.0/.
11 *
12 * @package   phpMyFAQ
13 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
14 * @author    Peter Beauvain <pbeauvain@web.de>
15 * @author    Olivier Plathey <olivier@fpdf.org>
16 * @author    Krzysztof Kruszynski <thywolf@wolf.homelinux.net>
17 * @author    Matteo Scaramuccia <matteo@phpmyfaq.de>
18 * @copyright 2003-2026 phpMyFAQ Team
19 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
20 * @link      https://www.phpmyfaq.de
21 * @since     2003-02-12
22 */
23
24namespace phpMyFAQ\Controller\Frontend;
25
26use DateTime;
27use League\CommonMark\Exception\CommonMarkException;
28use phpMyFAQ\Attachment\AttachmentException;
29use phpMyFAQ\Attachment\AttachmentFactory;
30use phpMyFAQ\Category;
31use phpMyFAQ\Core\Exception;
32use phpMyFAQ\Export\Pdf;
33use phpMyFAQ\Faq;
34use phpMyFAQ\Filter;
35use phpMyFAQ\Helper\AttachmentHelper;
36use phpMyFAQ\Tags;
37use phpMyFAQ\User\CurrentUser;
38use Symfony\Component\HttpFoundation\RedirectResponse;
39use Symfony\Component\HttpFoundation\Request;
40use Symfony\Component\HttpFoundation\Response;
41use Symfony\Component\Routing\Attribute\Route;
42
43final class PdfController extends AbstractFrontController
44{
45    public function __construct(
46        private readonly Faq $faq,
47        private readonly Tags $tags,
48    ) {
49        parent::__construct();
50    }
51
52    /**
53     * @throws Exception|\Exception|CommonMarkException
54     */
55    #[Route(
56        path: '/pdf/{categoryId}/{faqId}/{faqLanguage}',
57        name: 'public.pdf.faq',
58        requirements: [
59            'categoryId' => '\d+',
60            'faqId' => '\d+',
61            'faqLanguage' => '[a-z]{2}(_[a-z]{2})?',
62        ],
63        methods: ['GET'],
64    )]
65    public function index(Request $request): Response
66    {
67        $categoryId = Filter::filterVar($request->attributes->get('categoryId'), FILTER_VALIDATE_INT);
68        $faqId = Filter::filterVar($request->attributes->get('faqId'), FILTER_VALIDATE_INT);
69        $faqLanguage = Filter::filterVar($request->attributes->get('faqLanguage'), FILTER_SANITIZE_SPECIAL_CHARS, '');
70
71        if ($categoryId === null || $faqId === null) {
72            return new RedirectResponse($this->configuration->getDefaultUrl());
73        }
74
75        [$currentUser, $currentGroups] = CurrentUser::getCurrentUserGroupId($this->currentUser);
76
77        $this->faq->setUser($currentUser);
78        $this->faq->setGroups($currentGroups);
79
80        $category = new Category($this->configuration, $currentGroups, true);
81        $category->setUser($currentUser);
82
83        $this->tags->setUser($currentUser)->setGroups($currentGroups);
84
85        $pdf = new Pdf($this->faq, $category, $this->configuration);
86
87        $this->faq->getFaq($faqId);
88
89        if (!$this->faq->isFaqRecordVisible()) {
90            return new Response('', Response::HTTP_NOT_FOUND);
91        }
92
93        $this->faq->faqRecord['category_id'] = $categoryId;
94
95        if (!$this->configuration->get('records.disableAttachments')) {
96            try {
97                $attachmentHelper = new AttachmentHelper();
98                $attList = AttachmentFactory::fetchByRecordId($this->configuration, $faqId);
99                $this->faq->faqRecord['attachmentList'] = $attachmentHelper->getAttachmentList($attList);
100            } catch (AttachmentException) {
101                $this->faq->faqRecord['attachmentList'] = '';
102            }
103        }
104
105        $filename = 'FAQ-' . $faqId . '-' . $faqLanguage . '.pdf';
106        $pdfFile = $pdf->generateFile($this->faq->faqRecord, $filename);
107
108        $response = new Response();
109        $response->setExpires(new DateTime());
110        $response->headers->set('Content-Type', 'application/pdf');
111        $response->setContent($pdfFile);
112
113        return $response;
114    }
115}