Skip to content

Commit

Permalink
Implement fallback redirect url
Browse files Browse the repository at this point in the history
  • Loading branch information
matrikular committed May 27, 2016
1 parent 06c5f20 commit 355033e
Showing 1 changed file with 105 additions and 96 deletions.
201 changes: 105 additions & 96 deletions plugins/system/redirect/redirect.php
Expand Up @@ -53,6 +53,7 @@ public function __construct(&$subject, $config)
self::$previousExceptionHandler = set_exception_handler(array('PlgSystemRedirect', 'handleException'));
}


/**
* Method to handle an error condition from JError.
*
Expand Down Expand Up @@ -101,11 +102,9 @@ public static function handleException($exception)
*/
private static function doErrorHandling($error)
{
// Get the application object.
$app = JFactory::getApplication();

// Make sure the error is a 404 and we are not in the administrator.
if ($app->isAdmin() || $error->getCode() != 404)
if ($app->isAdmin() || ((int) $error->getCode() !== 404))
{
// Proxy to the previous exception handler if available, otherwise just render the error page
if (self::$previousExceptionHandler)
Expand All @@ -118,125 +117,135 @@ private static function doErrorHandling($error)
}
}

// Get the full current URI.
$uri = JUri::getInstance();
$current = rawurldecode($uri->toString(array('scheme', 'host', 'port', 'path', 'query', 'fragment')));
$uri = JUri::getInstance();

$url = rawurldecode($uri->toString(array('scheme', 'host', 'port', 'path', 'query', 'fragment')));
$urlRel = rawurldecode($uri->toString(array('path', 'query', 'fragment')));

$urlWithoutQuery = rawurldecode($uri->toString(array('scheme', 'host', 'port', 'path', 'fragment')));
$urlRelWithoutQuery = rawurldecode($uri->toString(array('path', 'fragment')));

// Attempt to ignore idiots.
if ((strpos($current, 'mosConfig_') !== false) || (strpos($current, '=http://') !== false))
// Why is this (still) here?
if ((strpos($url, 'mosConfig_') !== false) || (strpos($url, '=http://') !== false))
{
// Render the error page.
JErrorPage::render($error);
}

// See if the current url exists in the database as a redirect.
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(array('new_url', 'header')))
->select($db->quoteName('published'))
->from($db->quoteName('#__redirect_links'))
->where($db->quoteName('old_url') . ' = ' . $db->quote($current));
$db->setQuery($query, 0, 1);
$link = $db->loadObject();

// If no published redirect was found try with the server-relative URL
if (!$link || ($link->published != 1))
$dbo = JFactory::getDbo();

$query = $dbo->getQuery(true);

$query->select('*')
->from($dbo->qn('#__redirect_links'))
->where(
'('
. $dbo->qn('old_url') . ' = ' . $dbo->q($url)
. ' OR '
. $dbo->qn('old_url') . ' = ' . $dbo->q($urlRel)
. ' OR '
. $dbo->qn('old_url') . ' = ' . $dbo->q($urlWithoutQuery)
. ' OR '
. $dbo->qn('old_url') . ' = ' . $dbo->q($urlRelWithoutQuery)
. ')'
);

$dbo->setQuery($query);

$redirect = null;

try
{
$currRel = rawurldecode($uri->toString(array('path', 'query', 'fragment')));
$query = $db->getQuery(true)
->select($db->quoteName(array('new_url', 'header')))
->select($db->quoteName('published'))
->from($db->quoteName('#__redirect_links'))
->where($db->quoteName('old_url') . ' = ' . $db->quote($currRel));
$db->setQuery($query, 0, 1);
$link = $db->loadObject();
$redirects = $dbo->loadAssocList();

$possibleMatches = array_unique(
array($url, $urlRel, $urlWithoutQuery, $urlRelWithoutQuery)
);

foreach ($possibleMatches as $match)
{
if (($index = array_search($match, array_column($redirects, 'old_url'))) !== false)
{
$redirect = (object) $redirects[$index];

if ((int) $redirect->published === 1)
{
break;
}
}
}
}
catch (Exception $e)
{
JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 500, $e));
}

// If a redirect exists and is published, permanently redirect.
if ($link && ($link->published == 1))
// A redirect object was found and, if published, will be used
if (!is_null($redirect) && ((int) $redirect->published === 1))
{
// If no header is set use a 301 permanent redirect
if (!$link->header || JComponentHelper::getParams('com_redirect')->get('mode', 0) == false)
if (!$redirect->header || (bool) JComponentHelper::getParams('com_redirect')->get('mode', false) === false)
{
$link->header = 301;
$redirect->header = 301;
}

// If we have a redirect in the 300 range use JApplicationWeb::redirect().
if ($link->header < 400 && $link->header >= 300)
if ($redirect->header < 400 && $redirect->header >= 300)
{
$new_link = JUri::isInternal($link->new_url) ? JRoute::_($link->new_url) : $link->new_url;
$urlQuery = $uri->getQuery();

$oldUrlParts = parse_url($redirect->old_url);

$app->redirect($new_link, intval($link->header));
if (empty($oldUrlParts['query']) && $urlQuery !== '')
{
$redirect->new_url .= '?' . $urlQuery;
}

$destination = JUri::isInternal($redirect->new_url) ? JRoute::_($redirect->new_url) : $redirect->new_url;

$app->redirect($destination, (int) $redirect->header);
}

// Else rethrow the exeception with the new header and return
JErrorPage::render(new RuntimeException($error->getMessage(), $link->header, $error));
JErrorPage::render(new RuntimeException($error->getMessage(), $redirect->header, $error));
}

try
// No redirect object was found so we create an entry in the redirect table
elseif (is_null($redirect))
{
$referer = $app->input->server->getString('HTTP_REFERER', '');
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__redirect_links'))
->where($db->quoteName('old_url') . ' = ' . $db->quote($current));
$db->setQuery($query);
$res = $db->loadResult();

if (!$res)
{
// If not, add the new url to the database but only if option is enabled
$params = new Registry(JPluginHelper::getPlugin('system', 'redirect')->params);
$collect_urls = $params->get('collect_urls', 1);
$params = new Registry(JPluginHelper::getPlugin('system', 'redirect')->params);

if ($collect_urls == true)
if ((bool) $params->get('collect_urls', true))
{
$data = (object) array(
'id' => 0,
'old_url' => $url,
'referer' => $app->input->server->getString('HTTP_REFERER', ''),
'hits' => 1,
'published' => 0,
'created_date' => JFactory::getDate()->toSql()
);

try
{
$columns = array(
$db->quoteName('old_url'),
$db->quoteName('new_url'),
$db->quoteName('referer'),
$db->quoteName('comment'),
$db->quoteName('hits'),
$db->quoteName('published'),
$db->quoteName('created_date')
);

$values = array(
$db->quote($current),
$db->quote(''),
$db->quote($referer),
$db->quote(''),
1,
0,
$db->quote(JFactory::getDate()->toSql())
);

$query->clear()
->insert($db->quoteName('#__redirect_links'), false)
->columns($columns)
->values(implode(', ', $values));

$db->setQuery($query);
$db->execute();
$dbo->insertObject('#__redirect_links', $data, 'id');
}
catch (Exception $e)
{
JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 500, $e));
}
}
else
{
// Existing error url, increase hit counter.
$query->clear()
->update($db->quoteName('#__redirect_links'))
->set($db->quoteName('hits') . ' = ' . $db->quoteName('hits') . ' + 1')
->where('id = ' . (int) $res);
$db->setQuery($query);
$db->execute();
}
}
catch (RuntimeException $exception)
// We have an unpublished redirect object, increment the hit counter
else
{
JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 404, $exception));
$redirect->hits += 1;

try
{
$dbo->updateObject('#__redirect_links', $redirect, 'id');
}
catch (Exception $e)
{
JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 500, $e));
}
}

// Render the error page.
JErrorPage::render($error);
}
}

0 comments on commit 355033e

Please sign in to comment.