'url_redirection', 'primary' => 'id_url_redirection', 'multilang' => false, 'fields' => [ 'url' => ['type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 255], 'object_name' => ['type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 64], 'object_id' => ['type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true], 'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => false], 'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => false], ], ]; /** * @param string $url * @param string $object_name * @param int $object_id * @param bool $updateExisting * * @return bool */ public static function saveUrl(string $url, string $object_name, int $object_id, bool $updateExisting = false): bool { // $url = trim($url, '/'); // Remove leading/trailing slashes $url = trim(str_replace(Context::getContext()->shop->getBaseURL(true, false), '', $url), '/'); if (empty($url) || empty($object_name) || $object_id <= 0) { return false; } $existingRedirection = new URLRedirect(); if ($existingRedirection->getByUrl($url)) { if (!$updateExisting) { return false; // Do not update if we shouldn't. } // Update existing entry $existingRedirection->object_name = $object_name; $existingRedirection->object_id = $object_id; $existingRedirection->date_upd = date('Y-m-d H:i:s'); return $existingRedirection->update(); } $redirection = new self(); $redirection->url = $url; $redirection->object_name = $object_name; $redirection->object_id = $object_id; $redirection->date_add = date('Y-m-d H:i:s'); return $redirection->add(); } /** * Get redirection by URL. * * @param string $url * @return bool|ObjectModel */ public function getByUrl(string $url) { $url = trim($url, '/'); $sql = new DbQuery(); $sql->select('*'); $sql->from(self::$definition['table']); $sql->where('url = "' . pSQL($url) . '"'); if ($result = Db::getInstance()->getRow($sql)) { $this->id = (int) $result['id_url_redirection']; $this->url = $result['url']; $this->object_name = $result['object_name']; $this->object_id = (int) $result['object_id']; $this->date_add = $result['date_add']; $this->date_upd = $result['date_upd']; return $this; } return false; } public static function extractPath($requestUri) { // Remove query string if present $uri = parse_url($requestUri, PHP_URL_PATH); $segments = explode('/', trim($uri, '/')); // If the first segment is 2 letters, ignore it if (isset($segments[0]) && preg_match('/^[a-zA-Z]{2}$/', $segments[0])) { array_shift($segments); } return strtolower(implode('/', $segments)); } /** * This method hooks into the dispatcher to check if the current URL * is a 404 and if there's a redirection available for it. * This hook needs to be called `hookActionDispatcherBefore` in a module. * * @param array $params * @return void */ public static function hookActionDispatcher(array $params): void { if (!defined('_PS_ADMIN_DIR_') && $params['controller_class'] === 'PageNotFoundController') { $url = trim(str_replace(Context::getContext()->shop->getBaseURL(true, false), '', $_SERVER['REQUEST_URI']), '/'); if (!empty($url)) { $redirection = new URLRedirect(); if ($redirection->getByUrl($url)) { $targetUrl = ''; switch ($redirection->object_name) { case 'category': $targetUrl = Context::getContext()->link->getCategoryLink($redirection->object_id); break; case 'product': $targetUrl = Context::getContext()->link->getProductLink($redirection->object_id); break; case 'cms': $targetUrl = Context::getContext()->link->getCMSLink($redirection->object_id); break; // Add more cases for other object types (cms_category, supplier, manufacturer etc.) default: // Log the invalid object_name or maybe remove the redirection. PrestaShopLogger::addLog( 'Invalid object_name in URLRedirect table: ' . $redirection->object_name . ' URL: ' . $url, 3, // Severity: WARNING 0, // Error Code 'URLRedirect', // Object Class $redirection->id, // Object ID true ); return; // Don't redirect if the object name is invalid. } if (!empty($targetUrl)) { Tools::redirect($targetUrl); } } } } } }