Clean URLs

Please post answers on the most frequently asked questions about CMSimple
Post Reply
cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Clean URLs

Post by cmb » Sat Feb 02, 2013 1:35 pm

Hello Community,

some of you might prefer to have clean URLs with CMSimple. There is a recipe in the CMSimple Wiki, but this is somewhat outdated and has some drawbacks. Inspired by kweku's request, I had a look at this issue a while ago, but stopped halfway. Now another user asked for having clean URLs, so I had a further look at it, and it seems it's quite possible to have them without any particular problems or restrictions. However, it is possible that some plugins are not compatible.

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). You must not use subsites -- the following recipe will not work with those.

This recipe handles CMSimple_XH 1.5.x, but it should work for other versions and variants of CMSimple also.[1]

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 and $sl

    Somewhat at the beginning of cmsimple/cms.php you'll find the following line:

    Code: Select all

    $subsite_folder_array = explode('/',str_replace($_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI'])); // creates array                          
    Replace it with:

    Code: Select all

    $subsite_folder_array = explode('/', $_SERVER['SCRIPT_NAME']); // creates array                          
    Then find:

    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/cms.php. Replace it with the following:

    Code: Select all

    function a($i, $x) {
        global $sn, $u, $cf, $adm;
        if ($i == 0 && !$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 : '') . '">';
    }
  • Add a "base" element
    Find function head() in cmsimple/cms.php. Add the following lines before the return statement:

    Code: Select all

        global $sn;
        $t .= tag('base href="http'
            . (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 's' : '')
            . '://' . $_SERVER['SERVER_NAME']
            . ($_SERVER['SERVER_PORT'] < 1024 ? '' : ':' . $_SERVER['SERVER_PORT'])
            . $sn . '"') . "\n";
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). To change that for tinyMCE you have to extend your init file with the following:

Code: Select all

    document_base_url: "%BASE_URL%",
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 admin_menu() in cmsimple/cms.php and replace the following line:

Code: Select all

        $t .= '<li><a href="' . $sn . '?' . $su . '&' . $changeMode . '">' . $changeText . '</a></li>' . "\n";
with:

Code: Select all

        $t .= '<li>' . a($s, $changeMode) . $changeText . '</a></li>' . "\n";
For some convenient testing I've assembled a modified version of CMSimple_XH 1.5.6: http://3-magi.net/downloads/CMSimple_XH ... anURLs.zip

Christoph

PS: I've noticed some problems in IE. The solution is to use an absolute URL instead of an absolute path reference for the `base' element. Fixed in the description above.

PPS: Due to the use of SERVER_NAME and SCRIPT_NAME the solution will not work for some kinds of redirected domains (server internal redirects relying on symlinks).

PPPS: [1] There's an own recipe for CMSimple_XH 1.6.
Last edited by cmb on Thu Jan 09, 2014 3:46 pm, edited 3 times in total.
Reason: simplified .htaccess; added PS, PPS and PPPS
Christoph M. Becker – Plugins for CMSimple_XH

josde
Posts: 29
Joined: Wed Feb 06, 2013 4:59 pm

Re: Clean URLs

Post by josde » Fri Feb 15, 2013 4:08 pm

Hi Christoph,

can you please explain, which init-file für tinyMCE (init.php or init.js) I have to change and where exactly I have to insert the document_base_url: "%BASE_URL%",

Thanks
Josef

cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Re: Clean URLs

Post by cmb » Fri Feb 15, 2013 5:01 pm

Hi Josef,

you have to edit the init_*.js, that you're using (by default it's init_full.js, but you can change that under Plugins -> Tinymce -> Toolbar). Just change the file this way:

Code: Select all

{
    // General options

    document_base_url: "%BASE_URL%", // INSERT THIS LINE
    theme : "advanced",
...
Christoph
Christoph M. Becker – Plugins for CMSimple_XH

josde
Posts: 29
Joined: Wed Feb 06, 2013 4:59 pm

Re: Clean URLs

Post by josde » Fri Feb 15, 2013 5:19 pm

Hi Christoph,
thanks for your quick answer.
Josef

josde
Posts: 29
Joined: Wed Feb 06, 2013 4:59 pm

Re: Clean URLs

Post by josde » Fri Feb 22, 2013 3:35 pm

Hi Christoph,

can you please help me once more:

I changed the cmsimple/cms.php like described above. On my local machine (Xampp on Windows) it works fine. With the same changed file on my webserver I get the following error:
"Header-Information kann nicht geändert werden - die Header wurden bereits verschickt (die Ausgabe begann in /var/.../cmsimple/cms.php:1)"

Thanks
Josef

cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Re: Clean URLs

Post by cmb » Fri Feb 22, 2013 5:00 pm

Hi Josef,

either there's a BOM in cmsimple/cms.php, or the file doesn't start with <?php. I assume the former is the case, what would explain, why your online server reports the error: since PHP 5.4 such BOMs are ignored by PHP. In earlier versions they are sent verbatim to the webserver, what causes the header section to be terminated.

Christoph
Christoph M. Becker – Plugins for CMSimple_XH

josde
Posts: 29
Joined: Wed Feb 06, 2013 4:59 pm

Re: Clean URLs

Post by josde » Fri Feb 22, 2013 5:12 pm

Hi Christoph,

it was the BOM. Now it works.

Thanks
Josef

blogsash
Posts: 12
Joined: Thu Jun 06, 2013 2:50 am
Location: DE-Rostock
Contact:

Re: Clean URLs

Post by blogsash » Thu Jun 06, 2013 3:04 am

Hello Community,

I'm still a novice what CMSimple terms and've installed this modified version, which is offered here and have a few questions.

I have started a blog at http://blog.alexliebrecht.com and would provide search-engine-friendly URLs. However, when I proceed as described here, I have no success.

In the file there is no line cms.php

Code: Select all

$subsite_folder_array = explode('/',str_replace($_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI'])); // creates array
Or is it when I install the version and have to do anything. But I can not find any settings in this version where I can turn on search-engine-friendly URLs.

Can anyone help me? In advance thank you!

cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Re: Clean URLs

Post by cmb » Thu Jun 06, 2013 9:09 am

Hi,

it seems you have installed the modified version. Indeed there is no such line in cms.php, as it is already replaced in the modified version. The clean URLs do not have to be enabled; there already there: http://blog.alexliebrecht.com/archiv (in default CMSimple_XH this would be http://blog.alexliebrecht.com/?Archiv).

Note, that plugins which create URLs, don't create clean URLs per se. E.g. Realblog_XH creates http://blog.alexliebrecht.com/?blog&rea ... D=3&page=1; it's possible to request http://blog.alexliebrecht.com/blog?real ... D=3&page=1 (note the shifted question), but this is still not what one expects as clean URL (e.g. http://blog.alexliebrecht.com/blog/tagcloud-installiert).

If you absolutely want to have clean URLs for the blog, you may consider to set up the blog "manually": a normal CMSimple page for each article including a call to Comments_XH ({{{PLUGIN:comments('name_of_the_article');}}}, and a manually created overview with News or Teaser_XH. You can see such a blog on http://web57.ws/cms/ (with standard CMSimple URLs, what could be changed).

BTW: apparently the forum doesn't work, because there is a folder forum/ on the server. You may try to rename the page for testing purposes.

Christoph
Christoph M. Becker – Plugins for CMSimple_XH

Gert
Posts: 3078
Joined: Fri May 30, 2008 4:53 pm
Location: Berlin
Contact:

Re: Clean URLs

Post by Gert » Thu Jun 06, 2013 10:41 am

Hi blogsash,

the following is not for CMSimple, but only for the plugin RealBlog.

To create "user-friendly" or "clean" url's is not so easy, and I think it's not necessary at all, if you don't want to print the url's as deep link on your business card ;)

To create "search-engine-friendly" url's - that's possible by changing a few lines in the index.php of RealBlog. The title of the entries will appear in the adress line and will be added to the title of the entry-page (<title> ... </title> in the sourcecode).

Try this index.php for RealBlog:

http://www.ge-webdesign.de/userfiles/do ... _index.zip

or have a look here (title in the sourcecode and adress line of the browser):

http://www.ge-webdesign.de/cmsimplereal ... =51&page=1

Gert

PS: The empty spaces will/should be replaced by underscores for this solution, before publishing RealBlog 2.3 ("%20" in the link):

http://www.ge-webdesign.de/cmsimplereal ... =51&page=1

(new download available: http://www.ge-webdesign.de/userfiles/do ... _index.zip)
Gert Ebersbach | CMSimple | Templates - Plugins - Services

Post Reply