Added code to implement Dublin Core and Creative Commons RDF metadata.
authorEvan Prodromou <evanprodromou@users.mediawiki.org>
Sun, 4 Apr 2004 21:58:05 +0000 (21:58 +0000)
committerEvan Prodromou <evanprodromou@users.mediawiki.org>
Sun, 4 Apr 2004 21:58:05 +0000 (21:58 +0000)
If these features are turned on (with global flags), a metadata link tag is
provided to the appropriate action ('dublincore' or 'creativecommons'). When
the wiki script receives these actions, it creates RDF files on the fly.

Also includes two valuable general functions: one to show an HTTP error
(used when the flags are turned off), and one to do content negotiation
(used to determine the MIME type for RDF files).

A helper function is also added to page output to display metadata links.

includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/OutputPage.php
includes/Skin.php
index.php
languages/Language.php

index c0cc8a4..d731b01 100644 (file)
@@ -292,5 +292,17 @@ if( !isset( $wgCommandLineMode ) ) {
 }
 
 # Show seconds in Recent Changes
-$wgRCSeconds = false
+$wgRCSeconds = false;
+
+
+# RDF metadata toggles
+
+$wgEnableDublinCoreRdf = false;
+$wgEnableCreativeCommonsRdf = false;
+
+# Override for copyright metadata.
+
+$wgRightsPage = NULL;
+$wgRightsUrl = NULL;
+$wgRightsText = NULL;
 ?>
index 81739ba..e6a0552 100644 (file)
@@ -845,4 +845,101 @@ function wfVarDump( $var )
        }
 }
 
+/* Provide a simple HTTP error. */
+
+function wfHttpError($code, $label, $desc) {
+    
+    global $wgOut;
+    $wgOut->disable();
+    header("HTTP/1.0 $code $label");
+    header("Status: $code $label");
+    $wgOut->sendCacheControl();
+
+    /* Don't send content if it's a HEAD request. */
+    
+    if (strcmp($HTTP_SERVER_VARS['REQUEST_METHOD'],'HEAD') != 0) {
+       header("Content-type: text/plain");
+       print "$desc\n";
+    }
+}
+
+# Converts an Accept-* header into an array mapping string values to quality factors
+
+function wfAcceptToPrefs($accept, $def = "*/*") {
+    # No arg means accept anything (per HTTP spec)
+    if (!$accept) {
+       return array($def => 1);
+    }
+
+    $prefs = array();
+    
+    $parts = explode(",", $accept);
+    
+    foreach ($parts as $part) {
+       #FIXME: doesn't deal with params like 'text/html; level=1'
+       list($value, $qpart) = explode(";", $part);
+       if (!isset($qpart)) {
+           $prefs[$value] = 1;
+       } else if (preg_match('/q\s*=\s*(\d*\.\d+)/', $qpart, $match)) {
+           $prefs[$value] = $match[1];
+       }
+    }
+    
+    return $prefs;
+}
+
+/* private */ function mimeTypeMatch($type, $avail) {
+    if (array_key_exists($type, $avail)) {
+       return $type;
+    } else {
+       $parts = explode('/', $type);
+       if (array_key_exists($parts[0] . '/*', $avail)) {
+           return $parts[0] . '/*';
+       } else if (array_key_exists('*/*', $avail)) {
+           return '*/*';
+       } else {
+           return NULL;
+       }
+    }
+}
+
+#FIXME: doesn't handle params like 'text/plain; charset=UTF-8'
+#XXX: generalize to negotiate other stuff
+
+function wfNegotiateType($cprefs, $sprefs) {
+    $combine = array();
+    
+    foreach (array_keys($sprefs) as $type) {
+       $parts = explode('/', $type);
+       if ($parts[1] != '*') {
+           $ckey = mimeTypeMatch($type, $cprefs);
+           if ($ckey) {
+               $combine[$type] = $sprefs[$type] * $cprefs[$ckey];
+           }
+       }
+    }
+
+    foreach (array_keys($cprefs) as $type) {
+       $parts = explode('/', $type);
+       if ($parts[1] != '*' && !array_key_exists($type, $sprefs)) {
+           $skey = mimeTypeMatch($type, $sprefs);
+           if ($skey) {
+               $combine[$type] = $sprefs[$skey] * $cprefs[$type];
+           }
+       }
+    }
+    
+    $bestq = 0;
+    $besttype = NULL;
+    
+    foreach (array_keys($combine) as $type) {
+       if ($combine[$type] > $bestq) {
+           $besttype = $type;
+           $bestq = $combine[$type];
+       }
+    }
+    
+    return $besttype;
+}
+
 ?>
index e4f79a1..908205a 100644 (file)
@@ -46,6 +46,12 @@ class OutputPage {
        function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
        function addLink( $rel, $rev, $target, $type="", $media="" ) { array_push( $this->mLinktags, array( $rel, $rev, $target, $type, $media ) ); }
 
+        function addMetadataLink( $type, $target ) {
+           static $haveMeta = false;
+           $this->addLink(($haveMeta) ? "alternate meta" : "meta", "", $target, $type);
+           $haveMeta = true;
+       }
+
        # checkLastModified tells the client to use the client-cached page if
        # possible. If sucessful, the OutputPage is disabled so that
        # any future call to OutputPage->output() have no effect. The method
index 6a416c8..1002e41 100644 (file)
@@ -95,15 +95,30 @@ class Skin {
 
        function initPage( &$out )
        {
-               global $wgStyleSheetPath;
                $fname = "Skin::initPage";
                wfProfileIn( $fname );
                
                $out->addLink( "shortcut icon", "", "/favicon.ico" );
-               
+
+               $this->addMetadataLinks($out);
+           
                wfProfileOut( $fname );
        }
        
+        function addMetadataLinks( &$out ) {
+           global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
+
+           if ($action == 'view') {
+               # note: buggy CC software only reads first "meta" link
+               if ($wgEnableCreativeCommonsRdf) {
+                   $out->addMetadataLink('application/rdf+xml', wfLocalUrl($wgTitle->getPrefixedURL(), "action=creativecommons"));
+               }
+               if ($wgEnableDublinCoreRdf) {
+                   $out->addMetadataLink('application/rdf+xml', wfLocalUrl($wgTitle->getPrefixedURL(), "action=dublincore"));
+               }
+           }
+       }
+    
        function outputPage( &$out ) {
                global $wgDebugComments;
                
index a2f1782..6906028 100644 (file)
--- a/index.php
+++ b/index.php
@@ -108,6 +108,22 @@ if ( $search = $wgRequest->getText( 'search' ) ) {
                case "print":
                        $wgArticle->view();
                        break;
+                case "dublincore":
+                        if (!$wgEnableDublinCoreRdf) {
+                            wfHttpError(403, "Forbidden", wfMsg("nodublincore"));
+                        } else {
+                            include_once("Metadata.php");
+                            wfDublinCoreRdf($wgArticle);
+                        }
+                        break;
+                case "creativecommons":
+                        if (!$wgEnableCreativeCommonsRdf) {
+                            wfHttpError(403, "Forbidden", wfMsg("nocreativecommons"));
+                        } else {
+                            include_once("Metadata.php");
+                            wfCreativeCommonsRdf($wgArticle);
+                        }
+                        break;
                case "edit":
                case "submit":
                        if( !$wgCommandLineMode && !$wgRequest->checkSessionCookie() ) {
index 52c812e..69e8fbe 100644 (file)
@@ -1548,6 +1548,15 @@ amusement.",
 'tooltip-specialpages' => 'List of all special pages',
 'tooltip-upload' => 'Upload images or media files [alt-u]',
 'tooltip-specialpage' => 'This is a special page, you can\'t edit the page itself.',
+
+# Metadata
+"nodublincore" => "Dublin Core RDF metadata disabled for this server.",
+"nocreativecommons" => "Creative Commons RDF metadata disabled for this server.",
+"notacceptable" => "The wiki server can't provide data in a format your client can read.",
+
+# Attribution
+
+"anonymous" => "Anonymous user(s) of $wgSitename"
 );
 
 #--------------------------------------------------------------------------