@@ -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 ,
0 commit comments