Orderly: Drag and Drop WordPress Ordering

If you've ever made a WordPress-powered site that deviates from the normal blog structure, you know how fantastic registering your own post types can be. If you want to order that custom data manually though, it's quite tricky. Orderly is a very simple WordPress plug-in that allows you to add a simple drag and drop sortable to a post type including posts, pages, and custom post types registered with register_post_type. No more sorting by date and manually changing the post dates.

Orderly Installed in WordPress 3.2

Installation

Download and extract the "orderly" plug-in folder into your wp-content/plugins directory, or optionally, add as a git submodule if you are using git:

From the root of git repository:

git submodule add git://github.com/typeoneerror/Orderly.git wp-content/plugins/orderly
git submodule init
git submodule update

Next log into the WordPress admin and "Activate" the Orderly plugin on the plugins page.

Orderly uses the jQuery UI Sortable plug-in which is bundled with Wordpress so there should be no other dependencies.

Using it

Installing the plug-in will add a menu to Settings > Orderly in the wp-admin. You can select which post types you want to be sortable there. It will display "Post" and "Page" by default as well as any types you register with register_post_type.

If you'd prefer to use the code directly, to add manual drag and drop ordering to a post type menu, simple use the orderly_register_orderable_post_type convenience method in your functions.php template file.

For example, to make the built-in Pages sortable:

orderly_register_orderable_post_type('page');

Or, if you've used register_post_type to register a custom post type with WordPress, Orderly support can also be added to these. Example:

register_post_type('work',
    array(
        'labels' => array(
            'name' => __('Work', MY_LANG),
            'singular_name' => __('Work', MY_LANG),
            'search_items' => __('Search Work', MY_LANG),
            'add_new_item' => __('Add New Work', MY_LANG),
            'edit_item' => __('Edit Work', MY_LANG),
            'new_item' => __('New Work', MY_LANG),
            'view_item' => __('View Work', MY_LANG),
            'not_found' => __('No work found.', MY_LANG),
        ),
        'description' => 'Content added to the work section is displayed in the portfolio.',
        'public' => true,
        'has_archive' => false,
        'hierarchical' => false,
        'menu_position' => 5,
        'rewrite' => array(
            'slug' => 'work',
        ),
        'supports' => array('title', 'editor', 'thumbnail'),
        'taxonomies' => array('client', 'category', 'post_tag', 'page-attributes'),
    )
);

orderly_register_orderable_post_type('work');

You can wrap the plug-in calls in a test to make sure the plug-in is active:

if (function_exists('orderly_register_orderable_post_type'))
{
    orderly_register_orderable_post_type('work');
}

Once registered, a sub-menu will appear under the post type sidebar menu. In our example above, there would be a sidebar called "Work" which would have a submenu called "Order Work". Clicking this link will take you to the admin page. Drag and drop the list of posts there to change the order and click "Save Order" to save the order. The plug-in simply updates the menu_order property of WordPress' posts table, so sort by that on the front end:

$loop = new WP_Query(array(
    'post_type' => 'work',
    'order'     => 'ASC',
    'orderby'   => 'menu_order',
));

Download Orderly on Github

November 8th, 2011 | Permalink

Easy Translation of Wordpress Admin Texts

Taking a break from iOS development to work on some front-end development on a Wordpress site. Now that Wordpress 3.2 has a pretty badass custom post-type system, it's much easier to create custom admin elements and it makes it a logical CMS choice for many projects. To contribute to making a more customized user experience for a client, I wanted to change some existing texts in the admin tool, but not make a whole language file with .mo and .pot files and all that (no thanks). Here's how this is accomplished.

First in your template's functions.php, make sure we're in the admin context with is_admin. We then load an .ini file that'll contain all our custom translations:

if (is_admin())
{
    $translations = parse_ini_file(dirname(__FILE__) . '/translations.ini');
    function my_gettext($translation, $text, $domain)
    {
        global $translations;
        if (isset($translations[$text]))
        {
            return $translations[$text];
        }
        return $translation;
    }
    add_filter('gettext', 'my_gettext', null, 3);
}

my_gettext will be called whenever Wordpress asked for translated text with the __() helper. If the original text is set in the .ini file as a key, it'll instead return our defined text. And here's how that file looks:

; translations.ini
; Old text=New text
Featured Image=Thumbnail
Remove featured image=Remove thumbnail

In this case, when Wordpress requests the string 'Featured Image', 'Thumbnail' will be displayed instead. That's it. 

Special thanks to Soulseekah on the Wordpress Stackexchange for the assist on simple translations.

October 18th, 2011 | Permalink

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