Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

Ever since I've started sharing my blog posts on Twitter, I've wanted to have my own URL shortener. There was no such feature with FlatPress out-of-the-box, so I went ahead and made my own plugin. This post shows how to write a shortener plugin for FlatPress and then how to configure it to redirect from the short to real URLs.

An example of this feature is shortening this post's URL: http://www.igorkromin.net/index.php/2015/02/07/add-a-url-shortener-plugin-to-flatpress/ to this: http://kr0m.in/6joXUt4. When the user goes to the short URL, they are automatically redirected to the long URL.

This post assumes that pretty URLs are being used already and that you have two domain names registered, the real, 'long' domain name, and the 'short' domain name. The examples I will use here are what I have set up for this blog, igorkromin.net and kr0m.in respectively.

Before you get started make sure your hosting provider sets up the short URL as an alias to your long URL in their DNS server otherwise this will not work.

The plugin consists of a handful of PHP files and a Smarty template for configuring options in the admin screen for flatpress. The basic idea with this plugin is to take the FlatPress internal post ID, which contains a unique 8 digit number, convert it to a short ID and use that for the short link. Then, when the short link is received, the short ID is converted back to the 8 digit ID, an the post link is looked up using FlatPress' get_permalink call.

Before going further, lets look at the structure and contents of the plugin. First there is the plugin directory, shorturl, which will be inside the fp-plugins directory. The shorturl directory structure is as follows:
shorturldir.png


The admin.plugin.shorturl.tpl file has the configuration template for the admin screen, the plugin.shorturl.php file has the plugin code to set up the config screen and to add a Smarty filter that generates the short URLs, the redirect.php file is used to redirect short URLs to the real, long URLs and finally the shorturl.php file has some helper functions for shortening FlatPress IDs. The helper functions were taken from this StackOverflow question.



Lets look at the configuration template first. The plugin needs to know the short URL domain in order to generate short links, so that has to be configurable. There is a very easy to use API for adding plugin options so I used that, but it requires a template to generate the config screen.
 admin.plugin.shorturl.tpl
<h2>Short URLs Configuration</h2>
{include file=shared:errorlist.tpl}
{html_form}
<dl>
<dt>Specifies the domain name to use when generating short URLs.</dt>
<dd><input type="text" name="shorturl" id="shorturl" class="input-block-level" value="{$shortdomain}" /></dd>
<p>Add the following to the .htaccess file:</p>
<p class="text-success">
{literal}RewriteCond %{HTTP_HOST} ({/literal}{$shortdomain}{literal}$) [NC]<br/>
RewriteRule ^(.*)$ {/literal}{$flatpress.www}{literal}fp-plugins/shorturl/redirect.php?r=$1 [L,R=301]{/literal}
</pre>
</p>
<p>In a template, generate the URL using a page ID like this:</p>
<p class="text-success">
{literal}{$id|link:short_post_link}{/literal}
</p>
</dl>
<div class="buttonbar">
{html_submit class="btn btn-success" name="save" id="save" value="Save"}
</div>
{/html_form}


This creates a screen that look like this (assuming you have the same theme as me):
shorturlconf.png


Next, the plugin.shorturl.php file adds a filter called short_post_link which eventually calls the psh_shorturl function to generate the short URL. The rest of the code here sets up the admin configuration screen and handles saving of the plugin options.
 plugin.shorturl.php
<?php
require_once('shorturl.php');
/*
Plugin Name: ShortUrl
Plugin URI: http://www.igorkromin.net/
Description: Generates a short URL for a page ID.
Author: ikromin
Version: 1.0
Author URI: http://www.igorkromin.net/
*/
function psh_shorturl($str, $id) {
$shortId = shorturl_toBase(str_replace('-', '', str_replace('entry', '', $id)), 62);
return 'http://' . plugin_getoptions('shorturl', 'domain') . '/' . $shortId;
}
add_filter('short_post_link', 'psh_shorturl', 100, 2);
// Admin Config Panel
if (class_exists('AdminPanelAction')) {
// Add a text description to the plugin config
$lang['admin']['plugin']['submenu']['shorturl'] = 'Short URLs Config';
class admin_plugin_shorturl extends AdminPanelAction {
var $shortdomain = '';
function setup() {
$this->smarty->assign('admin_resource', 'plugin:shorturl/admin.plugin.shorturl');
$this->shortdomain = plugin_getoptions('shorturl', 'domain');
$this->smarty->assign('shortdomain', $this->shortdomain);
}
function onsubmit() {
if (isset($_POST['shorturl'])) {
$domain = $_POST['shorturl'];
$domain = str_replace('http://', '', $domain);
$len = strlen($domain);
if (substr($domain, $len - 1) == '/') {
$domain = substr($domain, 0, $len - 1);
}
$this->shortdomain = $domain;
$this->smarty->assign('shortdomain', $this->shortdomain);
plugin_addoption('shorturl', 'domain', $this->shortdomain);
plugin_saveoptions();
}
}
}
admin_addpanelaction('plugin', 'shorturl', true);
}
?>


The redirect.php file uses the short ID passed in as a URL parameter to get back the original FlatPress ID, it then looks up the post in the FlatPress database and gets it's permalink. Then the browser is redirected to this long URL (permalink).
 redirect.php
<?php
chdir(__DIR__ . '/../..'); // simulate working from blog root
require_once('defaults.php');
require_once(INCLUDES_DIR.'includes.php');
require_once(PLUGINS_DIR.'shorturl/shorturl.php');
if (function_exists('system_init')) {
system_init();
}
else {
plugin_loadall();
}
$baseurl = $fp_config['general']['www'];
if (isset($_GET['r'])) {
$id = $_GET['r'];
$id = shorturl_to10($id, 62);
if (strlen($id) == 12) {
$entry = 'entry' . substr($id, 0, 6) . '-' . substr($id, 6);
$q = new FPDB_Query(array('start'=>0, 'count'=>1, 'fullparse'=>false, 'id'=>$entry), null);
if($q->hasMore()) {
list($id, $e) = $q->getEntry();
$url = get_permalink($id);
header('Location: ' . $url);
}
}
else {
header('Location: ' . $baseurl);
}
}
else {
header('Location: ' . $baseurl);
}
?>


...and finally the shorturl.php script has some helper functions that converts the base-10 ID to a base-62 ID. To make it a little interesting, I shuffled the base-62 character locations from their standard arrangement.
 shorturl.php
<?php
function shorturl_toBase($num, $b=62) {
$base='bu6BKGIxnh1T47iyZpeSrA8XvQfVCzHRt9OUE50jwq2mLg3kFDWNaYcJlMdoPs';
$r = $num % $b ;
$res = $base[$r];
$q = floor($num/$b);
while ($q) {
$r = $q % $b;
$q =floor($q/$b);
$res = $base[$r].$res;
}
return $res;
}
function shorturl_to10($num, $b=62) {
$base='bu6BKGIxnh1T47iyZpeSrA8XvQfVCzHRt9OUE50jwq2mLg3kFDWNaYcJlMdoPs';
$limit = strlen($num);
$res=strpos($base,$num[0]);
for($i=1;$i<$limit;$i++) {
$res = $b * $res + strpos($base,$num[$i]);
}
return $res;
}
?>


Now the plugin is ready it's time to configure it and add some lines to the .htaccess file. Make sure that you enable the plugin first, after that is done its configuration option will appear. Enter the domain name to use for the short URLs and click Save.

The configuration screen will display the exact lines that you'll need to add to the .htaccess file, the format for these is as below where SHORT_DOMAIN is your short domain name and the LONG_DOMAIN is the blog actual domain name.
 .htaccess
RewriteCond %{HTTP_HOST} (SHORT_DOMAIN$) [NC]
RewriteRule ^(.*)$ http://LONG_DOMAIN/fp-plugins/shorturl/redirect.php?r=$1 [L,R=301]


To generate a short URL, add this to the FlatPress theme template wherever you want the short URL to appear (within the entry block):
 FlatPress Theme
{$id|link:short_post_link}


One other thing I did was tweak the Pretty URLs plugin to the the FlatPress Blog URL instead of the base URL, without this change redirection will not work properly. An alternative solution to that is to have this plugin keep track of the long URL. The change is in the get_url() function, instead of setting $baseurl to BLOG_BASEURL, I set it to $fp_config['general']['www'].
 fp-plugins/shorturl/plugin.prettyurls.php
...
function get_url() {
global $fp_config;
$baseurl = $fp_config['general']['www']; //BLOG_BASEURL;
...


Now you're done.

-i

A quick disclaimer...

Although I put in a great effort into researching all the topics I cover, mistakes can happen. Use of any information from my blog posts should be at own risk and I do not hold any liability towards any information misuse or damages caused by following any of my posts.

All content and opinions expressed on this Blog are my own and do not represent the opinions of my employer (Oracle). Use of any information contained in this blog post/article is subject to this disclaimer.
Hi! You can search my blog here ⤵
NOTE: (2022) This Blog is no longer maintained and I will not be answering any emails or comments.

I am now focusing on Atari Gamer.