The wikitools approach is great in that its modular, relying on Drupal content types and input filters and other modules to work to together to provide a complete wiki. Its a very Drupal way to do it! ;-) But it presents one irk point for me, although I imagine that not everyone cares about this point. I call it the "canonical URL" problem.

Here is what I want: I want one canonical URL to refer to each wiki page. While other URLs may be able to land you on the same page, only this one URL should be displayed in the location bar and used in links on other wiki pages.


(1) If I type /wiki/My_Wiki_Page the location bar, it doesn't revert to /node/38 or something like that.
(2) I include a link in wikitext (ie. [[Other Page]]) it should generate a link to /wiki/Other_Page and no other link.

Obviously, #2 is dependent on the input filter that your using. This is one of the reasons that this is a difficult problem for wikitools, since it doesn't provide all of the parts.

#1 can be done with pathauto, but problematically. You can configure Pathauto to generate aliases in the same format as wikitools uses to search for node titles. But this makes your pathauto config completely geared at Wiki style aliases. What if you want to use Pathauto in a more usual way for the rest of your sites content? Ie. I want lower-case conversion for my blog entries by not wiki pages.

Also, pathauto contains some filtering support (which I believe is essential) that the node title look-up in wikitools does not. For example, putting non-alphebetic characters or non-English characters are not filtered in anyway by wikitools for the title look-up. But they *may* be filtered in your wikitext filter and pathauto config.

In a normal configuration, Title/URL conversion can happen 3 different places, all in different ways:

(1) By Wikitools looking up a title based on a URL (ie. wiki/My_Page_Title)
(2) By your input filter, generating links (ie. [[My Page Title]])
(3) By pathauto generating the alias to the page (ie. wiki/My_Page_Title)

This all works pretty normally, until we go beyond just spaces. Let's say in my wikitext, I have a link that looks like [[What should I do now, John?]]. For example, let's say this creates a link like "/wiki/What_should_I_do_now%20, John?". Clicking on this link, will bring you to a create node page which give the title "What should I do now, John" (without the question mark). Saving the page, pathauto decides to remove the "comma", so you get an alias like "/wiki/What_should_I_do_now_John". So, we now have 3 different names for the same page..

Anyway, do you see where I'm going with this?

I don't know what the solution is. But my vague idea, is that there should be a function in wikitools which creates the "canonical URLs" for wiki pages, which supports filtering for non-alphabetical characters and unicode like pathauto does. Then there should be support for hooking into the common wikitext filter modules and the pathauto module so that this function can optionally be used. This will more than likely require participation from the other projects.

I'm going to do some more experimentation and I'll comment back if I've got any good ideas. If anyone else comes up with something, please let me know! Thanks.


dsnopek’s picture

Status: Active » Needs review
2.18 KB

I have the beginnings of a solution to this problem...

Attached a patch, that allows wikitools to create aliases for wiki nodes under the wiki path. It uses wikitools_wikilink_drupal_path() to come up with the alias destination. When using pearwiki_filter, there is an option you can enable to cause it to also use wikitools_wikilink_drupal_path() for links created from wiki syntax. So, the aliases and the links created will match!

This can be used with pathauto if you disable pathauto for any of the wiki node types. This can be done (not entirely obviously) by making both the default pattern and the node type pattern empty. This way pathauto can continue to be used for all other node types.

Comments on the patch are welcome! I'd gladly make any changes necessary for inclusion upstream. Thank you!

cwgordon7’s picture

Status: Needs review » Needs work

I believe you are going about this the wrong way; we should be changing the response of the wikitools page from redirect to inline display, imo.

cwgordon7’s picture

Version: 5.x-1.2 » 6.x-1.0

Plus, new features go into the 6.x version, please :). Then they can be backported.

dsnopek’s picture

741 bytes

Displaying inline is a brilliant idea! Then there is no need for aliases.

Attached is a patch (against 6.x-1.0 this time!) that attempts to do this, but I don't like it for two reasons:

  • Setting $_GET['q'] seems wrong. But I couldn't come up with an other way to get the tabs shown. menu_local_tasks() is what gets the tabs, and it calls menu_get_item() without any arguments, which defaults to using $_GET['q'] as the path.
  • While sub-page URLs do work with the option turned on, the links on the tabs point to the node/id/tab URL. This is another symptom of setting $_GET['q'].

Do you have any advice? I've only ever displayed the contents of a node using theme('node') which doesn't deal the tabs, so I'm kind of lost.


dsnopek’s picture

Actually, I have an idea but I won't get to try it until later... What if the wikitools module implemented its own sub-pages (callbacks in wikitools_menu() returning '$wiki_path/%title/subpage', etc) based on wikitools_subpages(). That way these sub-pages belong to the current $_GET['q'].

There's two worries have about this, but I won't know until I try it in practice: (1) After turning on sub-pages, drupal may not recognize the new menu entries. I usually have to uninstall/reinstall modules that I'm working on to get new menu stuff to register. (2) Permissions to see sub-pages may be out of wack since we will have a surrigate menu item.

What do you think?

starflower’s picture

That sounds great, at least for now - any chance I could get a version of the patch for 5.x-1.2? I can't use 6 yet due to lack of support for a stable version of Gallery2. I don't care so much about the sub-page URLs (though of course it'd be nice), I just need a good option for the main page URLs.



cwgordon7’s picture

As said, after this goes into 6.x, this can be backported.

dsnopek’s picture

1.28 KB

I've done a bunch of experimenting and messing with hook_menu() like I described in comment #5 is just way too problematic.

In order to get the menu_router entries working right, I actually have to pull the existing 'node/%/subpage' entries and modify them for the wiki path. Since the new entries only get added at module install, you have to enable/disable wikitools every time you do something that could change the subpages.

Comparatively, setting $_GET['q'] is the best of all evils, so I'm going to stick with that. I've added to the original patch a wikitools_proprocess_page() function which will re-write the links in the tabs to reflect the wikipath. So far this is the best ideas I've got! Please let me know what you think.

As far as backporting to 5.x, I'd be happy to do that once this patch is accepted, because we use 5.x in production so I'll need to do that to use it anyway.


dsnopek’s picture

1.32 KB

I just realized that my previous patch neglected to check that wikitools_subpages_handling() == 'url' when re-writing the tab links. Here is a new version that does.

cwgordon7’s picture

Ok, please use menu_set_active_path() as mentioned above.
Also, please comply to coding standards. In particular no space after if (.

dsnopek’s picture

1.33 KB

Changed! Thanks for the heads up on menu_set_active_item(), having an API to set $_GET['q'] certainly makes me feel better about doing that!

Please let me know if you need anything else. Thank you!

cwgordon7’s picture

Please conform to coding standards. See, and/or use the coder module.

dsnopek’s picture

1.33 KB

I apologize! I did read the coding standards yesterday, prompted by your post, and I thought that all I had going on was the space in the if(), but I see now that I was wrong.

The coder module is very helpful, thanks for the suggestion! Attached is a patch where I fixed all problems it reported in my changes.

dsnopek’s picture

Using this in practice for a little while has revealed a number of problems with this approach.. Namely, it is very easy to end up on the "node/$node->nid" page.

Here are a number of common situation, after which you will be forwarded to "node/$node->nid":

  1. You're browsing the wiki while not logged in, you see something you want to edit, so you log in using the login form on the sidebar.
  2. You click over to the edit tab, then save your changes.
  3. You leave a comment.

I believe its possible to hook into all these situations (like the "talk" module does for comments) and instead forward you to the wikitools_wikilink_drupal_path() page. But anything else we don't don't think up in advance, will have this problem. So, ideally, we'd want to check when you are going to "node/$node->nid" which is a wiki page and forward you to the wikitools_wikilink_drupal_path() page.

One way to do this is with aliases, per the way my first patch worked. I'm not currently aware of another way, but I'll be doing some research in the next couple of days, and I'll see what I can find.

dsnopek’s picture

2.67 KB

Ok! I have new patch which solves the problems I was having in practice with the old patch, as described in comment #14.

There are two changes:

  • We redirect from "node/$node->nid" to the location on the wiki path. This is done as early as possible in hook_init(), using code adapted from the path_redirect module.
  • The tab link rewriting stuff has been removed. Since it is so easy to break the illusion that you're on a tab of the document on the wiki path (ie. if you preview a comment, or get an error, etc..), I decided it wasn't worth going through the trouble. If anything it would just lead to more confusion because the URL could change in unexpected ways.

I have a feeling that I am finally closing in on the "right" solution. As always, comments are welcome! Thanks!

cwgordon7’s picture

Hm. I don't think this is the right way to do this, it is contrary to wikitools' philosophy of remaining lightweight. In particular, it should be able to be turned off (the redirection). Secondly, I challenge that this is the right way to redirect at all, why are you doing wacky stuff with base_path...?

dsnopek’s picture

2.68 KB

Certainly its possible to make it turn-off-able. In response to "why are you doing wacky stuff with base_path...?": Its because I copied that code from path_redirect which did it that way. ;-)

I guess my feelings about the "right-ness" of this approach had less to do with how it was done (the code), but rather what it was doing (the behavior).

Attached is a patch which removes alot of the cruft copied from path_redirect (although, I don't know if any of it was necessary in some cases, ie. page caching) and makes the redirect optional.

If you have any suggestions for how this could be done better, I would appreciated it greatly! Just pointers to code or functions or docs would be enough.

Thank you again, especially for your patience, while I try to work this out.

cwgordon7’s picture

Why not implement hook_boot instead of hook_init? Would this not have significant performance effects? Also, if we're loading the node now, would it not make sense to load it through the admittedly heavier (but statically cached) node_load function, so that when we're running menu_execute_active_handler, it is much faster?

Otherwise, looking pretty good. :) Also, please set this to patch (code needs review) when you make a change that requires review, that way it'll make sense on my issue queue.

dsnopek’s picture

Thanks for the suggestions!

I just tested using hook_boot() and it crashes saying "Fatal error: Call to undefined function node_load()". It appears that by the time this hook runs, the node module hasn't yet been loaded.

According to the docs for hook_boot(): "This hook is called before modules or most include files are loaded into memory." But for hook_init(): "when this hook is called, all modules are already loaded in memory."

I'm a little confused about your comments regarding node_load(), because I am already using it. Or do you mean in a different place or way? I read through the code for node_load() and it appears to me that the way its used in this patch would cause the node to be statically cached.

In an unrelated note: I've been thinking about the checkbox that's added to the admin page. From a UI perspective, this would look more attractive if it were added to the wikitools_options list of checkboxes. I was thinking of calling it "Node Redirect" and changing "Automatic Redirect" to be "Move Redirect" to reduce ambiguity (but leaving its internal name as "auto redirect" as to not break upgrades). What do you think? Or should I just leave it the way it is?

No new patch for today! :-)

Leonth’s picture

This seems to be a clunky workaround. The "canonical URLs" are not really recognized by Drupal, so (for example) links in "most popular content" or "navigation" blocks still use the classic node/nid url. When users click on them they do get redirected to the right canonical url, but this is the worst thing for SEO and usability (nobody likes jumping around redirects, especially search engines).

I believe the right solution is to create a token usable by token.module which represent the canonical url. Then we can use the token in pathauto settings, replacing [title-raw] for node types used as wiki pages.

Leonth’s picture

Oopsie - pathauto strips punctuations *after* getting the data from Token. So any punctuation on the supposed "canonical url" gets removed/replaced according to pathauto settings.

So the best - but probably the most complicated - solution for this, IMO:
1. Create a new token for use with Token module. The token (perhaps [wikitools-wiki-title]?) should represent the "canonical url" (the current wikitools_wikilink_drupal_path() can be used). Punctuations can still be there, it is pathauto's job to strip them.
2. Use the token for all wikipage url patterns in pathauto, so all urls to wikipage nodes now become canonical urls (be sure to tweak pathauto punctuation settings, if you want parantheses and commas in urls).
It appears that pathauto can be configured to accept mixed cases so this is not needed.
3. Create a simple input format that converts everythng in [[...]] to canonical url. Use the function pathauto_cleanstring() if pathauto is loaded - the function ensures that the canonical url is produced if the string inside [[...]] == title of wikipage.

Or, if you can bear lowercase urls, only step 3 is necessary. The future [wikitools-wiki-title] will only differ with [title-raw] in character cases. Just remember to enable the desired punctuations in pathauto and mind the removal of words from title when pathauto constructs urls - those settings define your so called canonical urls.

The only trouble with this approach is that when a link leads to nonexsistent page and wikitools is configured to present node creation form then, the default page title is still the modified url, not the content of the link (e.g [[hey, you!]] will create the page "hey,-you!"). We need to revert the modification made by pathauto by re-replacing all separators.

cwgordon7’s picture

@dsnopek: yes, you are right, I was not thinking, hook_boot will not work. For the node_load thing, I've been thinking about it, and it's not really worth it.

@Leontius Adhika Pradhana: I'm not quite sure I understand your idea. Would this be integrating with pathauto for node URLs, thus making this dependent upon pathauto? Or would we be integrating directly with the token module? For each of these approaches there are problems associated: with pathauto, we would lose "page moved" etc. functionality, and with token, I don't see an idiot-proof way of being able to determine the node from the tokenized path.

Leonth’s picture

Pathauto approach:
That's right - "page moved" won't work anymore. Any other feature (search, creation of new node) will still work. But actually pathauto with Path Redirect module can achieve the same result. Yes the feature will depend on pathauto.

Please let me re-describe my approach. The idea is to use the same function when creating a link and creating a url for a new page:

  1. we make an input format (or perhaps just a flexifilter export) that turns [[How are you, John?]] to <a href="[something]/wiki/How_are_you,_John_">How are you, John?</a> (the url is created by pathauto; use pathauto's function for this).
  2. If "wiki/How_are_you,_John_" exists (path made by pathauto), everything goes as usual.
  3. If "wiki/How_are_you,_John_" does not exist, wikitools deducts the page title from the url. We then use the page title for search and node creation.

I think this is what Mediawiki (the app behind wikipedia) works. dsnopek does it all in the definition of this issue, except that he/she does NOT use pathauto's function. Here is the flexifilter for this functionality:

 a:8:{s:5:"label";s:17:"Wikitools linking";s:11:"description";s:52:"Converts [[wiki-style phrases]] to appropriate links";s:2:"id";s:1:"2";s:7:"enabled";b:1;s:8:"advanced";b:1;s:5:"delta";s:1:"1";s:10:"components";a:3:{i:0;a:3:{s:5:"class";s:22:"flexifilter_chunk_grab";s:8:"settings";a:7:{s:6:"starts";s:2:"[[";s:4:"ends";s:2:"]]";s:11:"pass_limits";i:0;s:14:"case_sensitive";i:0;s:12:"include_rest";i:1;s:4:"step";s:7:"process";s:10:"components";a:1:{i:0;a:3:{s:5:"class";s:24:"flexifilter_advanced_php";s:8:"settings";a:2:{s:4:"code";s:172:"if (module_exists('wikitools') && module_exists('pathauto')) {
  return l($text, wikitools_wiki_path() . '/' . pathauto_cleanstring($text));
else {
  return $text;

Now the problem is where "wikitools deducts the page title from the url". Wikimedia does this by replacing separators (in the example "_") with spaces. [[How are you, John?]] will ask you to create a new page titled "How are you, John " (note the trailing space). The link STILL works even if you forget to change the trailing space with "?" for the new page. It seems that Mediawiki does this - I checked it out in Wikipedia's sandbox.

dsnopeck's approach is very fine for people that do not use pathauto. So I think the best move is to commit dsnopeck's patch and then implement "replacing separators with spaces" as an option.

Token approach:
Please dismiss the token approach, it is too complicated and does not work because pathauto modifies the string from token module before using it.

PS: you can call me Leon :)

cwgordon7’s picture

Ok, I agree. So we should have the pathauto behavior that degrades into dsnopek's idea.

dsnopek’s picture

@Leon: the token thing was my first idea too and I ran into the same problem! :-)

If I'm interpreting your idea correctly, its just configuring your input filter and pathauto in a particular way? Or does it require changes to wikitools that I missed. Anyway, I do use pathauto, but I want my wiki pages to follow a scheme different than pathauto. For example, I don't want any words removed or transliterated in wiki titles -- but I do for Stories or blog posts. In practice, I want the wiki URL to be as true to the title as possible, which just means underscores for spaces and URL encoding for special characters.

I understand the "URLs not being recognized by Drupal" concern. This is why my first patch created aliases, rather than doing the inline display and redirect stuff. Personally, I wouldn't mind keeping that as an option. The way I see my current patch, is just taking the old model (going to a wiki link and redirecting to the node) and reversing it (going to a node and redirecting to the wiki link).

However, I'm only concerned about the location bar and links inside wiki content (which will be followed by search engines correctly) being true to the canonical URL. Other links, like on "most popular content", etc don't bother me because to certain extent, there will *always* be links to the node URL since so many modules internally build "node/$node->nid" links no matter what the alias is set to.

@cwgordon7: Do you have any comments about my ideas with regard to the checkbox on the admin page?

Thanks guys! I'm glad this discussion is getting some attention.

Leonth’s picture

For example, I don't want any words removed or transliterated in wiki titles -- but I do for Stories or blog posts. In practice, I want the wiki URL to be as true to the title as possible, which just means underscores for spaces and URL encoding for special characters.

That is going to be the problem of Pathauto. Perhaps you can request a feature so that some paths can be treated differently.

This is why my first patch created aliases, rather than doing the inline display and redirect stuff.

I missed the first patch, I thought it is the same as the last :(. This is almost identical to my approach, but that approach:

  1. does not require such changes in Pathauto: great!
  2. uses wikitools_wikilink_drupal_path() instead of pathauto_cleanstring(): perfectly OK, even better
  3. does not solve the "page moved" problem. Now this is bad. We need to integrate with Path Redirect (what a headache) or update wikitools_wikilink_drupal_path() to also search for page moves. Both solution breaks "Page moved:..." messages.

So there are now 3 approaches to solve this problem:

  1. create url aliases for all paths without pathauto (dsnopeck's 1st patch). "page moved" a problem.
  2. redirect "node/xx" to "wikipath/page_name", then display node content inline at "wikipath/page_name" (dsnopeck's 2nd + cwgordon7's approach). Links are not aliases, so "genuine node/xx" urls in blocks, menus etc. don't get converted to "wikipath/page_name".
  3. create url aliases with pathauto. Wiki urls get the same Pathauto treatment as any other nodes (unless Pathauto changes). "page moved" works via Path Redirect but messages can not b displayed.

I don't think any is clearly superior than any other. Should we seek to implement all 3? :( Or some hybrid, 1+1>2 approach?

dsnopek’s picture

There are no problems with using with pathauto with either of my approaches (alias or inline display). You just have to disable pathauto for the wiki node types and then it stays out of your way. See #239556: documentation for disabling pathauto per node type.

Personally, I prefer approach #2. Aliases will still result in redirects from "node/$node->nid" to the alias name. This approach seems the cleanest and self contained to me. But, it might make sense to allow the user to choose approach #1 if they want.

Approach #3 seems to have more to do with the input filter and pathauto than wikitools. As far as I can tell, you should be able to do this approach right now without any code changes to wikitools.

Leonth’s picture

I think I now thoroughly understand the idea! I think approach #1 and #2 should both be committed and be made optional. And we should really document these 3 approaches, with its advantages and disadvantages... Sorry for taking your time explaining to me.

Small improvement: use 301 permanent redirects for the node/xx paths (better for search engines).

dsnopek’s picture

It was no problem! I think I went through the exact same series of possibilities -- even in the same order ;-) -- as I have been working on this problem and testing out the solutions in practice.

As far as using 301 redirects, I think that would be problematic. The browser will cache 301 redirects, so if the user changes the title of a wiki node, any users that have previously been redirected, will continue to be redirected to the wrong URL.

If we do choose to provide approach #1 (aliases) as well, we will need to decide if we want to attempt to provide support for the potential "sync" issues. For example:

  • If the user created pages without having the alias generation turned on, and they turn it on, do we attempt to bulk generate the aliases?
  • If the aliases come out of sync in some way (ie. another user naively edits them in the "URL alias" admin page), do we provide a way to re-generate them?
  • If the user is using alias generation, but then decides to turn it off (possibly because they have such a large number of them and its slowing things down) do we provide a way to bulk remove them?

Of course, we can choose to ignore this aspect of it and just leave it up to the user to correct any sync issues. Which would be fine by me! ;-) I'd like to hear cwgordon7's opinion, however, before putting together a new patch.

Approach #2 has as atleast one of its virtues being easy to turn on and off. If the redirects prove to be undesirable at some point, the user can disable them without any side-effects. It also leaves the job of maintaining the idea of the wiki path to wikitools alone, while allowing other modules (path and pathauto) to do the job they were intended to do for other content. This is the reason that I now prefer this approach.

Thanks again for contributing to this discussion! I think the end result can only be improved by hearing the needs of all interested parties.

Leonth’s picture

Status: Needs work » Needs review

Now that you said that, approach #1 seems to be problematic. I don't think wikitools should handle those path-syncing issues, it is too much work and and too much deviation from the purpose of wikitools. Maybe we should not implement this because it will cause confusion if those sync problem arises.

About the 301 redirect: That's right... If we use 301 redirects it will be very easy for vandals to change titles in wiki pages and screw a lot of things.So no permanent redirect then.

I read and tested dsnopek's last patch, everything seems to be ok. Waiting for cwgordon's reply :)

Rush_iam’s picture

Is this patch is still needed for 6.x-1.1?
How to apply it to the new version?

nirvanajyothi’s picture

I dont think so. The URLs point to .com/wiki/title with new wikitools.

emok’s picture

I think I have been using a solution similar to number 3 in #26 (Pathauto and a new Freelinking filter/plugin). My wiki is a bit "internal" so I have not required all features found on some wikis, e.g. I do no coloring based on whether a link target exists or not. (Then it is OK to cache the filtered pages.)

1. Freelinking turns [[The page]] into a reasonable guess (using Pathauto's transliteration or a custom table) of the real url_alias (by default set by Pathauto). In my case this is an ASCII-only, lowercase url. My Freelinking-plugin doesn't even search for the node to see if it exists, during filtering. It is essential that aliases use the "base directory" of the wiki, e.g. /mywiki/the_page.
How your [[ ]]-filter (e.g. Freelinking or Flexifilter) should treat non-existing nodes is a matter of taste, I leave all the handling up to Wikitools.

2. When Drupal recieves a page request like /mywiki/the_page, two things can happen:
a) The alias exists an you see the node, just like on non-wiki nodes. For me even some simple transliterations seems to work with core/Pathauto aliases – "the_päge" is OK to use instead of "the_page".
b) Because of the "/mywiki/"-prefix Wikitools will wake up and do a more extensive search. If it finds a node with a perfectly matching title, it redirects. If only an old revison's title matches it shows the Page moved message. The matching can fail in some cases, e.g. with a "?" in the title and URL Wikitools does not get the "?" and does not find the nearly-matching title. Although it would make the query slow, perhaps the search must run node titles through some transliteration/simplification to increase the chance of finding the node?

If no page is found, Wikitools prompts to create the page. Here I guess an improvment to Wikitools would be to always propose a title with the first character upper-case even if the URL was lowercase.

As already pointed out by dsnopek in #25 this approach will require that you can make Pathauto give you all aliases like you want, and that they start with the base path that Wikitools listens to. So if you want to remove certain words from titles (to get aliases) only on some parts of your site (some content types I presume) then a small improvement in Pathauto seems like the best solution in my opinion. Maybe a checkbox per node-type, "Do not block any words in URLs of this type" or the opposite?

I guess I should post somehting to the Freelinking module about my additions to it, but maybe it is possible also using some other filter or Flexifilter. I attached my plugin for Freelinking 6.x-3.0-alpha1 here in case it will help anyone understand what I mean.
IMHO there is no need to change Wikitools, though two ideas for improvements were mentioned in b) and just after. Or if you decide to change Wikitools then I'd appreciate options to keep it doing (as little) as it is now.

cwgordon7’s picture

I haven't committed this patch because I'm not convinced that this will not cause an infinite redirect loop on sites without pathauto. I intend to test it to make sure such a redirect does not occur - or if it does occur, disable the setting for sites without path/pathauto, or at least provide a descriptive warning.

hba’s picture

Hi guys. dsnopek's patch seems like just what I'm looking for. Are there any plans on committing the patch any time soon?

TripleEmcoder’s picture


dsnopek’s picture

Version: 6.x-1.0 » 6.x-1.3
3.03 KB

I don't know if anyone is still interested in this functionality, but I'm still using it on my site! Here is an updated patch that works for wikitools version 1.3.

dsnopek’s picture

3.37 KB

Here is an updated version of this patch which correctly takes the language of the node into account when building the redirect url. This is important because the wiki path is language specific.

Ie. a node with nid 31, a title "Page 1" and language set to "en" will be found when doing:

But not:

So visiting this URL:

... should redirect all the way to That's what this latest patch accomplishes.

kenorb’s picture