Skip to content

Commit 9e35c99

Browse files
committed
fix: corrected URL schemes
1 parent 3fe7bd4 commit 9e35c99

File tree

7 files changed

+78
-42
lines changed

7 files changed

+78
-42
lines changed

phpmyfaq/src/phpMyFAQ/Bookmark/BookmarkFormatter.php

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,15 @@ public function format(object $bookmark): ?array
6666
$category = new Category($this->configuration);
6767
$categoryId = $category->getCategoryIdFromFaq((int) $faqData['id']);
6868

69-
$base = rtrim($this->configuration->getDefaultUrl(), characters: '/') . '/index.php';
70-
$query = http_build_query(
71-
[
72-
'action' => 'faq',
73-
'id' => (int) $faqData['id'],
74-
'cat' => $categoryId,
75-
'artlang' => $faqData['lang'] ?? '',
76-
],
77-
numeric_prefix: '',
78-
arg_separator: '&',
79-
encoding_type: PHP_QUERY_RFC3986,
69+
$url = sprintf(
70+
'%scontent/%d/%d/%s/%s.html',
71+
$this->configuration->getDefaultUrl(),
72+
$categoryId,
73+
(int) $faqData['id'],
74+
$faqData['lang'],
75+
Link\Util\TitleSlugifier::slug($faqData['title']),
8076
);
8177

82-
$url = $base . '?' . $query;
83-
8478
$link = new Link($url, $this->configuration);
8579
$title = (string) ($faqData['title'] ?? '');
8680
$link->text = Strings::htmlentities($title);

phpmyfaq/src/phpMyFAQ/Controller/Frontend/FaqController.php

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ final class FaqController extends AbstractFrontController
5252
/**
5353
* Displays the form to add a new FAQ
5454
*
55-
* @throws Exception|LoaderError
55+
* @throws Exception|LoaderError|\Exception
5656
*/
5757
#[Route(path: '/add-faq.html', name: 'public.faq.add', methods: ['GET'])]
5858
public function add(Request $request): Response
@@ -167,7 +167,51 @@ public function solution(Request $request): Response
167167
$slug = TitleSlugifier::slug($faqData['question']);
168168

169169
// Redirect to the canonical FAQ URL
170-
$url = sprintf('/faq/%d/%d/%s.html', $faqData['category_id'], $faqData['id'], $slug);
170+
$url = sprintf('/content/%d/%d/%s/%s.html', $faqData['category_id'], $faqData['id'], $faqData['lang'], $slug);
171+
172+
return new RedirectResponse($url, Response::HTTP_MOVED_PERMANENTLY);
173+
}
174+
175+
/**
176+
* Redirects short content URLs to the full FAQ page
177+
*
178+
* @throws Exception|\Exception
179+
*/
180+
#[Route(path: '/content/{faqId}/{faqLang}', name: 'public.faq.redirect', methods: ['GET'])]
181+
public function contentRedirect(Request $request): Response
182+
{
183+
$faqId = Filter::filterVar($request->attributes->get('faqId'), FILTER_VALIDATE_INT, 0);
184+
$faqLang = Filter::filterVar($request->attributes->get('faqLang'), FILTER_SANITIZE_SPECIAL_CHARS);
185+
186+
if ($faqId === 0 || empty($faqLang)) {
187+
return new Response('', Response::HTTP_NOT_FOUND);
188+
}
189+
190+
$faq = $this->container->get('phpmyfaq.faq');
191+
192+
// Query the FAQ data directly for the specified language
193+
$result = $faq->getFaqResult($faqId, $faqLang);
194+
195+
if ($this->configuration->getDb()->numRows($result) === 0) {
196+
return new Response('', Response::HTTP_NOT_FOUND);
197+
}
198+
199+
$row = $this->configuration->getDb()->fetchObject($result);
200+
if (!$row) {
201+
return new Response('', Response::HTTP_NOT_FOUND);
202+
}
203+
204+
$category = $this->container->get('phpmyfaq.category');
205+
$categoryId = $category->getCategoryIdFromFaq($faqId);
206+
207+
if ($categoryId === 0) {
208+
return new Response('', Response::HTTP_NOT_FOUND);
209+
}
210+
211+
$slug = TitleSlugifier::slug($row->thema);
212+
213+
// Redirect to the canonical FAQ URL
214+
$url = sprintf('/content/%d/%d/%s/%s.html', $categoryId, $faqId, $faqLang, $slug);
171215

172216
return new RedirectResponse($url, Response::HTTP_MOVED_PERMANENTLY);
173217
}
@@ -176,29 +220,28 @@ public function solution(Request $request): Response
176220
* Displays a single FAQ article with comments, ratings, and related content
177221
*
178222
* @throws Exception|LoaderError|\Exception
179-
*
180-
*
181223
*/
182-
#[Route(path: '/faq/{categoryId}/{faqId}/{slug}.html', name: 'public.faq.show', methods: ['GET'])]
224+
#[Route(path: '/content/{categoryId}/{faqId}/{faqLang}/{slug}.html', name: 'public.faq.show', methods: ['GET'])]
183225
public function show(Request $request): Response
184226
{
185227
$faqSession = $this->container->get('phpmyfaq.user.session');
186228
$faqSession->setCurrentUser($this->currentUser);
187229

188230
// Get parameters
189-
$cat = Filter::filterVar($request->attributes->get('categoryId'), FILTER_VALIDATE_INT, 0);
231+
$categoryId = Filter::filterVar($request->attributes->get('categoryId'), FILTER_VALIDATE_INT, 0);
190232

191233
// Get faqId from route attributes (new routes) or query parameters (legacy/backward compatibility)
192234
$faqId = Filter::filterVar($request->attributes->get('faqId'), FILTER_VALIDATE_INT);
193-
if (!$faqId) {
194-
$faqId = Filter::filterVar($request->query->get('id'), FILTER_VALIDATE_INT, 0);
195-
}
196235

197-
// Get language from route parameter (for /content/ URLs) or query parameter (for legacy URLs)
236+
// Get language from route parameter (for /content/ URLs)
198237
$requestedLanguage =
199-
$request->attributes->get('language') ?? $request->query->get('artlang') ?? $this->configuration
200-
->getLanguage()
201-
->getLanguage();
238+
Filter::filterVar(
239+
$request->attributes->get('language'),
240+
FILTER_SANITIZE_SPECIAL_CHARS,
241+
) ?? Filter::filterVar(
242+
$request->attributes->get('faqLang'),
243+
FILTER_SANITIZE_SPECIAL_CHARS,
244+
) ?? $this->configuration->getLanguage()->getLanguage();
202245

203246
// Temporarily set the language in session for this request
204247
$session = $this->container->get('session');
@@ -246,7 +289,7 @@ public function show(Request $request): Response
246289
$faqVisits->logViews($faqId);
247290

248291
// Check if category and FAQ are linked
249-
if (!$category->categoryHasLinkToFaq($faqId, $cat)) {
292+
if (!$category->categoryHasLinkToFaq($faqId, $categoryId)) {
250293
return new Response('', Response::HTTP_NOT_FOUND);
251294
}
252295

@@ -270,7 +313,7 @@ public function show(Request $request): Response
270313
$url = sprintf(
271314
'%scontent/%d/%d/%s/%s.html',
272315
$this->configuration->getDefaultUrl(),
273-
$cat,
316+
$categoryId,
274317
$faqId,
275318
$language,
276319
TitleSlugifier::slug($question),
@@ -300,7 +343,7 @@ public function show(Request $request): Response
300343

301344
// Services for social sharing
302345
$faqServices = new Services($this->configuration);
303-
$faqServices->setCategoryId($cat);
346+
$faqServices->setCategoryId($categoryId);
304347
$faqServices->setFaqId($faqId);
305348
$faqServices->setLanguage($this->configuration->getLanguage()->getLanguage());
306349
$faqServices->setQuestion($question);
@@ -333,7 +376,7 @@ public function show(Request $request): Response
333376
'metaDescription' => $seoData->getDescription(),
334377
'solutionId' => $faq->faqRecord['solution_id'],
335378
'solutionIdLink' => './solution_id_' . $faq->faqRecord['solution_id'] . '.html',
336-
'breadcrumb' => $category->getPathWithStartpage($cat, '/', true),
379+
'breadcrumb' => $category->getPathWithStartpage($categoryId, '/', true),
337380
'question' => $question,
338381
'answer' => $answer,
339382
'attachmentList' => $attachmentList,

phpmyfaq/src/phpMyFAQ/Service/McpServer/FaqSearchToolExecutor.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ private function formatResultsAsJson(array $results): string
143143

144144
private function buildFaqUrl(int $faqId, string $language): string
145145
{
146-
$baseUrl = $this->configuration->getDefaultUrl();
147-
return rtrim($baseUrl, '/') . '/index.php?action=faq&cat=0&id=' . $faqId . '&artlang=' . $language;
146+
return $this->configuration->getDefaultUrl() . 'content/' . $faqId . '/' . $language;
148147
}
149148
}

phpmyfaq/src/public-routes.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@
7575
'methods' => 'GET',
7676
],
7777
'public.faq.show' => [
78-
'path' => '/faq/{categoryId}/{faqId}/{slug}.html',
78+
'path' => '/content/{categoryId}/{faqId}/{language}/{slug}.html',
7979
'controller' => [FaqController::class, 'show'],
8080
'methods' => 'GET',
8181
],
82-
'public.content.show' => [
83-
'path' => '/content/{categoryId}/{faqId}/{language}/{slug}.html',
84-
'controller' => [FaqController::class, 'show'],
82+
'public.faq.redirect' => [
83+
'path' => '/content/{faqId}/{faqLang}',
84+
'controller' => [FaqController::class, 'contentRedirect'],
8585
'methods' => 'GET',
8686
],
8787
'public.forgot-password' => [

tests/phpMyFAQ/Bookmark/BookmarkFormatterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function testFormatValidBookmark(): void
6060
$this->assertArrayHasKey('id', $result);
6161
$this->assertArrayHasKey('answer', $result);
6262
$this->assertSame(1, $result['id']);
63-
$this->assertStringContainsString('index.php?action=faq', $result['url']);
63+
$this->assertStringContainsString('/content/', $result['url']);
6464
}
6565

6666
public function testFormatReturnsNullWhenFaqIdMissingOrInvalid(): void

tests/phpMyFAQ/Controller/Api/AttachmentControllerTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ public function testListWithAttachmentsFound(): void
134134

135135
$file1 = $this->createStub(File::class);
136136
$file1->method('getFilename')->willReturn('attachment-1.pdf');
137-
$file1->method('buildUrl')->willReturn('index.php?action=attachment&id=1');
137+
$file1->method('buildUrl')->willReturn('attachment/1');
138138

139139
$file2 = $this->createStub(File::class);
140140
$file2->method('getFilename')->willReturn('attachment-2.pdf');
141-
$file2->method('buildUrl')->willReturn('index.php?action=attachment&id=2');
141+
$file2->method('buildUrl')->willReturn('attachment/2');
142142

143143
$attachmentController = $this->createAttachmentControllerTestDouble([$file1, $file2]);
144144

@@ -149,11 +149,11 @@ public function testListWithAttachmentsFound(): void
149149
$expectedData = [
150150
[
151151
'filename' => 'attachment-1.pdf',
152-
'url' => 'https://www.example.org/index.php?action=attachment&id=1',
152+
'url' => 'https://www.example.org/attachment/1',
153153
],
154154
[
155155
'filename' => 'attachment-2.pdf',
156-
'url' => 'https://www.example.org/index.php?action=attachment&id=2',
156+
'url' => 'https://www.example.org/attachment/2',
157157
],
158158
];
159159

tests/phpMyFAQ/Service/McpServer/FaqSearchToolExecutorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function testCallWithResults(): void
9292
$this->assertSame(42, $jsonData['results'][0]['id']);
9393
$this->assertSame('What is phpMyFAQ?', $jsonData['results'][0]['question']);
9494
$this->assertStringContainsString(
95-
'https://example.com/index.php?action=faq&cat=0&id=42&artlang=en',
95+
'https://example.com/content/42/en',
9696
$jsonData['results'][0]['url'],
9797
);
9898
}

0 commit comments

Comments
 (0)