Relative Image Links in Wordpress Uploader

Wordpress has a very sophisticated image uploader that allows you to insert images directly into your post. It inserts images with an absolute path, including the full path to your image as an absolute link. My guess is this is for SEO and theming purposes, but if you're just building a one-off site using Wordpress as your platform, you might want to have a relative URL in there instead, i.e.:

/wp-content/uploads/2011/07/image.jpg

instead of:

http://yoursite.com/wp-content/uploads/2011/07/image.jpg

Relative attachment URLs would be useful if you were working locally at a dev domain or localhost or if you moved the website to a different server. Forcing Wordpress to insert a relative link into the database is pretty simple; you can do this by hooking a filter on the wp_handle_upload method:

function yoursite_get_relative_attachment_path($path)
{
    $paths = (object)parse_url($path);
    return $paths->path;
}

function yoursite_wp_handle_upload($info)
{
    $info['url'] = yoursite_get_relative_attachment_path($info['url']);
    return $info;
}
add_filter('wp_handle_upload', 'yoursite_wp_handle_upload');

This filter method receives the info about the upload which will be saved in the database after the upload completes. You parse the URL of the image and grab just the relative path and send it back. Your image's path in the database will now be relative to the root of your site.

That's great, but Wordpress still inserts the full site path on the front end and when you use the "Insert Image" button when writing your post. Easy fix:

function yoursite_wp_get_attachment_url($url)
{
    return yoursite_get_relative_attachment_path($url);
}
add_filter('wp_get_attachment_url', 'yoursite_wp_get_attachment_url');

By attaching another relative URL filter to the wp_get_attachment_url filter, anywhere where Wordpress requests an attachment URL will return the path relative to the root.

I haven't tested this too much with the rest of the platform, but it seems to work well so far for me. I typically create custom one-off sites with Wordpress, so I'm not super concerned with creating reusable themes.

Here's the final snippet that you'd add to functions.php. You'd just replace yoursite with your site's namespace.

function yoursite_get_relative_attachment_path($path)
{
    $paths = (object)parse_url($path);
    return $paths->path;
}

function yoursite_wp_handle_upload($info)
{
    $info['url'] = yoursite_get_relative_attachment_path($info['url']);
    return $info;
}
add_filter('wp_handle_upload', 'yoursite_wp_handle_upload');

function yoursite_wp_get_attachment_url($url)
{
    return yoursite_get_relative_attachment_path($url);
}
add_filter('wp_get_attachment_url', 'yoursite_wp_get_attachment_url');
July 6th, 2011 | Permalink

On Process: Generating Documentation with Markdown, PHP, and HTMLdoc

Working on a fantastic project lately; a PHP platform developed with Smarty template engine that will power three (and more) websites. Each website has a shared library used to bootstrap the app and the site-specific logic is contained in the extensible smarty templates.

Each site has a large body of "documentation" files. The client's previous situation was such that each person responsible for the documentation was using their own (and thus, different) solution. So I recommended settling on a standardized documentation format.

I thought Markdown was a great fit and found a fantastic PHP port of John Gruber's tool. This particular version—Markdown Extra—extends the Markdown port to footnotes, tables, and other nice things. I created a very simple smarty plugin (the initial version below) for documentation writers to be able to load in a markdown file into a Smarty Template:

// smarty/plugins/block.markdown.php

function smarty_block_markdown($params, $content, &$template, &$repeat)
{
    if (!$repeat)
    {
        if (isset($params['source']))
        {
            $source = $params['source'];
            $contents = file_get_contents($source);
            $rendered = Markdown($contents);
        }
        else if (!empty($content))
        {
            $rendered = Markdown($content);
        }
        else
        {
            return "";
        }

        return $rendered;
    }
}

This is quite a simplified version of the final plugin. The final includes support for replaceable tokens among other things, but basically, it's used like so:

{* render the contents of a file called markdown/file/name.md as HTML *}
{markdown source="markdown/file/name"}{/markdown}

{* render the markdown source in the block directly *}
{markdown}
# header {#header-id}

This is some markdown.
{/markdown}

So why separate the markdown instead of just injecting it directly into the smarty views or just writing it in HTML? Well, part of the requirements of the project was that any documentation written for the website should be able to be easily converted to a PDF. So how do we do that? After some research on what tools would be easy for others to use as well, it ended up being a simple process; in short:

  1. Load markdown files, parse with Markdown Extra, converting to HTML.

  2. Take the concatenated HTML and pipe the output into HTMLDOC.

HTMLDOC is an open-source command-line tool that converts HTML documents into PDFs. I decided to use this tool to automate the build of the PDF documentation. So for web viewing, Markdown is converted to HTML and cached on subsequent requests as HTML via Smarty, and for download, the PDF docs are created using the same Markdown; a nice separation of concerns, I thought.

Here's a section of the build-docs PHP script that is run during the ANT build for each site. Prior to this section, the file looks in the documentation and loads specified markdown files and parses them with Markdown extra and loads the concatenated results into a temporary HTML file. This file is then piped into HTMLDOC:

$command = "htmldoc ";
$command .= "--book "; // generate in book format with TOC
$command .= "--links "; // link up hyperlinks
$command .= "--title "; // include a title page
$command .= "--toctitle " . escapeshellarg($toc_title) . " "; // TOC title
$command .= "--linkstyle "underline" "; // what to do with hyperlinks
if ($title_image)
{
    $command .= "--titleimage " . escapeshellarg($title_image) . " ";
}
$command .= "--footer h./ ";
$command .= "--header .t. ";
//$command .= "--bodyfont helvetica ";
$command .= "-t pdf14 ";
$command .= "-f {$output_file} {$temp_file}";

exec($command, $result, $return);

We execute the htmldoc command via PHP and the documentation PDF is generated. The variables allow us to create a bootstrap file for each site's documentation to configure the output a little bit.

The final requirement for the documentation was the addition of tables of contents to any markdown file and documentation. The documentation writers wanted to be able to have a list of the <h1-6> tags linked up to the corresponding section on the page. I accomplished this by adding another parsing block to Markdown Extra. In short, this block uses Markdown Extra's existing list of parsed headers and wraps them in a <ul> list with anchor tag links. The regular expression for matching the "toc" is as follows:

"/{toc(?:|?([1-6])(?::([1-6]))?)?}/

Ain't regex lovely? This matches some of the following, replacing it with the rendered unordered list where it appears in the markdown document.

  • {toc} renders the entire table of contents.
  • {toc|3} would display <h1> through <h3> tags in the table of contents.
  • {toc|2:5} would display <h2> through <h5> tags in the table of contents.

Anyway, that's some of the process stuff I've been plugging away on lately. I've sort of become obsessed with writing everything in Markdown now. If I need to send to another developer or client, I'll do something like the following:

alias markdown='/path/to/Markdown_1.0.1/Markdown.pl'
markdown my-doc-file.md | htmldoc --format pdf14 - > my-doc-file.pdf

(Obviously there'll be a bunch of params for htmldoc as seen in the PHP example above). Quite simply converting Markdown and piping to htmldoc. Of course, I don't get to use my fancy extended Markdown with tables of contents, but for day to day writing, it's ideal. Bam, lovely looking PDF.

Depending on the completion of these projects, I may release the updated Markdown Extra with Table of Contents and the related Markdown Smarty plugins. Check back later with me.

July 1st, 2011 | Permalink

Android: Changing ListView Background Colors

This will be the first post about my experiences learning Android development. At the moment, I'm working on a small application for the project/code management software Codebase (http://codebasehq.com). The aim of this article is to show how to create custom background colors for ListView interactions in Android; that is to say, make the background of ListView rows not that ugly green or orange gradient.

codebase app

← In my primary Activity that first loads when you start up the application, we're displaying a list of activity logs from the user's activity feed. The layout file for this is quite simple:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <include android:id="@+id/custom_title" 
        layout="@layout/custom_title"/>
    <ListView android:id="@+id/android:list"
        style="@style/ListView"
        android:layout_weight="1"/>
    <include android:id="@+id/navigation_dashboard" 
        layout="@layout/navigation_dashboard"/>
</LinearLayout>

So the ListView is what we need to "style" here. You can see that I'm referencing a @style property called ListView. That's defined in res/values/styles.xml. This is a resource file which is compiled into a Java class for use at runtime. So we define "ListView" style here, and then we can reference it in out layout above with @style/ListView or in code at R.style.ListView.

res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="ListView">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:background">@color/off_white</item>
        <item name="android:cacheColorHint">@color/off_white</item>
        <item name="android:listSelector">@drawable/list_selector</item>
    </style>
</resources>

You can see here that I've defined a property for android:listSelector. This sets a drawable that tells our ListView how to display the selected rows in the list. I reference a list_selector drawable which is defined in res/drawable/list_selector.xml. Again, this is another resource file, so we can access it in XML resources or code like we did with the styles. For this app, I'm using an off white color for the background of the ListView. The cacheColorHint is a setting that tells the list that it'll be drawn on this color background. It helps speed up scroll speeds as well.

res/drawable/list_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- touch down -->
    <item
        android:drawable="@drawable/list_selector_pressed"
        android:state_pressed="true"/>
    <!-- selected -->
    <item
        android:drawable="@drawable/list_selector_selected"
        android:state_selected="true"
        android:state_focused="false"
        android:state_pressed="false"/>
</selector>

This file is a state list drawable. It defines a set of drawables that represent the state of our property; in this case "listSelector". Above, you can see we've set a drawable for "state_pressed" and "state_selected". Each of these is another resource file.

res/drawable/list_selector_pressed.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
            <size android:width="1dip"/>
            <size android:height="1dip"/>
        </shape>
    </item>
</layer-list>

res/drawable/list_selector_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
            <size android:width="1dip"/>
            <size android:height="1dip"/>
        </shape>
    </item>
</layer-list>

Each item just defines a rectangle shape that's basically 1x1 density independent pixels (dip). This will fill the background of the rows of the ListView. So when you tap the list view row, it will use the drawable that represents the pressed state and fill the background with the drawable white rectangle shape.

So changing list view background colors is easy, it just requires a bunch of files!

February 25th, 2011 | Permalink

The TextMate Super Function (AS3/PHP)

Following my obsession with TextMate snippets and commands, I created a function snippet which extended the basic function and added a few new useful features. This snippet is mapped to Shift + Enter. Just type the name of your function...

myFunction

and hit Shift + Enter after it. The following snippet is inserted:

/**
 *
 *
 * @return
 */
public function myFunction()
{

}

The first tab stop is inside the parentheses so you can add some parameters, hit tab again to focus on the scope (public). We use a simple regular expression here to add "_" or "__" to the method name depending on if you type public|private|protected. The rest of the tabs go through the return statement, docblock and finally end inside the function declaration.

I've got both an AS3 and PHP version. Starting with the PHP version:

cat <<SNIPPET
/**
 * $4
 *
 * @return $3
 */
${2:public} function ${2/(private)|(protected)|(.+)/(?1:__)(?2:_)(?3:)/}${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}($1)
{
	$0
}
SNIPPET

And the AS3 version is basically the same with just a return type defined:

cat <<SNIPPET
/**
 * $4
 *
 * @return ${5:$2}
 */
${3:public} function ${3/(private)|(protected)|(.+)/(?1:__)(?2:_)(?3:)/}${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}($1):${2:void}
{
	$0${2/void$|(.+)/(?1:return null;)/}
}
SNIPPET

I'd also like to eventually add @param docs to the docblock as you type out parameters. Would love some suggestions there.

You can download both the PHP and AS3 Function Commands here. You can also download my TextMate theme Plum Dumb, or—if you're into PureMVC—you can download my PureMVC TextMate templates.

December 29th, 2010 | Permalink

Game Center Achievement Notification

Game Center has a notification window that slides down and informs the GKLocalPlayer that they've been authenticated. There is no built-in way to display achievements that the user may have earned during use of your application. The GKAchievementNotification classes are a way to display achievements awarded to the player in the same manner as the authenticated message—similar to Xbox Live style achievement dialogs. The achievement dialogs are added to the UIWindow view of your application:


Achievement notifications in the upcoming Cee-lo 1.1 update.

Using It

You can grab the code from github. Add the folder (.h, .m, images) to your Xcode project. The GKAchievementHandler class handles the display of the notifications. You'll primarily use that (there'd usually be no reason to create a notification directly). When your player earns an achievement, you can notify them of this via GKAchievementHandler:

// grab an achievement description from where ever you saved them
GKAchievementDescription *achievement = [[GKAchievementDescription alloc] init];

// notify the user
[[GKAchievementHandler defaultHandler] notifyAchievement:achievement];

You can also use custom messages instead of a GKAchievementDescription object:

[[GKAchievementHandler defaultHandler] notifyAchievementTitle:@"High Roller" andMessage:@"Earned 100 points online."];

Customization

Apples Guidelines state that "it is up to you to do so in a way that fits the style of your game". and Allan Schaffer of Apple stated in the forums that "[the] best way to do that would be to present a custom dialog using the look and feel of your game" (emphasis, his). This to me means you may be rejected for using Apple's artwork in a custom application. If this worries you, use the setImage: methods to change the logo displayed in the dialog or change the gk-icon.png images in your images. You can also set the image to nil to not show any image:

[[GKAchievementHandler defaultHandler] setImage:nil];

You can also edit the gk-notification.png images to change the stretchable background.

October 1st, 2010 | Permalink
previous 1 2 next