PHP Magic

On my new site I post my musical compositions like this:

Ode to Ted Kennedy MP3, 1:52, 1.35MB
Ode to Ted Kennedy MIDI, 7.69KB
Ode to Ted Kennedy PDF, 25.47KB
Ode to Ted Kennedy Score (Sibelius 6), 40.85KB

I upload each file through WordPress to the /files/ directory with subdirectories for years and months enabled. The filename is the title of the musical composition followed by my initials and the date of posting, and I use hyphens as spacers. I use a modded version of WPaudio to turn MP3 links into JavaScript-based music players.

Wouldn’t it be nice if I could automate the creation of these links instead of having to type the filenames four times, the title four times, the size of each file, and the length of the MP3?

The first step was to download and enable Exec-PHP so I could use PHP code in posts. Then I checked “Disable the visual editor when writing” in my profile and under Settings > Writing I unchecked “WordPress should correct invalidly nested XHTML automatically.” Next, I wrote this function and added it to my theme’s functions.php file:

function flnk($e = ‘mp3’, $t = ‘MP3’, $a = ”, $c = ”, $l = ”) {
if($c != ”) $c .= ‘, ‘;
$d = wp_upload_dir();
$n = array(‘Bytes’, ‘KB’, ‘MB’, ‘GB’);
$b = ‘/’ . get_the_time(‘Y/m’) . ‘/’ . basename(get_permalink()) .
‘-rxt-‘ . get_the_time(‘Ymd’) . $a . ‘.’ . $e;
$p = $d[‘basedir’] . $b;
$u = $d[‘baseurl’] . $b;
if(file_exists($p)) $f = filesize($p);
else $f = ‘1000’;
if($e == ‘mp3’) {
$i = round(($f/(12000))-.5);
if($l == ”) $m = floor($i/60) . ‘:’ .
str_pad($i % 60, 2, 0, STR_PAD_LEFT);
else $m = $l;
$m .= ‘, ‘;
if($e != ‘mp3’) $z = ‘ target=”_blank”‘;
echo ‘<a href=”‘ . $u . ‘”‘ . $z . ‘>’ . get_the_title() . ‘ ‘ .
$t . ‘, ‘ . $c . $m . round($f/pow(1000, ($i = floor(log($f,
1000)))), 2) . $n[$i] . ‘</a>’ . “n”;

This function gets the post title, post date, and slug [basename(get_permalink())] to assemble the title and URL. It uses PHP’s filesize() function to get the size of the file, then converts it to a number like 500.00 and expresses it in Bytes, KB, MB, or GB depending on the size. If the file is an MP3, the length is also displayed by dividing the file size by 12,000 and subtracting 0.5 seconds for excess data in the MP3 file. Then the number is rounded and the seconds are padded to two digits (2:3 becomes 2:03). This returns an accurate length if the file is 96kbps CBR (most of mine are). If the file is NOT an MP3, target=”_blank” is added to the link so it opens in a new window (MP3s are handled by the WPaudio plugin) Finally, the link is echoed.

For the links I displayed at the beginning of this post, all I have to do now is upload the files, title the post, write a description, choose categories, and then copy and paste this code to the post:

<?php flnk(‘mp3’, ‘MP3’); flnk(‘mid’, ‘MIDI’); flnk(‘pdf’, ‘PDF’); flnk(‘sib’, ‘Score (Sibelius 6)’); ?>

The function has 5 arguments: the file extension ($e), filetype title ($t), text to append to the filename ($a), special description ($c), and custom length ($l). Usually I only use the first 2. If I used a different bitrate for the MP3 file, I override the length like this: <?php flnk('mp3', 'MP3', '', '', '1:21'); ?>. I’ve only used the third and fourth functions on the piano version of Inferno as follows:

<?php flnk(‘mp3’, ‘MP3’, ‘-piano’, ‘Piano Only’); flnk(‘mid’, ‘MIDI’, ‘-piano’, ‘Piano Only’); flnk(‘pdf’, ‘PDF’, ‘-piano’, ‘Piano Only’); flnk(‘sib’, ‘Score (Sibelius 6)’, ‘-piano’, ‘Piano Only’); ?>

The above code generated this output:

Inferno MP3, Piano Only, 1:46, 1.28MB
Inferno MIDI, Piano Only, 8.62KB
Inferno PDF, Piano Only, 38.07KB
Inferno Score (Sibelius 6), Piano Only, 43.83KB

A little work now will save me a lot of time in the long run. I only have to type the title and description for each composition I post now. While this will increase my server’s load and slow down my website slightly, I can always use caching if becomes popular.