=== added directory 'modules/rdf' === added file 'modules/rdf/rdf.api.php' --- modules/rdf/rdf.api.php 1970-01-01 00:00:00 +0000 +++ modules/rdf/rdf.api.php 2009-06-15 09:15:22 +0000 @@ -0,0 +1,51 @@ + array( + 'rdftype' => 'sioc:Post', + 'title' => array('dc:title'), + 'created' => array( + 'properties' => array('dc:date', 'dc:created'), + 'datatype' => 'xsd:dateTime', + 'callback' => 'date_iso8601', + ), + 'name' => array('foaf:name'), + 'uid' => array('sioc:has_creator', 'foaf:maker'), + ) + ); +} + +/** + * Allow modules to override existing mappings. + * + * @param $mappings + * An associative array of mappings + * @return + * void + * + */ +function hook_rdf_mapping_alter(&$mapping) { +} + +/** + * @} End of "addtogroup hooks". + */ === added file 'modules/rdf/rdf.info' --- modules/rdf/rdf.info 1970-01-01 00:00:00 +0000 +++ modules/rdf/rdf.info 2009-06-15 08:23:40 +0000 @@ -0,0 +1,6 @@ +; $Id$ +name = RDF +description = Supports RDF mappings. +package = Core +core = 7.x +files[] = rdf.module === added file 'modules/rdf/rdf.module' --- modules/rdf/rdf.module 1970-01-01 00:00:00 +0000 +++ modules/rdf/rdf.module 2009-06-15 08:36:20 +0000 @@ -0,0 +1,114 @@ + 'dc:title', + ); + $stored_mapping = &drupal_static(__FUNCTION__, $default_mapping); + + if (!is_null($mapping)) { + $stored_mapping = $mapping; + } + + return $stored_mapping; +} + +/** + * Returns the page level RDF mapping from the dictionary. + * + * @return array + * the page level RDF mapping + */ +function drupal_get_rdf_page_mapping() { + return drupal_set_rdf_page_mapping(); +} + +/** + * Returns RDFa attributes for output in XHTML elements. + * + * @param $mapping + * An array containing either a simple mapping or a complex array with + * property, datatype and callback. + * @param $data + * @return string + * An XHTML string ready for insertion into a tag. + */ +function drupal_rdfa_attributes($mapping, $data = NULL) { + if (!isset($mapping['property'])) { + $attributes['property'] = implode(' ', $mapping); + } + else { + $attributes['property'] = implode(' ', $mapping['property']); + + if (isset($mapping['callback']) && !is_null($data)) { + $callback = $mapping['callback']; + + if (drupal_function_exists($callback)) { + $attributes['content'] = call_user_func($callback, $data); + } + if (isset($mapping['datatype'])) { + $attributes['datatype'] = $mapping['datatype']; + } + } + } + + return drupal_attributes($attributes); +} + +/** + * Allow the module to redefine its variables for the page metadata. + * + * This could allow us to avoid modifying theme.inc so much. + * + * @param $variables + * An array of variables to be exposed to the page template. + * @return + * None. + */ +function rdf_preprocess_page(&$variables) { + // dsm(array("rdf_preprocess_page" => drupal_get_rdf_page_mapping())); +} \ No newline at end of file === added file 'modules/rdf/rdf.test' --- modules/rdf/rdf.test 1970-01-01 00:00:00 +0000 +++ modules/rdf/rdf.test 2009-06-08 20:33:05 +0000 @@ -0,0 +1,94 @@ + t('RDF mappings'), + 'description' => t('Test RDF mapping hooks.'), + 'group' => t('RDF'), + ); + } + + function setUp() { + parent::setUp('rdf', 'rdf_test'); + } + + /** + * Test that the mappings are correctly returned and processed by the hooks. + */ + function testMappings() { + // Test that the mapping is returned correctly by the hook. + $mapping = rdf_get_mapping('rdf_test_container'); + $this->assertIdentical($mapping['rdftype'], array('sioc:Post'), t('Mapping for rdftype is sioc:Post.')); + $this->assertIdentical($mapping['title'], array('dc:title'), t('Mapping for title is dc:title.')); + $this->assertIdentical($mapping['created'], array('dc:created'), t('Mapping for created is dc:created.')); + $this->assertTrue(in_array('sioc:has-creator', $mapping['uid']), t('Mapping for uid contains sioc:has-creator')); + $this->assertTrue(in_array('dc:creator', $mapping['uid']), t('Mapping for uid contains dc:creator')); + + // Test that an empty array is returned when a container has no mappings. + $mapping = rdf_get_mapping('rdf_test_nonexistent_container'); + $this->assertTrue(is_array($mapping) && empty($mapping), t('Empty array returned for container with no mappings')); + + // Test that the mappings are altered correctly. + $mapping = rdf_get_mapping('rdf_test_another'); + $this->assertTrue(in_array('dc:title', $mapping['title']), t('Mapping for title contains dc:title')); + $this->assertTrue(in_array('sioc:title', $mapping['title']), t('Mapping for title contains sioc:title')); + $this->assertTrue(in_array('sioc:has-creator', $mapping['uid']), t('Mapping for uid contains sioc:has-creator')); + $this->assertTrue(in_array('foo:bar', $mapping['uid']), t('Mapping for uid contains foo:bar')); + $this->assertFalse(in_array('dc:creator', $mapping['uid']), t('Mapping for uid does not contain dc:creator')); + $this->assertTrue(in_array('foaf:Person', $mapping['name']), t('Mapping for name contains foaf:Person')); + $this->assertFalse(in_array('dc:creator', $mapping['name']), t('Mapping for name does not contain dc:creator')); + $this->assertIdentical($mapping['rdftype'], array('foaf:Person'), t('Mapping for rdftype was changed')); + $this->assertFalse(isset($mapping['foobar']), t('Mapping for foobar was removed.')); + } + + /** + * Test manually setting and getting the page mapping. + */ + function testPageMapping() { + // Default value should be returned if nothing was explicitly set. + $this->assertEqual(drupal_get_rdf_page_mapping(), array('title' => 'dc:title'), t('Default mapping is set correctly.')); + + // If we manually set a mapping, that should replace the default. + drupal_set_rdf_page_mapping(array('foobar' => 'foo:bar')); + $this->assertEqual(drupal_get_rdf_page_mapping(), array('foobar' => 'foo:bar'), t('Custom mapping overrides default mapping.')); + } +} + +class RdfaMarkupTestCase extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => t('RDFa markup'), + 'description' => t('Test RDF markup generation.'), + 'group' => t('RDF'), + ); + } + + function setUp() { + parent::setUp('rdf', 'rdf_test'); + } + + function testDrupalRdfaAtributes() { + $date = '2009-05-14'; + $isoDate = date(DATE_ISO8601, strtotime($date)); + + $expectedType = 'datatype="xsd:dateTime"'; + $expectedProperty = 'property="dc:created"'; + $expectedValue = "content=\"$isoDate\""; + $mapping = rdf_get_mapping('rdf_complex_test'); + $attributes = drupal_rdfa_attributes($mapping['date'], $date); + + $this->assertNotEqual(FALSE, strpos($attributes, $expectedType)); + $this->assertNotEqual(FALSE, strpos($attributes, $expectedProperty)); + $this->assertNotEqual(FALSE, strpos($attributes, $expectedValue)); + + $expectedProperty = 'property="dc:title"'; + $mapping = rdf_get_mapping('rdf_test_container'); + $attributes = drupal_rdfa_attributes($mapping['title']); + + $this->assertNotEqual(FALSE, strpos($attributes, $expectedProperty)); + } +} + + === added directory 'modules/rdf/tests' === added file 'modules/rdf/tests/rdf_test.info' --- modules/rdf/tests/rdf_test.info 1970-01-01 00:00:00 +0000 +++ modules/rdf/tests/rdf_test.info 2009-05-12 16:33:29 +0000 @@ -0,0 +1,8 @@ +; $Id$ +name = "RDF module tests" +description = "Support module for RDF module testing." +package = Testing +version = VERSION +core = 7.x +files[] = rdf_test.module +hidden = TRUE === added file 'modules/rdf/tests/rdf_test.module' --- modules/rdf/tests/rdf_test.module 1970-01-01 00:00:00 +0000 +++ modules/rdf/tests/rdf_test.module 2009-06-08 20:33:05 +0000 @@ -0,0 +1,83 @@ + array( + 'rdftype' => array('sioc:Post'), + 'title' => array('dc:title'), + 'created' => array('dc:created'), + 'uid' => array( + 'sioc:has-creator', + 'dc:creator', + ), + 'foobar' => array('foo:bar'), + ), + 'rdf_test_another' => array( + 'title' => array('dc:title'), + 'rdftype' => array('sioc:User'), + 'name' => array('dc:creator'), + 'uid' => array( + 'sioc:has-creator', + 'dc:creator', + ), + 'foobar' => array('foo:bar'), + ), + 'rdf_complex_test' => array( + 'date' => array( + 'datatype' => 'xsd:dateTime', + 'callback' => 'rdf_test_date', + 'property' => array('dc:created'), + ), + ) + ); +} + +/** + * Implementation of hook_rdf_mapping_alter(). + */ +function rdf_test_rdf_mapping_alter(&$mapping) { + // Add a single mapping without overriding anything. + $mapping['rdf_test_another']['name'][] = 'foaf:Person'; + + // Add a multi-value mapping without overwriting anything. + $mapping_addition = array( + 'rdf_test_another' => array( + 'title' => 'sioc:title', + ), + ); + $mapping = array_merge_recursive($mapping, $mapping_addition); + + // @TODO - in both above examples, what happens if we declare the same + // property more than once-- so that 'title' equals for instance + // array('foaf:Person', 'dc:title', 'foaf:Person') + // should/could we force values to unique at some point? + + // Override (replace) a single property. + if (isset($mapping['rdf_test_another']['uid'])) { + $mapping['rdf_test_another']['uid'] = array_diff($mapping['rdf_test_another']['uid'], array('dc:creator')); + $mapping['rdf_test_another']['uid'][] = 'foo:bar'; + } + + // Delete a specific property. + $mapping['rdf_test_another']['name'] = array_diff((array)$mapping['rdf_test_another']['name'], array('dc:creator')); + + // Delete all mappings for an attribute. + unset($mapping['rdf_test_another']['foobar']); + + // Replace a mapping. + $mapping['rdf_test_another']['rdftype'] = array('foaf:Person'); +} + +function rdf_test_date($date) { + return date(DATE_ISO8601, strtotime($date)); +} === modified file 'modules/system/page.tpl.php' --- modules/system/page.tpl.php 2009-05-28 16:44:05 +0000 +++ modules/system/page.tpl.php 2009-06-09 21:18:12 +0000 @@ -160,9 +160,9 @@
-
+
>
-

+
=== modified file 'modules/system/system.module' --- modules/system/system.module 2009-06-16 08:41:35 +0000 +++ modules/system/system.module 2009-06-16 10:18:14 +0000 @@ -237,7 +237,9 @@ 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', 'rss' => 'http://purl.org/rss/1.0/', + 'tags' => 'http://www.holygoat.co.uk/owl/redwood/0.1/tags/', 'sioc' => 'http://rdfs.org/sioc/ns#', + 'skos' => 'http://www.w3.org/2004/02/skos/core#', 'xsd' => 'http://www.w3.org/2001/XMLSchema', ); } === modified file 'includes/theme.inc' --- includes/theme.inc 2009-06-13 19:34:57 +0000 +++ includes/theme.inc 2009-06-16 09:31:56 +0000 @@ -1744,11 +1744,21 @@ $name = $object->name; } + if (!empty($object->rdf_mapping['name'])) { + $name = '' . check_plain($name) . ''; + } + if (user_access('access user profiles')) { - $output = l($name, 'user/' . $object->uid, array('attributes' => array('title' => t('View user profile.')))); + if (!empty($object->rdf_mapping['uid'])) { + $user_uri = url('user/' . $object->uid, array('fragment' => 'this')); + $output = '' . l($name, 'user/' . $object->uid, array('attributes' => array('title' => t('View user profile.'), 'about' => $user_uri), 'html' => TRUE)) . ''; + } + else { + $output = l($name, 'user/' . $object->uid, array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE)); + } } else { - $output = check_plain($name); + $output = $name; } } elseif ($object->name) { @@ -1965,6 +1975,36 @@ $variables['scripts'] = drupal_get_js(); $variables['tabs'] = theme('menu_local_tasks'); $variables['title'] = drupal_get_title(); + + $variables['rdfa_page_about_typeof'] = ''; + $variables['rdfa_page_title'] = ''; + + // @TODO move conditional logic to an rdf.inc file-- if it has to be in core required, it should be encapsulated as well as possible + if (module_exists('rdf')) { + // Contruct the RDFa markup. + $rdf_page_mapping = drupal_get_rdf_page_mapping(); + //var_dump($rdf_page_mapping); + if (!empty($rdf_page_mapping['rdftype'])) { + $variables['rdfa_page_about_typeof'] = ' about="#this" typeof="' . implode(' ', (array)$rdf_page_mapping['rdftype']) . '"'; + } + else { + // Even if we don't have an RDF type for the resource described on the page + // we create a URI for it. + $variables['rdfa_page_about_typeof'] = ' about="#this"'; + } + if (!empty($rdf_page_mapping['title'])) { + $variables['rdfa_page_title'] = ' property="' . implode(' ', (array)$rdf_page_mapping['title']) . '"'; + } + } + else { + // we still need to create blank variables + // @TODO move conditional logic to an rdf.inc file-- if it has to be in core required, it should be encapsulated as well as possible + $variables['rdfa_page_about_typeof'] = ''; + $variables['rdfa_page_title'] = ''; + } + + // TODO create a separate non-RDFa related patch. + $variables['title_rendered'] = $variables['title'] ? '

' . $variables['title'] . '

' : ''; // RDFa allows annotation of XHTML pages with RDF data, while GRDDL provides // mechanisms for extraction of this RDF content via XSLT transformation // using an associated GRDDL profile.