Ok, so I was trying to find a way to do custom routes so some posts could subdirectories of /content/writing but not show /writing in the URLs.
The Kirby docs about routing explain part of this, but not exactly how to handle the images in those content directories.
After a couple of hours, here’s what I came up with. It seems to work, but I’d love feedback and am also posting this in case it helps other people.
The structure of the content looks something like this:
– content
– -- writing
– -- – writing.txt
– -- – writing1.png
– -- – writing2.png
– -- – post1
– -- – -- post1-1.jpg
– -- – -- post1-2.jpg
– -- – -- post.txt
– -- – post2
– -- – -- post2-1.jpg
– -- – -- post2-2.jpg
– -- – -- post.txt
– -- some-other-page
– -- – page.txt
– -- – image.svg
– -- error
– -- – error.txt
– -- – error-image.gif
Test URLs:
- /error/image1.jpg
- /writing
- /writing/post2
- /writing/writing1.png
- /post1
- /post1/post1-1.jpg
- /post2
- /post2/post2-2.jpg
- /some-other-page
- /some-other-page/image.svg
Routes in config.php
/*
---------------------------------------
Custom Routing
to hide /writing from URLs, while keeping /content tidy
note: Our assumed stub directory is /writing/
cf. http://getkirby.com/docs/advanced/routing#omitting-the-blog-folder-in-urls
---------------------------------------
*/
c::set('routes', array(
array(
'pattern' => '(:any)/([a-zA-Z0-9_-]+(.jpg|.png|.gif|.svg))',
'action' => function($stub, $filename) {
/**
* See if the stub is a real content directory
* If not, see if it is a sub-directory of our
* removed directory: /writing
*/
$page = @page($stub);
if (!$page) {
$page = @page('writing/'.$stub);
}
/**
* If the page exists and is a real page
* (e.g. /error), it will have a url
*/
if( @$page->url() ) {
/**
* See if the file really exists in that content directory.
*/
$file = @$page->files()->find($filename);
if ( !$file || $file == null ) {
/**
* Handle actual 404 missing images
*/
return false;
// return go( 'error' );
} else {
$fileURL = $file->url();
}
}
/**
* Load the actual image or the error page if it doesn't exist.
*/
return go( $fileURL ? $fileURL : 'error' );
}
),
array(
'pattern' => '([a-zA-Z0-9_-]+)', // Page slug is alphanumeric with dashes
'action' => function($uid) {
$page = page($uid);
if(!$page) $page = page('writing/' . $uid);
if(!$page) $page = site()->errorPage();
return site()->visit($page);
}
),
array(
'pattern' => 'writing/([a-zA-Z0-9_-]+)',
'action' => function($uid) {
return go( $uid );
}
),
));
.htaccess
which (among other things) forces trailing slashes
################# REDIRECT LINKS (and Kirby)
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
#############
### Redirects
RewriteRule ^build-2013/?$ /writing-for-beginners/ [R=301,NC,L]
RewriteRule ^services/?$ /what-i-do/ [R=301,NC,L]
RewriteRule ^work/?$ /projects/ [R=301,NC,L]
############
### Security
# block text files in the content folder from being accessed directly
RewriteRule ^content/(.*)\.(txt|md|mdown)$ error [R=301,L]
# block all files in the site folder from being accessed directly
RewriteRule ^site/(.*) error [R=301,L]
# block all files in the kirby folder from being accessed directly
RewriteRule ^kirby/(.*) error [R=301,L]
#############
### Real Files
## if this is an existing folder/file then leave
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
#############
### Cache-busting of JS and CSS versions
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.([0-9\-]+)\.(js|css)$ $1.$3 [L]
#############
### Trailing Slashes
## if no trailing slash then redirect to url with trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]+|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
#############
### The Panel
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^panel/(.*) panel/index.php [L]
####################
### Kirby Site Pages
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/? index.php [L]
</IfModule>