2013-07-22 16:31:07 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
2013-06-21 00:45:33 +02:00
|
|
|
* @param SS_HTTPRequest $request The request object
|
2014-02-10 21:35:13 +01:00
|
|
|
* @throws SS_HTTPResponse_Exception
|
2013-07-22 16:31:07 +02:00
|
|
|
*/
|
|
|
|
public function onBeforeHTTPError404($request) {
|
2015-08-20 14:19:08 +02:00
|
|
|
// We need to get the URL ourselves because $request->allParams() only has a max of 4 params
|
|
|
|
$params = preg_split('|/+|', $request->getURL());
|
2016-05-31 16:41:32 +02:00
|
|
|
$cleanURL = trim(Director::makeRelative($request->getURL(false), '/'));
|
2013-07-22 16:31:07 +02:00
|
|
|
|
|
|
|
$getvars = $request->getVars();
|
|
|
|
unset($getvars['url']);
|
|
|
|
|
|
|
|
$page = self::find_old_page($params);
|
2016-05-31 16:41:32 +02:00
|
|
|
$cleanPage = trim(Director::makeRelative($page), '/');
|
|
|
|
if (!$cleanPage) {
|
|
|
|
$cleanPage = Director::makeRelative(RootURLController::get_homepage_link());
|
|
|
|
}
|
2013-07-22 16:31:07 +02:00
|
|
|
|
2016-05-31 16:41:32 +02:00
|
|
|
if ($page && $cleanPage != $cleanURL) {
|
2013-07-22 16:31:07 +02:00
|
|
|
$res = new SS_HTTPResponse();
|
|
|
|
$res->redirect(
|
|
|
|
Controller::join_links(
|
|
|
|
$page,
|
|
|
|
($getvars) ? '?' . http_build_query($getvars) : null
|
|
|
|
), 301);
|
|
|
|
throw new SS_HTTPResponse_Exception($res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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 array('foo', 'bar')
|
|
|
|
* @param SiteTree $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
|
|
|
|
*/
|
|
|
|
static public function find_old_page($params, $parent = null, $redirect = false) {
|
2013-12-06 14:28:08 +01:00
|
|
|
$parent = is_numeric($parent) ? SiteTree::get()->byId($parent) : $parent;
|
|
|
|
$params = (array)$params;
|
2013-06-21 00:45:33 +02:00
|
|
|
$URL = rawurlencode(array_shift($params));
|
2013-07-22 16:31:07 +02:00
|
|
|
if (empty($URL)) { return false; }
|
|
|
|
if ($parent) {
|
|
|
|
$page = SiteTree::get()->filter(array('ParentID' => $parent->ID, 'URLSegment' => $URL))->First();
|
|
|
|
} else {
|
|
|
|
$page = SiteTree::get()->filter(array('URLSegment' => $URL))->First();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$page) {
|
|
|
|
// If we haven't found a candidate, lets resort to finding an old page with this URL segment
|
2013-06-21 00:45:33 +02:00
|
|
|
$oldFilter = array(
|
|
|
|
'"SiteTree_versions"."URLSegment"' => $URL,
|
|
|
|
'"SiteTree_versions"."WasPublished"' => true
|
|
|
|
);
|
|
|
|
if($parent) {
|
|
|
|
$oldFilter[] = array('"SiteTree_versions"."ParentID"' => $parent->ID);
|
|
|
|
}
|
|
|
|
$query = new SQLSelect(
|
2013-07-22 16:31:07 +02:00
|
|
|
'"RecordID"',
|
|
|
|
'"SiteTree_versions"',
|
2013-06-21 00:45:33 +02:00
|
|
|
$oldFilter,
|
2013-07-22 16:31:07 +02:00
|
|
|
'"LastEdited" DESC',
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
1
|
|
|
|
);
|
|
|
|
$record = $query->execute()->first();
|
|
|
|
if ($record) {
|
|
|
|
$page = SiteTree::get()->byID($record['RecordID']);
|
|
|
|
$redirect = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($page && $page->canView()) {
|
|
|
|
if (count($params)) {
|
|
|
|
// 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 $page->Link() . implode('/', $params);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We've found the final, end all, page.
|
|
|
|
return $page->Link();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|