<?phpnamespace App\Services\Seo;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\DependencyInjection\ContainerInterface;use Twig\Environment;use App\Entity\Seo\Redirection;use Symfony\Component\HttpFoundation\RequestStack;class Redir{ private $em; private $container; private $twig; private RequestStack $requestStack; private array $redirectionCache = []; public function __construct(EntityManagerInterface $em, ContainerInterface $container, Environment $twig, RequestStack $requestStack ) { $this->em = $em; $this->container = $container; $this->twig = $twig; $this->requestStack = $requestStack; } public function getUrl($slug) { // Essayer d'abord avec le slug nettoyé classique $cleanSlug = $this->removeAppPath($slug); // Utiliser la nouvelle méthode de recherche avec variantes $query = $this->em->getRepository(Redirection::class)->findBySlugVariants($cleanSlug, true); // Si pas trouvé, essayer avec le slug original if (!$query) { $query = $this->em->getRepository(Redirection::class)->findBySlugVariants($slug, true); } if(!$query) { return false; } if($query->getUrl() == "/") { return $this->getBaseUrl(); } return $this->getBaseUrl().$query->getUrl(); } public function getType($slug) { $cleanSlug = $this->removeAppPath($slug); // Utiliser la même méthode pour la cohérence $query = $this->em->getRepository(Redirection::class)->findBySlugVariants($cleanSlug, true); if (!$query) { $query = $this->em->getRepository(Redirection::class)->findBySlugVariants($slug, true); } if(!$query) { return false; } return (int)$query->getType(); } /** * Obtenir la base d'URL * @return string */ private function getBaseUrl() { $appEnv = $this->container->get('router')->getContext()->getBaseUrl()."/"; if($appEnv != "/app_dev.php/") { $appEnv = "/"; } $hostName = $_SERVER['HTTP_HOST']; $protocol = "http"; if($_SERVER["HTTPS"] == "on") { $protocol = "https"; } return $protocol.'://'.$hostName.$appEnv; } /** * Obtenir la suppression de l'environnement de dev et de production apparaissant dans l'URL * @param $slug * @return array|string|string[] */ private function removeAppPath($slug) { $search = ['/app_dev.php/','/app.php/']; $replace = ['','']; $slug = str_replace($search, $replace, $slug); $firstLetter = substr($slug,0,1); if($firstLetter == "/") { $slug = substr($slug,1); } // Décoder l'URL pour convertir les caractères encodés $slug = urldecode($slug); // Normaliser tous les types de tirets $unicodeDashes = ['‐', '–', '—', '―']; $slug = str_replace($unicodeDashes, '-', $slug); return $slug; } /** * Transforme les liens href dans le contenu HTML en appliquant les redirections */ public function transformLinksInContent(string $content): string { // Regex pour capturer les attributs href avec guillemets doubles OU simples $pattern = '/href=(["\'])([^"\']*)\1/i'; return preg_replace_callback($pattern, function($matches) { $quote = $matches[1]; // Guillemet utilisé (" ou ') $originalUrl = $matches[2]; // L'URL $transformedUrl = $this->transformUrl($originalUrl); return 'href=' . $quote . $transformedUrl . $quote; }, $content); } /** * Transforme une URL en appliquant les redirections si nécessaire */ public function transformUrl(string $url): string { // Si l'URL est vide ou commence par #, on la retourne telle quelle if (empty($url) || strpos($url, '#') === 0) { return $url; } // Ne traiter que les URLs qui commencent par / ou https://hiringnotes.com/ if (strpos($url, '/') !== 0 && strpos($url, 'https://hiringnotes.com/') !== 0) { return $url; // URL non traitée (externe, mailto:, tel:, etc.) } // Extraction du chemin à vérifier $pathToCheck = $this->extractPathFromUrl($url); if (!$pathToCheck) { return $url; // URL invalide ou non traitée } // Vérification s'il existe une redirection pour ce chemin $redirection = $this->findRedirection($pathToCheck); if ($redirection) { // Construction de l'URL redirigée return $this->buildRedirectedUrl($url, $pathToCheck, $redirection->getUrl()); } return $url; // Pas de redirection trouvée } /** * Extrait le chemin d'une URL (relative ou absolue) */ public function extractPathFromUrl(string $url): ?string { // URL relative commençant par / if (strpos($url, '/') === 0) { // Pour /fr/page -> on veut fr/page return $this->removeAppPath($url); } // URL absolue avec https://hiringnotes.com/ if (strpos($url, 'https://hiringnotes.com/') === 0) { // Pour https://hiringnotes.com/fr/page -> on veut fr/page $path = parse_url($url, PHP_URL_PATH); return $path ? $this->removeAppPath($path) : null; } // Toute autre URL n'est pas traitée return null; } /** * Trouve une redirection pour un chemin donné */ private function findRedirection(string $path): ?object { // Utilisation du cache pour éviter les requêtes répétées if (isset($this->redirectionCache[$path])) { return $this->redirectionCache[$path]; } // Recherche UNIQUEMENT par slug avec visibility=true $redirection = $this->em->getRepository(Redirection::class)->findOneBy([ 'slug' => $path, 'visibility' => true ]); $this->redirectionCache[$path] = $redirection; return $redirection; } /** * Construit l'URL redirigée en préservant le format original */ private function buildRedirectedUrl(string $originalUrl, string $originalPath, string $redirectedPath): string { // URL absolue avec https://hiringnotes.com/ if (strpos($originalUrl, 'https://hiringnotes.com/') === 0) { $parsedUrl = parse_url($originalUrl); $newUrl = 'https://hiringnotes.com/' . ltrim($redirectedPath, '/'); if (isset($parsedUrl['query'])) { $newUrl .= '?' . $parsedUrl['query']; } if (isset($parsedUrl['fragment'])) { $newUrl .= '#' . $parsedUrl['fragment']; } return $newUrl; } // URL relative commençant par / if (strpos($originalUrl, '/') === 0) { $parsedUrl = parse_url($originalUrl); $newUrl = '/' . ltrim($redirectedPath, '/'); if (isset($parsedUrl['query'])) { $newUrl .= '?' . $parsedUrl['query']; } if (isset($parsedUrl['fragment'])) { $newUrl .= '#' . $parsedUrl['fragment']; } return $newUrl; } // Fallback (ne devrait pas arriver avec la nouvelle logique) return $redirectedPath; } /** * Précharge toutes les redirections en cache (optionnel, pour optimiser les performances) */ public function preloadRedirections(): void { $redirections = $this->em->getRepository(Redirection::class)->findBy(['visibility' => true]); foreach ($redirections as $redirection) { if ($redirection->getSlug()) { $this->redirectionCache[$redirection->getSlug()] = $redirection; } if ($redirection->getUrl()) { $this->redirectionCache[$redirection->getUrl()] = $redirection; } } }}