Hello Community,
the following is a recipe to have clean URLs with CMSimple_XH 1.6. Note, that plugins might still produce "classic" URLs.
Requirements
You need an Apache server with mod_rewrite enabled, and need to be confident editing source code files (see
http://www.cmsimple-xh.org/wiki/doku.ph ... es_offline).
Prepare your site to have almost clean URLs
At first change the configuration setting of Uri -> Seperator to "/". Then have a look at your page URLs. If the page headings contain special characters, you have to get rid of them; see
http://www.cmsimple-xh.org/wiki/doku.ph ... n_headings.
I recommend this step anyway, even if you're not interested in clean URLs, as it makes the URLs better readable and exchangeable, and is necessary to make deep links from some platform (such as Facebook) working.
Add the necessary rewrite rules for the webserver
Add a file .htaccess in the root folder of the CMSimple installation (right beside the main index.php). Insert the following:
Code: Select all
RewriteEngine on
# Do not rewrite requests to existing directories and files:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Everything else is a CMSimple_XH page request,
# so shift the subfolders to the beginning of the query string
RewriteRule ^([A-z]{2}/)?(.*)$ $1?$2 [QSA]
Modify CMSimple to cater for the clean URLs
- Change $sn
Find the following code in cmsimple/cms.php:
Code: Select all
$sn = preg_replace(
'/([^\?]*)\?.*/', '$1',
sv(($iis ? 'SCRIPT_NAME' : 'REQUEST_URI'))
);
and replace it with:
Code: Select all
$sn = preg_replace('/index\.php$/', '', $_SERVER['SCRIPT_NAME']);
- Change the links that CMSimple produces
Find function a() in cmsimple/functions.php. Replace it with the following:
Code: Select all
function a($i, $x)
{
global $sn, $u, $cf;
if ($i == 0 && !XH_ADM) {
if ($x == '' && $cf['locator']['show_homepage'] == 'true') {
return '<a href="' . $sn . $u[0] . '">';
}
}
return isset($u[$i])
? '<a href="' . $sn . $u[$i] . (!empty($x) ? '?' . $x : '') . '">'
: '<a href="' . $sn . (!empty($x) ? '?' . $x : '') . '">';
}
Find function ml() in cmsimple/functions.php, and replace it with the following:
Code: Select all
function ml($i)
{
global $f, $sn, $tx;
$t = '';
if ($f != $i) {
$t .= '<a href="' . $sn . $i . '">';
}
$t .= $tx['menu'][$i];
if ($f != $i) {
$t .= '</a>';
}
return $t;
}
- Add a "base" element
Find function head() in cmsimple/tplfuncs.php. Add the following lines before the return statement:
Code: Select all
global $sn;
$t .= tag('base href="' . CMSIMPLE_URL . '"') . PHP_EOL;
Now the basic modifications are done and you can test your site. When you navigate around even in second languages everything should be alright and you already have clean URLs.
Duplicate Content
You might have already noticed, that the old URLs (those after switching to
almost clean URLs) still work. That's basically no problem, but search engines don't like this
duplicate content (i.e. the same page accessible via more than one URL). The solution is to insert a
canonical link element. Please note, that
ge_canonical doesn't cater for clean URLs.
So put the following to
userfuncs.php:
Code: Select all
<?php
/**
* Returns the canonical link tag. Works only for clean URLs.
*
* @global string The absolute path to the directory of the folder which contains index.php.
* @global string The GET parameter of the current page.
* @global array The GET parameters of all pages.
* @param array $ignoreParams The paramaters to ignore in the canonical URL (e.g. print).
* @return string The (X)HTML.
*/
function canonical($ignoreParams = array())
{
global $sn, $su, $u;
$params = array();
$allParams = explode('&', $_SERVER['QUERY_STRING']);
foreach ($allParams as $param) {
$param = explode('=', $param);
$key = $param[0];
if ($key != $su && !in_array($key, $ignoreParams)) {
$params[$key] = isset($param[1]) ? $param[1] : null;
}
}
ksort($params);
$newParams = array();
foreach ($params as $key => $value) {
$newParams[] = $key . (isset($value) ? "=$value" : '');
}
$baseURL = 'http'
. (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 's' : '')
. '://' . $_SERVER['SERVER_NAME']
. ($_SERVER['SERVER_PORT'] < 1024 ? '' : ':' . $_SERVER['SERVER_PORT'])
. $sn;
$canonicalSU = $su == $u[0] ? '' : $su;
$url = $baseURL . $canonicalSU;
if (!empty($newParams)) {
$url .= '?' . (empty($canonicalSU) ? '&' : '')
. implode('&', $newParams);
}
$link = tag('link rel="canonical" href="'
. htmlspecialchars($url, ENT_COMPAT, 'UTF-8') . '"') . "\n";
return $link;
}
/*
* Insert the canonical link to the "head" element, when not in admin mode.
*/
if (!$adm) {
$hjs .= canonical(array('logout', 'print'));
}
?>
Please note, that the argument to canonical() at the bottom of the code should be extended by further GET parameters, which should be ignored in the canonical link. Which one, depend on extensions you're using. E.g. for Calendar you might change the line to:
Code: Select all
$hjs .= canonical(array('logout', 'month', 'print', 'year'));
Missing stylesheet for the editor
When you log in to the back-end, you'll notice, that the template's stylesheet isn't used by the editor any more (tinyMCE and CKeditor)[1]. To change that for tinyMCE you have to extend your
init file with the following:
Toggling between edit and view mode in the back-end
Switching to view mode in the back-end will change to the "non clean" URLs. That's no problem, but you can change this behavior easily. Find function XH_adminMenu() in cmsimple/adminfuncs.php and replace the following line[2]:
Code: Select all
'url' => '?' . $su . '&' . $changeMode,
with:
Code: Select all
'url' => $su . '&' . $changeMode,
Enjoy,
Christoph
PS: [1] It is used for top level pages, however, but not for subpages.
PPS: [2] Since CMSimple_XH 1.6.2 the line is:
Code: Select all
'url' => $sn . '?' . $su . '&' . $changeMode,
what has to be replaced with:
Code: Select all
'url' => $sn . $su . '&' . $changeMode,