Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
FormsController
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
3 / 3
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 translate
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3/**
4 * The Administration Forms Controller
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2024-2026 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2024-12-27
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Controller\Administration;
21
22use phpMyFAQ\Core\Exception;
23use phpMyFAQ\Enums\Forms\FormIds;
24use phpMyFAQ\Enums\PermissionType;
25use phpMyFAQ\Filter;
26use phpMyFAQ\Forms;
27use phpMyFAQ\Language\LanguageCodes;
28use phpMyFAQ\Session\Token;
29use phpMyFAQ\Translation;
30use Symfony\Component\HttpFoundation\Request;
31use Symfony\Component\HttpFoundation\Response;
32use Symfony\Component\Routing\Attribute\Route;
33use Twig\Error\LoaderError;
34use Twig\TwigFilter;
35
36final class FormsController extends AbstractAdministrationController
37{
38    public function __construct(
39        private readonly Forms $forms,
40    ) {
41        parent::__construct();
42    }
43
44    /**
45     * @throws Exception
46     * @throws LoaderError
47     * @throws \Exception
48     */
49    #[Route(path: '/forms', name: 'admin.forms', methods: ['GET'])]
50    public function index(Request $request): Response
51    {
52        $this->userHasPermission(PermissionType::FORMS_EDIT);
53
54        return $this->render('@admin/configuration/forms.twig', [
55            ...$this->getHeader($request),
56            ...$this->getFooter(),
57            'formDataAskQuestion' => $this->forms->getFormData(FormIds::ASK_QUESTION->value),
58            'formDataAddContent' => $this->forms->getFormData(FormIds::ADD_NEW_FAQ->value),
59            'csrfActivate' => Token::getInstance($this->session)->getTokenString('activate-input'),
60            'csrfRequired' => Token::getInstance($this->session)->getTokenString('require-input'),
61            'ad_entry_id' => Translation::get(key: 'ad_entry_id'),
62            'ad_entry_active' => Translation::get(key: 'ad_entry_active'),
63            'ad_categ_translate' => Translation::get(key: 'ad_categ_translate'),
64            'msgHintDeactivateForms' => Translation::get(key: 'msgHintDeactivateForms'),
65        ]);
66    }
67
68    /**
69     * @throws Exception
70     * @throws LoaderError
71     * @throws \Exception
72     */
73    #[Route(path: '/forms/translate/{formId}/{inputId}', name: 'admin.forms.translate', methods: ['GET'])]
74    public function translate(Request $request): Response
75    {
76        $this->userHasPermission(PermissionType::FORMS_EDIT);
77
78        $formId = (int) Filter::filterVar($request->attributes->get('formId'), FILTER_VALIDATE_INT);
79        $inputId = (int) Filter::filterVar($request->attributes->get('inputId'), FILTER_VALIDATE_INT);
80
81        // Get supported languages for adding new translations
82        $languages = [];
83        $translatedLanguages = $this->forms->getTranslatedLanguages($formId, $inputId);
84        foreach (LanguageCodes::getAllSupported() as $code => $language) {
85            if (in_array($code, $translatedLanguages, strict: true)) {
86                continue;
87            }
88
89            $languages[] = $language;
90        }
91
92        // Twig filter for language codes
93        // Isn't separated as TwigExtension because of a special function and handling of 'default'
94        // value in this context
95        $twigFilter = new TwigFilter('languageCode', static function (string $string): ?string {
96            if ($string === 'default') {
97                return $string;
98            }
99
100            return LanguageCodes::get($string);
101        });
102
103        $this->addFilter($twigFilter);
104        return $this->render('@admin/configuration/forms.translations.twig', [
105            ...$this->getHeader($request),
106            ...$this->getFooter(),
107            'translations' => $this->forms->getTranslations($formId, $inputId),
108            'ad_sess_pageviews' => Translation::get(key: 'ad_sess_pageviews'),
109            'csrfTokenEditTranslation' => Token::getInstance($this->session)->getTokenString('edit-translation'),
110            'csrfTokenDeleteTranslation' => Token::getInstance($this->session)->getTokenString('delete-translation'),
111            'csrfTokenAddTranslation' => Token::getInstance($this->session)->getTokenString('add-translation'),
112            'languages' => $languages,
113            'formId' => $formId,
114            'inputId' => $inputId,
115        ]);
116    }
117}