# 301 Redirect from /index.php?id=8 to /alias.html
# 301 Redirect from /page, /page/ to /page.html
# 301 Redirect from non domain.com url to www.domain.com url (requires .htaccess edit)
# If you switch Friendly URLs off, it redirects /page.html and /page to /index.php?id=48 - this enforces the options that have been selected.
# 301 Redirect /{site_start}, /{site_start}.html to root folder / (no page in url)
# Menu links pointing to "www.domain.com/{start_page}" are changed to "www.domain.com" (Can turn off)
# If a page is marked as a folder in the modx system, it shows as /dir/ and not /dir.html (can turn off)
# 301 Redirect /folder to /folder/ to mimic apache, only happens when file is marked as folder (can be turned off)
# Individual URL and link rewriting. For example, you can set rss feed to default to feed.rss, not feed.rss.html. Also, menu links can link directly to the folder name rather than having to go through an extra level of redirects.
# Any suggestions?
Version 1.0 (summary of all versions up to 1.0)
--------------
# FIXED: All known bugs as of 02/24/2007
# ADDED: Added ability to enforce alternate url extensions such as .cc or .xml
Version 0.7
--------------
# ADDED: If a page is marked as a folder in the modx system, it shows as /dir/ and not /dir.html (can turn off)
# ADDED: 301 Redirect /folder to /folder/ to mimic apache, only happens when file is marked as folder (can be turned off)
Version 0.6
-------------
# FIXED BUG: When installed in modx is subfolder calling /index.html does infinite redirect
# FIXED BUG: When installed in modx is subfolder any redirect adds an extra folder to a redirect url
&editDocLinks=Edit document links;int;1 &makeFolders=Rewrite containers as folders;int;1 &override=Enable manual overrides;int;0 &overrideTV=Override TV name;string;seoOverride
// Strict URLs
// version 1.0
// Enforces the use of strict URLs to prevent duplicate content.
// By Jeremy Luebke @ www.xuru.com
// Contributions by Brian Stanback @ www.stanback.net
// On Install: Check the "OnWebPageInit" & "OnWebPagePrerender" boxes in the System Events tab.
// Plugin configuration: &editDocLinks=Edit document links;int;1 &makeFolders=Rewrite containers as folders;int;1 &override=Enable manual overrides;int;0 &overrideTV=Override TV name;string;seoOverride
// For overriding documents, create a new template variabe (TV) named seoOverride with the following options:
// Input Type: DropDown List Menu
// Input Option Values: Disabled==-1||Base Name==0||Append Extension==1||Folder==2
// Default Value: -1
// NOTE: You must set "Enable manual overrides" in plugin configuration to 1 to enable this TV
// # Include the following in your .htaccess file
// # Replace "example.com" & "example\.com" with your domain info
// RewriteCond %{HTTP_HOST} .
// RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
// RewriteRule (.*) http://www.example.com/$1 [R=301,L]
// Begin plugin code
$e = &$modx->event;
if ($e->name == 'OnWebPageInit')
{
$myProtocol = ($_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
$s = $_SERVER['REQUEST_URI'];
$parts = explode("?", $s);
$documentIdentifier = ($modx->documentIdentifier) ? $modx->documentIdentifier : $modx->config['error_page']; // Set error page document ID if page is not found
$alias = $modx->aliasListing[$documentIdentifier]['alias'];
if ($makeFolders) $isfolder = (count($modx->getChildIds($documentIdentifier, 1)) > 0) ? 1 : 0;
if ($override && $overrideOption = $modx->getTemplateVarOutput($overrideTV, $documentIdentifier))
{
switch ($overrideOption[$overrideTV])
{
case 0:
$isoverride = 1;
break;
case 1:
$isfolder = 0;
break;
case 2:
$makeFolders = 1;
$isfolder = 1;
}
}
if ($isoverride)
{
$strictURL = preg_replace('/[^\/]+$/', $alias, $modx->makeUrl($documentIdentifier));
}
elseif ($isfolder && $makeFolders)
{
$strictURL = preg_replace('/[^\/]+$/', $alias, $modx->makeUrl($documentIdentifier)) . "/";
}
else
{
$strictURL = $modx->makeUrl($documentIdentifier);
}
$myDomain = $myProtocol . "://" . $_SERVER['HTTP_HOST'];
$newURL = $myDomain . $strictURL;
$requestedURL = $myDomain . $parts[0];
if ($documentIdentifier == $modx->config['site_start'])
{
if ($requestedURL != $modx->config['site_url'])
{
// Force redirect of site start
header("HTTP/1.1 301 Moved Permanently");
$qstring = preg_replace("#(^|&)(q|id)=[^&]+#", '', $parts[1]); // Strip conflicting id/q from query string
if ($qstring) header('Location: ' . $modx->config['site_url'] . '?' . $qstring);
else header('Location: ' . $modx->config['site_url']);
exit;
}
}
elseif ($parts[0] != $strictURL)
{
// Force page redirect
header("HTTP/1.1 301 Moved Permanently");
$qstring = preg_replace("#(^|&)(q|id)=[^&]+#", '', $parts[1]); // Strip conflicting id/q from query string
if ($qstring) header('Location: ' . $strictURL . '?' . $qstring);
else header('Location: ' . $strictURL);
exit;
}
}
elseif ($e->name == 'OnWebPagePrerender')
{
if ($editDocLinks)
{
$myDomain = $_SERVER['HTTP_HOST'];
$furlSuffix = $modx->config['friendly_url_suffix'];
$baseUrl = $modx->config['base_url'];
$o = &$modx->documentOutput; // get a reference of the output
// Reduce site start to base url
$overrideAlias = $modx->aliasListing[$modx->config['site_start']]['alias'];
$overridePath = $modx->aliasListing[$modx->config['site_start']]['path'];
$o = preg_replace("#((href|action)=\"|$myDomain)($baseUrl)?($overridePath/)?$overrideAlias$furlSuffix#", '${1}' . $baseUrl, $o);
if ($override)
{
// Replace manual override links
$sql = "SELECT tvc.contentid as id, tvc.value as value FROM " . $modx->getFullTableName('site_tmplvars') . " tv ";
$sql .= "INNER JOIN " . $modx->getFullTableName('site_tmplvar_templates') . " tvtpl ON tvtpl.tmplvarid = tv.id ";
$sql .= "LEFT JOIN " . $modx->getFullTableName('site_tmplvar_contentvalues') . " tvc ON tvc.tmplvarid = tv.id ";
$sql .= "LEFT JOIN " . $modx->getFullTableName('site_content') . " sc ON sc.id = tvc.contentid ";
$sql .= "WHERE sc.published = 1 AND tvtpl.templateid = sc.template AND tv.name = '$overrideTV'";
$results = $modx->dbQuery($sql);
while ($row = $modx->fetchRow($results))
{
$overrideAlias = $modx->aliasListing[$row['id']]['alias'];
$overridePath = $modx->aliasListing[$row['id']]['path'];
switch ($row['value'])
{
case 0:
$o = preg_replace("#((href|action)=\"($baseUrl)?($overridePath)?|$myDomain$baseUrl$overridePath/?)$overrideAlias$furlSuffix#", '${1}' . $overrideAlias, $o);
break;
case 2:
$o = preg_replace("#((href|action)=\"($baseUrl)?($overridePath)?|$myDomain$baseUrl$overridePath/?)$overrideAlias$furlSuffix/?#", '${1}' . rtrim($overrideAlias, '/') . '/', $o);
break;
}
}
}
if ($makeFolders)
{
// Replace container links
foreach ($modx->documentListing as $id)
{
if (count($modx->getChildIds($id, 1)))
{
$overrideAlias = $modx->aliasListing[$id]['alias'];
$overridePath = $modx->aliasListing[$id]['path'];
$o = preg_replace("#((href|action)=\"($baseUrl)?($overridePath)?|$myDomain$baseUrl$overridePath/?)$overrideAlias$furlSuffix/?#", '${1}' . rtrim($overrideAlias, '/') . '/', $o);
}
}
}
}
}
If a page is marked as a folder in the modx system, it should be only seen as /dir/ and not /dir.html (can turn off)
Think about documents with comments, they need to be marked as directory because comments are stored in as child document.
need to check the "OnWebPageInit" box in the System Events tab.
1) If you switch Friendly URLs off, it redirects /page.html and /page to /index.php?id=48 - so essentially, this enforces the options that have been selected.
2) Visiting www.domain.com redirects to www.domain.com/index.html - a good and useful anti-duplication feature.
2) I was actually doing it the opposite way "# 301 Redirect /index, /index.html to root folder / (no page in url)". SE’s see www.comain.com/ as the root of the whole website. They see /index.html as a different document. It would be a bad idea to 301 redirect the root of the website to a document in my opinion. Instead /index.html will redirect back to the root www.comain.com/.
$strictURL = $modx->makeUrl($modx->documentIdentifier);
$strictURL = str_replace(".css.html",".css",$strictURL);
$strictURL = str_replace(".xml.html",".xml",$strictURL);
# 301 Redirect /folder to /folder/ to mimic apacheThat too should be optional, I’d prefer /news to /news/
But you misunderstand. 1 & 2 are not feature requests, they are features that I have discovered already work whilst testing.

Incidentally, it’s probably worth pointing out that I hardwire references to feed.xml and stylesheet.css where I use them because [~11~] adds the .html (which I don’t want)!
To make the site_home page go the other way, you’d probably have to build the target strict URL of the site_home, and change the headers accordingly. You have to be careful here as it’s easy to end up with an infinite loop; indeed in testing a possible solution my browser detected the infinite loop and no longer follows 301 redirects for my test domain. I’m hoping a reboot will solve that but in the meantime have reverted the change I made.
Well, you can’t literally check for index.* because that might not be the name of the home page. That’s why I tried building a comparison string based on $modx->makeUrl(1); - although again, the home page might not be 1 - I just couldn’t find the proper variable for site_home. I think this line will work, I just got something simple wrong and can’t do anymore tests for a bit.
I was actually thinking of a simple conditional statement to check and see if the URI was www.domain.com/index* and doing the redirect and if it was domain.com/ then the main plugin code would be skipped. I think that