thingswithbits updated

I’ve been occupied with several other websites, designing, and other non-here things in the past months, and really wanted to not look at the old template I was using as a stand-in here. So I spent a few hours last night trying something. Then I threw it out.

This is a contingent design, based on the theme I use on francesdath.info, with much stripped out and some other things thrown in (it also is not finished, so expect broken pieces). It’s far more minimal than I originally intended, but somehow this is enough for me.

I’m also not sure how I’ll use the news section anymore, as I don’t really have the time to do everything in my life and write about code and design — especially when supernaut has been alive for over seven years. Perhaps just to use it to mention more briefly whatever it is I happen to be doing in design.

Some ways to customise the WordPress Visual Editor and HTML Editor

What started out as just wanting to add some buttons to the visual editor for standard html tags like <cite> and <ins> turned into something of a leviathan. Without a plugin, such as TinyMCE Advanced, there isn’t a non-code way to make changes, and even this plugin or others which can extend the TinyMCE editor are fairly limited to either rearranging what’s there, adding the standard extended sets, or adding styles to the styles menu.

After my moderate success with adding new custom buttons, I decided for something a little more ambitious. What I wanted turned out to be unnecessarily difficult and I still don’t have an ideal solution: I simply wanted to columnise text content. I thought I had the answer with CSS3 columns, which are in principle brilliant, but in use turned out to have all kinds of limitations and weirdnesses (and I’m not talking about lack of Internet Explorer support, which can anyway be worked around with columnizer.js or other methods). So … how about a custom button that will wrap text in something like <div class=”column-left”>?

Cleaning up and ordering the Visual Editor buttons

First things first. The visual editor has quite a few buttons that are either never going to get used, or shouldn’t get used. How about cleaning up that and arranging everything so that the buttons match the available text formatting options in a somewhat intuitive way? This is the simplest thing and goes in functions.php

On a sidenote, I have started splitting off everything from functions.php and putting code for specific tasks into separate files in a folder called ‘functions’, and then use PHP’s ‘include’, in the functions.php, like so:

1
include("functions/functions-tinymce.php");

The standard TinyMCE editor can have several rows for buttons, but really two is more than enough. To arrange the order of the buttons and choose which ones you want, this is what’s necessary:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//tinymce row 1
if( !function_exists( 'my_tinymce_row_1' )) {
    function my_tinymce_row_1($buttons) {
        return array( 'formatselect', 'bold', 'italic', 'underline', 'sub', 'sup', 'strikethrough', 'inser', 'cite', 'blockquote', 'bullist', 'numlist', 'link', 'unlink', 'anchor', 'outdent', 'indent', 'charmap', 'separator', 'add_image', 'add_video', 'add_audio', 'add_media', 'separator', 'fullscreen',  'fullscreen', 'wp_adv'
        );
    }
    add_filter("mce_buttons", "my_tinymce_row_1", 0);
}
 
//tinymce row 2
if( !function_exists( 'my_tinymce_row_2' )) {
    function my_tinymce_row_2($buttons) {
        return array( 'pastetext', 'pasteword', 'removeformat', 'spellchecker', 'wp_help'
        );
    }
    add_filter("mce_buttons_2", "my_tinymce_row_2", 0);
}

I prefix the function name with the website name to keep everything coherent, so instead of my_tinymce_row_1, I would have, e.g. fangxishi_tinymce_row_1

The important stuff is in returning the array of buttons. There is a list of standard buttons, but also you can use the inspector and select any button in the Visual Editor to find its name, e.g:

1
<td><a id="content_charmap" href="javascript:;" class="mceButton mceButtonEnabled mce_charmap" onmousedown="return false;" onclick="return false;" title="Insert custom character"><span class="mceIcon mce_charmap"></span></a></td>

For the character map, looking in there is ‘mce_charmap’. Just get rid of ‘mce_’ and that’s the buttons’ name.

I also added the ‘add media’ buttons, which I thought would be useful when I was trying the idea to use two visual editors to split content into two columns.

You can also do the same for the Format dropdown menu.

Then I wanted to add a button for ‘cite’ and ‘ins’, both of which are in TinyMCE Advanced, but I didn’t want a whole plugin for this. Unlike most of WordPress stuff, this is getting into seriously poorly documented territory, and it took quite a while to find something close to useful that I could then hack into shape.

Basic Styles dropdown menu formatting

Why not use the Styles dropdown menu, which is simple and well-documented? Well, yes. For things when you just need <span class=”foo”>, this works fine. To make a drop-caps style:

1
2
3
4
5
6
7
8
9
if ( !function_exists( 'my_tinymce_styles' )) :
function my_formatTinyMCE($init) {
    $init['theme_advanced_buttons2_add'] = 'styleselect';
    $init['theme_advanced_styles'] = 'Drop Caps=drop-cap';
    return $init;
    }
endif;

add_filter('tiny_mce_before_init', 'my_tinymce_styles' );

The name in the styles dropdown menu will be ‘Drop Caps’ and the class added to the span will be “drop-caps”, then style with CSS.

For anything more complicated (i.e. not in a <span>) …

Adding a custom button

The code for this gets split into two parts; first that in functions.php, which then calls a js file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//add cite button

function add_cite_button() {
   // can user edit? then continue
   if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') )
     return;
 
   // add in visual editor only
   if ( get_user_option('rich_editing') == 'true') {
     add_filter("mce_external_plugins", "add_cite_tinymce_plugin");
     add_filter('mce_buttons', 'register_cite_button');
   }
}
 
function register_cite_button($buttons) {
   array_push($buttons, "cite");
   return $buttons;
}

// load tinymce plugin
function add_cite_tinymce_plugin($plugin_array) {
   $plugin_array['cite'] = get_bloginfo('template_url') . '/functions/tinymce/cite_editor_plugin.js';
   return $plugin_array;
}

function my_refresh_mce($ver) {
  $ver += 3;
  return $ver;
}

add_filter( 'tiny_mce_version', 'my_refresh_mce');
add_action('init', 'add_cite_button');

Without going into too much depth (because I just wanted to get things working), firstly this checks to see if a user has permissions to edit. If yes, then add the custom button only to the Visual Editor. Then register a new button, here called ‘cite’, and following that, load the custom code for that button, the ‘cite_editor_plugin.js’. Then force TinyMCE to clear its cache before adding everything.

Then we move over to the js.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(function() {
    tinymce.create('tinymce.plugins.cite', {
        init : function(ed, url) {
            ed.addButton('cite', {
                title : 'Cite Text',
                image : url+'/cite.png',
                onclick : function() {
                    ed.selection.setContent('<cite>' + ed.selection.getContent() + '</cite>');
                }
            });
        },
        createControl : function(n, cm) {
            return null;
        }
    });
    tinymce.PluginManager.add('cite', tinymce.plugins.cite);
})();

Whereas the code in functions.php is generic and will simply initiate the adding of a new button, the button itself needs to be made. In this case it wraps the selected text in the <cite> tags. A custom button image is used (which I took from TInyMCE). Here, clicking the ‘cite’ button will wrap any selected text in <cite> tags. This is done with ‘ed.selection.setContent’. Other options are possible, for example opening a popup for adding data for shortcodes, depending on the function used here.

As with any other buttons, this can be added and arranged in the Visual Editor with the previous code.

Advanced Styles dropdown menu items

Having successfully added the missing styles, and cleaned up the menu, I started to think about how I could implement a user-based two-column option. I tried some shortcodes and other plugins that were meant to do this, but with how the website I’ve been working on was built, these didn’t work. Anyway, I like to have my own code.

To really make the Styles menu useful, we can build arrays that works with the buttons themselves.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function site_columns_init($settings) {
    $style_formats = array (
        array (
            'title' => 'Column Left',
            'block' => 'div',
            'classes' => 'column-links',
            'wrapper' => true
        ),
        array (
            'title' => 'Column Right',
            'block' => 'div',
            'classes' => 'column-rechts',
            'wrapper' => true
        )
    );
    $settings['style_formats'] = json_encode( $style_formats );
    return $settings;
}

add_filter( 'tiny_mce_before_init', 'site_columns_init' );

function site_columns( $buttons ) {
    array_unshift( $buttons, 'styleselect' );
    return $buttons;
}

add_filter( 'mce_buttons_2', 'site_columns' );

Make an array, give the Styles menu item a title element (e.g. div), a class name and add it to the Styles menu. (Make sure the styles menu has also been added to the first code’s array of menu items) There are quite a few other options that can be used with this also, alisothegeek covers it very well.

Unfortunately, while this works brilliantly for a lot of things, for making columns it fails simply because this doesn’t work across paragraphs, that is to say it wraps only complete paragraphs in the div and won’t allow for half the text of a single paragraph in each column.

Styling the HTML quicktags

In the end I opted for the not-quite ideal method of jumping into the HTML editor for columnising. This, unlike adding new menu items or most other things associated with the Visual Editor, is simple and quick (found on scribu).

1
2
3
4
5
6
7
8
function site_custom_quicktags() {
    wp_enqueue_script(
        'site_custom_quicktags',
                get_bloginfo('template_url') . '/functions/quicktags/custom-quicktags.js',
        array( 'quicktags' )
    );
}
add_action( 'admin_print_scripts', 'site_custom_quicktags' );

It barely needs explaining. Load a new button from a .js file after the quicktags menu has loaded. In the .js file, it’s one line per button:

1
2
edButtons[edButtons.length] = new edButton( 'col l', 'col-l', '<div class="column-links">', '</div>', '' );
edButtons[edButtons.length] = new edButton( 'col r', 'col-r', '<div class="column-rechts">', '</div>', '' );

This makes two buttons which wrap any content in a div with class ‘left’ or ‘right’, which can then be styled in CSS into columns. It’s also a bit rough, and can mess with paragraph formatting when swapping back and forth between editors, but is as close as I’ve found yet to a workable multi-column option.

Multiple columns using multiple visual editors?

This was my last thought, and in practice, if the post editor page is built appropriately, it’s probably the most controllable option.

I use WPalchemy for building all my metaboxes, and won’t go through the whole process for this here. WPAlchemy is very simple to set up and get working (even in some of the unorthodox situations I’m using it in), and Dimas has made a quick addition to the code which allows for multiple Visual Editors. All the above code also works with these, and outputting the content into two separate left and right column divs in the template is trivial.

Ending

If all this is done, it’s also worthwhile adding a stylesheet to the Visual Editor that reflects the site’s styles. or otherwise helps with visualising all this.

1
add_editor_style();

in functions.php and then a stylesheet called ‘editor-style.css’ is all it takes.

Also, while all this was for some specific tasks (namely cleaning up the visual editor menu, adding two new buttons, and finding a way to add a div for columns), the methods apply to pretty much anything that could require additional markup of some kind. And while there are plugins that do some of this, it’s much more fun to write my own code.

An intricate custom menu with WPAlchemy

The last few days I’ve been working on a site for Dasniya Sommer. Her current site – one of the first I made as a freelancer in early-2009 – is all hand-coded, static HTML, and we’ve been talking for a while about transferring it into WordPress.

This is not so straightforward, as her site exists all on one page, sliding around like a giant map seen through the small window of a browser. Also there are many technical issues: multiple menu structures, back buttons, URL paths that don’t function very well at the moment; and things she’d like to have more control over: drag-to-rearrange page order, easy adding of different kinds of content (video, images, texts), easy multilingual possibilities …

One of the main issues was how to have a per-page specific navigation menu. This is not so difficult if the content exists on separate pages; there’s a lot of option, from wp nav_menu to using Wigets and dynamic sidebars. For some sections I used the former, building specific menus for the index and sub-indexs, but for individual pages, all sitting on a single vast page and requiring all their links to be anchors going to somewhere else on the overall site, there wasn’t a simple method.

I thought about making unique nav_menu menus and then calling them using a custom field which would add the menu name to the function that displays the menus, but there were some obvious problems with this. First, she would have to leave the page she was writing in to make the menu, then go back to that page and add the menu name. Second, with pages and menus being separate, it would be difficult to keep track of what went where and the possibility of a hundred orphan menus that should be deleted if only you could be sure they weren’t in use … mess.

So I decided on a method that’s not quite elegant (I really wanted to integrate nav_menus directly into a page as a custom field, and have the created menu only appear on that page in wp_admin), but works quite well, using WPAlchemy again and some rather effective PHP.

The idea is simple:

  1. Have a custom field on every page
  2. Have checkboxes for all the main navigation sections (Index, Videos, Texts and so on)
  3. Have a single checkbox called ‘Weiter’ with an additional text field to which an anchor link can be entered for going to a specific next page
  4. Have a checkbox called ‘Zurück’ which will go to the previously viewed page/area/Seite (a simple back button)
  5. Be able to drag-drop rearrange them in wp_admin and have that reflected on the site
  6. For nav items that are unchecked, they simply don’t appear
  7. Call it from its own template part (e.g. loop-nav.menu.php) to keep the index.php clean
  8. Have it work on any page or custom post type
Setting Up WPAlchemy and the Meta Boxes

This is very straightforward, using the standard WPAlchemy method in functions.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// wpalchemy setup
define('_TEMPLATEURL', WP_CONTENT_URL . '/' . stristr(TEMPLATEPATH, 'themes'));
include_once 'customfields/wpalchemy.php';
include_once 'customfields/MediaAccess.php';
// include css to style the custom meta boxes in wp_admin
if (is_admin()) {
    wp_enqueue_style('custom_meta_css', _TEMPLATEURL . '/customfields/meta.css');
}
$wpalchemy_media_access = new WPAlchemy_MediaAccess();

// metaboxes for page-specific navigation
$nav_metabox = new WPAlchemy_MetaBox(array (
    'id' => '_custom_nav_meta',
    'title' => 'Navigation Menu',
    'template' => TEMPLATEPATH . '/customfields/dasniyasommer-nav-menus.php',
    'types' => array('post', 'page', 'custom post types'),
    'context' => 'normal',
    'autosave' => TRUE,
    'mode' => WPALCHEMY_MODE_EXTRACT,
    'prefix' => '_nav_',
    ));

This has a slightly different install path and filename than standard, and I’m using the wpalchemy_media_access class for making adding video and images easy’; it’s not necessary for the nav menus, but otherwise nothing special here.

The nav-menu Custom Field

This is where everything happens. Most of this is fairly straightforward also, but I’ll go through it a bit.

  1. First I make an array of all the menu items I want
  2. Then I output them as checkboxes
  3. I make them drag-reorderable by wrapping them in a div class=”nav-menu-item” and use jQuery .sortable to act on the class “nav-menu” that they are all contained in
  4. I add a bit of CSS to make it obvious they can be dragged
  5. Then I want to deal with a specific instance, the ‘Weiter’ checkbox, to which I want to add a text field, and then treat everything else. I do this with a simple if/else statement.

In general, this is the standard checkbox setup code from WPAlchemy; only the addition of the if/else statement, and css/js is different.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<div class="my_meta_control">

<label>Page Navigation Menu</label><br />
    <div class="nav-menu">
        <?php $items = array( 'Weiter', 'Zurück', 'Tanz Dokumentiert', 'Bilder', 'Lesen', 'Quellen', 'Zur Zeit', 'Demnächst', 'Index'); ?>

        <?php foreach ($items as $i => $item): ?>

            <?php $mb->the_field('nav_menu');
                if ( $item == 'Weiter' ) { ?>
                    <div class="nav-menu-item">
                        <input type="checkbox" name="<?php $mb->the_name(); ?>[]" value="<?php echo $item; ?>"<?php $mb->the_checkbox_state($item); ?>/>
                        <?php echo $item; ?>
                        <input type="text" name="<?php $metabox->the_name('url'); ?>" value="<?php $metabox->the_value('url'); ?>"/>
                    </div> <?php
                    }
                else {
                ?>
            <div class="nav-menu-item">
                <input type="checkbox" name="<?php $mb->the_name(); ?>[]" value="<?php echo $item; ?>"<?php $mb->the_checkbox_state($item); ?>/> <?php echo $item; ?>
            </div>
            <?php } endforeach; ?>
        </div>
</div>
<style>
    #_custom_nav_meta_metabox .nav-menu-item {
        border: 1px solid #ccc;
        padding: 5px;
        margin: 0 10px 5px;
        cursor: move;
    }
   
    .nav-menu-item label {
        margin-top: 0;
        padding-top: 0;
    }
   
    .nav-menu-item input[type='text'] {
    margin-top: 6px;
    margin-bottom: 0;
    }
</style>

<script type="text/javascript">
    jQuery(function($) {
        $('#_custom_nav_meta_metabox .nav-menu').sortable();
    });
</script>

That’s it, and it looks like this in wp_admin:

Dasniya Sommer custom field nav-menu using WPAlchemy

One thing that still needs to be sorted out is that while drag-dropping works, and updates correctly on the site, in wp_admin it only shows the default structure once the page is saved. Also a possibility to add new menu items would be nice, though for Dasniya’s site it’s unnecessary.

The template code

Then all this needs to be outputted into the template. I’m using

1
get_template_part( 'loop', 'nav-menu' );

in the index.php template (or wherever else) and keeping the templates themselves a bit more orderly.

Here the process is somewhat more complex, and took me quite a while to get it all working.

  1. First set everything up using ‘global’
  2. Making a direct call to the meta in the second line seems necessary with query_posts() and setup_postdata()
  3. See if there’s any data, and if so continue
  4. Begin outputting everything into a list, using foreach
  5. Split off ‘Weiter’ again, and treat it differently before outputting the rest
  6. For Weiter, use the contents of the textarea for the link anchor
  7. Split off ‘Zurück, and make the href only ‘#’ instead of the menu item name
  8. To use the nav-item titles as anchor links and classes, use PHP strtolower and preg_replace to convert them to lowercase, replace spaces with a dash, and replace umlauts with the two-letter variants
  9. Use some jQuery to treat ‘Zurück’ as a back button.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    global $nav_metabox;
    $meta_nav = ($nav_metabox->the_meta());
    if($meta_nav) : ?>

    <p> this is the list of standard links:</p>
    <ul class="nav-menu">
    <?php
    foreach ($meta_nav['nav_menu'] as $nav_item) {
        // begin the li and a setup
        echo '<li class="nav-item"><a href="';
        // split here. if $nav_item is Weiter, then get the #link and put it in href - not using preg_replace in class as it's just 'Weiter'
        if ($nav_item == 'Weiter') {
            echo $nav_metabox->the_value('url') . '" class="' . strtolower($nav_item) . '">' . $nav_item . '</a>';
        }
        // if $nav_item is Zurück, use '#' for href – for simple back button
        elseif ($nav_item == 'Zurück') {
            echo '#" class="' . strtolower(preg_replace('/ü/', 'ue', $nav_item)) . '">' . $nav_item . '</a>';         
        }
        // if it's not Weiter, then output all the other $nav_items as usual - convert to lower case, replace ' ' with '-', replace ä/ü with ae/ue to deal with umlauts
        else {
            echo '#' . strtolower(preg_replace(array('/\ /', '/\ä/', '/\ü/'), array('-', 'ae', 'ue'), $nav_item)) . '" class="' . strtolower(preg_replace(array('/\ /', '/\ä/', '/\ü/'), array('-', 'ae', 'ue'), $nav_item)) . '">' . $nav_item . '</a>';
        }
        // finish up and close the li
        echo '</li>';
        } ?>
       
    </ul>
    <?php
    endif;
The back button

For the ‘Zurück’ button, once it’s had its link anchor replaced with just a ‘#’, when clicked it should go to the previous page/section/Seite on the index page. I’m aware of the limitations of this as a ‘back button’ method, but really felt that unless I made ‘Zurück’ in wp_admin the same as ‘Weiter’ there isn’t another useful option (and even that would cause different problems). So:

1
2
3
4
5
6
7
//go back to the previous Seite
$(document).ready(function(){
    $('a.zurueck').click(function(){
        parent.history.back();
        return false;
    });
});
Finishing

It feels a little unorthodox, and there were some difficulties getting it working properly. My php regex is probably atrocious, but I’ve never done such stuff before. I’m very happy with how unproblematic it was to get WPAlchemy to do this, perhaps less happy with how WordPress can be somewhat opaque in how it handles data under various circumstances, and my having to brute-force solve some issues with getting the data to show properly.

Overall it works very well according to what I needed, and works very well for Dasniya, though I’d still love to have found a way to do this with wp_nav_menu. I’d also love to be able to incorporate the WordPress link button into the ‘Weiter’ Field. It looks like this (with all nav-items checked):

Dasniya Sommer custom field nav-menu Site

Setting up a local development server for WordPress on my Mac

This has been something I’ve been planning to do for a long time and even made several attempts at it, all of which failed in various ways. Somehow at 3am last night it finally worked. Excitement!

The idea is very simple: Macs come with Apache web server installed, as well as PHP. SQL needs to be manually installed, but is simple, using a package and including a System Preferences prefpane for activation. Getting all of this running is not so complicated. Getting it working together, from a more friendly directory than somewhere buried in /Library or elsewhere, along with useable URLs instead of localhost/~myname, and running WordPress is a bit of a tussle.

So, first I downloaded everything: MySQL 5, PHP, as well as two other useful tools I’ll come back to: VirtualHostXphpMyAdmin, and Sequel Pro.

One thing I didn’t download was MAMP. This is a self-contained environment for running websites locally on a Mac. It includes a whole pile of stuff including Apache, PHP and MySQL. Which is why I didn’t want to use it. For those who just need a simple, click-it-works method, MAMP is probably fine. But when Apache and PHP are already installed, it seems to me a curious way to go about it. It also comes in at several hundred MB, with all its additional libraries, which I don’t like.

I have tried it before and got it working with one site, but found it quite limited compared to the method I’m going to attempt to describe below.

MySQL

MySQL installs with a package to /usr/local/mysql-(version-OS-processor e.g. 5.5.13-osx10.6-x86_64), with an additional folder also appearing in the same location called just mysql, which is an alias (or symlink) to the above installed version.

Along with this in /var/mysql/ is mysql.sock. This file can be elsewhere for a standard install of OS X (in /tmp), and the location in /var is I think default for OS X Server, but I found in my setting up of all this, the /var location worked.

This filepath may also need to be set in php.ini which is found in /etc/. If it’s not it will use the default system location. This is in several places in php.ini, and is simply like this:

1
mysql.default_socket = /var/mysql/mysql.sock

in the [MySQL] section.

Installing the prefpane and clicking to start MySQL Server should now give the message, “The MySQL Server Instance is running“.

PHP

PHP is already installed, but updating to the latest version is a good idea – especially if you’re running PHP4 instead of PHP5. Unlike MySQL, there’s no package installer, so it means messing around with Terminal and hand-editing files. The INSTALL file in the download gives all the information one could need.

I did this on a previous attempt to get all this running, so have forgotten the details, but some important things are in /etc/apache2/httpd.conf:

1
LoadModule php5_module libexec/apache2/libphp5.so

needs to be unchecked, as well as the AddType for PHP so .php is treated as such (and not as html).

Restarting Apache (in System Preferences > Sharing > Web Sharing) now should have all this working.

A simple test is to drop a file info.php into the default website directory (this can be either ~/Sites, or /Library/WebServer/Documents or whatever might have been set in httpd.conf) with the following:

1
<?php phpinfo(); ?>

Going to http://localhost in your browser should then throw up your php settings. If yes!, then excitement and on to installing other things. If no! then gnashing of teeth and messing around with lots of annoying things.

It’s not working

I had this so many times. On at least two previous occasions, I gave up because nothing would work. Of course this is in part because I’ve messed around with my system so much things are not … quite … right. But there are certain things which are problems with setting this up on OS X.

In short these problems (for me at least) related to one of the following:

  • things pointing to incorrect file paths
  • incorrect permissions on files or file paths
  • incoherent weirdness

The first thing to remember is if in System Preferences both Apache and MySQL say they are running, then it’s likely they are.

It took me a while to work out that if  ’Can’t connect to Server’ is what I get in your browser, then it’s probably because what I’m trying to open is not the site – this is still so when I click on the links in Sharing that are supposed to point to my website.

One of the most useful pieces of help comes from Apple itself, Web Sharing – “Forbidden 403″ message appears instead of website content, which advises making a file in apache2/users/ called ‘shortname.conf’ (where shortname is your User shortname) and adding the following:

1
2
3
4
5
6
<Directory "/Users/shortname/Sites/">
Options Indexes MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>

Which seemed to fix my 403 issues. For me it seems there are permissions issues with having sites in my Home folder outside of ~/Sites, so I left them there and made an alias to that folder which goes somewhere useful, as well as in the Sidebar.

VirtualHostX

Once I’d gotten all this nominally working, fun could occur.

The problem with having all this is that it is limited to running one website unless you want to drown in further configuration. I have a few sites at the moment I want to be able to access without the turgidity of having to work on a site hosted half a world away – not just for the slowness; it’s also an issue of poor use of resources.

VirtualHostX is disconcertingly simple to use. This simple even:

  1. Add a Domain Name. I use the real site name prefixed with dev. for all this.
  2. Set the Local Path. For me a specific folder in ~/Sites for each website
  3. Check ‘Enable this Virtual Host’
  4. Click ‘Apply Changes’
  5. Restart Apache
  6. Double-click the Domain name in the left column
  7. Happiness.

This is of course predicated on everything else already working, but once I’d got the issue of pointing to the correct directory and the 403 problem fixed, this worked first time.

(The developer also has an interesting post on piracy and how he tried to make a difference given that over 80% of this app was running pirated or cracked serials. I was wondering myself about this, the price of the app – around €17,- – versus what it does (i.e. can I do it myself by editing the particular files needed to run different domains?). I would certainly purchase it if it was a) €10 or b) I actually had an income at the moment …)

Back to SQL

The usual way I deal with SQL is with phpMyAdmin. It’s ugly, unintuitive, obviously written by people who took offense at having to leave the command line in 1984, and does what it’s supposed to. Somewhere in all this last night I discovered Sequel Pro. It looks like a Mac app, is simple to use, can create new databases and users locally or connect to remote ones, is currently free.

Connecting to SQL was as simple as entering the Host as 127.0.0.1 and user as root. From there making new databases (ones with identical names as the various WordPress sites I wished to make local versions of), and duplicating users and their passwords who could connect to those databases was about as simple as using VirtualHostX.

WordPress

The obvious way to do this seemed to be to export the database from the live site and import it into my local install via Sequel Pro. At the same time, just copy over the entire site from remote to local. Actually this works, with several caveats.

Having tried this twice now, in my situation it seems best to set everything up and then import in the remote site:

  1. Create a new database with the same settings as the remote site (Host can be localhost, 127.0.0.1, or the VirtualHostX-assigned Domain Name
  2. Drag a fresh install of WordPress into the site directory
  3. Run the install, setting the database Host as ‘localhost’
  4. I have to copy-paste the resulting settings as WordPress can’t seem to write to wp-config.php
  5. If everything works, a fresh version of WordPress should be running.

From here I copied over the remote site database and files

  1. In Sequel Pro, import the remote database over the top of the existing one you’ve just made
  2. Some lines in the database table ‘options’ will need to be edited so that the Site URL and WordPress URL point to the local site and not the remote:
    1
    2
    option_name: siteurl: set to VirtualHostX Domain Name
    option_name: home: set to VirtualHostX Domain Name
  3. In the site folder, add the site-specific template and check this is working
  4. In the site folder, add the site-specific plugins and check they are working
  5. If permalinks don’t work or more ’403 Forbidden’ occurs, add this to the .htaccess file in the site root folder on the first line:
    1
    Options +FollowSymLinks
  6. Clean up resulting mess
Finishing Up

There are still some small weirdnesses, and I’m not sure how easy it would be to go the other way, i.e. once finished in the dev site to transfer it back without too many hassles. Also certain things I do on all live sites, e.g. .htaccess stuff, ssh, various security things, caching and database plugins and so on are not really necessary on a local site, so there needs to be a slightly considered process in moving from local to remote.

The time saved though, from each page refresh by working locally, as well as the small environmental goodness of not using the internet half way around the world to a shared server somewhere for what should in fact always be done locally is a good reason to spend half a day getting this working.

A mullet post shortcode

I’m working on a site at the moment which has something of a single page portfolio layout. One of the pages / sections has the latest news. Not wanting to have the length of this section creep on, I wanted to use the famous Mullet Loop – the first post in its entirety, the remaining however many just as post titles. Easy enough to do if I wanted to drop it into a template page but …

Using the WordPress code to output top-level pages into a single page doesn’t seem to want to also include the page with the news, or more accurately, its content. (ok, I probably could have used another Template page for this, but anyway …)

Shortcode? Yes!

Finding some code that would output the pages as a list was easy. Finding something a little more flexible took a little longer. Adding in the extra get_whatever, was 5 minutes. Making a loop in the shortcode function took a bit of thinking as to where exactly the loop was looping and how to get it to do so.

After a an hour or so testing and generally messing about, I have this in my functions.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function theme_name_recent_posts($atts){
    extract(shortcode_atts(array('limit' => 3), $atts));
 
    $q = new WP_Query('posts_per_page=' . $limit);
 
    $list = '<div class="recent-posts">';
   
    if ($q->have_posts()) :
    $count = 0;
    while($q->have_posts()) : $q->the_post();
        $count++;
        if ($count == 1) :
        $list .= '<div class="post">' . get_the_date() . '<a href="' . get_permalink() . '">' . get_the_title() . '</a>' . get_the_content() . '</div>';
        else :
        $list .= '<div class="post">' . get_the_date() . '<a href="' . get_permalink() . '">' . get_the_title() . '</a>' . '</div>';
        endif;
    endwhile;
    endif;
 
    wp_reset_query();
 
    return $list . '</div>';
}
 
add_shortcode('recent-posts', 'theme_name_recent_posts');

Which I can then add to any page I want with, setting the number of pages with ‘limit’:

1
[recent-posts limit="4"]

CSS and lang attributes, or, Multilingual Styling

The last week I’ve been uploading video to my other website, francesdath.info, which I’ve become much more engaged with since dumping into WordPress.

I also began thinking about making the site multilingual, as I’ve worked in China for some projects and now live in Berlin. The latter being of certain importance to me because I hold a somewhat traditional idea that it’s important to learn the language of the country I live in, and that one can never really be part of a place until able to converse.

Having done a couple of sites using qTranslate, I felt uncomplicated about adding this into my site. Despite some shortcomings in both WordPress and qTranslate, it’s really the best plugin for what should be native in WordPress, and anyway, none of the shortcomings I’ve fell over can’t be fixed with something in either the template or functions.php.

It all took about 15 minutes to install and set up. Being a fan of the two-letter language codes, and wanting to keep the usual minimalism of the site, I copy-pasted the following into my functions.php, which I also used on sumiyang.com (I’m not sure where I found this originally, i think maybe here):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function curPageURL() {
    $pageURL = 'http';
     if ($_SERVER["HTTPS"] == "on") {
        $pageURL .= "s";
    }
     $pageURL .= "://";
     if ($_SERVER["SERVER_PORT"] != "80") {
          $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
     }
    else {
          $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
     }
return $pageURL;
}

function langlist () {
   echo '<ul>';
      echo '<li><a href="' . qtrans_convertURL(curPageURL(), 'en') . '">en</a></li>';
      echo '<li><a href="' . qtrans_convertURL(curPageURL(), 'de') . '">de</a></li>';
      echo '<li><a href="' . qtrans_convertURL(curPageURL(), 'zh') . '">zh</a></li>';
   echo '</ul>';
}

Then in the header.php, I just added:

1
2
3
<div id="languages">
    <?php langlist(); ?>
</div>

Followed by some very minimal css.

And then I ran into a problem.

I was using the pseudoclass :after with content=”blah” to add some text in the menu – all the white background text after the links. It was an appropriate solution at the time, but oh did it mess with my 15 minutes site multilingualising, because while you can throw qTranslate shortcodes around pretty much anywhere, they don’t work in a style sheet.

I tried – of course – jQuery. Find some text, replace it with some extra text, some spans and a bit of CSS and identicalness would ensue. It didn’t. I think it might be because of how I have WordPress set up to add useful classes to the wp_nav_menu, but in any case, the changes weren’t made no matter what I tried.

So I started wondering I could use media queries to target different style sheets for different languages – fully aware of the pain of that path (multiple stylesheets to maintain), as well as the overkill, just needing a few lines in multiple languages. While media queries is very powerful and brilliant for so many reasons, it doesn’t do languages.

And then…

This is the most brilliant thing I’ve found in CSS in ages:

Styling using language attributes

I couldn’t believe it. You can style elements in CSS based on the html language declaration. Even better, there’s a pseudoclass, :lang(). Brilliant! I had to run around for a bit until I calmed down.

Then there was the anxious moment, would it work with concatenating pseudoclasses?

Yes!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#access li.about:after {
    content: " Frances d'Ath";
    color: #000;
    background-color: #fff;
    padding: 1px 2px 2px 0px;
}

#access li.about:lang(de):after {
    content: "Frau d'Ath";
}

#access li.about:lang(zh):after {
    content: "方希石";
}

Nice!

You can see this on francesdath.info, using the language buttons in the top right.

In immediate hindsight, it’s obvious there would be something like this. It can solve a lot of problems simply: different fonts for different languages (with @font-face!) is the first that comes to mind. Also, lack of support in certain nameless browsers will ruin it for the rest of us. But I’m just completely thrilled at what an elegant and smart method this is. (Now I just have to translate sixteen pages into two new languages.)

HTML5 video sadness and disappointment

With Firefox 4 arriving, I discovered some quirks in how it dealt with video using my default Flowplayer setup (which I eventually traced to some stuff in htaccess), and feeling frustrated with the difficulty of Flash video, I decided – after months of on-off reading on HTML5 video to throw myself into it. I ended up deciding to unthrow myself.

I’ve been using Flowplayer for a couple of years now. It’s powerful, configurable, plays video really well, can do all sorts of fancy pseudostreaming and bandwidth detection (if your server is set up for it), and it runs on Flash. Even still, it will work on iPhone and iPad if you use the correct plugin. Why change? Well partly because of a curiosity about HTML5 video, and partly because of Flowplayer’s limitations.

I’d done a bit of research before, and decided to use VideoJS, as it has some nice features, and for older browsers falls back to Flash using Flowplayer, so I could just wrap the fallback code around my existing video code and happiness should ensue.

And happiness did, for a moment.

But then …

This is more-or-less several paragraphs about my frustration with the rubbish state of video in browsers. When I made my first website (in Flash) just before going to China the first time, there was no video in Flash and little beyond QuickTime-embedded . A hacky/brilliant workaround using JavaScript to strip the chrome off a QuickTime movie, overlay it in the page, and communicate with it from the Flash controls was as good as it got. And really, eight years later, it’s not much better.

Think about putting an image into a web page. Use the img tag. Almost any file format will work without a second thought in all browsers, so then you can get onto the fun stuff, galleries, animation … but having to spend most of your effort just on dealing with shoddy browser support for a picture does not play a part.

So why is video so difficult?

Once I’d got my head around the setup of the video tag, and understood generally how it worked, tested in a few browsers and felt quite good, I started coming up against multiple problems. Broadly these are in three areas: dealing with the different handling of different browsers, dealing with getting the video ready for different browsers, and having a workflow that doesn’t make me cry.

The last one is crucial. I use WordPress because I want to be able to hand over the entering of content to the person whose website it is. I don’t want to tell her, “download ffmpeg, install via command line, and then to compress your video, enter (string of gibberish)”. If I have to stop to understand how something works, what’s it going to be like for people who just want to get their video up?

Unlike getting video ready for Flowplayer, which is simply encoding to h264 and can be done with minimal hassle with something like Handbrake or even QuickTime 7, HTML5 video needs it in three different formats, the latter two – WebM and OGG – unless you want to get into aforementioned command line, have few options on a Mac.

I tried installing the two codecs for Quicktime (WebM and Xiph) and found the results to be poor. Blocky video, mediocre colour fidelity, softness and more (or rather less), all which point to the most significant problem with HTML5 video: WebM and OGG are nowhere near good enough for web video.

I also tried Miro Video Converter, which unlike all the others (bar Permute) does all the necessary formats. Using ffmpeg in the back, its drag-drop efficiency is commendable, and were it not for the inability to adjust the defaults would be one to consider using, but again, the quality simply wasn’t good enough. (I should mention, the video source for the tests was a variety including at best HD and at worst f4v.) I settled on Permute, which is one step up, and gives a modicum of configuration, but still the poor rendering of WebM and OGG can’t be ignored.

If this wasn’t bad enough, and it was admittedly workable – I could see how to put together a workflow for people that wouldn’t horrify them, that got them from edited video to the three files, uploaded and into WordPress using metaboxes, all not beyond an average internet user’s capabilities – it could have at least been offset by the browsers doing something useful like respecting the ‘preload’ attribute.

preload is the killer for HTML5 video and the single fundamental reason why it’s unworkable and will remain so until browser vendors stop pretending it’s “1998 browser war!”

There are three possible preload options: none, metadata (loads the first frame and makes sure it can play whatever it is), and auto – which (seems to) loads the video in the background once a page is finished loading. The latter is useful for a page in which all there is is a video to watch, but for a site with say five videos on one page, each of around 80-100mb, with browsers who think preload=”none” is something to ignore, it’s horrific.

The only workaround I saw was a truly ugly JavaScript hack, replacing the splash image with the video element when clicked. I cringed. Even thinking along the same lines, using jQuery to load an external file with the video code is just stupid.

Other things that annoyed me in no particular order: when clicking another video or link, the current video keeps playing; no easy possibility for html over the video or splash image; no simple support for bandwidth detection or SD/HD options … I could go on, but I really did cry with frustration at what should be so simple.

It’s so disappointing that in 2011 browsers are still pathetic at handling video. It makes it horrible for people making websites as well as people who just want to add video to their own sites and don’t want to be hobbled by the limitations of YouTube or Vimeo. And it’s insulting for all of us with Chrome and Firefox pretending WebM and OGG are acceptable and pulling the ‘open’ and ‘free’ trope against h.264.

I want video to work just like img. If it doesn’t, there is no point in using anything other than Flash.

For the moment, I stay with Flowplayer and h.264 with Flash. It’s not perfect, and has its own frustrations, but at least it works.

A sticky footer pretending to be a link

Finishing up francesdath.info, I noticed there was a lack of credits for the background images. I didn’t want to have something obvious interrupting every page, but equally putting something in the alt tag, while adequate for those who poke around, wasn’t quite in the spirit of attribution.

I had an idea for a question mark in the bottom right corner, unobtrusive, yet also noticeable, matching the formatting for links throughout the site, that when hovered over would show a box with details of performance, performers in the photograph, and photographer’s name.

I tried a couple of options, first looking at tooltips, but the formatting, even with jQuery, wasn’t so simple. I also didn’t really want to go to jQuery anyway. What I wanted was to create a metabox with the three fields, which would spit the content into whatever markup could be most agreeable to being styled.

The metabox part was easy, about 30 minutes sticking it all together and testing. The styling though…

Once I’d discarded the tooltips approach, the next method seemed to be the the Eric Meyer pure CSS popups method, sticking a span inside a link and display: none until hover and then showing it. Ok for single lines of text that don’t need additional styling, but for what I wanted, each item on a separate line, it didn’t work.

Perhaps I should have read around more, but it occurred to me that a div can handle the :hover pseudo element just as well as a link can, so then I could have one div that I’d attach that to, and another div inside that which would be displayed or not, opening up all manner of possibilities, like this:

1
2
3
4
5
6
7
8
<div id="credits">
    <div class="details">
        <p>performance: <?php global $credits_metabox; $credits_metabox->the_value('credits_performance'); ?></p>
        <p>performers (l-r): <?php global $credits_metabox; $credits_metabox->the_value('credits_performers'); ?></p>
        <p>photographer: <?php global $credits_metabox; $credits_metabox->the_value('credits_photographer'); ?></p>
    </div>
    <span class="question">?</span>
</div><!-- #credits -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#credits {
    position: fixed;
    bottom: 0;
    right: 0;
}

#credits span.question {
    color: #fff;
    background-color: #54cbff;
    padding: 1px 2px 1px 2px;
    cursor: pointer;
    text-align: right;
}

#credits div.details {
    display: none;
}

#credits:hover div.details {
    display: block;
    position: relative;
    z-index: 100;
    background: #000;
    top: 13px;
    width: auto;
}

#credits:hover div.details p {
    padding: 1px 2px 2px;
    color: #fff;
    text-align: right;
}

Besides the miscellaneous styling, what’s important is the #credits styling to fix it in the bottom right corner, and the display: none of .details, as well as the display: block and styling with #credits:hover. the cursor: pointer helps in that it changes the default arrow to a standard link pointer; a slight visual cue. I’m sure I could have written it more concisely and neatly, and additionally I could add a CSS3 fadein transition, but I had to get to rehearsal.

CSS Tooltip Div Hidden

CSS Tooltip Div hover Shown

2011.touchandplay.org

Today the 2011.touchandplay.org Festival site went live. After last year’s festival site, I organised the transferral of the site, formerly at a .eu domain, to it’s own sub-domain, now at 2010.touchandplay.org, and separating off touchandplay.org onto its own, which is my next project.

The festival last year was in Berlin, and this year moves to Cardona, Spain, near Barcelona. I wanted to keep aspects of the design, as well as much of the structure, as it is not so small, with over a hundred pages. In the last year also, I’ve spent so much time in WordPress that organising all the templates with conditional tags, shortcodes and functions.php was a fairly simple process. Coming straight from Brussels though – and not having a laptop for last week as the deadline came up, gave me a few 5am finishes.

So, first in Photoshop, keeping the splattery title, and creating a much simpler background – it’s not often I do sites with light typography on a dark background. The background images themselves are of the venue, currently being renovated, with the architectural plans laid over the top. Keeping the content areas legible then was very important.

Some of the code I’ve been writing in the previous weeks and months turned up here, including the shortcode for adding Flowplayer video, the very simple PHP background image rotator, other bits and pieces including the use of tags on pages for different workshop types, coupled with a conditional statement to only show the tags section on workshops with tags.

Still little things to fix up, but nice for all of us to see it alive on a sunny Spring Equinox in Berlin.

2011 Touch&Play Festival

francesdath.info

The last few days in my spare time around other projects, cycling around Berlin, midnight yoga, weekend yoga & shibari workshops and other stuff, I’ve been updating my venerable performance website, francesdath.info. Almost ten years old, but with a name change half-way when zeroballet.info was lost, it’s been through several incarnations.

The original was in Flash, when people were all making beautiful sites using this, and miniml was the choice of font. Then, when the split occurred, and supernaut.info went off on her own (first into Movable Type, then not so long ago into WordPress), or some time after, I became frustrated with how difficult it was to add new content, and so threw together a static HTML design in an afternoon.

That one lasted for a long time with few changes, though the last year I was always thinking of replacing the monospaced font with Anonymous Pro and sticking it all into WordPress.

WordPress did seem a little excessive for what is a mostly unchanging website, several pages with little content and one with (I always planned but never added) a lot of video. Then there was the issue of recreating the video playlist in a WordPress page. Some pondering, and I solved that, and all the other stuff, menus, background images, typography, proper semantic-ish structure, all the usual plugins I add that give a modicum of functionality, all fell together.

The 404 page is rather special too.

francesdath.info

 

PHP ‘random’ background image rotator?

All I wanted was something simple that would show a different, random background image on each new page.

I didn’t want to have to use something heavy like Supersized (which I’ve used on another project), nor did I want to use the Hiveware rotate.php method as it doesn’t necessarily reload once a background image is cached, the problem I had last year with 2010.touchandplay.org.

I’ve been using the 100% CSS background image method quite a bit. It’s simple, needs no jQuery, and is only a dozen lines. I wanted something just as simple and uncomplicated for random image rotation. This is what I used:

1
2
3
4
<?php $randomvar = rand(1,7); ?>
<div id="hintergrund">
<img src="<?php bloginfo('template_directory'); ?>/images/backgrounds/background-<?php echo $randomvar;?>.jpg" class="bg" />
</div>

$randvar selects a number between 1 and 7. It’s not truly random, but for the sake of what I need, approximately unpredictable is as good as random. Then I have the background images in a folder (using the WordPress template_directory path), seven in total, named background-n.jpg. I simply used echo to get the random number and insert it in the image file name.

Flowplayer Playlists and WPAlchemy Meta Boxes

I seem to be spending a lot of time working out semi-clever ways to not just get video into WordPress, but to do it in a customised way that is also easy for an imagined user to deal with. The last couple of times I’ve written about this, I’ve been using Flowplayer with More Fields. This time I needed something a little different.

I’d been meaning to put my performance website, francesdath.info into WordPress for a long time. In a way it doesn’t need it, being so simple (it took an afternoon to code it). But I wanted to touch up the typography with Anonymous Pro, and also I had ideas for the video.

Some Background

I originally coded the video for francesdath.info in .f4v – obviously requiring an update. More importantly, I had all the video on one page and used the Flowplayer Playlist plugin to make an orderly list of videos. I originally thought of putting the video on each project page, but then something about the single page with the playlist appealed to me.

Thoughts

For some days I’d been going through the process in my head, what exactly would I need to do. Obviously going the Custom Fields way was necessary, but with some unknowns. The first being that the field would need to have Meta Boxes added dynamically, otherwise I’d be limited to n-number of videos, or forced to add a new Custom Field every time I wanted a new video.

Then there was the question of spitting the results of the fields into Flowplayer’s Playlist array. In itself not so difficult, provided there was a little leeway with stray line-ending commas and all the brackets and bits were in the right place.

This though, I thought, would probably be simply a matter of inexorable shoving until it caved in, as opposed to a dynamically added series of Meta Boxes that I had only one idea about: More Fields, which I have been using until now wouldn’t be able to do it.

WPAlchemy

I discovered ages ago, when I was still terrified of Custom Fields and even using plugins for this hurt my head. So when I was searching and searching for answers, its appearance was at least familiar, though not necessarily comforting as it looked a little not-simple, and the time spent in learning it might be wasted if it couldn’t do what I wanted.

It turned out it could do what I wanted. Dynamically added Meta Boxes, a huge degree of customisation (even multiple Visual Editors if you’re so inclined), and the wonderful ability to include or exclude boxes from pages – something I achieved in the past through adding a Page_ID class to the body in the wp_admin editor and display:none. Ugly but satisfactory. The first thing then, was working out how it worked.

WPAlchemy requires a few things, not necessarily in any specific place if you feel like editing the default file paths and names. wpalchemy.php does the legwork and I only vaguely peered into that. meta.css styles the admin editor, so the Meta Boxes look like they belong, thought some of this is handled by wpalchemy.php. Then there are the files you make, which contain the Meta Boxes themselves. In addition, some code is added to functions.php that hauls all this together, and then some lines added into whatever theme template to make it appear in the real world.

functions.php

The starting place is here. First I added a fairly standard chunk that calls the relevant JavaScript files, either (in this case) on a single page, or on a child page.

1
2
3
4
5
6
7
8
9
10
11
12
// set the parent page id for productions and put the flowplayer js into the header
function flowplayer_video() {
    //is_page for page, is_child for sub-page
    if ( is_page( 'Page_ID' ) ) { ?>
    <script type="text/javascript" src="<?php bloginfo("stylesheet_directory"); ?>/js/flowplayer-3.2.6.min.js"></script>
    <script type="text/javascript" src="<?php bloginfo("stylesheet_directory"); ?>/js/flowplayer.playlist-3.0.8.min.js"></script>
    <script type="text/javascript" src="<?php bloginfo("stylesheet_directory"); ?>/js/flowplayer.ipad-3.2.1.js"></script>
<?php
    }
}

add_action('wp_head', 'flowplayer_video');

This is all fairly straightforward, just calling the relevant Flowplayer JavaScript, Playlist and iPad plugins.

Next is the setting up of WPAlchemy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// get the wpalchemy php
define('_TEMPLATEURL', WP_CONTENT_URL . '/' . stristr(TEMPLATEPATH, 'themes'));

include_once 'file/path/wpalchemy.php';
 
// include css to style the custom meta boxes in wp_admin
if (is_admin()) {
    wp_enqueue_style('custom_meta_css', _TEMPLATEURL . '/file/path/meta.css');
}

// this is the call for the video meta boxes
$video_metabox = new WPAlchemy_MetaBox(array (
    'id' => '_custom_video_meta',
    'title' => 'Video Playlist',
    'template' => TEMPLATEPATH . '/file/path/meta_video.php',
    'types' => array('page'),
    'context' => 'normal',
    'autosave' => TRUE,
    'mode' => WPALCHEMY_MODE_EXTRACT,
    'prefix' => '_video_',
    'include_post_id' => Page_ID,
    'hide_editor' => TRUE,
    ));

A little summary: First we get the wpalchemy.php file, located wherever you like. I put all the files into a single directory as this seemed the most organised approach for me. Then you call the meta.css for styling in wp_admin.

Next is excitement. $video_metabox is the name I’ve given to the new Meta Box. There are a variety of setup options which are explained in the documentation. For my purposes, I used a prefix to keep all the data together, as well as the WPALCHEMY_MODE_EXTRACT mode, which seemed to be a better option for the dynamically generated fields. I didn’t want the visual editor at all (though the absence of Media Library Upload/Insert buttons was a problem), and was very happy to only include it on one page. The path to the meta_video.php is where I went next.

meta_video.php

This is where the actual Meta Boxes that appear in wp_admin are put together. WPAlchemy has a lot of options, which are included in the download package and can be seen by uploading and setting it up. It took me a little while to work out how it all functioned, and then I put together this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<div class="my_meta_control">

    <?php if ( current_user_can( 'upload_files' ) ) : ?>
        <div id="media-buttons" class="hide-if-no-js">
            <?php do_action( 'media_buttons' ); ?>
        </div>
    <?php endif; ?>
 
    <h4>Set up the video playlist here.</h4>
   
    <label>Video Splash image</label>
 
    <p>
        <input type="text" name="<?php $metabox->the_name('splash_image'); ?>" value="<?php $metabox->the_value('splash_image'); ?>"/>
        <span>Get the Splash Image URL from the Media Library</span>
    </p>
   
        <label>Video details</label><br/>

    <?php while($mb->have_fields_and_multi('video_file')): ?>
    <?php $mb->the_group_open(); ?>
   
        <p class="video-item" style="float:left;">Video Item</p>
        <a href="#" class="dodelete button" style="float:right;">Remove</a>

        <p>
        <?php $mb->the_field('video_file_url'); ?>
        <input type="text" name="<?php $mb->the_name(); ?>" value="<?php $mb->the_value(); ?>"/>
        <span>Get the video file URL from the Media Library</span>
       
        <?php $mb->the_field('video_file_title'); ?>
        <input type="text" name="<?php $mb->the_name(); ?>" value="<?php $mb->the_value(); ?>"/>
        <span>Enter the video title</span>
       
        <?php $mb->the_field('video_file_subtitle'); ?>
        <input type="text" name="<?php $mb->the_name(); ?>" value="<?php $mb->the_value(); ?>"/>
        <span>Enter the video subtitle</span>
       
        <?php $mb->the_field('video_file_time'); ?>
        <input type="text" name="<?php $mb->the_name(); ?>" value="<?php $mb->the_value(); ?>"/>
        <span>Enter the video length e.g. 03:37</span>
        </p>

    <?php $mb->the_group_close(); ?>
    <?php endwhile; ?>

    <p><a href="#" class="docopy-video_file button">Add</a></p>

    <input type="submit" class="button-primary" name="save" value="Save">
   
</div>

SImplifying, and from top to bottom (and last to first), my last problem was the lack of a Media Library button that I’d erased by hiding the Visual Editor. My ugly but works method was to search through the WordPress core files for the call in the templates for this, and then paste that in above everything else. the ‘media_buttons’ part is this. It doesn’t allow entering content into a field, but then all I need to do is copy-paste the link, so it’s not so important.

The next section is a Meta Box for the video splash image, ‘splash_image’, with a name and value, which will be used later in the template. Below that, is the dynamic loop of Video Items. have_fields_and_multi(‘video_file’) starts it all, and also will be used later in the template. Then there are just fields for the video file URL, Title, Subtitle and Time. More could be added as it is quite extensible.

At the top and bottom of this section is a ‘Remove’ and ‘Add’ button, and then one to save it all. In the editor, it looks like this:

Video Meta Boxes

page-video.php

Then this all must be taken from the database and arranged in a template. I made a template called page-video.php, a very standard one with all the junk stripped out and after spending a couple of hours working out how WPAlchemy calls the data, came up with this:

1
2
3
4
5
6
<div class="video-player">
    <a class="player plain" id="ipad">
        <img src="<?php $video_metabox->the_value('splash_image'); ?>" alt="" />
    </a>
</div>
<!--<div id="appleControls" class="controls"></div>-->

The div classes and ids are standard Flowplayer. The img gets the splash image by first deciding which WPAlchemy_MetaBox to get (the first line in functions.php – $video_metabox), and then which value, in this case ‘splash_image’. Once I worked out how it was calling the data, putting together the video playlist was not so difficult.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
window.onload = function () {
    $f("ipad", "<?php bloginfo("stylesheet_directory"); ?>/swf/flowplayer-3.2.7.swf", {
        play: null,
        clip: {
            baseUrl: 'http://francesdath.info',
            onFinish: function () {
                this.unload()
                }
            },
        playlist: [
            <?php while($video_metabox->have_fields('video_file')) { ?> {
                url: '<?php $video_metabox->the_value('video_file_url'); ?>',
                title: '<?php $video_metabox->the_value('video_file_title'); ?>',
                subTitle: '<?php $video_metabox->the_value('video_file_subtitle'); ?>',
                time: '<?php $video_metabox->the_value('video_file_time'); ?>'
                },
            <?php } ?>     
            ],
        plugins:  {
            controls: {
                url: "<?php bloginfo("stylesheet_directory"); ?>/swf/flowplayer.controls-3.2.4.swf",
                all: false,
                play: 'true',
                scrubber: 'true',
                fullscreen: 'true',
                height: 20,
                opacity: 1.0,
                buttonOverColor: '#ffffff',
                backgroundGradient: 'none',                                            
                backgroundColor: 'transparent',
                progressGradient: 'none',
                borderRadius: '0px',
                progressColor: '#ffffff',
                bufferGradient: 'none',
                sliderGradient: 'none',
                durationColor: '#ffffff',
                buttonColor: '#ffffff',
                sliderColor: '#000000',
                bufferColor: '#445566',
                timeBgColor: 'transparent',
                timeBorder: 'none',
                timeColor: '#ffffff',
                autoHide: 'true',
                tooltipColor: 'transparent',
                tooltipTextColor: '#ffffff',
                tooltips: {
                    buttons: true,
                    fullscreen: 'Fullscreen'
                    },
                }, 
            },
        canvas: {
            backgroundGradient: 'none',
            backgroundColor: '#000000',
            },
        });$f("ipad").playlist(".clips").controls("appleControls").ipad({ simulateiDevice: true, controls: false });
};

Flowplayer does its setup in JavaScript (though still uses Flash for some of the control which is my main dislike of it as it makes coding for iPhone/iPad irritating, even with the iPad plugins). Much of this is just standard setup stuff, which I won’t go into here. The heart of it is in the playlist setup.

Again it calls to $video_metabox, and then to have_fields, which showed up at the start of the dynamic Meta Box loop, in this case the field, ‘video_file’. The Flowplayer playlist uses url, title, subTitle, and time as properties to build the playlist, though some can be excluded. Replacing hard-coded paths with calls to the video_file values, video_file_url, video_file_title, video_file_subtitle, video_file_time was enough to get it all working, once it was all wrapped with php tags.

Finishing

Most of this took an afternoon to get through, the slowness often being in dealing with miniscule issues rather than overall functioning. For what I wanted to do, it works quite well, the main problems being with Flowplayer and difficulties with functioning on iPad and iPhone, something that is on my list to sort out next. With minimal knowledge, you could copy-paste your way through this, but it might be better to find a plugin that does it unless you enjoy messing about like this.

Oh, and you can look at it here: francesdath.info/wordpress/video, which will lose the ‘wordpress’ once the site goes live.

Excluding Custom Fields from Specific Pages in wp-admin

I’ve been using More Fields to create Custom Fields in danielschlusser.com, and came up with the issue of not wanting specific fields to appear on certain pages in WordPress Admin. Hiding them on the live site is easy, but working out how to have only fields appear on certain pages while editing in wp-admin…

The first problem is remove_meta_box doesn’t work with this plugin. The second problem is the arguments for this function are pretty limited unless you use Custom Post Types, and I’d decided very early on that I was taking on enough in this site and didn’t want to complicate things with this other wayward variable.

Poking around in Safari’s Web Inspector I experienced disappointment. Although the post_id shows up for the Upload / Insert buttons, proving it can occur, it shows up nowhere else meaning targeting a custom field via a unique page class wasn’t immediately possible.

More searching and failure.

In the end I decided on a less-than-ideal-but-uh-I-just-want-this-to-work method of adding some info to the admin-header.php in wp-admin. Not the most ideal method and doing it via functions.php would be the better way, but I couldn’t work out how and I’d already spent the day staring at code.

The body class of wp-admin already contained some classes, so I just added some extra ones to admin-header.php:

1
<body class="wp-admin no-js <?php echo apply_filters( 'admin_body_class', '' ) . " $admin_body_class"; ?> <?php echo apply_filters( 'post_id', '' ) . "page-$post_id"; ?> child-of-<?php echo apply_filters( 'post_parent', '' ) . "$post->post_parent"; ?>">

The page-$post_id returns the class of the current page i.e. class=”page-127″. The second declaration returns the class of the current page’s parent, i.e. class=”child-of-122″ The former allows me to style a unique page in wp-admin, while the latter allows me to style every child page, exactly as you can in a live site.

From there, it’s a simple matter of using CSS to first hide the custom fields from every page except the ones I want them on, and then show them on those pages:

1
2
3
4
5
6
7
body #post-body #normal-sortables #video {
    display: none;
}

body.child-of-127 #post-body #normal-sortables #video {
    display: block !important; /* !important is not strictly necessary */
}

This goes in the CSS file, wp-admin.css, which is (probably messily) called in functions.php with:

1
2
3
4
5
6
function fields_exclusion() {
    $url = get_option('siteurl');
    $url = $url . '/wp-content/themes/thingswithbits/css/wp-admin.css';
    echo '<link rel="stylesheet" type="text/css" href="' . $url . '" />';
}
add_action('admin_head', 'fields_exclusion');

Two Ways to Put Flowplayer into WordPress — Custom Fields & Shortcodes

In April last year, I wrote a method for getting Flowplayer to work in WordPress. Not an especially elegant method, using PHP and editing HTML in the Visual Editor – certainly not enjoyable or appropriate for the vast majority of WordPress users who don’t want to stare at code.

Since then, with WordPress 3, I put together method using Custom Fields, which I’ve been using a lot in on various projects. Last night, wondering how to deal with video in the body of a news post, I thought of using Shortcodes, and the last couple of hours, I hacked together something that works…ish.

Method 1 — Flowplayer and Custom Fields.

I’ve been using the More Fields plugin since I first discovered it because I think it’s the simplest to understand and use both in WordPress Admin and in adding code to various templates.

I made a new Field Box called ‘Video’, with the fields, Video Title, Video Caption, Video File, and Splash Image. Each of these are of the Field Type, ‘Text’. An additional field, Add Video (Field Type, ‘Radio’) is used as a CSS class to hide the entire Video element if there is no video on a page.

Flowplayer WordPress More Fields Setup

As a custom Field in a new Page, it looks like this:

Flowplayer WordPress Custom Field

The process for using the custom field is straightforward.

  1. If you have a video to add, click the ‘include’ radio button
  2. Write a title
  3. Write a caption
  4. Upload the video and using the Media Browser, copy-paste the video file path
  5. Upload the splash image and using the Media Browser, copy-paste the video file path

Giving both the video and splash image a useful, descriptive name is also helpful.

Next is Joy of Code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<div id="video" class="<?php meta('add-video'); ?>">
    <h4><?php meta('video-title'); ?></h4>
   
    <div id="video-player">
        <a class="player plain" id="ipad" href="<?php meta('video-file'); ?>"><img src="<?php meta('splash-image'); ?>" alt="Video File: <?php meta('video-file'); ?>" /></a>
       
    <script language="JavaScript">
        window.onload = function() {
            $f("ipad", "<?php bloginfo("stylesheet_directory"); ?>/swf/flowplayer-3.2.5.swf", {
                play: null,
                logo: {
                    fullscreenOnly: true,
                    },
                clip: {
                    onFinish: function () {
                    this.unload()
                    }
                },
                plugins: {
                    controls: {
                        url: "<?php bloginfo("stylesheet_directory"); ?>/swf/flowplayer.controls-3.2.3.swf",
                        all: false,
                        play: 'true',
                        scrubber: 'true',
                        fullscreen: 'true',
                        height: 20,
                        opacity: 1.0,
                        buttonOverColor: '#ffffff',
                        backgroundGradient: 'none',    
                        backgroundColor: 'transparent',
                        progressGradient: 'none',
                        borderRadius: '0px',
                        progressColor: '#ffffff',
                        bufferGradient: 'none',
                        sliderGradient: 'none',
                        durationColor: '#ffffff',
                        buttonColor: '#ffffff',
                        sliderColor: '#000000',
                        bufferColor: '#445566',
                        timeBgColor: 'transparent',
                        timeBorder: 'none',
                        timeColor: '#ffffff',
                        autoHide: 'true',
                        tooltipColor: 'transparent',
                        tooltipTextColor: '#ffffff',
                        tooltips: {
                            buttons: true,
                            fullscreen: 'Fullscreen'
                            },
                        },
                    },
                canvas: {
                    backgroundGradient: 'none',
                    backgroundColor: '#191919',
                    },
            }).ipad();
        }
    </script>
    </div><!-- #video-player -->
</div><!-- #video -->

A brief description.

This is the standard Flowplayer setup I’m using at the moment, minus pseudostreaming and bandwidth detection. It’s also using the iPad JavaScript Plugin, so providing the video has been encoded in a useful format for iDevices, it will work on them also.

Into this, the More Fields PHP meta values are inserted:

1
2
3
4
<?php meta('add-video'); ?>
<?php meta('video-caption'); ?>
<?php meta('video-file'); ?>
<?php meta('splash-image'); ?>

‘add-video’ adds a class of either ‘include’ or ‘exclude’ to the video div wrapper. When it’s set to ‘exclude’ it just has a declaration in the CSS of ‘display: none’. A bit hacky, but does the trick. ‘video-caption’ is self-explanatory. ‘video-file’ and ‘splash-image’ are the full file-paths for the files found in the Media Browser.

The good thing about this method is that it is made visually clear by using a custom field. It’s also possible to include instructions with each input field. This all goes in whatever template you wish to have the video in. At the moment I tend to make a specific template for pages this.

A further addition for efficiency happiness is the following chunk which goes in functions.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// first figure out if a page is a child because we only want to load flowplayer js on pages with video
function is_child($pid) {
    // $pid = The ID of the ancestor page
    global $post; // load details about this page
    $anc = get_post_ancestors( $post->ID );
    foreach($anc as $ancestor) {
        if(is_page() && $ancestor == $pid) {
        return true;
        }
    }
        return false; // we're elsewhere
};

// now set the parent page id for productions and put the flowplayer js into the header
function flowplayer_video() {
    if ( is_child( '127' ) ) { ?>
    <script type="text/javascript" src="<?php bloginfo("stylesheet_directory"); ?>/js/flowplayer-3.2.4.min.js"></script>
<?php
    }
}

add_action('wp_head', 'flowplayer_video');

Not loading unnecessary JavaScript is good, especially with Flowplayer, which has several individual documents. This function only loads the files if the pages happen to be children of a particular parent page. It’s not a solution for every situation, but equally is easily extendable.

Method 2 — Flowplayer and Shortcodes

This was something I’ve been thinking about for a while, for a site for a theatre director I’m close to finishing. The first method was what I came up with for video on the Productions pages, but I also wanted to be able to have the option to include video in news posts in the blog section, as he currently does on his blog.

Somehow I got thinking about shortcodes, which until last night when I first began reading about them had no idea how to go about implementing them. Turns out to be stupid-simple. I built this around the example I found here.

The process very similar to using custom field meta values, and instead of it being hard-coded into a template, it goes in the functions.php and it only used when needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
function flowplayer_shortcode( $atts, $content = null ) {
    extract( shortcode_atts( array(
        'title' => '',
        'image' => '',
        'src' => '',
        ),
    $atts ) );
    $output .= '<div class="news-video"' . '\n';
    $output .= '<script src="http://thingswithbits.info/wordpress/wp-content/themes/thingswithbits/js/flowplayer-3.2.4.min.js" type="text/javascript"></script>';
    $output .= '<h4>'.$title.'</h4>' . "\n";
    $output .= '<a class="player plain" id="ipad" href="'.$src.'"><img src="'.$image.'" alt="Video File: '.$src.'" /></a>' . "\n";
    $output .= '<script language="javascript">
                    window.onload = function () {
                        $f("ipad", "http://thingswithbits.info/wordpress/wp-content/themes/thingswithbits/swf/flowplayer-3.2.5.swf", {
                            play: null,
                            clip: {
                                onFinish: function () {
                                    this.unload()
                                    }
                                },
                            plugins: {
                               controls: {
                                    url: "http://thingswithbits.info/wordpress/wp-content/themes/thingswithbits/swf/flowplayer.controls-3.2.3.swf",
                                    all: false,
                                    play: \'true\',
                                    scrubber: \'true\',
                                    fullscreen: \'true\',
                                    height: 20,
                                    opacity: 1.0,
                                    buttonOverColor: \'#ffffff\',
                                    backgroundGradient: \'none\',                                              
                                    backgroundColor: \'transparent\',
                                    progressGradient: \'none\',
                                    borderRadius: \'0px\',
                                    progressColor: \'#ffffff\',
                                    bufferGradient: \'none\',
                                    sliderGradient: \'none\',
                                    durationColor: \'#ffffff\',
                                    buttonColor: \'#ffffff\',
                                    sliderColor: \'#000000\',
                                    bufferColor: \'#445566\',
                                    timeBgColor: \'transparent\',
                                    timeBorder: \'none\',
                                    timeColor: \'#ffffff\',
                                    autoHide: \'true\',
                                    tooltipColor: \'transparent\',
                                    tooltipTextColor: \'#ffffff\',
                                    tooltips: {
                                        buttons: true,
                                        fullscreen: \'Fullscreen\'
                                        },
                                    },
                                },
                            canvas: {
                                backgroundGradient: \'none\',
                                backgroundColor: \'#000000\',
                                },
                            }).ipad();
                        }
                </script>'
. "\n";
    $output .= '</div><!-- end .news-video-->' . "\n";
    return $output;
}
add_shortcode('video', 'flowplayer_shortcode');

Using the same idea as method 1, there is a video title, splash image and video file in the shortcode, which gets pulled into the  flowplayer_shortcode function and out comes Flowplayer video in WordPress.

Flowplayer WordPress Shortcode

(Please excuse the borked code display, I really need to try a new plugin.)

fontographie

Early rising to Kreuzberg and after a time to wake Matthi up in Reichenbergerstr. Breakfast peanutbutter and coffee, talking across queer and politics and Berlin and so to work.

My project for the coming months is for Daniel Schlusser, better known as our man in berlin, though he isn’t. In Berlin, I mean. Theatre director and rather talented to boot, and perhaps other things to write of with him shortly.

A new website. Excitement of jQuery, some ideas for typography. Matthi is a typographer and genius in FontLab and Illustrator, so I ask him how to dismantle a font, remove various bits that make up a letter, all of which have names I don’t know. I thrill for beautiful typography, and it’s what I enjoy possibly the most in design, but actual making of fonts is deeply unfamiliar to me. So this is a story of how I learn about fonts.

The two things I wanted to do were convert a font into an outline (not to be confused, I think, with a outline font), and chops bits off. My approach, as Matthi laughed, was very Photoshop. Much messing around ensued, and without his help, I’d have been doing it for months in my awful untrained way.

So…

Using the serif font, Tenderness from dot colon and opening in FontLab Studio, which to be uncharitable strikes me as an application ported to OSX without much thought towards standard user interface behaviour. Then opening a single letter or glyph in its own window and exporting as .eps. Now for playing.

Opening the .eps file in Illustrator and first hacking away bits (which I haven’t done in my test glyphs as I was more interested in workflow possibilities), and then turning it into an outline. The process is quite simple, once I learnt it, but I wouldn’t have stumbled onto it on my own.

Selecting the entire glyph and then setting the fill color to transparent and stroke to black, gives a one pixel outline. Opening the stroke pane and setting the weight to 6 pixels gives it some width. Then the important bit, selecting from the menu – Object – Path – Outline Stroke makes the vector path the width of the new 6 pixel outline. Saving as .eps again finishes the work in Illustrator.

Copy-Paste, back into the glyph in FontLab, aligning with the original, then shift-selecting to select the original before deleting (fixing up the mess, I called it), and saving the results…

First to export as something useful, .ttf, though it seems to not preview properly in FontExplorer… nonetheless! My first attempts at font stuff. (I’m not sure it will even be used, and there’s more work to do yet…)

6.4.2010 small

WordPress Security (in many small steps)

(This is for people who like reading code, cross-posted at supernaut.info)

Earlier this year supernaut got hacked. Many other of my WordPress installs did also, perhaps because they occupy the same shared hosting space. I learnt a lot about website and WordPress security very quickly – even to the point of inadvertently vanishing all but my index page for quite some time. Nothing if not clever, I am.

Because I am doing all my projects in WordPress at the moment, and also seem to have turned quite a few people over to using it also, I thought to document my approach and methods. The first thing I do then, is read. A lot.

I have a subjective and not-too carefully analysed approach to learning, especially when it comes to finding out information on a topic I know nothing about and need to know much quickly. It applies to everything, not simply limited to web design or computer stuff. I search and read and search and read and keep repeating until the same stuff starts to come up over and over again. Then I start to think I might be on the right path. So I might try a few things then. The key here is easiness. Anything requiring more than a few clicks, a few lines of text or modifications is not a reasonable solution.

Things that break this early get thrown away. A plug-in that asks for stupid things, or doesn’t perform without me rewriting some line in php.ini is not going to stay installed long. I wondered often if this was the wrong approach, but really, basic, effective security should be as simple to understand as a household door key. You shouldn’t have to build a lathe in order to cut the key yourself.

So, having done some research and playing, I slowly put together something useful. This is a mix of things I’ve been using for a while, and new things I’m adding at the moment, in response to pissy annoying php exploits, sql injections and other clever irritations.

Installing WordPress.

The first thing to change during an install is the database table prefix wp_. If you’ve already installed WordPress, it’s possible to also change this either using a plugin, or by editing wp-config.php and changing the table prefixes in phpMyAdmin.

Once logged in, make a new user with administrator privileges and suitably complex password (OSX Keychain Access has a very good password generator), log in with the new user and delete the user, ‘Admin’.

Now is also a good time to delete the default theme (after uploading your new one of course). As with the user named ‘Admin’, the wp_ table prefix and other defaults, botnet code injection methods look for these defaults as an easy place to start.

To avoid messiness, I think it’s better to leave installing plugins till last, though because information is sent in the clear unless using SSL or SSH, it’s probably a good idea to change the password again when it’s all finished.

Get rid of install.php

After your installation is finished, you don’t need this file, located in wp-admin. Delete it, or change the name, or even better log attempts to access it with this (just change the email address to receive notifications):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php // install.php replacement page: http://perishablepress.com/press/2009/05/05/important-security-fix-for-wordpress/ ?>
<?php header("HTTP/1.1 503 Service Temporarily Unavailable"); ?>
<?php header("Status 503 Service Temporarily Unavailable"); ?>
<?php header("Retry-After 3600"); // 60 minutes ?>
<?php mail("email@domain.tld", "Database Error", "There is a problem with teh database!"); ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Error Establishing Database Connection</title>
    </head>
    <body>
        <h1>Error Establishing Database Connection</h1>
        <p>We are currently experiencing database issues. Please check back shortly. Thank you.</p>
    </body>
</html>
Dealing with wp-config

Every time I open this file and see the database name, user, password and host all in plain text, I get a little queasy. There are several ways to make this less painful, firstly using htaccess, which I’ll cover later. A quite elegant solution is to put all the sensitive information in a separate php file outside the root web directory, and make a call to that in the wp-config file.

First make a new file, config.php stick it (on Dreamhost) in the /home directory, chmod to 644, and cut-paste the following from the original wp-config.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'database-name');

/** MySQL database username */
define('DB_USER', 'username');

/** MySQL database password */
define('DB_PASSWORD', 'p@s5w0rD');

/** MySQL hostname */
define('DB_HOST', 'sqlhost.domainname.tld');

/**
 * WordPress Database Table prefix.
 *
 * You can have multiple installations in one database if you give each a unique
 * prefix. Only numbers, letters, and underscores please!
 */

$table_prefix  = 'prefix_';

/** force ssl login and admin - might slow things down */
/** on dreamhost must pay for ssl cert, hence not used */
/** define('FORCE_SSL_ADMIN', true); */

?>

Then in the original file, just put:

1
include('/home/path/to/config.php');

For those lucky enough to have SSL on their server, using FORCE_SSL_ADMIN is an excellent idea. Changing permissions to 640 also is a good idea.

Adding Unique Authentication Keys takes about 30 seconds, and gives four separate keys to be used with your password. Copy-paste from the Secret Key online generator, it will look like this:

1
2
3
4
define('AUTH_KEY',        ' ;+ Xk*Kf:y3e1L?.,r[Hx<m;rV57d>2WL#<#3[ d]!#+$79/pSAF(HrGEAfS`a4');
define('SECURE_AUTH_KEY', '.k0zMi[@f&)E>~y=ZqO6~IfHS$S SP8d>C]S@:zhxh?H]VtXEpqV?p-OJV*O~3?v');
define('LOGGED_IN_KEY',   '~:b*7/m+Lx|-irCxYAHQn1t2$sYA+2}+*2c@!_,9/D2-H5cJ_:wJ8X7|-p%W&xGh');
define('NONCE_KEY',       '%#T+Y*|N>cq/2m3CRqR}SCM  BodKio`<x+?nMAe6,qgU:YiyKgEu,%<er>>qS$V');
Functions.php

Most themes have a functions.php file which does all sorts of exciting things, writing bits to the theme templates, interacting with WordPress admin interface… A couple of extra lines provide a little obscurity. WordPress puts its version number in the header in wp_generator, and also a link to xml-rpc.php, which for most people is unnecessary – unless they are using a blogging client like Marsedit – and a risk. This quickly removes both, as well as hiding information about failed login attempts through the browser:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
//security stuff
add_filter('login_errors',create_function('$a', "return null;"));

function removeHeadLinks() {
    remove_action('wp_head', 'rsd_link');
    remove_action('wp_head', 'wlwmanifest_link');
}
add_action('init', 'removeHeadLinks');

function no_generator() { return''; }
    add_filter('the_generator', 'no_generator');
?>
htaccess

.htaccess is a joyous little world unto itself, like finding a hole in your backyard that leads into a vast cave system. mmm spelunking.

Much of my learning about security has revolved around what can be done with htaccess, and in particular Perishable Press and their 4G Blacklist. And much of what I do for security takes place here.

Starting with denying access to all to read the htaccess file itself. Then there is the WordPress hook that allows the install to exist in a different directory location to the site url. For those again who have SSL on their server, forcing SSL can be done here for admin and login. Then there are a bunch of protections to stop access to certain important files, install.php, wpconfig.php, and the WordPress readme.html.

Using gzip compression to deliver files and adding content expires information doesn’t strictly have much to do with security, but really, the difference in load times the former can make to a site, and the general usefulness of expires tags make this one to automatically add.

For those on Dreamhost, the DH-PHP handlers is automatically added when using the site-specific php.ini installer, something I’ll cover a bit further down.

Hotlinking prevents leechers sucking images and other content off your site, one of the first things I ever learnt how to prevent, when supernaut suddenly had massive bandwidth use as my images turned up in all manner of places.

The no-referrer section is specifically to thwart spammers circumventing your site altogether and trying to inject comment spam directly into the comments php. It’s also possible to block access to xml-rpc here, and use login passwords via httpasswd for extra security on the login page, both not included here.

Then comes the Perishable Press 4G Blacklist, a cornucopia of amazingness, which I left out for sake of brevity (haha). I have included two lines that need to be commented out in order for the browser-based file manager AjaXplorer to function ok.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# === DENY HTACCESS ===
<files .htaccess>
order allow,deny
deny from all
</files>
# === END DENY HTACCESS ===

# === BEGIN WORDPRESS ===
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# === END WORDPRESS ===

# === FORCE SSL ===
#RewriteRule !^/wp-(admin|login|register)(.*) - [C]
# === END FORCE SSL ===

# === PROTECT install.php ===
<Files install.php>
    Order Allow,Deny
    Deny from all
    Satisfy all
</Files>
# === END PROTECT install.php ===

# === PROTECT readme.html
<files readme.html>
    Order deny,allow
    deny from all
</files>
# === END PROTECT readme.html

# === PROTECT wpconfig.php ===
<files wp-config.php>
order allow,deny
deny from all
</files>
# === PROTECT wpconfig.php ===

# === DH-PHP handlers ===
AddHandler fastcgi-script fcg fcgi fpl
AddHandler php-fastcgi .php
Action php-fastcgi /cgi-bin/dispatch.fcgi
# === END DH-PHP handlers ===

# === BEGIN GZIP FILE TYPES BY EXTENSION ===
<Files *.html>
SetOutputFilter DEFLATE
</Files>
<Files *.css>
SetOutputFilter DEFLATE
</Files>
<Files *.js>
SetOutputFilter DEFLATE
</Files>
<Files *.ttf>
SetOutputFilter DEFLATE
</Files>
# === END GZIP FILE TYPES BY EXTENSION ===

# === BEGIN CONTENT EXPIRES ===
#set expire dates
<IfModule mod_expires.c>
ExpiresActive on
# 60 seconds * 60 minutes * 24 hours * 7 days
ExpiresDefault A604800
# 60 seconds * 60 minutes * 24 hours
ExpiresByType text/html A86400
</IfModule>
<FilesMatch "\.(ico|pdf|flv|f4v|m4v|jpg|jpeg|png|gif|swf|js|css|ttf)$">
# configure ETag
FileETag none
# max-age set to one week as above
Header set Cache-Control "max-age=604800, public, must-revalidate"
# if you use ETags, you should unset Last-Modified
# Header unset Last-Modified
</FilesMatch>
# === END CONTENT EXPIRES ===

#  === DISABLE HOTLINKING ===
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png|ico)$ [NC]
RewriteCond %{HTTP_REFERER} !^https?://([^.]+\.)?domainname\. [NC]
RewriteRule \.(gif|jpe?g?|png|ico)$ - [F,NC,L]
</ifModule>
#=== END DISABLE HOTLINKING ===

# === DENY ACCESS TO NO-REFERRER REQUESTS ===
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .wp-comments-post\. [NC]
RewriteCond %{HTTP_REFERER} !.*domainname\. [OR,NC]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule (.*) - [F,L]
</IfModule>
# === END DENY ACCESS TO NO-REFERRER REQUESTS ===

# === PERISHABLE PRESS 4G BLACKLIST ===

(snip…)

# QUERY STRING EXPLOITS
<IfModule mod_rewrite.c>
# this line stops ajaxplorer working
RewriteRule ^(.*)$ - [F,L]
</IfModule>

# CHARACTER STRINGS
<IfModule mod_alias.c>
 # BASIC CHARACTERS
# RedirectMatch 403 \/\/ ajaxplorer again
</IfModule>
robots.txt

Equally effective, and probably overkill, using robots.txt can grant or forbid access to a slew of places, particularly directories that you don’t want spidered, as well as any and all WordPress directories, using Disallow: /wp*.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
User-agent: *
Disallow: /cgi-bin
Disallow: /lurking
Disallow: /phpsecinfo
Disallow: /wp-*
Disallow: /tag
Disallow: /author
Disallow: /wget/
Disallow: /httpd/
Disallow: /i/
Disallow: /f/
Disallow: /t/
Disallow: /c/
Disallow: /j/
 
User-agent: Mediapartners-Google
Allow: /
 
User-agent: Adsbot-Google
Allow: /
 
User-agent: Googlebot-Image
Allow: /
 
User-agent: Googlebot-Mobile
Allow: /
 
User-agent: ia_archiver-web.archive.org
Disallow: /
 
Sitemap: http://www.domainname.tld/sitemap.xml
php.ini and phpsecinfo

Getting deeper into the system still and further yet from WordPress, modifying php.ini, the file that sets up what php can do is another essential. Dreamhost doesn’t make it easy to edit the php.ini, but fortunately there’s a script which installs it locally. More excitement ahead.

As with htaccess, much can be done in php.ini to prevent messiness. The following seem to work rather well. I’ll leave this uncommented upon except to say AjaXplorer needs fopen to be on, and shall devote a future post to elaborating on php.ini security.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
open_basedir = /home/site/folder:/home/site/tmp/folder
disable_functions = exec,passthru,system,proc_open,popen,curl_multi_exec,parse_ni_file,show_source
expose_php = Off
error_reporting = E_ALL & ~E_NOTICE
register_globals = Off

; Whether to allow HTTP file uploads.
file_uploads = On
upload_tmp_dir = /home/site/folder/tmp/php
; Maximum allowed size for uploaded files.
upload_max_filesize = 200M

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
allow_url_fopen = On

; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
allow_url_include = Off

In addition to editing php.ini, and making sure there isn’t a file lying around called info.php with phpinfo() inside, phpSecInfo is an invaluable tool for assaying the security of your website, the results from which can be directly used to edit php.ini.

FTP, or rather SFTP.

As with passwords being sent in the clear, so too is FTP on its own not so great. Dreamhost allows for shell plus SFTP access with FTP disabled, which is both sensible for using desktop FTP clients (such as the amazing Transmit), and for searching out code injections. Time to open Terminal.

Commandline access is essential for a number of reasons, and instead of using the username/password combination, create passwordless login using private keys.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Generate a RSA private key

ssh-keygen -t rsa

// copy the key to your website

scp ~/.ssh/id_rsa.pub user@domainname.tld:~/

//ssh into your website
ssh user@domainname.tld

//Make a new folder, .ssh and copy the key to the authorized_keys file, then delete the key
mkdir .ssh
cat id_rsa.pub >> .ssh/authorized_keys
rm id_rsa.pub

//Set all permissions
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Why might this all be useful? Going back to when I was hacked earlier this year, I could have gone though all the files on all my sites looking for base64 code, instead I opened Terminal, SSH’ed in and sent this command:

1
find . -name "*.php" -exec grep "base64" '{}' \; -print

Which searches through all files with the extension .php for the string base64 and dumps the results on screen. I found every instance of the hack in a matter of seconds.

Plugins for security.

Leaving aside all that code now…

WordPress is amazing because of its plugins and the community around its development. The problem though, for any plugin is twofold. Which one does the task you want the best (while integrating with the rest of your setup), and is updated frequently enough to not become a liability?

After the initial hack, I had many installed, which I then uninstalled because of small irritations and annoyances. After changing all my passwords to 16+ characters, including as many of type !@£$%^&_ as allowable, WordPress File Monitor has become an installation standard.

Rather than provide security, it lets you know when any modifications to files and folders have occurred, and in which. Notification via email and/or Dashboard alert, alterable scan intervals and directory path exclusions for me make this indispensable. When a new exploit emerges, instead of panicking and manually scanning all my installs for changes (which I do anyway out of nervous boredom), I can be fairly secure they will show up here. Of course, the idea is not to get hacked in the first place.

I’ve read a lot of good things about AskApache Password Protect, but I’ve never got it working, despite adding all the .htaccess files and even chmod up to 666. I would at least play with it otherwise, but for now don’t want to spend the time on it.

In general though (and said with a caveat that I don’t really know WordPress very well), much or all security that can be done with plugins can be done in other ways – .htaccess, robots.txt. php.ini, wp-config, sql changes and so on. Also, so many of the plugins haven’t been updated recently, which for me is worse than no protection due to the false sense of security.

During the course of the last two days, while I went through all the security stuff I could find, websites, pdfs, my own archives, I came across a couple of other plugins which I think are useful.

Semi Secure Login Reimagined provides about as good public and secret key encryption for passwords as possible if you don’t have access to SSL.

WP Security Scan I found useful for a post-install check to make sure all the settings were as minimally tight as could be. In the interests of not having hundreds of plugins, I uninstalled it after.

404 Notifier does just that, though I suspect getting off my ass and reading the logs (or ssh and then grepping them for 404s) would be a better idea.

Sources

Much of my information for this comes from a few places.

The WordPress Codex itself is a good place to start, and the Plugin directory also worth spending time in.
Perishable Press is invaluable, and not just for security.
Digging into WordPress, both the website and the book are the fundamental step-by-step guide for all things security and WordPress.
The WordPress community, across many blogs, forums, books, comments and bits and pieces.

Oh, and while this applies also to WordPress 2.9.x, I’m currently running the 3.0 beta on thingswithbits.info where I tested all this. (hopefully this all doesn’t add to confusion.)

Shifting Daniel Jaber into WordPress

Daniel Jaber is the second choreographer and dancer I’ve done a website for. Coming from Dasniya Sommer, I was intent on messing around with jQuery again, and finding something distinctive to build his site around. The initial site, as with Dasniya, was hand-coded, relying on jQueryTools, which I discovered through Flowplayer for much of the interactivity.

Two big problems emerged. Firstly was the pain of updating static HTML. Even though I write my blog posts in this way, and have no difficulty screening out code from in front of my eyes, this way of managing a site is painful. The second big problem was the conflicts between how the content on the page was loaded and both video and images. The plan had always been to put the site into WordPress, and so I did.

The idea for using Daniel as his own background image was a fairly inevitable one, remembering when I first saw him, all piercings, blue mohawk, tattoos. I first tried supersized for this, but found it slightly heavy for just a single image. Lucky then CSS-Tricks had the perfect, all-css answer, which has become one of my favourite bits of code, being fond as I am of huge background images.

First though, I had an idea for the menu, coming from jQueryTools’ accordion tabs, with much eviscerating of CSS and some slowing down of the slide effect. This though, I could never get to work in WordPress. Much messing around in jQuery, dynamically adding classes and divs and removing them from elsewhere, I could even get it to work using an identical sidebar HTML structure to WordPress, but when I tried to use it in WordPress, weirdness ensued. I really wanted to use this though, because it’s the only accordion I’d seen with different times for the sliding effect.

But WordPress has almost everything, and I fell upon jQuery Accordion Menu for WordPress, which has very similar code, taking a couple of hours at the most to get the CSS right and working rather nice.

Of course when I added the page crossfade eyecandy, it broke again. My fault for using redirectPage.

supernaut still uses the Flash-based sIFR method for using nice fonts, but the last couple of sites I’ve been rather enjoying the combination of open-source fonts and @font-face. Not one of those beautiful new CSS3 adventure like opacity or rounded corners, even Internet Explorer 5 supported this, and lately with a deluge of options for pretty typography, it has become increasingly popular. And far easier to implement that sIFR also. Oh, the title font is Anonymous Pro, which I think is one of the most elegant monospace fonts around (also important that is has Unicode-based character set, important for things like ü and ß).

Being dance, video was always going to be lurking. I wrote about my fun with Flowplayer and WordPress earlier, and still finishing this, with bandwidth check, pseudostreaming and the inevitable full-screen option shuffling this way. I’d rather be doing this all in HTML5 though, and shall come up with a graceful degradation from that to this in my next project.

A bunch of small plugins helped me along the way also. Add From Server let me add video to the WordPress Media Libary after I’d uploaded via FTP – perfect for large file sizes, and modifying allowable upload file types meant I could get the f4v there also.

pageMash made structuring the site and reordering projects as they move from ‘soon’ to ‘now’ to ‘then’ so much nicer than blah-ing around editing the pages themselves, and PHP Execution made it possible to do the Flowplayer video cludge.

Elsewhere, Lightbox Plus for a not-overpowering image gallery, though I am still working on this. DB Cache Reloaded and Hyper Cache for the necessary site caching, as long as I don’t forget to disable them when I’m busy working. PHPEnkoder, based on my favourite Hivelogic anti-spam email encoder. And WordPress File Monitor, which is about the most useful anti-hacking plugins I’ve found.

Oh, and page crossfade! I know it’s a bit Flash 2001, but I really did want to recreate the page fade-out/-in from the original site. (Not so good if JavaScript is turned off though.)

Daniel Jaber Website small

Customised Flowplayer in WordPress

Last year while working on dasniyasommer.de and dealing with presenting video in an attractive way with much backend flexibility, I found Flowplayer. It’s remained my favourite video player, though with doing all my projects at the moment in WordPress, I went through a struggle the last days with it.

On another project I did recently, bedrohtevoelker.de (a simple transfer into WordPress using a template to make updating content easier), I used FV WordPress Flowplayer, but like all the plugins, and all the other players I’ve seen, there was little or no possibility to customise the controller or other background aspect.

I’ve been working on bringing Daniel Jaber’s website into WordPress in the last week. The original site, hand-coded falls apart in three quite important areas. Firstly, being html it’s a pain to update. Secondly, the combination of site structure and function make it a pain to get video and images to work properly, and thirdly, it breaks in the standard browser that things break in.

I thought I’d begin by first uploading all the text content, using Blueprint CSS again, which I’m customising more and more with each project, formatting this, and the general site structure and layout, deal with the image overlays, and then move onto the accordion menu and perhaps AJAX-ing the page loading after I’d done the video. The last couple of days have been video.

Much searching and trialling of plugins led me to think it was not going to be easy to recreate the video player as I’d coded it using this approach, so I started to look for both another workable option, and a fallback (ugh) in case there wasn’t.

My first serious approach was Manually Adding Flowplayer to a WordPress Theme, a step in the right direction, but not so manageable also. So then I started thinking, well it’s just a clump of Javascript with some specific HTML on the end, why can’t I just paste that into the HTML editor in WordPress? Because when you do things like that, WordPress breaks them. My next idea was, well, is there anyway to not-break them? Somehow my feeble brain stumbled back towards inserting PHP into a post.

Hallo WordPress PHP Execution Plugin. Though I did try the highly downloaded Exec-PHP first, it only allows pages to be written in HTML mode, not so good for people who just want to upload content. PHP Execution semi-allows this. in Visual mode, the PHP sits behind an image, so doesn’t get converted into junk. The semi-part is that if you edit a page in Visual mode, it breaks, but there is a cludge-ish workaround.

I started first by following the original article, adding the Flowplayer code to my page template, to make sure it worked and where it broke, then transferring it into a test-page and seeing the same. In the end, very little went askew. The plugin handles indented code formatting without letting WordPress stick a p or br tag between every new line, and respecting for the most part spaces as spaces, and the occasional addition of \ escapes was all the extra I added.

The only place it really gets affected is a matter of styling, where any line breaks between divs and other html markup, i.e. the last lines which create the player and controller have a br added between. Running all these lines into one fixed that, and the css I used in the original layout largely carried across to the new site – though I cleaned it up a little and took advantage of some CSS3 rounded corners.

Once this was all done, I decided to add a little pleasure for Daniel while editing a project page. The standard PHP Execution plugin covers the code in a small purple-ish ‘PHP’ graphic. I thought it’d be nicer, as the idea is for him to do everything besides the video in visual mode, to replace that graphic with a corresponding one representing the splash image for the player. A couple of minutes in Photoshop and then changing a couple of lines in the plugin’s css and happiness ensued.

What’s left to do then is get this working with multiple players on the same page and add in some of the other good features such as bandwidth streaming. With all of Flowplayer contained in the JavaScript or in a couple of lines of html and only making calls to either the player’s JavaScript or .swf files, this method seems to be the best I’ve come across that allows for both the abilities of the player and the simplicity of WordPress to work together. The only place it seems to break is if you edit the page in visual mode, but at least visual mode isn’t ruled out entirely, and copy-pasting the player code with edits for the correct file paths in html mode as a last step is an acceptable-ish compromise.

Oh and the code below, using the CodeColorer Plugin, which works fine from ecto also.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
echo '<div id="video">
<script type="text/javascript">
window.onload = function () {
$(function() {
    $f("player", "/path/to/flowplayer-3.1.5.swf", {
        play: null,
        clip: {
            baseUrl: \'http://danieljaber.com\'
        },
        playlist: [
            {
                url: \'/path/to/video.f4v\',
                title: \'a title\',
                subTitle: \'a sub-title, ...\',
                time: \'3:07\'
            }
        ],
        plugins:  {
        controls: null,    
        },
        canvas: {
        backgroundGradient: \'none\',
        backgroundColor: \'#000000\',
        },
    }).controls("appleControls");
});
};
</script>
<a class="player plain" id="player"><img src="/path/to/splash-image.jpg" alt="splash image" /></a><div id="appleControls" class="controls"></div>
</div>'

?>

flowplayer php wordpress admin small

flowplayer php wordpress site small