157 lines
5.8 KiB
PHP
157 lines
5.8 KiB
PHP
<?php
|
|
|
|
use PrestaShop\PrestaShop\Adapter\ObjectManager;
|
|
use PrestaShop\PrestaShop\Core\Localization\TranslatorInterface;
|
|
|
|
class URLRedirect extends ObjectModel
|
|
{
|
|
public $url;
|
|
public $object_name;
|
|
public $object_id;
|
|
public $date_add;
|
|
public $date_upd;
|
|
|
|
public static $definition = [
|
|
'table' => '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;
|
|
}
|
|
|
|
$redirection = URLRedirect::getByUrl($url);
|
|
if ($redirection->id) {
|
|
if (!$updateExisting) {
|
|
return false; // Do not update if we shouldn't.
|
|
}
|
|
|
|
// Update existing entry
|
|
$redirection->object_name = $object_name;
|
|
$redirection->object_id = $object_id;
|
|
$redirection->date_upd = date('Y-m-d H:i:s');
|
|
return $redirection->update();
|
|
}
|
|
|
|
|
|
|
|
$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 URLRedirect
|
|
*/
|
|
public static function getByUrl(string $url): URLRedirect
|
|
{
|
|
$url = trim(urldecode($url), '/');
|
|
$sql = new DbQuery();
|
|
$sql->select('*');
|
|
$sql->from(self::$definition['table']);
|
|
$sql->where('url = "' . pSQL($url) . '"');
|
|
$object = new self();
|
|
if ($result = Db::getInstance()->getRow($sql)) {
|
|
|
|
$object->id = (int) $result['id_url_redirection'];
|
|
$object->url = $result['url'];
|
|
$object->object_name = $result['object_name'];
|
|
$object->object_id = (int) $result['object_id'];
|
|
$object->date_add = $result['date_add'];
|
|
$object->date_upd = $result['date_upd'];
|
|
}
|
|
|
|
return $object;
|
|
}
|
|
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 = URLRedirect::getByUrl($url);
|
|
if ($redirection->id) {
|
|
$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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|