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:
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):
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