From f9724668807c7b946d9b8e8b31622d8dfdaf7903 Mon Sep 17 00:00:00 2001 From: Stephen Shkardoon Date: Tue, 23 Jul 2013 02:31:07 +1200 Subject: [PATCH] Refactor old page redirector into an extension --- code/controllers/ContentController.php | 27 +------- code/controllers/ModelAsController.php | 73 ++++----------------- code/controllers/OldPageRedirector.php | 91 ++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 code/controllers/OldPageRedirector.php diff --git a/code/controllers/ContentController.php b/code/controllers/ContentController.php index 9bc553ea..113749bc 100644 --- a/code/controllers/ContentController.php +++ b/code/controllers/ContentController.php @@ -22,6 +22,8 @@ class ContentController extends Controller { protected $dataRecord; + private static $extensions = array('OldPageRedirector'); + private static $allowed_actions = array( 'successfullyinstalled', 'deleteinstallfiles', // secured through custom code @@ -168,31 +170,6 @@ class ContentController extends Controller { 'URLSegment' => rawurlencode($action) ))->first(); if(class_exists('Translatable')) Translatable::enable_locale_filter(); - - // if we can't find a page with this URLSegment try to find one that used to have - // that URLSegment but changed. See ModelAsController->getNestedController() for similiar logic. - if(!$child){ - $child = ModelAsController::find_old_page($action,$this->ID); - if($child){ - $response = new SS_HTTPResponse(); - $params = $request->getVars(); - if(isset($params['url'])) unset($params['url']); - $response->redirect( - Controller::join_links( - $child->Link( - Controller::join_links( - $request->param('ID'), // 'ID' is the new 'URLSegment', everything shifts up one position - $request->param('OtherID') - ) - ), - // Needs to be in separate join links to avoid urlencoding - ($params) ? '?' . http_build_query($params) : null - ), - 301 - ); - return $response; - } - } } // we found a page with this URLSegment. diff --git a/code/controllers/ModelAsController.php b/code/controllers/ModelAsController.php index b4495fbf..7cb68837 100644 --- a/code/controllers/ModelAsController.php +++ b/code/controllers/ModelAsController.php @@ -7,6 +7,7 @@ * @subpackage control */ class ModelAsController extends Controller implements NestedController { + private static $extensions = array('OldPageRedirector'); /** * Get the appropriate {@link ContentController} for handling a {@link SiteTree} object, link it to the object and @@ -108,31 +109,6 @@ class ModelAsController extends Controller implements NestedController { if(class_exists('Translatable')) Translatable::enable_locale_filter(); if(!$sitetree) { - // If a root page has been renamed, redirect to the new location. - // See ContentController->handleRequest() for similiar logic. - $redirect = self::find_old_page($URLSegment); - if($redirect) { - $params = $request->getVars(); - if(isset($params['url'])) unset($params['url']); - $this->response = new SS_HTTPResponse(); - $this->response->redirect( - Controller::join_links( - $redirect->Link( - Controller::join_links( - $request->param('Action'), - $request->param('ID'), - $request->param('OtherID') - ) - ), - // Needs to be in separate join links to avoid urlencoding - ($params) ? '?' . http_build_query($params) : null - ), - 301 - ); - - return $this->response; - } - $response = ErrorPage::response_for(404); $this->httpError(404, $response ? $response : 'The requested page could not be found.'); } @@ -146,47 +122,20 @@ class ModelAsController extends Controller implements NestedController { return self::controller_for($sitetree, $this->request->param('Action')); } - + /** + * @deprecated 3.2 Use OldPageRedirector::find_old_page instead + * * @param string $URLSegment A subset of the url. i.e in /home/contact/ home and contact are URLSegment. - * @param int $parentID The ID of the parent of the page the URLSegment belongs to. + * @param int $parentID The ID of the parent of the page the URLSegment belongs to. * @return SiteTree */ - static public function find_old_page($URLSegment,$parentID = 0, $ignoreNestedURLs = false) { - - $useParentIDFilter = SiteTree::config()->nested_urls && $parentID; - - // First look for a non-nested page that has a unique URLSegment and can be redirected to. - if(SiteTree::config()->nested_urls) { - $pages = SiteTree::get()->filter("URLSegment", rawurlencode($URLSegment)); - if($useParentIDFilter) { - $pages = $pages->filter("ParentID", (int)$parentID); - } - - if($pages && $pages->Count() == 1 && ($page = $pages->First())) { - $parent = $page->ParentID ? $page->Parent() : $page; - if($parent->isPublished()) return $page; - } - } - - // Get an old version of a page that has been renamed. - $URLSegmentSQL = Convert::raw2sql(rawurlencode($URLSegment)); - $query = new SQLQuery ( - '"RecordID"', - '"SiteTree_versions"', - "\"URLSegment\" = '$URLSegmentSQL' AND \"WasPublished\" = 1" . ($useParentIDFilter ? ' AND "ParentID" = ' . (int)$parentID : ''), - '"LastEdited" DESC', - null, - null, - 1 - ); - $record = $query->execute()->first(); - - if($record && ($oldPage = DataObject::get_by_id('SiteTree', $record['RecordID']))) { - $oldParent = $oldPage->ParentID ? $oldPage->Parent() : $oldPage; - // Run the page through an extra filter to ensure that all extensions are applied. - if(SiteTree::get_by_link($oldPage->RelativeLink()) && $oldParent->isPublished()) return $oldPage; + static public function find_old_page($URLSegment, $parent = null, $ignoreNestedURLs = false) { + Deprecation::notice('3.2', 'Use OldPageRedirector::find_old_page instead'); + if ($parent) { + $parent = SiteTree::get()->byId($parent); } + $url = OldPageRedirector::find_old_page(array($URLSegment), $parent); + return SiteTree::get_by_link($url); } - } diff --git a/code/controllers/OldPageRedirector.php b/code/controllers/OldPageRedirector.php new file mode 100644 index 00000000..e13bb3bc --- /dev/null +++ b/code/controllers/OldPageRedirector.php @@ -0,0 +1,91 @@ +allParams()), function($v) { return ($v !== NULL); }); + + $getvars = $request->getVars(); + unset($getvars['url']); + + $page = self::find_old_page($params); + + if ($page) { + $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) { + $URL = Convert::raw2sql(array_shift($params)); + 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 + // TODO: Rewrite using ORM syntax + $query = new SQLQuery ( + '"RecordID"', + '"SiteTree_versions"', + "\"URLSegment\" = '$URL' AND \"WasPublished\" = 1" . ($parent ? ' AND "ParentID" = ' . $parent->ID : ''), + '"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; + } +} +