Posts Tagged “howto”

I’m working on a project that partially involves the development of a website in Drupal to act as a directory of people who have graduated from a given University. Seems easy. I went into the project thinking it would be a trivial application of Taxonomies, or maybe some generic CCK fields.

Nope. Turns out the problem is much more difficult and complex than I initially thought.

Taxonomies won’t work, because of the need to tie a number of values together, namely the year the degree was awarded (say, “1992″), the type of degree (say, “BSc”), the specialization of the degree (say, “Zoology”), and the granting institution (say, “University of Calgary”).

That could be an easy thing to solve with CCK - just add four text fields. Done.

BUT - people can earn more than one degree. Of different types, in different years, from different institutions.

Taxonomies fail. Generic CCK fields fail.

What I came up with is a new CCK field type, cryptically named “University Degrees”, that defines the four values that describe a degree. This solves the problem quite tidily, and supports multiple values, predefined valid sets of values, and can integrate with Views to be used as filters and sorting fields.

In building this module, I leaned heavily on a couple of web pages (CCK Sample and What is the Content Construction Kit?) that describe how parts of the module should work, and provided some sample code. In the spirit of contributing back what I learned, I’m going to document the module to help others needing to do similar things.
Read the rest of this entry »

Comments 29 Comments »

I worked with our Faculty of Education to build a community blogging website for use by after-degree student teachers as part of their personal/professional development, reflection, and collaboration process, as well as to collect materials for use in ePortfolios. They had a set of pretty simple constraints. Because the student teachers would be writing about activities in the K-12 classroom, and likely would be posting media (photos, videos, etc…) they needed to restrict access to the site - there could be no public access to this content. Additionally, they needed to control with a fairly fine granularity which individuals within the community would be able to see specific pieces of content. Because of these constraints, we couldn’t just load up WPMU and set them free, nor could we just point them to WordPress.com or Blogger.com. What to do…

Drupal, of course. It’s got a blogging module available out of the box (it takes a checkbox to enable it). OK. Blogging is taken care of. Members just have to click “Create content” and select “Blog post”. Easy peasey.

Want to allow members of the community to create their own groups? Organic Groups. It’s amazingly flexible, and has an added bonus, in this case, of also enabling access control to content based on group membership (after enabling Organic Groups, go to the settings page for the module and enable “Access Control”). Meaning that the student teachers could create as many private group contexts as they like, and then grant access to their content to any of their groups (and only those groups) if desired. Very powerful stuff.

OK. So now we have a bunch of student teachers blogging their brains out. That’s a lot of content to keep track of. Their professors and practicum teachers need to keep up on all of the relevant posts, and provide feedback in a timely manner. How to provide tools to let individuals track content that they’re allowed to see, that they haven’t seen yet, and that they need to respond to… Views. Drupal’s Views module is killer for this. It’s basically a database query generator, where you can provide a set of criteria to filter content, and create a display on the website. So I created a couple of handy views to help people keep up.

The first view was a simple “all content that has been posted to any of your groups, sorted in reverse chronological order” - this is the “river of news” display, which meant that members didn’t have to go hunting through their various groups (some had over a dozen group memberships) to find new content. It’s all merged, sorted, and presented to them on the front page of the site. This let members keep their fingers on the pulse of the community - they could see at a glance what was being published in all of the groups they cared about. This view also displayed the number of comments (and any new comments were flagged) so people could easily follow up on conversations.

The second view was intended to help members keep up with new content - essentially an “inbox” to be used by professors and teachers. This view was a clone of the first “river of news” view, but only displayed unread items. As a professor viewed a blog post, it would get dropped out of this view for them.

We also used the Book module to create documentation on the site (how to use the site, as well as pages with links to other resources, an FAQ, etc…) and we enabled the Forum module to create a separate non-blog discussion board within the site (but this never really got used much…)

That’s really all there is to it - Drupal just handles the rest, and once it’s configured it takes very little care and feeding.

Here’s the stuff we used (the site was built a year ago on Drupal 4.7, but I’m listing what would be used as of the current Drupal 5.3):

I’ll try to revise this post to clarify stuff as needed, but this is the basic recipe. The best thing to do is just start downloading and playing…

Comments 10 Comments »

We use the Events module to manage workshops here in the Teaching & Learning Centre, and use the “Upcoming Events” block to display the next few workshops on our website. Works great, but the default text leaves a bit to be desired. By default, it shows the event title, and “(2 days)” - which indicates that the event begins in 2 days.

But, it could also mean that the event lasts for 2 days.

So, I just added a trivial change to the event.module file, adding the following line of code at line 1847 (on my copy of the file, which was checked out on June 4, 2007):

$timeleft = 'starts in ' . $timeleft;

That changes the text indicator in the “Upcoming Events” block to read:

(starts in 2 days)

Which is much clearer in meaning. Easy peasy. I just have to remember to edit the module after updating, if this doesn’t make it in…

Comments 4 Comments »

I migrated my blog from Drupal 5 to WordPress 2 nearly 2 weeks ago. The process wasn’t as painful as I thought it would be, thanks to a handy howto via vrypan.net. Another resource I refer to every time I get into tweaking MySQL rows is UrbanMainframe’s MySQL search and replace tipsheet. Thanks to both of these great resources for helping me through the migration.

This guide is intended only to document what I did. It’s not a polished howto or manual. There is no warranty. If you blow up your database because you didn’t work with offline backup copies, I won’t be able to help you. Actually, if you’re that silly, I won’t be willing to help you, either. Your mileage may vary.

Use a backup copy of your Drupal database, and a fresh WordPress database.

The basic process I followed was:

  1. Work from offline copies of the databases. Dump your Drupal 5 database, import it into a fresh database (say “drupalmigration” or something creative). I did the migration on a separate machine from my “live” server - I used my desktop box, with local copies of MySQL and Apache. Anything with a decent version of MySQL on it will do.
  2. Install WordPress, (you don’t need to install Drupal for this migration) using the same database server containing the copy of your Drupal database (use “wordpress” as the name of the new WordPress database).
  3. Now that you’ve got WordPress and Drupal running on the same database server, in separate databases, run this MySQL script which I modified slightly after the file provided by vrypan.net. The script assumes the WordPress database is called “wordpress” and the Drupal database is called “drupalmigration” - feel free to modify the script to match the database names you need to use, if they differ.
  4. That should do it. Log into your WordPress site. You might have to hand tweak the usernames, but all posts and comments should be there…

One additional thing I had to do was fix the comment_ID values in the wp_comments table. After migration, they were too big for the data type, and things went poopy. I’m sure there’s an elegant way to renumber rows in MySQL. I used brute force, by dumping the table to a .sql file and opening that in a text editor to do a search-and-replace to lower the numbers used as primary keys. I then moved the old table out of the way (renaming it to “wp_comments_old“) and imported the new wp_comments table definition and content. It was a funky thing to have to do, but it solved all kinds of comment-related misbehaviour.

Test things out in the migrated database. If all seems well, go ahead and dump the wordpress database to a .sql file, and import it into a new database on your server. Install and configure WordPress on your server to use this new database. You may need to manually change the URL used by the blog, so that it matches the “live” server rather than whatever you used as a staging/migration server. The values are in the wp_options table, with option_name of “siteurl” and “home” - change those values to whatever matches the root URL for your blog.

You’ll also have to make sure all files are in the proper place, so URL references from the old Drupal content doesn’t point off to 404 error pages. That’s an exercise left to the reader. I just SSHed into my server and used a lot of cp -R drupal/directoryname wordpress/directoryname - being paranoidally careful to copy files rather than just moving them. Always keep backups.

Update: I’ve updated the SQL script to automatically set the comment and category counts, so it should appear to work better now.

Comments 35 Comments »

We’re using the Event module to list our workshops at the Teaching & Learning Centre, and the Signup module to let people register to attend workshops (or other events). It’s working really quite well, but we needed to add some extra fields to the registration form so we could track Faculties, Status, etc…

“Sure,” I said, “Drupal’s open source, so we should be able to add any fields we want. Worst case scenario? We’d have to fork Signup.module and maintain our own version with our custom fields in it.”

I then proceeded to drag my feet, not looking forward to having to maintain a module for something as simple as adding some custom fields. Maybe I could use the FormsAPI and insert the fields through some custom code?

So, I poked through the signup.module source code to see what would be involved. I’d braced for some rather convoluted and involved hackery. I blocked my schedule for the day so I’d have time to dedicate to the task.

Then, I saw that the module developers had already done the work for me. They implemented the signup form’s fields as a themable method, letting me override it on a per-theme basis. Without having to touch the code for the module itself. Brilliant. Absofrakking brilliant. So, I added this code to our theme’s template.php file (the theme is called “uofc_thisisnow”):

function uofc_thisisnow_signup_user_form() {
	$form['signup_form_data']['#tree'] = TRUE;
	$form['signup_form_data']['Name'] = array(
		'#type' => 'textfield',
		'#title' => t('Name'),
		'#size' => 40,
		'#maxlength' => 64
	);
	$form['signup_form_data']['Phone'] = array(
		'#type' => 'textfield',
		'#title' => t('Phone'),
		'#size' => 40,
		'#maxlength' => 64
	);
	$form['signup_form_data']['Faculty'] = array(
		'#type' => 'textfield',
		'#title' => t('Faculty or Department'),
		'#size' => 40,
		'#maxlength' => 64
	);
	$form['signup_form_data']['Status'] = array(
		'#type' => 'select',
		'#title' => t('Status'),
		'#default_value' => t('Faculty Member'),
		'#options' => array(
			'faculty' => t('Faculty Member'),
			'staff' => t('Staff'),
			'student' => t('Student'),
			'other' => t('Other')
		)
	);
  return $form;
}

That results in a signup form that looks like this:

TLC Workshop Signup with Custom FieldsTLC Workshop Signup with Custom Fields

The beauty of this, since it exposes the full FormsAPI, we can add select menus, radio boxes, default values, etc… Without having to touch the code of the Signup module itself. Very cool stuff.

Comments 12 Comments »

Just installing Mambo for a demo of various CMS options to the team tomorrow. The Mambo 4.5.2.3 installer borked while creating a table, choking on a missing default value for “rating_sum”.

Easy fix. Line 221 of mambo/installation/sql/mambo.sql is dealing with setting up the content_rating table. Modify the sql thusly:

  `rating_sum` int(11) unsigned NOT NULL default '0',

Aside from that silly sql bug, the Mambo installer is pretty slick. I’ll likely blog my early thoughts of it as a CMS, after I’ve played with it for awhile…

Update: Well, looks like my Mambo installation is pretty much borked. I can’t edit content - keep getting MySQL errors on missing tables or fields. I’ll try nuking and reinstalling, but this was a fresh install from the latest build, so I’m not sure what could be wrong…

Update: Nope. It’s still borked. Install claims to have run successfully, but any attempt to edit content results in this:

DB function failed with error number 1054
Unknown column 'c.access' in 'on clause' SQL=SELECT c.*, g.name AS groupname, cc.name, u.name AS editor, f.content_id AS frontpage, s.title AS section_name, v.name AS author
 FROM mos_content AS c, mos_categories AS cc, mos_sections AS s
 LEFT JOIN mos_groups AS g ON g.id = c.access
 LEFT JOIN mos_users AS u ON u.id = c.checked_out
 LEFT JOIN mos_users AS v ON v.id = c.created_by
 LEFT JOIN mos_content_frontpage AS f ON f.content_id = c.id
WHERE c.state >= 0 AND c.catid=cc.id AND cc.section=s.id AND s.scope='content' AND c.sectionid='1'
 ORDER BY cc.ordering, cc.title, c.ordering
 LIMIT 0,10

Update: Mambo was borked, but the Joomla fork of the project installed perfectly…

Comments 3 Comments »

Creative Commons License
This work is licensed under a Creative Commons Attribution 2.5 Canada License.