silverstripe-cms/code/Controllers/OldPageRedirector.php

118 lines
4.1 KiB
PHP
Raw Normal View History

<?php
2016-07-22 01:32:32 +02:00
namespace SilverStripe\CMS\Controllers;
2016-08-10 06:08:39 +02:00
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
2016-09-09 01:26:24 +02:00
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Core\Extension;
2016-07-22 01:32:32 +02:00
2024-01-18 22:00:46 +01:00
/**
* @extends Extension<ContentController|ModelAsController>
*/
2017-01-25 21:59:25 +01:00
class OldPageRedirector extends Extension
{
/**
* On every URL that generates a 404, we'll capture it here and see if we can
* find an old URL that it should be redirecting to.
*
* @throws HTTPResponse_Exception
*/
public function onBeforeHTTPError404(HTTPRequest $request)
2017-01-25 21:59:25 +01:00
{
// We need to get the URL ourselves because $request->allParams() only has a max of 4 params
2022-04-13 07:07:59 +02:00
$params = preg_split('|/+|', $request->getURL() ?? '');
$cleanURL = trim(Director::makeRelative($request->getURL(false)) ?? '', '/');
2017-01-25 21:59:25 +01:00
$getvars = $request->getVars();
unset($getvars['url']);
$page = self::find_old_page($params, 0);
if (!$page) {
$page = self::find_old_page($params);
}
2022-04-13 07:07:59 +02:00
$cleanPage = trim(Director::makeRelative($page) ?? '', '/');
2017-01-25 21:59:25 +01:00
if (!$cleanPage) {
$cleanPage = Director::makeRelative(RootURLController::get_homepage_link());
}
2017-01-25 21:59:25 +01:00
if ($page && $cleanPage != $cleanURL) {
$res = new HTTPResponse();
$res->redirect(
Controller::join_links(
$page,
($getvars) ? '?' . http_build_query($getvars) : null
),
301
);
throw new HTTPResponse_Exception($res);
}
}
2017-01-25 21:59:25 +01:00
/**
* Attempt to find an old/renamed page from some given the URL as an array
*
* @param array $params The array of URL, e.g. /foo/bar as ['foo', 'bar']
2017-01-25 21:59:25 +01:00
* @param SiteTree|null $parent The current parent in the recursive flow
* @param boolean $redirect Whether we've found an old page worthy of a redirect
*
* @return string|boolean False, or the new URL
*/
public static function find_old_page($params, $parent = null, $redirect = false)
{
$parent = is_numeric($parent) && $parent > 0 ? SiteTree::get()->byID($parent) : $parent;
2017-01-25 21:59:25 +01:00
$params = (array)$params;
2022-04-13 07:07:59 +02:00
$URL = rawurlencode(array_shift($params) ?? '');
2017-01-25 21:59:25 +01:00
if (empty($URL)) {
return false;
}
$pages = SiteTree::get()->filter([
2017-01-25 21:59:25 +01:00
'URLSegment' => $URL,
]);
if ($parent || is_numeric($parent)) {
$pages = $pages->filter([
'ParentID' => is_numeric($parent) ? $parent : $parent->ID,
]);
2017-01-25 21:59:25 +01:00
}
$page = $pages->first();
if (!$page) {
// If we haven't found a candidate, lets resort to finding an old page with this URL segment
$pages = $pages
->filter('WasPublished', 1)
2017-01-25 21:59:25 +01:00
->sort('LastEdited', 'DESC')
->setDataQueryParam("Versioned.mode", 'all_versions');
2017-01-25 21:59:25 +01:00
$record = $pages->first();
if ($record) {
$page = SiteTree::get()->byID($record->ID);
2017-01-25 21:59:25 +01:00
$redirect = true;
}
}
2017-01-25 21:59:25 +01:00
if ($page && $page->canView()) {
2022-04-13 07:07:59 +02:00
if (count($params ?? [])) {
2017-01-25 21:59:25 +01:00
// We have to go deeper!
$ret = self::find_old_page($params, $page, $redirect);
if ($ret) {
// A valid child page was found! We can return it
return $ret;
} else {
// No valid page found.
if ($redirect) {
// If we had some redirect to be done, lets do it. imagine /foo/action -> /bar/action, we still want this redirect to happen if action isn't a page
return Controller::join_links($page->Link(), implode('/', $params));
2017-01-25 21:59:25 +01:00
}
}
} else {
// We've found the final, end all, page.
return $page->Link();
}
}
2017-01-25 21:59:25 +01:00
return false;
}
}