Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
66.67% covered (warning)
66.67%
24 / 36
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
StopWordController
66.67% covered (warning)
66.67%
24 / 36
33.33% covered (danger)
33.33%
1 / 3
19.26
0.00% covered (danger)
0.00%
0 / 1
 list
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 delete
81.82% covered (success)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
4.10
 save
44.44% covered (danger)
44.44%
8 / 18
0.00% covered (danger)
0.00%
0 / 1
15.40
1<?php
2
3/**
4 * The Admin Stop Word 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 2023-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     2023-10-28
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Controller\Administration\Api;
21
22use phpMyFAQ\Controller\AbstractController;
23use phpMyFAQ\Core\Exception;
24use phpMyFAQ\Enums\PermissionType;
25use phpMyFAQ\Filter;
26use phpMyFAQ\Language;
27use phpMyFAQ\Session\Token;
28use phpMyFAQ\StopWords;
29use phpMyFAQ\Translation;
30use Symfony\Component\HttpFoundation\JsonResponse;
31use Symfony\Component\HttpFoundation\Request;
32use Symfony\Component\HttpFoundation\Response;
33use Symfony\Component\Routing\Attribute\Route;
34
35final class StopWordController extends AbstractController
36{
37    #[Route(path: 'stopwords', name: 'admin.api.stopwords', methods: ['GET'])]
38    public function list(Request $request): JsonResponse
39    {
40        $this->userHasPermission(PermissionType::CONFIGURATION_EDIT);
41
42        $language = Filter::filterVar($request->query->get('language'), FILTER_SANITIZE_SPECIAL_CHARS);
43
44        $stopWords = new StopWords($this->configuration);
45        if (Language::isASupportedLanguage($language)) {
46            $stopWordsList = $stopWords->getByLang($language);
47            return $this->json($stopWordsList, Response::HTTP_OK);
48        }
49
50        return $this->json(['error' => 'Language not supported'], Response::HTTP_BAD_REQUEST);
51    }
52
53    #[Route(path: 'stopword/delete', name: 'admin.api.stopword.delete', methods: ['DELETE'])]
54    public function delete(Request $request): JsonResponse
55    {
56        $this->userHasPermission(PermissionType::CONFIGURATION_EDIT);
57
58        $data = $this->getJsonObject($request);
59
60        $stopWordId = Filter::filterVar($data->stopWordId ?? null, FILTER_VALIDATE_INT);
61        $stopWordsLang = Filter::filterVar($data->stopWordsLang ?? '', FILTER_SANITIZE_SPECIAL_CHARS, '');
62
63        $stopWords = new StopWords($this->configuration);
64        if (!Token::getInstance($this->session)->verifyToken('stopwords', (string) ($data->csrf ?? ''))) {
65            return $this->json(['error' => Translation::get(key: 'msgNoPermission')], Response::HTTP_UNAUTHORIZED);
66        }
67
68        if (null !== $stopWordId && Language::isASupportedLanguage($stopWordsLang)) {
69            $stopWords->setLanguage($stopWordsLang)->remove((int) $stopWordId);
70            return $this->json(['deleted' => $stopWordId], Response::HTTP_OK);
71        }
72
73        return $this->json(['error' => 'Language not supported'], Response::HTTP_BAD_REQUEST);
74    }
75
76    /**
77     * @throws \Exception
78     */
79    #[Route(path: 'stopword/save', name: 'admin.api.stopword.save', methods: ['POST'])]
80    public function save(Request $request): JsonResponse
81    {
82        $this->userHasPermission(PermissionType::CONFIGURATION_EDIT);
83
84        $data = $this->getJsonObject($request);
85
86        $stopWordId = Filter::filterVar($data->stopWordId ?? null, FILTER_VALIDATE_INT);
87        $stopWordsLang = Filter::filterVar($data->stopWordsLang ?? '', FILTER_SANITIZE_SPECIAL_CHARS, '');
88        $stopWord = Filter::filterVar($data->stopWord ?? null, FILTER_SANITIZE_SPECIAL_CHARS);
89
90        $stopWords = new StopWords($this->configuration);
91        if (!Token::getInstance($this->session)->verifyToken('stopwords', (string) ($data->csrf ?? ''))) {
92            return $this->json(['error' => Translation::get(key: 'msgNoPermission')], Response::HTTP_UNAUTHORIZED);
93        }
94
95        if (null !== $stopWord && Language::isASupportedLanguage($stopWordsLang)) {
96            $stopWords->setLanguage($stopWordsLang);
97
98            if (null !== $stopWordId && -1 < $stopWordId) {
99                $stopWords->update((int) $stopWordId, $stopWord);
100                return $this->json(['updated' => $stopWordId], Response::HTTP_OK);
101            }
102
103            if (!$stopWords->match($stopWord)) {
104                $stopWordId = $stopWords->add($stopWord);
105                return $this->json(['added' => $stopWordId], Response::HTTP_CREATED);
106            }
107
108            return $this->json(['error' => 'Stop word already exists'], Response::HTTP_BAD_REQUEST);
109        }
110
111        return $this->json(['error' => 'Language not supported'], Response::HTTP_BAD_REQUEST);
112    }
113}