Sentimental Minions

The theatricalities of the humble bookmark

  • a

  • Archives

  • Tweetions

Archive for the ‘Drupal’ Category

Weapons of choice: ZendCore, etc.

Posted by Avadhut on 1 October 2008

Most of my development happens in Drupal, PHP, jQuery, MySQL, PostGreSQL, and all good things associated. Until recently, I used to swear by separate PHP and Apache installations. But managing updates for everything involved—Apache, PHP, jQuery, Drupal—separately had become a real bitch: the innumerable backups, migrations, and restorations.

So when Drupal 6 was released, I was thrilled with the new Update module. And it was time I found a server-PHP stack that could support production-scale deployments. Enter ZendCore. The installer not only allows you to use Zend’s own PHP (with FastCGI) and Apache Web Server (ZendCoreApache) but also plays nice with your existing installations. Buy a subscription with Zend, and they will take care of updating Apache and PHP for you too. It also allows you to download and install database servers of your choice—MySQL, DB2, etc.

ZendCore also comes bundled with Zend Framework, which provides an extremely good set of PHP functionalities. I have only gotten as far as Lucene search, but things look very promising.

Drupal runs like a peach on this stack, which is most important for me at the moment, and it supports my other custom Web-apps developed using the Zend framework.

I am almost tempted to shell out on ZendPlatform, which is an enormously feature-rich Web-app server. It handles PHP, Java, and HTTP monitoring, supports session clustering (yummy!), and comes with a really cool Download Server that frees up Apache of monotonous tasks involving huge downloads so that it can handle some of the more serious stuff.

However, I still could not get myself to switch to Zend Studio. Or maybe I just refuse to let go of my beloved Komodo IDE. What? What was that? Dreamweaver? Who? The one that pisses memory all over the place? Yeah I dumped it with DotNetNuke. 😛

The worst excuse I have heard anyone give me for still sticking to Dreamweaver is the Code/Design view. Please, it is a joke. Any standards-aware Web designer will tell you that. It still gloats about its Table layout like it were the 90s. Besides, how long does it take to write a line of CSS, alt+tab your way to your browser, and press F5? Also, what’s with the no-Linux-option? Not even a binary? What is taking Adobe so long? Hurry the fuck up. And don’t even get me started with the abyssmal FTP editing. I have actually shut my PC mid-day and gone home coz’ of it. Free FTP programs have no issues handling huge files. Then why does it have to be such a task for a $500 software to do it? If my server supports long sessions, then so should Dreamweaver. To top it all off, it is way overpriced. Did you see the CS3 release—not only is it godforsakenly bloated (it was consuming 20% CPU just idling), it also expects me to pay Adobe almost three times more than what it would charge my American friends.

The thing I like the most about Zend is that none of the components are prone to lock-ins. Use whichever tool you want, it will still behave with the etiquette expected out of good-natured software. Want to use ZendCore’s PHP with your own Apache deployment? It’s OK. ZendCore won’t hold any grudges. Some other people do need to take a lesson from here. Can you hear me Microsoft? Just because I use Exchange does not mean that I would want to use Office Communication Server. Let me connect to other software!

So, the list would proceed as follows:

  • Webserver-PHP stack: ZendCore
  • PHP frameworks: Zend Framework, Drupal (I use it as one :))
  • Javascript: jQuery, Prototype
  • IDE: Komodo
  • Database server: MySQL, MSSQL, PostGreSQL
  • Mail server: Apache James
  • OS: Does it even matter?

Posted in Drupal, Foo, System design, Zend, ZendCore-Drupal | Leave a Comment »

PHP script for the migration of data from Drupal 5.x to 6.x

Posted by Avadhut on 14 September 2008

Ok. Drupal 6 is probably the best thing since bread came sliced. Views 2, the new and improved CCK, and the updater—it’s like updating your anti virus—has made life so much easier. Updating Web application frameworks has never been easier.

This updater alone is incentive enough to upgrade your Drupal 4.x and 5.x installations to Drupal 6.x. Unfortunate it is then that this moat to be crossed is filled with non-upgraded module crocodiles and inexplicable PHP error sharks.

There are two approaches to converting a Drupal 5.x site to 6.x:
1. Upgrading: For this, all contrib. modules installed in your 5.x better be ported to 6.x, and also pray that Watchdog has encountered no life-threatening PHP errors. That periodic cron runs, database updates, & zilch-modification of core modules were a must go without saying.
2. Migration: Setup a crisp, clean Drupal 6.x site, and painstakingly port all data from your 5.x behemoth to your 6.x kiddo. Migration can be performed either manually (pray, lord, pray if your site has more than 500 nodes) or through scripts.

Although approach 1, if it works without spewing any errors, is enough to incite a hallelujah from even the most ardent of the non-believers, we all know how rare it is. And the pre-requisites to it are just too many and too hard to fulfill.

The only solution in cases where an upgrade is not possible, then, is the use of automated migration scripts. Currently, there is no such unified migration script available. I have broken down the script I used to migrate my 5.x site to 6.x for the migration of users, simple-content-type posts, comments, taxonomy, & forum posts. Migrating the theme itself (blocks, nodes, templates, etc.) would require one to get their hands dirty with PHP.

Before we begin, we need our PHP migration script to set certain variables:

< ?php
set_time_limit(0);
//MySQL globals
$mysql_server = "localhost";//change this server for your Drupal installations
$mysql_user = "root";//Ideally, should be root
$mysql_pass = "pass";//Corresponding password
$conn = mysql_connect($mysql_server,$mysql_user,$mysql_pass);//MySQL connection string
//If your 5.x and 6.x installations reside on different servers, you will need two sets of server names, usernames, and passwords.
?>

Also, in my scripts, tables prefixed “drupal.” and “timesnow.” belong to the 5.x and 6.x sites, respectively. Please change these accordingly for your databases.

Lastly, these scripts are not optimized with regard to execution. So do not expect unified inserts to insert multiple tuples.

User migration script:

This script, currently, only migrates users, e-mail addresses, uids, and passwords. It does not take care of the profile fields, which can be handled through other customized scripts as profile fields for each installation can differ. It does not import “usernode” content type either. This is coz’ usernodes are typically not required in 6.x, as user profile pages can be styled using tpl.php files themselves. Also, it is important that the uids from your orignal installtion be migrated to your current installation accurately coz’ comments and nodes that we will migrate later on are linked to the users through these uids.

There are absolutely no differences between the Users table in 5.x and 6.x. Both of them have the same 18 fields. So you can go ahead and use the following script without even thinking:

< ?php
//first, we delete all users, if any, from the new table, except for the admin
$query = "delete from timesnow.users where uid not in (0,1)";
mysql_query($query);
print "User table cleared.
";
//now we start inserting users into the new table
$query = "select * from drupal.users where uid not in (0,1)";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$query = "insert into timesnow.users values('" . $row&#91;0&#93; . "','" . $row&#91;1&#93; . "','" . $row&#91;2&#93; . "','" . $row&#91;3&#93; . "','" . $row&#91;4&#93; . "','" . $row&#91;5&#93; . "','" . $row&#91;6&#93; . "','" . $row&#91;7&#93; . "','" . mysql_real_escape_string($row&#91;8&#93;) . "','" . $row&#91;9&#93; . "','" . $row&#91;10&#93; . "','" . $row&#91;11&#93; . "','" . $row&#91;12&#93; . "','" . $row&#91;13&#93; . "','" . $row&#91;14&#93; . "','" . $row&#91;15&#93; . "','" . $row&#91;16&#93; . "','" . $row&#91;17&#93; . "')";
	if (!mysql_query($query)) {
		print $query;
	}
	$ucnt += 1;
}
print $ucnt . " users inserted.";
?>

An easy one that was, wasn’t it. Now, for some taxonomy.

[Note: You can even take a backup of the old Users table using mysqldump and restore it into the new one. Just make sure that you delete the insertion statements for UIDs 0 and 1.]

Migrating taxonomy:

Now, this is the tricky part. Broken down, the minimal unit of taxonomy data in Drupal is a “term,” which has an associated “tid” (term id). Terms can be fixed taxonomies or free tags. Each node (if applicable) and forum post has an associated tid, which maps it to the term that the user has assigned to it. Therefore, it is imperative that this data is migrated accurately.

The migration script for taxonomy will migrate the hierarchies, term-node relations, vocabularies, etc.:

< ?php
$query = "truncate timesnow.vocabulary";
mysql_query($query);
print "Vocabulary table cleared.
";
$query = "truncate timesnow.vocabulary_node_types";
mysql_query($query);
print "Vocabulary_node_types table cleared. 

";
$query = "truncate timesnow.term_data";
mysql_query($query);
print "Term_data table cleared.
";
$query = "truncate timesnow.term_hierarchy";
mysql_query($query);
print "Term_hierarchy table cleared.
";
$query = "truncate timesnow.term_node";
mysql_query($query);
print "Term_node table cleared.
";
$query = "truncate timesnow.term_relation";
mysql_query($query);
print "Term_relation table cleared.
";
$query = "truncate timesnow.term_synonym";
mysql_query($query);
print "Term_synonym table cleared.
";
print "
";

$query = "select * from drupal.vocabulary";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$query = "insert into timesnow.vocabulary values('" . $row&#91;0&#93; . "','" . mysql_real_escape_string($row&#91;1&#93;) . "','" . mysql_real_escape_string($row&#91;2&#93;) . "','" . mysql_real_escape_string($row&#91;3&#93;) . "','" . $row&#91;4&#93; . "','" . $row&#91;5&#93; . "','" . $row&#91;6&#93; . "','" . $row&#91;7&#93; . "','" . $row&#91;8&#93; . "','" . $row&#91;9&#93; . "','" . $row&#91;10&#93; . "')";

	if (!mysql_query($query)) {
			print $query;
	}
}
print "Vocabulary plugged in.
";

$query = "select * from drupal.vocabulary_node_types";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$query = "insert into timesnow.vocabulary_node_types values('" . $row&#91;0&#93; . "','" . $row&#91;1&#93; . "')";

	if (!mysql_query($query)) {
			print $query;
	}
}
print "Vocabulary node types set.

";

$query = "select * from drupal.term_data";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$query = "insert into timesnow.term_data values('" . $row&#91;0&#93; . "','" . $row&#91;1&#93; . "','" . mysql_real_escape_string($row&#91;2&#93;) . "','" . mysql_real_escape_string($row&#91;3&#93;) . "','" . $row&#91;4&#93; . "')";

	if (!mysql_query($query)) {
			print $query;
	}
}
print "Term_data plugged in.
";

$query = "select * from drupal.term_hierarchy";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$query = "insert into timesnow.term_hierarchy values('" . $row&#91;0&#93; . "','" . $row&#91;1&#93; . "')";

	if (!mysql_query($query)) {
			print $query;
	}
}
print "Term_hierarchy plugged in.
";

$query = "select * from drupal.term_node";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$nid = $row&#91;0&#93;;
	$tid = $row&#91;1&#93;;
	$query = "select vid from drupal.node where nid = " . $nid;
	$qr2 = mysql_query($query);
	$row2 = mysql_fetch_row($qr2);
	$vid = $row2&#91;0&#93;;
	$query = "insert into timesnow.term_node values('" . $nid . "','" . $vid . "','" . $tid . "')";

	if (!mysql_query($query)) {
			print $query;
	} else {
		$tncnt += 1;
	}
}
print "Term_node plugged in (" . $tncnt . " records entered).
";
?>

You must’ve noticed that I am clearing out all associated tables before each insert block. This is coz’ it is important that the tids, tid-vid pairings, and tid-nid pairings be unique and as they are in the old database. Otherwise it will cause either of the following two problems: (a) terms won’t get attached to your nodes accurately or (b) the insert statements will throw primary key and/or unique key errors.
This script is out-of-the-box too. With just the database name changes (from timesnow. to your database name), it can be run as it is.

And now for the big Kahuna—migrating forum posts.

Migrating forums:

Three parts to this script—forum topics have to be attached to their respective terms, forums posts have to go into the node table, and forum comments have to be migrated. The first part has already been taken care of in the previous script, so we are simply dealing with inserting comments and forum nodes. Again an out-of-box script, this one:

< ?php
$cnt = 0;
$commentcnt = 0;
$query = "select * from drupal.node where type = 'forum'";
$noders = mysql_query($query);
while ($row = mysql_fetch_row($noders)) {
	$nid = $row&#91;0&#93;;
	$vid = $row&#91;1&#93;;
	$type = $row&#91;2&#93;;
	$title = mysql_real_escape_string($row&#91;3&#93;);
	$uid = $row&#91;4&#93;;
	$status = $row &#91;5&#93;;
	$created = $row&#91;6&#93;;
	$changed = $row&#91;7&#93;;
	$comment = $row&#91;8&#93;;
	$promote = $row&#91;9&#93;;
	$moderate = $row&#91;10&#93;;
	$sticky = $row&#91;11&#93;;
	//Insertion into node
	$query="insert into timesnow.node values('" . $nid . "','" . $vid . "','" . $type . "','','" . $title . "','" . $uid . "','" . $status . "','" . $created . "','" . $changed . "','" . $comment . "','" . $promote . "','" . $moderate . "','" . $sticky . "','0','0')";
	if (!mysql_query($query)) {
		print $query;
	}

	$query = "select * from drupal.node_revisions where nid = " . $nid;
	$node_revisionrs = mysql_query($query);
	$nrow = mysql_fetch_row($node_revisionrs);
	$body = mysql_real_escape_string($nrow&#91;4&#93;);
	$teaser = mysql_real_escape_string($nrow&#91;5&#93;);
	$log = mysql_real_escape_string($nrow&#91;6&#93;);
	$timestamp = $nrow&#91;7&#93;;
	$format = mysql_real_escape_string($nrow&#91;8&#93;);
	//Insertion into node_revision
	$query="insert into timesnow.node_revisions values('" . $nid . "','" . $vid . "','" . $uid . "','" . $title . "','" . $body . "','" . $teaser . "','" . $log . "','" . $timestamp . "','1')";
	if (!mysql_query($query)) {
		print $query;
	}

	$query = "select * from drupal.node_comment_statistics where nid = " . $nid;
	$node_comment_statistics_rs = mysql_query($query);
	$ncsrow = mysql_fetch_row($node_comment_statistics_rs);
	$last_comment_timestamp = $ncsrow&#91;1&#93;;
	$last_comment_name = mysql_real_escape_string($ncsrow&#91;2&#93;);
	$last_comment_uid = $ncsrow&#91;3&#93;;
	$comment_count = $ncsrow&#91;4&#93;;
	//Insertion into node_comment_statisitcs
	$query = "insert into timesnow.node_comment_statistics values ('" . $nid . "','" . $last_comment_timestamp . "','" . $last_comment_name. "','" . $last_comment_uid . "','" . $comment_count. "')";
	if (!mysql_query($query)) {
		print $query;
	}

	$query = "select * from drupal.comments where nid = " . $nid;
	$commentrs = mysql_query($query);
	while ($row = mysql_fetch_row($commentrs)) {
		$query = "insert into timesnow.comments values ('" . $row&#91;0&#93; . "','" . $row&#91;1&#93; . "','" . $row&#91;2&#93; . "','" . $row&#91;3&#93; . "','" . mysql_real_escape_string($row&#91;4&#93;) . "','" . mysql_real_escape_string($row&#91;5&#93;) . "','" . $row&#91;6&#93; . "','" . $row&#91;7&#93; . "','" . $row&#91;9&#93; . "','" . $row&#91;10&#93; . "','" . $row&#91;11&#93; . "','" . $row&#91;13&#93; . "','" . $row&#91;14&#93; . "','" . $row&#91;15&#93; . "')";
		if (!mysql_query($query)) {
			print $query;
		}

		$commentcnt += 1;
	}
	$cnt += 1;
}

print $cnt . " rows inserted.
";
print $commentcnt . " comments inserted.
";

//Inserting into forum
$query = "select * from drupal.forum";
$queryresult = mysql_query($query);
while ($row = mysql_fetch_row($queryresult)) {
	$nid = $row&#91;0&#93;;
	$vid = $row&#91;1&#93;;
	$tid = $row&#91;2&#93;;
	$query = "insert into timesnow.forum values('" . $nid . "','" . $vid . "','" . $tid . "')";

	if (!mysql_query($query)) {
			print $query;
	} else {
		$forumcnt += 1;
	}
}
print $forumcnt . " records updated into the forum table.
";
?>

Certain table structures have changed in 6.x. But these scripts handle those too.

Now, moving on into content migration. Due to CCK, content migration will have to take into account many different things. I am not going to post a generic content migration script, coz’ I don’t have one, and that is coz’, frankly, I did not need one. I just needed one for a simple content type with just a title and body and terms of all sorts associated with it, with comments.

My content type was called “multi_user_blog.” You may have to change that for your needs. But basically, what the following script does is inserts content title, body, and associates comments. It is like a building block for all your node migrations. A lot of things have changed in Drupal 6.x when it comes to nodes and associated comments and revisions. There have been translation fields added to the node table itself. Also, the vid (version id) in the node_revision table is set to auto increment in 6.x. This vid is also associated with different terms. Thus, each version can now have its own terms in 6.x.

Moving right along to the script, it is pretty straight forward:

< ?php
$query = "truncate timesnow.node";
mysql_query($query);
print "Node table cleared.
";
$query = "truncate timesnow.node_revisions";
mysql_query($query);
print "Node_revisions table cleared.
";
$query = "truncate timesnow.node_comment_statistics";
mysql_query($query);
print "Node_comment_statistics table cleared.
";
$query = "truncate timesnow.comments";
mysql_query($query);
print "Comments table cleared.
";
$query = "truncate timesnow.forum";
mysql_query($query);
print "Forum table cleared.
";

?>
<hr />
Inserting multi_user_blogs
< ?php
$query = "select * from drupal.node where type = 'multi_user_blog'";
$noders = mysql_query($query);
while ($row = mysql_fetch_row($noders)) {
	$nid = $row&#91;0&#93;;
	$vid = $row&#91;1&#93;;
	$type = $row&#91;2&#93;;
	$title = mysql_real_escape_string($row&#91;3&#93;);
	$uid = $row&#91;4&#93;;
	$status = $row &#91;5&#93;;
	$created = $row&#91;6&#93;;
	$changed = $row&#91;7&#93;;
	$comment = $row&#91;8&#93;;
	$promote = $row&#91;9&#93;;
	$moderate = $row&#91;10&#93;;
	$sticky = $row&#91;11&#93;;
	//Insertion into node
	$query="insert into timesnow.node values('" . $nid . "','" . $vid . "','" . $type . "','','" . $title . "','" . $uid . "','" . $status . "','" . $created . "','" . $changed . "','" . $comment . "','" . $promote . "','" . $moderate . "','" . $sticky . "','0','0')";
	if (!mysql_query($query)) {
		print $query;
	}

	$query = "select * from drupal.node_revisions where nid = " . $nid;
	$node_revisionrs = mysql_query($query);
	$nrow = mysql_fetch_row($node_revisionrs);
	$body = mysql_real_escape_string($nrow&#91;4&#93;);
	$teaser = mysql_real_escape_string($nrow&#91;5&#93;);
	$log = mysql_real_escape_string($nrow&#91;6&#93;);
	$timestamp = $nrow&#91;7&#93;;
	$format = mysql_real_escape_string($nrow&#91;8&#93;);
	//Insertion into node_revision
	$query="insert into timesnow.node_revisions values('" . $nid . "','" . $vid . "','" . $uid . "','" . $title . "','" . $body . "','" . $teaser . "','" . $log . "','" . $timestamp . "','" . $format . "')";
	if (!mysql_query($query)) {
		print $query;
	}

	$query = "select * from drupal.node_comment_statistics where nid = " . $nid;
	$node_comment_statistics_rs = mysql_query($query);
	$ncsrow = mysql_fetch_row($node_comment_statistics_rs);
	$last_comment_timestamp = $ncsrow&#91;1&#93;;
	$last_comment_name = mysql_real_escape_string($ncsrow&#91;2&#93;);
	$last_comment_uid = $ncsrow&#91;3&#93;;
	$comment_count = $ncsrow&#91;4&#93;;
	//Insertion into node_comment_statisitcs
	$query = "insert into timesnow.node_comment_statistics values ('" . $nid . "','" . $last_comment_timestamp . "','" . $last_comment_name. "','" . $last_comment_uid . "','" . $comment_count. "')";
	if (!mysql_query($query)) {
		print $query;
	}

	$query = "select * from drupal.comments where nid = " . $nid;
	$commentrs = mysql_query($query);
	while ($row = mysql_fetch_row($commentrs)) {
		$query = "insert into timesnow.comments values ('" . $row&#91;0&#93; . "','" . $row&#91;1&#93; . "','" . $row&#91;2&#93; . "','" . $row&#91;3&#93; . "','" . mysql_real_escape_string($row&#91;4&#93;) . "','" . mysql_real_escape_string($row&#91;5&#93;) . "','" . $row&#91;6&#93; . "','" . $row&#91;7&#93; . "','" . $row&#91;9&#93; . "','" . $row&#91;10&#93; . "','" . $row&#91;11&#93; . "','" . $row&#91;13&#93; . "','" . $row&#91;14&#93; . "','" . $row&#91;15&#93; . "')";
		if (!mysql_query($query)) {
			print $query;
		}

		$commentcnt += 1;
	}

	$cnt += 1;
}
print $cnt . " rows inserted.
";
print $commentcnt . " comments inserted.
";
?>

Studying this script can you give you some clues/insights to migrating content on your own site.
I am working on an auto content migration script that will enable migration of all content types, associated tables, fields, etc.

Also in works is the profile migration script.

In the meanwhile, let me know if I can improve on these OR if you have some script to contribute (I will credit, promise). 🙂

If you do crack the auto content migration script for all CCK content types before me I will take you out for a meal, and throw in a free conversation, if you are in a can-buy-me-a-meal range. If you feel like my efforts deserve a meal, I am a complete meal slut. Oh, and why meals? Coz’ they are fun and desirable and leave one satisfied and contented.

That’s all folks!

Posted in Drupal, Drupal 6.x, Drupal migration, Meals, Open source, PHP scripts, Social media | 6 Comments »

My comeuppance

Posted by Avadhut on 24 August 2007

First, a question: How’s this for a pick-up line?

O Watery-eyed woman, please tell me your good name.

Moving on to more important matters now: Past few days of inactivity on the blog have actually been due to work. More precisely, Drupal. No no. Don’t get me wrong. Not the bad kind of work. The good kind of work. The kind that has you scrambling to your desk every morning to finish what you left incomplete the night before, but with a smile on your face. 🙂

Now, I am not going to delve into the inherent goodness of open source and how it is a great big boon to mankind and will one day save us from extinction. But it is, and it will!

You see, everything I have ever wanted to ask about Drupal, everything I ever wanted to make it do—I could and I could. Communities hold a plethora of knowledge, and not just about Drupal but also MySQL and PHP and Apache and Ubuntu.

But it wasn’t always this sweet.

Let me start a few years back. How back? When free open-source OSes were a rarity and Windows won the people’s choice award for facilitating easy downloading of backdoor trojans and spontaneous formatting of hard drives.

One of those evenings, I suddenly got into a fit of career pangs, as one is wont to at that age and time of day. All my usual a-wondering had disappeared. It suddenly occurred to me that I was not exactly what you would call prime recruitment material. The horror of horrors!

This was the time when software had just reversed the poor trends and IT companies were beginning to flock college campuses again. Anyone with serious job hopes was rushing to their “computer classes” after school/college and locking themselves away with the usual “computer” job preparation materials: SimCity, Basic, etc.

(I have been told that things are easier nowadays. Last year someone from NITT told me that some of the top IT names don’t even interview anymore. All you needed to do was just clear the written test. Sigh.)

Till then I had assured myself that software was not my cup of tea and I would save myself (one is cocky at that age and with that level of blood sugar on a daily basis) for one of Mumbai’s glitzier hotels—as a master chef. Hey, I could cut onions faster than Sanjeev Kapoor could say “khana khazana.”

And then one weekend morning I lay in bed and decided to quickly overview my career plans for a few minutes. But not for too long as the bread pakoda ran out after 8:30 or so.

Now, I knew, back then, that I couldn’t program to save my life. The meta syllabus included a moderately difficult course on Basic and Windows 98. I’d passed through with flying colors scoring one mark more than the required threshold. The highlight of the period used to be watching the bugger—a Mr. Camelius, the high strung nervous sort—struggle with an early morning class on BASIC, break into a sweat, and then finally faint into the arms of a vigilant fellow in the front row.

Later, in college, I often wondered why someone would want a C program that printed out a pyramid of prime numbers. What essential human endeavor struggles for the want of good pyramid prime programs?

“Houston we have a problem!”
“We know. Perhaps a particular problem pertaining to the pyramid prime processor?”
“We like the alliteration Houston!”
“Merely making the mundane mirthful mister!”
“Ok! cut it…”

I hated most forms of programming. And particularly, the fancy shmancy prime number, sorting, pyramid type programs.

But then what certainty was there that I could make it into one of those hotels? They seldom came to Modern Colleges, let alone the Ganeshkhind one. Was I being foolhardy I wondered, as I lay in bed with an eye on the clock.

Then later that evening I decided that I must hedge my risk. I had to ensure that I knew the bare minimum to make it into a software firm just in case my core hotelier dreams fell flat.

So I asked myself—what I could do on a war footing. The threat loomed large that I would have to give GRE and then do an MS and PhD because I couldn’t get a job.

“Unix man. Unix is the way to go. That and Networking. Just focus on those two.”

I shared my thoughts with myself during one of the many walks to the gate for chai.

For one whole month I sat hunched over a UNIX manual and a huge textbook on Networking.

Who was that networking by? Ah yes. Tennenbaum. Andrew Tennenbaum I think.

After a month I thought I was ready to try out some of my newly learnt computing skills on my computer—Octagon, that’s what I called it back then (don’t ask me why).

Two hours later I was back in my room pulling out an old Barron’s guide to the GRE from under the bed and already mouthing words like apothecary and apothegm, fighting back the tears.

It was the worst thulping by an open source operating system I have ever received in my life.

Why were there backslashes everywhere? Why was vi editor such a cold-hearted bitch? Why do I have to press seven keys simultaneously to scroll down one page? Why? Why? Why weren’t things like the way its said in the manual:

finger–display information about local and remote users

When in reality it was more like this:

finger–put in eye in one smooth motion to get in the mood for vi editor

It was a futile struggle. Around me Unix maestros were clearly enjoying themselves enormously:

“Hey there is a problem with my port. Can someone just finger me right now!” .

was the sort of thing one Unix maestro would say to the other excitedly

For close to a year I never crossed my path with Unix ever again.

Till one night, after much recommendation from a friend I decided to give this RedHat thing a shot. I followed the manual by the letter. I slipped in the CD, booted from the disc, played around with my partitions a little bit, set up a root user and finally waited with bated breath while the installation happened.

Everything except the sound card and the PPPOE connection for the internet at home seemed to be working fine.

I could try to get them to work too. I checked the user forums and there was a wealth of information such as this response from a RedHat expert:

This is bug 2825 (http://https://bugzilla.redhat.com/show_bug.cgi?i d=2825) . The work around is to ~# ln -f /etc/pppd/resolv.conf /etc/resolv.conf

To which, someone with a sense of humor replied:

I can confirm this bug. I am using a tap0 bridge to emulate PPPoE on a Globespan chipset-based USB aDSL bridge and the latests stable eciadsl-usermode drivers (which, btw are not in Universe). It would be nice to have an updated pppd perhaps backported from Dapper.
I know that Debian’s choice of using kernel-mode PPPoE makes rp-pppoe unnecessary, but I wonder if it would be possible to update rp-pppoe to 3.7 for those that still in using it.

I laughed heartily back then and decided that, for at least the time being, I was ok without the sound.

Its been more than six years since that day. I breathe open source now. All my development happens on a LAMP setup, and dabbling in Drupal is second nature to me. Forum posts are no longer cryptic, and even I have probably turned into one of those “humorous” responders on the several bug forums that are so ubiquitous today. Reverse engineering was never easier and manuals are a waste of time. Microsoft who? Ahhh … life is sweet indeed.

Posted in Drupal, Foo, Social media | 23 Comments »

Turbulent confabulations

Posted by Avadhut on 9 July 2007

My second site in Drupal.

index.png

Front page: Modules used: Panels, views, & a custom banner generation module. Although, Drupal does have a contrib Banner module for 5.1, I wasn’t too happy with the functionality. So coded my own module to handle things like Banner rotation, displaying of a recruitment banner when a new posting is uploaded, etc. Minimum work for the end user, in this case—HR. (Note: The banners in this image are simply an example—placeholders till the Web team comes up with new banners). Also, the search box and newsletter subscription form has been shifted to the top of the page and can be toggled (a tab-ing script in JS).

editage.png

Team page: Modules used: Custom Banner module, views, panels. Notice how the side-bar has appeared on this page now. This was not done through Panels (that would require too many CSS workarounds), instead a template-level workaround/hack was implemented.

cnbc_news1.png

News page: Modules used: Views, Panels. Notice how the date has been displayed—this, again, was a template level hack implemented in node.tpl.php. The blockquotes have been styled to attract attention fast to the important bits, like in newspapers. Makes for easier skimming through.

faqs.png

FAQs page: Modules used: Views, CCK, ConTemplate. Instead of using the contrib FAQs module, I used CCK to create a custom FAQ type. Further, the displaying of the content on the FAQs page—questions on top with named anchor links below—was automatically generated by using a template defined in ConTemplate. Easier for HR to upload questions without meddling with any coded bits.

cutlture.png

Work culture: A static page, but it was made AJAX-y by using the accordion functionality of MooFX.

employee-speak.png

Employee speak: Modules used: Views. Employee Speak was implemented as a custom data type and this listing page was generated using Views. All icons were handcrafted to go with the theme of the site.

colin_speak.png

Employee speak (Individual pages): Modules used: Views, Panels, ConTemplate. Notice how author names and Taxonomy are not linked and the submission line is styled quite differently as compared to the default Drupal style. This is again a template-level hack implemented in node.tpl.php.

careers.png

Careers page: Modules used: Views, ConTemplate. An open/close Javascript wrapper was used to minimize the scrolling and dynamically display content without having to reload pages.

teams.png

Teams: Static content page.

contactus.png photos.png

Facility tour page: Again a static content page. However, the Lightbox Ver 2 Javascript plugin was used to display a slideshow of photos without having to reload pages—the main Web page grays out and a photo is overlayed on top of it with “next” and “prev” controls.

facility.png

Contact us: Simple static content page.

Like I said, it will be a while before this one goes live, but at least the port to Drupal has been performed. The level of CSS detailing Drupal allows you to define is mind boggling. All you need to do is understand the styling system (Drupal has several different style sheets to deal with—system.css, default.css, style.css, and any other style sheets that are bundled with the contrib modules).

I found the Firebug plugin for Firefox an excellent companion in styling Drupal sites as well as to ensure that your site is standards compliant—it helps unlock the complex levels and hierarchies realized by Drupal style sheets.

In the end, it would be the safest to say that no matter what your design looks like—custom tables for each page, differently styled lists on different pages, differently styled blocks on different pages, etc.—nothing is impossible in Drupal.

Posted in Drupal, Office, Visual sick | 7 Comments »

Visual sick

Posted by Avadhut on 6 June 2007

Finally, I have uploaded the screen-shots of my Intranet. A wonderfully powerful and ludicrously flexible system implement in Drupal. I wish I could upload a working version somewhere, but my company policies would not allow me to do so.

front1.png

Frontpage: Custom handcrafted theme, high-clarity PNG icons, etc. The layout and look of the page was possible due to two Drupal modules—Views and Panels. The event calendar on the left is AJAX based and also generates iCal feeds (for MS Outlook). RSS 2.0 feeds are listed at the bottom.  

handbook.png

Handbook: Uses the book module. Again modded and themed to suit our requirements.

submit-post.png

Posts: Being editors, my colleagues wanted everything from the posting section’s WYSIWYG editor. The answer was the FCKEditor. I modded it a bit to better suit our requirements. For post classification, I used a hybrid categorization technique wherein primary post classification is done by selecting hard-coded categories and secondary classification is performed by specifying (optional) free tags. Primary classification determines where all the posts show up, and secondary, aids discoverability.

forums.png

Forums: Taxonomy module facilitated the creation of several nested/flat forums. They are a big hit in the office, accounting for more than 35% of all the interaction. Discussions regarding everthing—from new process reengineering excercises to Intranet look & feel—were discussed on forums.

post_single.png

A simple node page: Shows how a single post/article looks. Notice the green arrows indicating nested comments—makes it easier to track conversations.

posts.png

Post tracker: Tracks all recent posts, new comments, etc. Life has been easy thanks to the Views module.

library.png

Library: Custom node type, Views, & jRating.

library_inner.png

Library listing: A book listing from the library. Custom data type themed using the ConTemplate module. Notice the AJAX-based rating module at the bottom. The “loan now” link auto-generates an email in MS Outlook and sends it to the designated librarian. Books loaned out do not have the loan now link, instead they display information regarding who has loaned the book, when, and when he/she plans to return it!

recommend.png

Recommend a resource: Allows anyone to recommend books/subscriptions for the organization to buy/subscribe to. Generated using the WebForm module. It auto mails the forms info to the designated person. Also, it allows someone with enough privelegs to view statistics regarding form submissions and download all submissions in a EXCEL format!

microsite.png

Microsite: A microsite developed entirely within the new system. Notice how the left and right blocks have changed with the change in site.

calendar.png

Event calendar: Allows all to view role-based events, download iCal feed for one/all events, add comments to events, etc. This page view feeds directly into/from the small block on the right.

And finally, for some shock value, below the graphical representation of the database schema—db_schema.png—knock yourself out!

Posted in Drupal, Visual sick | 11 Comments »