PDA

View Full Version : Where is the redirection performed?


ndoktoruser
01-28-2016, 07:49 AM
Hello all,

I have migrated my forum to vBulletin 4, then upgraded it to vBulletin 5.
In order to not lose the visitors who come from external links, I created a table with a redirection mapping from the old links to the new ones.

So where is redirection treatment performed in vBulletin 5?
I suppose the system tries to find the page related to the URL, (in case it doesn't) then it tries to match a redirection from vBulletin 4, (in case it doesn't) then it leads the user to a 404 page. However, I want to put some treatment before the 404, in the case I can find out it is a link from the old system, so I would redirect to the proper vBulletin 5 URL.

Thanks in advance!

ndoktoruser
02-17-2016, 11:59 AM
Hello everyone,

just to give an update to whoever has the same problem, I succeeded with my redirection.

I found that the class \vB5_Frontend_Routing (file: vb5/includes/vb5/frontend/routing.php) manages the requests and tries to find out what page should be displayed to the user.

Every page request will fall into \vB5_Frontend_Routing::setRoutes, which will try to create the route to the requested path. And this is the piece of the code:

try {
$message = ''; // Start with no error.
$route = Api_InterfaceAbstract::instance()->callApi('route', 'getRoute', array('pathInfo' => $path, 'queryString' => $_SERVER['QUERY_STRING']));
}



My problem was: once I migrated from an existing forum to vBulletin, I had to create redirection for all my existent threads and forums. However, once I have hundreds of thousands of links, it didn't seem smart adding all of them to htacess.

So, once I have a custom routine to create vBulletin path from a legacy path, this is my result:

try {
$message = ''; // Start with no error.
$route = Api_InterfaceAbstract::instance()->callApi('route', 'getRoute', array('pathInfo' => $path, 'queryString' => $_SERVER['QUERY_STRING']));
// begin: my custom redirection
if (isset($route) && $route == false) {
$newPath = MyClass::getVBPathFromLegacyPath($path); # this custom function returns string or false
if ($vbPath !== false) {
$route = Api_InterfaceAbstract::instance()->callApi('route', 'getRoute', array('pathInfo' => $path, 'queryString' => $_SERVER['QUERY_STRING']));
$route['redirect'] = $newPath; # this is important, so vBulletin will create a 301 redirection
}
}
// end: my custom redirection
}


As we can see, the code is executed only in the case vBulletin is not able to create a route. And it only creates a route in the case a newPath (which is a vBulletin path, created using vBulletin API) is successfully created.

To me, it seems safe. And I hope the redirect parameter set "by hand" doesn't break things at some point.

So far, in a test environment, everything looks fine.

Replicant
02-17-2016, 01:32 PM
This is good work. This particular problem comes up frequently and is one of the issues that causes VB5 to have a poor upgrade reputation. Nobody wants to lose their links that have been accumulated over years and wait for the search engines to re-index not to mention links in threads. I'd be interested in seeing the redirection table format. Thanks for sharing your work.

ndoktoruser
02-17-2016, 04:15 PM
You're welcome!


About my table, it is done and it is functional (in, fact, I created 2 tables: one for forums and other for threads), but as I put much more data than I need, I will improve the first solution.

The first solution was based in the thought: "Once I want to be sure that all my redirection work, I will save them in the DB, then I visit every single link and flag it as successful mapping. At the end, I add the redirection to htaccess".
However, I realized I don't need the htaccess at all.

Just a reminder: I migrated from Phorum 5.2 to vBulletin. This helped me a lot, because the structure of the link was pretty different.


First solution

Here it is the structure of the tables, later I will explain how I use them:

*note: I removed search indexes for some fields to keep the SQL shorter.
CREATE TABLE IF NOT EXISTS legacy_forum (
nodeid smallint(5) NOT NULL,
nodeparentid smallint(5) NOT NULL,
forumid smallint(5) NOT NULL,
forumparentid smallint(5) NOT NULL,
importforumid smallint(5) NOT NULL,
importforumparentid smallint(5) NOT NULL,
title varchar(70),
phorumSlug varchar(70),
`vb5Slug` varchar(70),
phorumUrl varchar(150),
`vb5Url` varchar(150),
UNIQUE KEY uky_objectId (nodeid)
) CHARSET=ucs2 COLLATE=ucs2_general_ci ENGINE=innodb;

CREATE TABLE IF NOT EXISTS legacy_thread (
nodeid mediumint(9) NOT NULL,
nodeforumid smallint(5) NOT NULL,
threadid mediumint(9) NOT NULL,
importthreadid mediumint(9) NOT NULL,
importforumid smallint(5) NOT NULL,
title varchar(70),
phorumSlug varchar(150),
`vb5Slug` varchar(220),
phorumUrl varchar(220),
`vb5Url` varchar(330),
phorumChecked tinyint(1) DEFAULT NULL,
vbChecked tinyint(1) DEFAULT NULL,
UNIQUE KEY uky_objectId (nodeid)
) CHARSET=ucs2 COLLATE=ucs2_general_ci ENGINE=innodb;

The tables are mainly mappings between ids, slugs and paths of Phorum and vBulletin.

everything with "import*" or "phorum*" is related to Phorum;
everything with "forum*" or "thread*" is related to vBulletin 4 (I only kept it in the table for safety reasons);
everything with "node*" and "vb*" is related to vBulletin 5.


The table legacy_forum was created from forum (forums in vB4) and node (table for all nodes - forums, threads, posts in vB5).
The table legacy_thread was created from thread (threads in vB4) and node (table for all nodes - forums, threads, posts in vB5).

All fields related to slugs and URLs were derived from the title.

As I learned more related to the redirection, I realized I simply need to treat the paths vBulletin can't treat, instead of creating rules or mapping to htaccess. So I do not need all that URL mapping.
The paths vBulletin can't treat (Phorum paths) already have the legacy id. So, I get the legacy id with preg_match, then I can fetch vBulletin nodeid from the legacy table and, at the end, get the correspondent route using vBulletin API.



Future improvement

Once I do not need the mapping, I removed it from the tables. I also removed the references to vB4.
At the end, those will be my redirection tables:

*note: I removed search indexes for some fields to keep the SQL shorter.
CREATE TABLE IF NOT EXISTS legacy_forum (
nodeid smallint(5) NOT NULL,
nodeparentid smallint(5) NOT NULL,
importforumid smallint(5) NOT NULL,
importforumparentid smallint(5) NOT NULL,
UNIQUE KEY uky_objectId (nodeid)
) CHARSET=ucs2 COLLATE=ucs2_general_ci ENGINE=innodb;

CREATE TABLE IF NOT EXISTS legacy_thread (
nodeid mediumint(9) NOT NULL,
nodeforumid smallint(5) NOT NULL,
importthreadid mediumint(9) NOT NULL,
importforumid smallint(5) NOT NULL,
UNIQUE KEY uky_objectId (nodeid)
) CHARSET=ucs2 COLLATE=ucs2_general_ci ENGINE=innodb;

In those tables, I still have information I do not use. However, I will keep some ids just for the sake of do not throw away some data that might useful.


_______________
Edit (1 day after I wrote the post): I tested the solution I wrote as "future improvement". Everything works fine. :)

MarkFL
02-17-2016, 04:20 PM
Yes, thank you very much for taking the time/effort and being conscientious enough to share what you found in resolving your issue to benefit others.

It is quite discouraging to see a user ask a question, and then they later reply only to say something like "Nevermind, I solved it." Sharing solutions is what makes this a real community! :)

ndoktoruser
02-18-2016, 06:38 AM
I agree with you.