David Fisco

15 Sep 2008

Objective of CodeTo add Dublin Core metadata to the <HEAD> element of HTML served from a Drupal-powered site.
Technologies You'll Need to Know
The following nascent code adds Dublin Core metadata to my site. It is based on my (also nascent) understanding of the Dublin Core specification. My site is a single-author site, so fields such as "creator" are set to one name only. This code does not support multiple-author sites.

My site uses
  • Drupal 6.4
  • Apache 2.2.9
  • PHPTemplate

This implementation requires placing a file called dublin_core.php into my theme directory.

The following is the contents of dublin_core.php. You'll need to change the variables in the first PHP block if you use this on your site.

$fisco_dublin_core_creator = "Fisco, David";
$fisco_dublin_core_publisher = "Fisco, David";
$fisco_dublin_core_rights_holder = "Fisco, David";
$fisco_dublin_core_language = "en";
$fisco_dublin_core_standard_copyright_notice = "Copyright © 2003-" . $current_year . " by David Fisco. All rights reserved worldwide.";

<link REL="SCHEMA.DC" HREF="http://purl.org/dc/elements/1.1/" />
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" />

<?php if ($title) { ?>
<meta NAME="DC.title" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print $title ?>" />
<?php } ?>
<meta NAME="DC.identifier" scheme="DCTERMS.URI" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'?'https':'http'; print '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; ?>" />
<meta NAME="DC.creator" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print $fisco_dublin_core_creator; ?>" />

$fisco_dublin_core_subjects_array = array();
if ($node->taxonomy) {
foreach ($node->taxonomy as $taxonomy_object) {
if ($taxonomy_object->name != 'Creative Commons') {
$fisco_dublin_core_subjects_array[] = $taxonomy_object->name;

if ($node->field_dublin_core_subjects[0]['value']) {
$fisco_dublin_core_subjects_array = array_merge($fisco_dublin_core_subjects_array, explode(';', $node->field_dublin_core_subjects[0]['value']));

if (count($fisco_dublin_core_subjects_array) > 0) {
$fisco_dublin_core_subjects_array = array_map('trim', $fisco_dublin_core_subjects_array);
$fisco_dublin_core_subjects_array = array_unique($fisco_dublin_core_subjects_array);
foreach ($fisco_dublin_core_subjects_array as $fisco_dublin_core_subject) { ?>
<meta NAME="DC.subject" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print str_replace('"', '', trim($fisco_dublin_core_subject)); ?>" />
<?php }
} ?>

<meta NAME="DC.publisher" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print $fisco_dublin_core_publisher; ?>" />
<meta NAME="DC.type" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="Text" />
<meta NAME="DC.format" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="text/html" />
<meta NAME="DC.language" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print $fisco_dublin_core_language; ?>" />

$current_year = getdate();
$current_year = $current_year['year'];
$copyright_notice = $fisco_dublin_core_standard_copyright_notice;
if ($creative_commons_content) {
$copyright_notice = 'This article is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License.';
print '<meta NAME="DCTERMS.license" xml:lang="' . $fisco_dublin_core_language . '" CONTENT="Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License." />';

<meta NAME="DC.rights" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print $copyright_notice; ?>" />
<meta NAME="DC.rightsHolder" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print $fisco_dublin_core_rights_holder; ?>" />
<meta NAME="DC.relation.IsPartOf" scheme="DCTERMS.URI" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print strtolower(substr($_SERVE["SERVER_PROTOCOL"],0,5))=='https'?'https':'http'; print '://' . $_SERVER['HTTP_HOST'] ?>" />

<?php if ($node->created) { ?>
<meta NAME="DCTERMS.created" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print date('r', $node->created); ?>" />
<?php } ?>

<?php if ($node->changed) { ?>
<meta NAME="DC.date.modified" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php print date('r', $node->changed); ?>" />
<?php } ?>

<?php if ($node->field_abstract[0]['value']) { ?>
<meta NAME="DCTERMS.abstract" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php echo htmlspecialchars(ereg_replace("<[^>]*>", "", $node->field_abstract[0]['value'])); ?>" />
<meta NAME="DC.description" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php echo htmlspecialchars(ereg_replace("<[^>]*>", "", $node->field_abstract[0]['value'])); ?>" />
<?php } ?>

<?php if ($node->field_intended_audience[0]['value']) { ?>
<meta NAME="DCTERMS.audience" xml:lang="<?php print $fisco_dublin_core_language; ?>" CONTENT="<?php echo htmlspecialchars(ereg_replace("<[^>]*>", "", $node->field_intended_audience[0]['value'])); ?>" />
<?php } ?>

The PHP code gets Dublin Core data from Drupal and Apache. For example, the "subject" field is drawn from Drupal's taxonomy terms, with a term called "Creative Commons" excluded. If you use the CCK module, you can define additional fields that will augment the Dublin Core metadata:
  • field_dublin_core_subjects: a semicolon-delimited list of additional subjects you want included in your metadata
  • field_abstract: a text field providing a Dublin Core abstract
  • field_intended_audience: a text field providing Dublin Core's audience field

If you don't use CCK, or choose not to add those fields, this code should still work.

Next, you'll need to call dublin_core.php in an appropriate place in the <HEAD> element of page.tpl.php, and any other templates that define pages on your site. Add this to the <HEAD> element of your page template:
 <?php include 'dublin_core.php'; ?>
My site has some content licensed under a full copyright with the remainder under a Creative Commons contract. This is the significance of the $creative_commons_content variable. I use a taxonomy term called "Creative Commons" to differentiate the contracts. If you want to use the same scheme, you'll need to include the following code in your page template, but dublin_core.php should not break if you don't use this approach.
$creative_commons_content = false;
$taxonomy_terms_array = array();

if (count($node->taxonomy)) {
foreach ($node->taxonomy as $tax_array_element) {
if ($tax_array_element->name == "Creative Commons") {
$creative_commons_content = true;
$taxonomy_terms_array[] = $tax_array_element->name;

It's clunky, but it's been getting the job done so far. Please feel free to send feedback.