It’s been a long time in coming, but I’ve finally migrated from Drupal 7 to
the static HTML-generating powerhouse that is Octopress. This is admittedly
a bit of a departure from how I’ve previously done things — I’ve always been
quite the server-side nerd, starting when I learned PHP in tenth grade — but so
far I’m rather enjoying it. This marks the fifth iteration of the site, and I
hope that I can finally focus more on posting content than on keeping
Drupal modules updated.

Why the move?

Drupal is a nightmare to keep updated. While this is common amongst server-side
open source content management systems, Drupal’s focus on small and modular
bits of functionality means keeping a site up-to-date with the latest contrib
code is somewhat of a challenge. And for a site I update maybe three or four
times a year, the likelihood of having out-of-date code online is rather high.

That’d be the main reason, beyond the fact I never really needed the raw power
that Drupal was able to provide. Yes, I tried making a “resume” content type
at one point, but it wasn’t any easier to keep maintained than my LinkedIn
account or the public Google Doc I sent as a PDF when I was still looking for
work.

Additionally, I’ve started really enjoying the workflow provided by Git,
particularly when combiend with the finesse and joie de vivre of GitHub. Not
only can I host all my posts for free on GitHub pages, but I also have a great
way of going back through my work and visualising the changes I’ve made over
time. The hope is I can start publishing to my blog more regularly, as well as
using it as a place to workshop writing.

Admittedly the theme needs a bit more work, but it’s nice to be back in
Bootstrap Country.

I still think aendrew.com itself will always be more of portfolio site while my
Tumblog will be more bloggy in content, but
with any luck I can find the right balance to make both worthwhile.

The reason I created OpenMusicFestival in the first place was so that I could migrate MotionNotion.com from WordPress (And its unsupported WordTour plugin) to Drupal 7.

While I suspect my original use of WordTour for a music festival was slightly weird (The system was designed for small record labels, but relationship between artists, events and venues made it work for my purposes), I’m releasing my Artist migration class in case somebody finds it useful and wants to migrate to OpenMusicFestival. Note that this only migrates Artists — the Event and Venues parts are incomplete (On that note, if somebody wants to do those, I’ll happily both give you credit on the project as well as include the code with OMF.).

<?php/** * @file * Migrate content from WordTour (WP) to OMF (Drupal) * * NOTE: THIS IS WOEFULLY INCOMPLETE. I would *love* to give somebody credit * for tidying up and completing this. */classWordTourMigrationextendsMigration{public$wp_prefix='wp_';//This is the entire first part of the table name.public$wp_db='';public$wp_user='';public$wp_pass='';public$wp_host='localhost';publicfunction__construct(){// Always call the parent constructor first for basic setupparent::__construct();// With migrate_ui enabled, migration pages will indicate people involved in// the particular migration, with their role and contact info. We default the// list in the shared class; it can be overridden for specific migrations.$this->team=array(newMigrateTeamMember('Ændrew Rininsland','aendrew@aendrew.com',t('Developer')),);// Individual mappings in a migration can be linked to a ticket or issue// in an external tracking system. Define the URL pattern here in the shared// class with ':id:' representing the position of the issue number, then add// ->issueNumber(1234) to a mapping.$this->issuePattern='http://drupal.org/node/:id:';}}/** * There are four essential components to set up in your constructor: * $this->source - An instance of a class derived from MigrateSource, this * will feed data to the migration. * $this->destination - An instance of a class derived from MigrateDestination, * this will receive data that originated from the source and has been mapped * by the Migration class, and create Drupal objects. * $this->map - An instance of a class derived from MigrateMap, this will keep * track of which source items have been imported and what destination objects * they map to. * Mappings - Use $this->addFieldMapping to tell the Migration class what source * fields correspond to what destination fields, and additional information * associated with the mappings. */classArtistMigrationextendsWordTourMigration{publicfunction__construct(){parent::__construct();//Set up other databaseDatabase::addConnectionInfo('wp','default',array('driver'=>'mysql','database'=>$this->wp_db,'username'=>$this->wp_user,'password'=>$this->wp_pass,'host'=>$this->wp_host,'prefix'=>$this->wp_prefix,));$this->description=t('Migrate the artists!');$this->map=newMigrateSQLMap($this->machineName,array('artist_id'=>array('type'=>'int','length'=>7,'not null'=>TRUE,'description'=>'Artist ID',)),MigrateDestinationNode::getKeySchema());$query=Database::getConnection('default','wp')->select('wtr_artists','a');$query->join('wtr_attachment','at','a.artist_id = at.attachment_target_id');$query->join('wtr_attachment','att','a.artist_id = att.attachment_target_id');$query->join('postmeta','pm','pm.post_id = att.attachment_type_id');$query->fields('a',array('artist_id','artist_name','artist_publish_date','artist_bio','artist_record_company','artist_social_links',));//$query->fields('att', array('attachment_info'));$query->fields('pm',array('meta_value'));//$query->addField('pm', 'meta_value', 'photo');$query->addExpression('GROUP_CONCAT(DISTINCT at.attachment_info)','genres');//Pull in genres.$query->condition('at.attachment_target','artist');$query->condition('at.attachment_type','genre');$query->condition('att.attachment_type','thumbnail');$query->condition('pm.meta_key','_wp_attached_file');$query->groupBy('a.artist_id');// Create a MigrateSource object, which manages retrieving the input data.$this->source=newMigrateSourceSQL($query,array(),NULL,array('map_joinable'=>FALSE));// Set up our destination$this->destination=newMigrateDestinationNode('artist',array('text_format'=>'full_html'));// Assign mappings TO destination fields FROM source fields.$this->addFieldMapping('title','artist_name');$this->addFieldMapping('uid')->defaultValue(1);$this->addFieldMapping('changed','artist_publish_date');$this->addFieldMapping('status')->defaultValue(1);$this->addFieldMapping('promote','')->defaultValue(0);$this->addFieldMapping('sticky','')->defaultValue(0);$this->addFieldMapping('revision')->defaultValue(0);$this->addFieldMapping('log')->defaultValue('Migrated to Drupal 7 from WordPress.');$this->addFieldMapping('comment')->defaultValue(1);$this->addFieldMapping('body','artist_bio')->arguments(array('format'=>'full_html'))->description('See prepareRow()');$this->addFieldMapping('created','artist_publish_date');$this->addFieldMapping('field_labels','artist_record_company')->separator(', ')->arguments(array('create_term'=>true));//$this->addFieldMapping('path', '');//$this->addFieldMapping('pathauto', '');$this->addFieldMapping('field_photo','meta_value');$this->addFieldMapping('field_photo:source_dir')->defaultValue('/Users/aendrew/Sites/mn_wp');$this->addFieldMapping('field_photo:preserve_files')->defaultValue(true);$this->addFieldMapping('field_photo:destination_file','meta_value');$this->addFieldMapping('field_photo:file_replace')->defaultValue(MigrateFile::FILE_EXISTS_REUSE);$this->addFieldMapping('field_photo:alt','artist_name');$this->addFieldMapping('field_photo:title','artist_name');$this->addFieldMapping('field_links','artist_social_links')->description('See prepare()');//Needs to be unserialized$this->addFieldMapping('field_genres','genres')->separator(',')->arguments(array('create_term'=>true));}publicfunctionprepareRow($row){//Prepare Thumbnails$thumb=trim($row->meta_value);//watchdog('migrate', 'Filename is ' . $thumb);$row->meta_value='wp-content/uploads/'.$thumb;}publicfunctionprepare(stdClass$node,stdClass$row){//Set up the links$links=unserialize($row->artist_social_links);$empty='a:10:{s:13:"artist_flickr";s:0:"";s:14:"artist_youtube";s:0:"";s:12:"artist_vimeo";s:0:"";s:15:"artist_facebook";s:0:"";s:14:"artist_twitter";s:0:"";s:13:"artist_lastfm";s:0:"";s:14:"artist_myspace";s:0:"";s:15:"artist_bandcamp";s:0:"";s:13:"artist_tumblr";s:0:"";s:19:"artist_reverbnation";s:0:"";}';if($node->field_links[LANGUAGE_NONE][0]['url']==$empty){unset($node->field_links);}else{$i=0;foreach($linksas$site=>$link){if(!empty($link)){$site_name=ucfirst(str_replace('artist_','',$site));if($site_name=="Youtube")$site_name="YouTube";if($site_name=="Lastfm")$site_name="Last.fm";if($site_name=="Youtube")$site_name="YouTube";if($site_name=="Myspace")$site_name="MySpace";$node->field_links[LANGUAGE_NONE][$i]['title']=$site_name;$node->field_links[LANGUAGE_NONE][$i]['url']=urldecode($link);$i++;}}}}}

Did this help you out? Have I saved you a tonne of time? Please leave me a comment letting me know!

After Minehost went belly-up, the communal Minecraft server I played on went dead —and stayed dead — for about 6 months. However, I have revived it, on brand spanking new hardway and several major iterations of Minecraft later! Not only that, but it’s running the bad-assery that is Tekkit Lite, which means you can do crazy things like build automated mining robots, write simple computer programs in-game, harness the power of volcanoes, even create whole new dimensions via books like in Myst.

Seriously, I have no idea why it took me so long to get on top of Tekkit. That shiz’s cray.

Because there’s not much in terms of anti-griefing code on the server right now, it’s invitation-only. Please contact me either via email, Twitter, Facebook, etc. if you want the address.

Over the last few months working with Drupal, I’ve wanted to become a more productive member of the community. To that end, I’ve been working on getting a full project approved in order to get “Git vetted” and thus be able to create full projects on Drupal.org.

OpenMusicFestival is a Drupal distribution enabling music festivals of all sizes to create a rich, semantically-enabled website. Functionality includes extensive artist listings (Complete with Soundcloud and YouTube streams), schedules, venue listings — and because it’s Drupal, more functionality like ticket sales and forums are only a module installation away.

In my ongoing quest to make a non-Java-based ManyEyes clone, I have launched VizCloud, a Drupal distribution intended to allow simple dataset upload and visualization construction. I pretty much have the dataset parts down (Provided and maintained via SocialCalc through Sheetnode, though I’m currently still developing the visualization aspect (Provided via d3.js — anyone with experience creating models in d3, please get back to me!).

Use Koding.com? Want to install Drupal — with Drush — really easily? Now you can, with my snazzy new Drupal Installer app. Just add it to your account’s apps via GitHub and you’ll have both a way to deploy Drupal in under 5 minutes, but also a control panel to manage your various sites.