Router
Questions answered by this recipe
- How can I make PmWiki urls look different?
- How can I make PmWiki fit into a pre-existing url structure?
- How can I make PmWiki use dashed-lower-case urls instead of CamelCaseUrls?
Installation
Place router.phpΔ
in your cookbook directory.
Add the following lines near the top of your config.php
file.
$aRoute=array(); #Routing instructions go here #$aRoute['PmWiki']='RoutedPmWiki'; include('cookbook/router.php');
Router is most useful with $EnablePathInfo
enabled but also works when it is disabled.
Usage Instructions
Disambiguation for link direction
- A url link
https://somesite....
is outside the wiki. - A wiki link
Group.Page
is inside the wiki. - Outbound = Translating from a wiki link
Group.Page
to a url linkhttps://example.com/Group/Page
- Inbound = Translating from a URL link
https://example.com/Group/Page
to a wiki linkGroup.Page
$GroupUrl
Router adds the page variable $GroupUrl that returns a routed URL to the base page of the current group. Instead of using <a href='{$ScriptUrl}/{$Group}'>{$Group}</a>
in a template file use <a href='{$GroupUrl}'>{$Group}</a>
$aRoute - Routing Instructions
Router expects to find an array of routing instructions in the global variable $aRoute. Routing instructions are processed first to last for inbound links and last to first for outbound links. Changes made by one instruction are passed on the the next instruction.
Routing instructions can be specified in a short and long format
Short Format:
$aRoute['MatchWiki']='MatchUrl';
Long Format:
$aRoute[]=array( 'Mode'=>'BeginsWith' ,'PageName'=>'MatchWiki' ,'Url'=>'MatchUrl' );
Both instructions do the same thing. For an outbound link, they look for a page name that begins with "MatchWiki" and substitute "MatchUrl" when a match is found.
https://example.com/MatchUrlGroup/MatchUrlPage
translates to a pmwiki pagename of MatchWikiGroup/MatchUrlPage
This instruction is symmetrical, so the reverse is true for an inbound link. The short instruction form uses the "BeginsWith" mode for matching.
Modes that currently exist are:
- Symetrical Modes
- BeginsWith
- Contains
- EndsWith
- ExactMatch
- Asymetrical Modes
- RegReplace
- Special Modes
- CamelCaseToLowerCase
Symetrical Examples:
Contains
$aRoute[]=array( 'Mode'=>'Contains' ,'PageName'=>'MatchWiki' ,'Url'=>'MatchUrl' );
https://example.com/MatchUrlGroup/MatchUrlPage
translates toMatchWikiGroup/MatchWikiPage
EndsWith
$aRoute[]=array( 'Mode'=>'EndsWith' ,'PageName'=>'MatchWiki' ,'Url'=>'MatchUrl' );
https://example.com/GroupMatchUrl/PageMatchUrl
translates toGroupMatchUrl/PageMatchWiki
ExactMatch
$aRoute[]=array( 'Mode'=>'ExactMatch' ,'PageName'=>'MatchWikiGroup/MatchWikiPage' ,'Url'=>'MatchUrlGroup/MatchUrlPage' );
https://example.com/MatchUrlGroup/MatchUrlPage
translates toMatchWikiGroup/MatchWikiPage
Also
$aRoute[]=array( 'Mode'=>'ExactMatch' ,'PageName'=>'Main/HomePage' ,'Url'=>'' );
https://example.com/
translates toMain/HomePage
But more interestingly, Main/HomePage
translates tohttps://example.com/
for outbound links.
Asymetrical Modes
Asymetrical modes only work in one direction. The direction to apply the routing instruction to is specified by adding another element.
,'Direction'=>'Out' or
,'Direction'=>'In'
The 'Direction' element can be used with any instruction mode.
RegReplace Example
$aRoute[]=array( 'Mode'=>'RegReplace' ,'Search'=>'/^MatchUrl/' ,'Replace'=>'MatchWiki' ,'Direction'=>'In' );
For inbound links,
https://example.com/MatchUrlGroup/MatchUrlPage
translates toMatchWikiGroup/MatchUrlPage
But this instruction is limited to only inbound links by the ,'Direction'=>'In'
part of the routing instruction. It is skipped when translating pagenames to URLs for outbound links because the regex doesn't translate the URLs correctly in the reverse direction.
So a related outbound instruction is needed.
$aRoute[]=array( 'Mode'=>'RegReplace' ,'Search'=>'/^MatchPage/' ,'Replace'=>'MatchUrl' ,'Direction'=>'Out' );
Now MatchPageGroup/MatchPagePage
correctly translates tohttps://example.com/MatchUrlGroup/MatchPagePage
The RegReplace instruction simply passes the values of 'Search' and 'Replace' to the php preg_replace()
function. If you specify a 'Limit' element in the routing instruction, that value will also be passed to preg_replace()
.
Special Modes
Special modes mess with urls in an extra special way. :)
CamelCaseToLowerCase Example
The 'CamelCaseToLowerCase' mode changes the entire pmwiki url structure from CamelCaseUrls to dashed-lower-case-urls. It functions in both directions unless you specifically add a 'Direction' element to the routing instruction.
$aRoute[]=array( 'Mode'=>'CamelCaseToLowerCase' );
https://example.com/url-group/url-page
translates toUrlGroup/UrlPage
and vice versa
When using CamelCaseToLowerCase in conjunction with the Apache mod-rewrite module, be sure to change your .htaccess to send all urls that start with lower case characters to index.php
.
Create your own routing modes
Add a function named RT_ModeName
to config.php
before including router.php
. The first parameter is the path and the second parameter is an array that contains a single routing instruction. The 'Direction' element is always present and indicates whether the path you are working on is for an inbound or outbound link. Router will add the 'Direction' element to the instruction array if it doesn't already exist. Be sure to return $path even if you don't change its value.
Values passed to the function in $aline['Direction'] are either 'In' or 'Out'. The rest of the $aline array keys are determined by your RT_ function.
The following function creates a routing mode named "Redirect"
$aRoute[]=array( 'Mode'=>'Redirect' ,'In'=>'Main/HomePage' ,'Out'=>'https://example.com/' ); /// /// Http Redirect to specified location when path matches /// /// $path: page name at various stages of translation in either Wiki or Url format. /// $aline: array containing a single routing instruction. /// function RT_Redirect($path,$aline) { if ('In'!=$aline['Direction']) { return $path; } if ($path==@$aline['In']) { header('Location: '.@$aline['Out'],TRUE,301); } return $path; }
Release Notes
- 2007-12-19r12beta - Now only needs to be included from
config.php
- 2007-11-20r11alpha - initial release
Comments
Um... Excuse me for incompetence, but can I do something using this recipe if I want to have page names to be exactly as they are named (like "Main/Wiki sAnDbOx") or (if having spaced filenames arent possible) to substitute "_" for " " and at the same time substitute "__" for "_" (to keep underscores if they are present)?
Kriss
You can have a url of https://example.com/Main/Wiki%20sAnDbOx
match a wiki page name of Wiki.SandBox
.
If there are just a few pages, hard code the translations with ExactMatch mode instructions.
Otherwise the CamelCaseToLowerCase mode would be an example to start from. But you would need a repeatable method to match Url names with Wiki names.
MagicBeanDip
See discussion at Router-Talk
User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.