Converting Drupal 6 to WordPress

I’ve just moved my blog from Drupal 6 to WordPress. There’s several reasons for this:

  • I was only using Drupal in the first place to get some experience using it. It’s a great CMS but is overkill for just running a blog.
  • WordPress comes with Akismet for reducing comment spam out-of-the-box.
  • I just got a Nexus 7, and there’s a nice WordPress app for Android.

I wasn’t, however, keen on losing my old posts and comments. No problem, Drupal and WordPress are both open source and widely used, there’ll be tools to convert between them, right? Actually, not so much.

The best thing I found was this post on Migrating Drupal to WordPress and the associated Java script (that’s a script, written in Java, not a JavaScript file).  I had to tweak the code a bit to get it working, I’ve put the resulting code on Github.

I’m not really a Java guy, so getting it to run was new for me. Here’s the steps I took (on Ubuntu 12.04):

  1. Dumped the databases for my existing Drupal and a clean WordPress install from my web server to SQL files on my local machine.
  2. Imported both files into a new database on my local machine.
  3. Downloaded the .java file
  4. Edited the database credentials in the .java file to match those on my local machine (wpPrefix variable, drPrefix variable and return line of getConnection method)
  5. Installed the dependencies required to compile and run the file
    ~/$: sudo apt-get install openjdk-6-jdk libmysql-java
  6. Compiled and ran the file
    ~/$: javac -cp . DrupalToWordpress.java
    ~/$: java -cp .:/usr/share/java/mysql.jar DrupalToWordpress
  7. Exported the resulting WordPress tables from the local database, and imported them back into the database on my web server

A bit of a palava I think you’ll agree, but as you can see, it worked!

100%

A little under a year ago, I mentioned on the Ubuntu UK Podcast that I had contributed money to a project on PledgeMusic. If you’re not familiar with PledgeMusic, it’s basically Kickstarter for music projects. The project in question was Ginger Wildheart’s “Triple Album Project” – If enough people pledged money, he would record 30 tracks. Everyone who pledged would get the tracks, and the chance to vote on the top 12 tracks, which would be released to the world as a single-disc album.

The result of the project is this:
UK Midweek album chart with 100% at Number 9
This is the UK Midweek Album Chart as it stands at the time of posting. The entry at Number 9 is “100%“, the single-disc album chosen by vote from the 30 tracks on “555%”, the triple album which was exclusively available to pledgers (I pledged extra for a physical copy – it’s also got the coolest packaging I’ve ever seen for a CD album).

The album’s entered straight into the top 10, among the likes of Justin Bieber, Cheryl Cole and Rhianna – all A-list celebrities with big record deals who are all over the mainstream media. This isn’t even a down to a big group of die-hard fans going out and buying the album – they already got a copy and more for pledging. This has happened through grassroots promotion, reviews, airplay, and word-of-mouth. No record company involved. I think that’s pretty amazing.

Ginger’s managed to pull this off because he’s got a big group of very loyal fans who trust him that whatever he records, they’ll want to hear it. He’s also a fantastic songwriter who knows a lot of talented people in the music industry, all of which makes this a really special album. It’s questionable as to whether the model would work on this scale with artists who don’t already have established fanbases, but even so, I think this is a major achievement.

Toggle XDebug Bookmarklet

If you code PHP, you probably use XDebug for debugging your code. Some IDEs deal with the gubbins required for starting and stopping the debugger for you, but other debugging clients (like DBGp Client for Vim) require you to manually append XDEBUG_SESSION_START=1 to the end of your page’s query string before you try to connect the debugger.

Inspired by this blog post, I wrote a bookmarklet to toggle XDebug on or off at the click of a button, by adding XDEBUG_SESSION_START=1 if it’s not already in the URL, or toggling between XDEBUG_SESSION_START=1 and XDEBUG_SESSION_STOP=1 if it is.

To add it to your browser, drag the following link to your Bookmarks toolbar
Toggle XDebug

The un-minified code is shown below:

javascript: (function() {
    var href=window.location.href;
    if (href.indexOf("XDEBUG_SESSION_START") != -1) {
        window.location.href = href.replace("START", "STOP")
    } else if (href.indexOf("XDEBUG_SESSION_STOP") != -1) {
        window.location.href = href.replace("STOP", 'START")
    } else {
        if (href.indexOf("?") != -1) {
           window.location.href = href+"&XDEBUG_SESSION_START=1"
        } else {
         window.location.href = href+"?XDEBUG_SESSION_START=1"
        }
    }
})()

Installing CyanogenMod on HTC Legend

For various reasons, I decided that it was time to do away with the stock firmware on my HTC Legend and install CyanogenMod.
The CyanogenMod wiki details the process for rooting the phone, installing a custom recovery image, an installing CM, but I found the following process much simpler:

NB: You will need a Windows PC.

  • Sign up for an account at http://htcdev.com/bootloader and log in
  • Select “HTC Legend*” from the –Select your device– menu
  • Follow the process to unlock your bootloader – As the warnings say, this may void your warranty, and attract extra repair costs if your phone breaks.
  • When complete, download the custom recovery image
  • Place the image in C:\Android and rename it to recovery.img
  • Install the custom recovery image with the command fastboot flash recovery recovery.img. You can now boot into Recovery by selecting “RECOVERY” from the bootloader menu.
  • Install CyanogenMod using the Method via Recovery

Apparrently some phones have issues with this method as the kernel needs to be flashed seperately from CM, but I didn’t find this necessary with the Legend.

Update 12/1/13: There’s a developer on the XDA-Developers forum who’s creating unoffical ports of newer CyanogenMod releases based on Android 4.x. I’ve just installed his CM 10 ROM using the same method as 7 and it runs great.

Setting up CoffeeScript on ubuntu

As I mentioned in a previous post, I recent learnt about CoffeeScript, a quick way of writing nice clean Javascript. The CoffeeScript website has instructions for installing the compiler, first requiring installation of Node.js, which a lot of tutorials show you how to install from Git, and also requiring NPM which is usually installed by curling a shell script directly into bash(!). On Ubuntu, the install process is much simpler and less ripe for security holes:

  1. Only required if running 10.04 LTS (Lucid Lynx):
    sudo add-apt-repository ppa:chris-lea/node.js
    sudo apt-get update
  2. sudo apt-get install nodejs npm
    sudo npm install -g coffeescript

Check that CoffeeScript is installed correctly by running

coffee -v

What I learnt at Dev8D 2012 – Day 3

Day 3

I decided that I’d spend the final day trying to write some code, so I began trying to implement the Google Docs Viewer idea from Day 1.

I started off trying to write a Moodle Filter plugin to change file download links into iframes. However it quickly became apparent that the link I wanted to change wasn’t actually processed by the filter, so I had to try something else.

I moved on to modifying the Moodle File Resource plugin – it currently attempts to embed PDF files if it can, so I used that as a starting point. However due to the previous 2 days of information being stuffed in my head, I didn’t do things in any logical order and ended up in a bit of a mess. I really need to start again with the following approach:
* Create a new table in Moodle’s database to hold single-use tokens against a file’s path
* Create a copy of Moodle’s file.php that allows you to request a file without logging in, but only if requested with a token that’s stored against that file’s path.
* Get this page working so that Google Docs Viewer can request the test file with the test token and display it.
* Change the code that attempts to embed PDFs to embed any file type supported by Google Docs Reader
* Get the embed code working for the test file with the test token
* Implement code to generate and store a single-use token when the resource page is requested, pass it to Google via the embed code and delete it after the file is requested once. Also implement a cron job to clean up expired tokens if they aren’t used.

I finished off the afternoon by having a chat with Ian Tasker from SchoolsICT (who also sponsored the event), and James and Nigel from ULCC who produce the Moodle ILP plugin. The discussion we had gave me a great insight into what their system is capable of, and I’m looking forward to get to grips with writing some plugins for it myself.

What I learnt at Dev8D 2012 – Day 2

Day 2

The second day of Dev8D started with my Moodle Plugins workshop. It was reasonably well attended and the people who were there seemed to find it useful. I certainly found it an enjoyable experience.

After lunch I attended Jack Franklin’s sessions on CoffeeScript. It’s a really interesting idea, and next time I’ve got some Javascript to write I’ll try writing CoffeeScript instead to see if it really does save me time and effort.

The project zone had a brilliant demo of the “ghetto touch-table” from the University of Southampton – basically a home-made Microsoft Surface-style set-up. The thing that really interested me about it was it’s simplicity – a sheet of Perspex with IR light shining through it, and a camera to pick up light that gets reflected down by an object touching the surface. It only had a few purpose-built apps that could use the touch functionality, but I’d love to see it again once they’ve got it controlling the OS.

What I learnt at Dev8D 2012 – Day 1

Dev8D 2012 has come and gone this week. The event’s so intense that I tend to forget each day what I did the previous day, so this post will try and order my thoughts a bit and make sure I remember what happened.

Day 1

In Alex Bilbie’s packed HTML5 talk, I finally understood that you really can start using HTML5 now. html5shiv adds support for new block elements like <section> and <article> to old versions of IE, which means you can semantically mark up a page’s structure without having to resort to a million <div> elements.

In the Unix and Vim surgery I learnt that using lines selected visually in Vim can be reselected by typing gv which I’ll be using a lot.

I was planning to enter the Jorum API challenge. Jorum is a repository for open educational resources, and I thought it would be a cool idea to try and implement a Moodle repository plugin to pull in resources from Jorum. However, the Jorum API needs some serious re-engineering to make it useful – it just returns too much data. You need to be able to search for keywords within a collection, request details of an item within the results, and request individual files within that item. Currently, trying to do this gives you all sorts of data pertaining to an object’s parents, children and siblings, to the extent that you can’t even work out what needs to be thrown away to end up with just what you wanted. Until a better API is available, I won’t be looking at it any further.

During the Afternoon I had a chat with the Moodle developers from the University of Sussex. They showed me Google Docs Viewer which lets you embed any PDF or MS Office file in a web page, even without a Google Docs account. This would have seriously cool applications if used in conjunction with Moodle resources, as it could be used to allow a lot of files that currently require office software to view to be viewable right in the Moodle page. There’s a bit of work to do making this work securely, but I think it’s feasible.

Un-commit in Git

I just accidentally made a commit in git that I didn’t want – I’d made several changes at once and wanted to commit them separately. Instead I did one big commit so I wanted to get back to a state where I had the uncommitted changes. The methods of undoing a commit (git reset and git revert) dont cut it here, as they just take you back to the previous commit, and lose the changes you made. Here’s what I came up with:

git show > ~/uncommit.patch # Take the commit I just made and store the differences in a patch
git reset --hard HEAD^ # Reset to the previous commit
patch -p1 < ~/uncommit.patch # Re-apply the changes

If you've got some changes that aren't committed yet that you still want to keep, you'll want to do make a second patch from the output of git diff before resetting.

Boogie Board Rip on Linux

I’m fed up of making notes on scrappy bits of paper that I lose, so with some money I got for Christmas I got myself a Boogie Board Rip. I’m not going to do a full-blown review here, but essentially it’s an etch-a-sketch on top of a portable graphics tablet. The graphics tablet bit is battery powered, and converts what you draw to PDF. The PDFs can be accessed by plugging the board into a PC via a Micro USB cable. Some people complain that it’s not very good for drawing, but I only wanted it for writing and it’s great for that.

After using the board for a couple of days I found this piece of software and this blog post. It turns out that as well as appearing as a USB storage device when plugged in, it also appears as a human interface device and spits out a stream of binary (32 bytes of it to be exact) for each event that occurs on the device (button presses, movement of the stylus, etc). With a bit of help from the aforementioned blog post I’ve managed to decode the binary and write a short Ruby script that reports what’s happened each time you do something.

The script as it stands at time of posting is shown below. The latest version is available on github.

begin
    lsusb = `lsusb`
    if lsusb.split("\n").select{|l| l.include? "2047:ffe7"}.count == 0
        raise "Boogie Board Rip not currently connected"
    end

    begin
        dmesg = `dmesg`
        bbdev = dmesg.split("\n").select{|l| l.match "2047:FFE7.*hidraw[0-9]"}.pop.match("(hidraw[0-9]+)").to_s
        raise RuntimeError if bbdev.empty? 
    rescue NoMethodError, RuntimeError
        raise "Boogie Board Rip detected, but device's path could not be determined"
    end

    events = []
    threads = []

    thread = Thread.new do
        board = File.new("/dev/"+bbdev, 'r')
        while true do
            data = board.sysread(32)
            event = Array.new()
            data.bytes { |b| event << b }
            events << event
        end
    end
    threads << thread

    thread = Thread.new do
        previous = Array.new(32, 0)
        current = []
        while true do
            current = events.shift
            next if current.nil?

            if current[10] != previous[10]
                state = current[10]
                pstate = previous[10]
                lock = 32
                erase = 4
                wake = 2
                if (pstate == pstate | lock) && (state != state | lock)
                    puts "Board unlocked"
                elsif (pstate != pstate | lock) && (state == state | lock)
                    puts "Board locked"
                end
                if (pstate == pstate | erase) && (state != state | erase)
                    puts "Erase released"
                elsif (pstate != pstate | erase) && (state == state | erase)
                    puts "Erase Pressed"
                end
                if (pstate == pstate | wake) && (state != state | wake)
                    puts "Wake released"
                elsif (pstate != pstate | wake) && (state == state | wake)
                    puts "Wake Pressed"
                end
            end
            if current[3] != previous[3]
                state = current[3]
                pstate = previous[3]
                detected = 32
                contact = 1
                if (pstate == pstate | detected) && (state != state | detected)
                    puts "Pen Lost"
                elsif (pstate != pstate | detected) && (state == state | detected)
                    puts "Pen Detected"
                end
                if (pstate == pstate | contact) && (state != state | contact)
                    puts "Pen contact lost"
                elsif (pstate != pstate | contact) && (state == state | contact)
                    puts "Pen contact detected"
                end
            end
            cury = current[4]+(current[5]*256)
            curx = current[6]+(current[7]*256)
            prey = previous[4]+(previous[5]*256)
            prex = previous[6]+(previous[7]*256)
            if cury != prey || curx != prex
                puts "Pen moved from ("+prex.to_s+","+prey.to_s+") to ("+curx.to_s+","+cury.to_s+")"
            end    
            previous = current
        end
    end
    threads << thread

    threads.each{ |thread| thread.join}
    
rescue RuntimeError => error
    puts error
end

It’s very rudimentary at the moment, and needs to be run as root so the device can be accessed, but hopefully with a bit more hacking I’ll be able to get something graphical up and running. It also strikes me that you should be able to use the Boogie Board like a Wacom tablet if someone would be good enough to write a device driver. It’s a bit beyond me but the information’s pretty much all there in the script!