Thinking about content types
If you've ever built a reasonably complicated site, you've likely experienced the joy of pondering content types. Frequently raised questions are: Should this thing be it's own content type? Or is it really just a field as part of another content type? And don't get me started on the is this really a taxonomy line of questioning.
So in planning the new and improved Harvard Stem Cell Institute (HSCI) site, I opened up OmniGraffle and started mapping out what types of things make up the institute. I made a list of the more concrete things that make up the institute and another list of things that were incidentally created by HSCI's actions. I call the the first group the "HSCI Entities" because they make up the heart of the institute, and the second "Supporting Content Types" because they are important on the site only as they relate to the entities. For example, it doesn't make sense to post a media link from the Boston Globe if it doesn't relate to any of HSCI's people, program, grants, or events.
I then added a fifth entity called "topic." I wanted to create a way of viewing everything that had to do with "diabetes" for example, including both entities and supporting content. Why didn't I use a taxonomy for this? Well I wanted to create an easy way to theme the page template for each term and also add fields (such as a banner image) to topics.

Once I knew how the entities were different from the supporting content types I added a node reference field to each supporting content type could reference an entities. That's why in the diagram the arrows point in that direction. It makes more sense from a content creation workflow perspective to add the relationship in this direction. When I'm adding a new press release, I want to add that it's about these three people. I don't want to go to those three people nodes a add the press release. But I do want the relationship to show up on both ends, which requires some views and theming that I'll get to later.
In addition to supporting content types and entities relating to each other, all of the entities and and relate to each other. And that brings me to the star diagram. Each arrow represents a relationship - the field living in one entity and pointing at the other. For example, when I create an event node, I can add that a specific person related. Or when I create a person node, I can add a topic in which they are interested. So I created a field named for each of these content types and set the node reference settings to only allow that same content type to be referenced. I then added the field to the content type that the arrow begins with. For example I created a field called "program" that could only reference programs and added it to the event content type; and I added this same field to grant.

I should mention that this site is more like a "public face" site, where only a small handful of people will ever log-in to create or edit content. Therefore I could have "person" as a CCK content type rather than getting involved with user stuff.
Finally, I decided that not all supporting content types are created equal, and put them into two groups: "articles" and "media and resources." This was so I could add one more node reference field that would allow me to say for instance, "this video is related to this press release." I set the field up so that it could only reference the media and resources content types and added it to the three article types.
The next challenge was getting all these relationships to show-up in both directions. Half of the relationship can be printed directly into a node template, but the other half needs a view
with the argument set to the node reference field. So I did just that, and added a view for the reverse of each node-reference.

<?php
$view_name = 'MyViewName'; //name of view
$limit = 3; // number of returns
$view_args = array();
$view = views_get_view($view_name);
if ($view) {
print "<p>I wanted this logic so that this paragraph would print only if there were results in MyViewName</p>";
print views_build_view('embed', $view, $view_args, FALSE, $limit);
}
?>
This doesn't work anymore. It seems that views_get_view() returns all the stuff that surround the rows (like the header, footer, extra divs) even if the view has no rows to display. After spending more time in the depths of view that I think a themer really should I came up with the following:
<?php
$view_name = 'MyViewName'; //name of view
$view_args = array();
$foo = views_get_view($view_name);
$foo_view = $foo->execute_display('default', $view_args);
$foo_count = $events_by_person->total_rows; //you can only check the total_rows after executed_display
if ($foo_count) {
print "<p>I wanted this logic so that this paragraph would print only if there were results in MyViewName</p>";
print $foo_view;
}
?>
So I apologize that this lengthy post is about a site that hadn't even gone live yet. But I'm sure that there will be more to report as it evolves.
Monday, April 28, 2008