=== 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-10-02 19:08:15 +0000
@@ -0,0 +1,47 @@
+ array(
+ 'rdftype' => array('sioc:Post'),
+ 'title' => array('dc:title'),
+ 'created' => array(
+ 'property' => array('dc:date', 'dc:created'),
+ 'datatype' => 'xsd:dateTime',
+ 'callback' => 'date_iso8601',
+ ),
+ 'name' => array('foaf:name'),
+ 'uid' => array('sioc:has_creator', 'foaf:maker'),
+ )
+ );
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
=== added file 'modules/rdf/rdf.crud.inc'
--- modules/rdf/rdf.crud.inc 1970-01-01 00:00:00 +0000
+++ modules/rdf/rdf.crud.inc 2009-10-02 17:06:27 +0000
@@ -0,0 +1,87 @@
+ $type,
+ 'bundle' => $bundle,
+ 'mapping' => serialize($mapping)
+ );
+
+ db_insert('rdf_mapping')->fields($fields)->execute();
+
+ return $mapping;
+}
+
+/**
+ * Read an RDF mapping record directly from the database.
+ *
+ * @param $type
+ * The entity type the mapping refers to.
+ * @param $bundle
+ * The bundle the mapping refers to.
+ * @return array
+ * An RDF mapping structure or FALSE if the mapping could not be found.
+ */
+function rdf_read_mapping($type, $bundle) {
+ $query = db_select('rdf_mapping')->fields(NULL, array('mapping'))
+ ->condition('type', $type)->condition('bundle', $bundle)->execute();
+
+ return unserialize($query->fetchField());
+}
+
+/**
+ * Update an RDF mapping binded to a bundle and an entity type.
+ *
+ * @param $type
+ * The entity type the mapping refers to.
+ * @param $bundle
+ * The bundle the mapping refers to.
+ * @param $mapping
+ * An associative array representing an RDF mapping structure. The required
+ * keys and values are
+ * type: The entity type the mapping refers to.
+ * bundle: The bundle the mapping refers to.
+ * mapping: An array describing the mapping of this bundle/entity.
+ * @return bool
+ */
+function rdf_update_mapping($type, $bundle, $mapping) {
+ $fields = array('mapping' => serialize($mapping));
+ $num_rows = db_update('rdf_mapping')->fields($fields)
+ ->condition('type', $type)->condition('bundle', $bundle)->execute();
+
+ return ($num_rows > 0);
+}
+
+/**
+ * Delete the mapping for the given pair of type and bundle from the database.
+ *
+ * @param $type
+ * The entity type the mapping refers to.
+ * @param $bundle
+ * The bundle the mapping refers to.
+ * @return bool
+ */
+function rdf_delete_mapping($type, $bundle) {
+ $num_rows = db_delete('rdf_mapping')->condition('type', $type)
+ ->condition('bundle', $bundle)->execute();
+
+ return ($num_rows > 0);
+}
=== added file 'modules/rdf/rdf.info'
--- modules/rdf/rdf.info 1970-01-01 00:00:00 +0000
+++ modules/rdf/rdf.info 2009-10-02 19:14:56 +0000
@@ -0,0 +1,10 @@
+; $Id$
+name = RDF
+description = Allows to map the site data structure to RDF and export it in RDFa.
+package = Core
+version = VERSION
+core = 7.x
+files[] = rdf.install
+files[] = rdf.module
+files[] = rdf.crud.inc
+files[] = rdf.test
=== added file 'modules/rdf/rdf.install'
--- modules/rdf/rdf.install 1970-01-01 00:00:00 +0000
+++ modules/rdf/rdf.install 2009-09-29 19:15:17 +0000
@@ -0,0 +1,40 @@
+ 'Stores custom RDF mappings for user defined content types or overriden module-defined mappings',
+ 'fields' => array(
+ 'type' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'description' => 'The name of the entity type a mapping applies to (node, user, comment, etc.).',
+ ),
+ 'bundle' => array(
+ 'type' => 'varchar',
+ 'length' => 128,
+ 'not null' => TRUE,
+ 'description' => 'The name of the bundle a mapping applies to.',
+ ),
+ 'mapping' => array(
+ 'description' => 'The serialized mapping of the bundle type and fields to RDF terms.',
+ 'type' => 'text',
+ 'not null' => FALSE,
+ 'size' => 'big',
+ 'serialize' => TRUE,
+ ),
+ ),
+ 'primary key' => array('type', 'bundle'),
+ );
+
+ return $schema;
+}
=== added file 'modules/rdf/rdf.module'
--- modules/rdf/rdf.module 1970-01-01 00:00:00 +0000
+++ modules/rdf/rdf.module 2009-10-02 19:53:37 +0000
@@ -0,0 +1,329 @@
+ array(
+ * 'rdftype' => array('sioct:Post'),
+ * 'title' => array(
+ * 'property' => array('dc:title'),
+ * ),
+ * 'created' => array(
+ * 'property' => array('dc:date', 'dc:created'),
+ * 'datatype' => 'xsd:dateTime',
+ * 'callback' => 'date_iso8601',
+ * ),
+ * 'replyof' => array(
+ * 'property' => array('sioc:reply_of'),
+ * ),
+ * 'name' => array(
+ * 'property' => array('dc:creator'),
+ * ),
+ * )
+ * );
+ */
+
+/*
+ * Load all public RDF CRUD API functions. Drupal currently has no
+ * mechanism for auto-loading core APIs, so we have to load them on
+ * every page request.
+ */
+require(DRUPAL_ROOT . '/modules/rdf/rdf.crud.inc');
+
+/**
+ * Returns the mapping for the attributes of the given bundle.
+ *
+ * @param $type
+ * An entity type.
+ * @param $bundle
+ * A bundle name.
+ * @return array
+ * The mapping corresponding to the requested type, bundle combo.
+ */
+function rdf_get_mapping($type, $bundle) {
+ // We retrieve the mapping from the entity info.
+ $entity_info = entity_get_info($type);
+ return !empty($entity_info['bundles'][$bundle]['rdf_mapping']) ? $entity_info['bundles'][$bundle]['rdf_mapping'] : NULL;
+}
+
+/**
+ * Saves an RDF mapping to the database.
+ *
+ * Takes a mapping structure returned by hook_rdf_mapping() implementations
+ * and creates or updates a record mapping for each encountered
+ * type, bundle pair. If available, adds default values for non-existent
+ * mapping keys.
+ *
+ * @param $mapping
+ * The RDF mapping to save, as an array.
+ * @return
+ * Status flag indicating the outcome of the operation.
+ */
+function rdf_save_mapping($mapping) {
+ // Adds default values for non-existent keys.
+ $new_mapping = $mapping['mapping'] + _rdf_get_default_mapping($mapping['type']);
+ $exists = (bool)rdf_read_mapping($mapping['type'], $mapping['bundle']);
+
+ if ($exists) {
+ rdf_update_mapping($mapping['type'], $mapping['bundle'], $new_mapping);
+ return SAVED_UPDATED;
+ }
+ else {
+ rdf_create_mapping($mapping['type'], $mapping['bundle'], $new_mapping);
+ return SAVED_NEW;
+ }
+}
+
+/**
+ * Implements hook_modules_installed().
+ *
+ * Checks if the installed modules have any RDF mapping definitions to declare
+ * and stores them in the rdf_mapping table.
+ */
+function rdf_modules_installed($modules) {
+ // We need to clear the caches of entity_info as this is not done right
+ // during the tests. see http://drupal.org/node/594234
+ cache_clear_all('entity_info', 'cache');
+ drupal_static_reset('entity_get_info');
+
+ foreach ($modules as $module) {
+ if (function_exists($module . '_rdf_mapping')) {
+ $mapping_array = call_user_func($module . '_rdf_mapping');
+ foreach ($mapping_array as $mapping) {
+ rdf_save_mapping($mapping);
+ }
+ }
+ }
+}
+
+/**
+ * Implements hook_modules_uninstalled().
+ */
+function rdf_modules_uninstalled($modules) {
+// TODO remove the RDF mappings.
+}
+
+/**
+ * Implements hook_entity_info_alter().
+ *
+ * Adds the proper RDF mapping to each entity type, bundle pair.
+ */
+function rdf_entity_info_alter(&$entity_info) {
+ // Loop through each entity type and its bundles.
+ foreach ($entity_info as $entity_type => $entity_type_info) {
+ if (isset($entity_type_info['bundles'])) {
+ foreach ($entity_type_info['bundles'] as $bundle => $bundle_info) {
+ if ($mapping = rdf_read_mapping($entity_type, $bundle)) {
+ $entity_info[$entity_type]['bundles'][$bundle]['rdf_mapping'] = $mapping;
+ }
+ else {
+ // If no mapping was found in the database, assign the default RDF
+ // mapping for this entity type.
+ $entity_info[$entity_type]['bundles'][$bundle]['rdf_mapping'] = _rdf_get_default_mapping($entity_type);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Returns ready to render RDFa attributes for the given mapping.
+ *
+ * @param $mapping
+ * An array containing a mandatory property key and optional datatype and
+ * callback keys.
+ * Example:
+ * array(
+ * 'property' => array('dc:created'),
+ * 'datatype' => 'xsd:dateTime',
+ * 'callback' => 'date_iso8601',
+ * )
+ * @param $data
+ * A value that needs to be converted by the provided callback function.
+ * @return array
+ * An array containing RDFa attributes ready for rendering.
+ */
+function drupal_rdfa_attributes($mapping, $data = NULL) {
+ $attributes['property'] = $mapping['property'];
+
+ if (isset($mapping['callback']) && isset($data)) {
+ $callback = $mapping['callback'];
+
+ if (function_exists($callback)) {
+ $attributes['content'] = call_user_func($callback, $data);
+ }
+ if (isset($mapping['datatype'])) {
+ $attributes['datatype'] = $mapping['datatype'];
+ }
+ }
+
+ return $attributes;
+}
+
+/**
+ * Implements hook_node_load().
+ */
+function rdf_node_load($nodes, $types) {
+ foreach ($nodes as $node) {
+ $node->rdf_mapping = rdf_get_mapping('node', $node->type);
+ // The node_load function does not reuse user_load(), so we need to
+ // regenerate the URI of the author of the node.
+ $node->rdf['user'] = array('uri' => _rdf_generate_user_uri($node->uid));
+ }
+}
+
+/**
+ * Implements hook_user_load().
+ */
+function rdf_user_load($users) {
+ // Generate an RDF resource URI for each user account.
+ foreach ($users as $user) {
+ $user->rdf = array('uri' => _rdf_generate_user_uri($user->uid));
+ }
+}
+
+/**
+ * Implements hook_comment_view().
+ *
+ * @param $comment
+ * A comment object.
+ */
+function rdf_comment_view($comment){
+ $comment->rdf_mapping = rdf_get_mapping('comment', 'comment');
+}
+
+/**
+ * Helper function to create a URI for the user object.
+ *
+ * @param $uid
+ * The user id the URI should be generated from.
+ * @return
+ * A URI including the base path of the site, e.g. '/subdomain/user/1#user'.
+ */
+function _rdf_generate_user_uri($uid) {
+ return base_path() . 'user/' . $uid . '#user';
+}
+
+/**
+ * Returns an ISO8601 formatted date based on the given date.
+ *
+ * Can be used as a callback for mappings.
+ *
+ * @param $date
+ * A unix timestamp.
+ * @return string
+ * An ISO8601 formatted date.
+ */
+function date_iso8601($date) {
+ return date(DATE_ISO8601, $date);
+}
+
+/**
+ * Implements MODULE_preprocess_HOOK().
+ */
+function rdf_preprocess_node(&$variables) {
+ // Add RDFa markup to the node container. The about attribute specifies the
+ // URI of the resource described within the HTML element, while the typeof
+ // attribute indicates its RDF type (foaf:Document, or sioc:User, etc.).
+ $variables['attributes_array']['about'] = $variables['node_url'];
+ $variables['attributes_array']['typeof'] = $variables['node']->rdf_mapping['rdftype'];
+
+ // Add RDFa markup to the title of the node. Because the RDFa markup is added
+ // to the h2 tag which might contain HTML code, we specify an empty datatype
+ // to ensure the value of the title read by the RDFa parsers is a literal.
+ $variables['title_attributes_array']['property'] = $variables['node']->rdf_mapping['title']['property'];
+ $variables['title_attributes_array']['datatype'] = '';
+
+ // In full node mode, the title is not displayed by node.tpl.php so it is
+ // added in the head tag of the HTML page.
+ // TODO centralize drupal_add_html_head() in a process function like it was
+ // done for the attributes in tpl files?
+ if ($variables['page']) {
+ $title_attributes['property'] = $variables['node']->rdf_mapping['title']['property'];
+ $title_attributes['content'] = $variables['title'];
+ drupal_add_html_head('');
+ }
+ // Add RDFa markup for the date.
+ // TODO use a theme_timestamp() function instead? see http://drupal.org/node/574954
+ $date_attributes_array = drupal_rdfa_attributes($variables['rdf_mapping']['created'], $variables['created']);
+ $variables['date'] = '' . $variables['date'] . '';
+}
+
+/**
+ * Adds RDFa attributes to the template variables.
+ *
+ * @param $variables
+ */
+function rdf_preprocess_field(&$variables) {
+ $entity_type = $variables['element']['#object_type'];
+ $instance = $variables['instance'];
+ $mapping = rdf_get_mapping($entity_type, $instance['bundle']);
+ $field_name = $instance['field_name'];
+
+ if (!empty($mapping) && !empty($mapping[$field_name])) {
+ foreach ($variables['items'] as $delta => $item) {
+ $variables['item_attributes_array'][$delta] = drupal_rdfa_attributes($mapping[$field_name], $item['#item']);
+ }
+ }
+}
+
+/**
+ * Implements MODULE_preprocess_HOOK().
+ */
+function rdf_preprocess_username(&$variables) {
+ if (!empty($variables['object']->account->rdf_mapping['name'])) {
+ if (isset($variables['object']->link_path)) {
+ $variables['object']->link_attributes['rel'] = $variables['object']->account->rdf_mapping['uid']['property'];
+ }
+ else {
+ $variables['object']->attributes['property'] = $variables['object']->account->rdf_mapping['name']['property'];
+ }
+ }
+}
+
+/**
+ * Implements MODULE_preprocess_HOOK().
+ */
+function rdf_preprocess_comment(&$variables) {
+ if (!empty($variables['comment']->rdf_mapping['rdftype'])) {
+ $variables['attributes_array']['typeof'] = $variables['comment']->rdf_mapping['rdftype'];
+ }
+ if (!empty($variables['comment']->rdf_mapping['title'])) {
+ $variables['title_attributes_array']['property'] = $variables['comment']->rdf_mapping['title']['property'];
+ $variables['title_attributes_array']['datatype'] = '';
+ }
+ if (!empty($variables['comment']->rdf_mapping['created'])) {
+ $date_attributes_array = drupal_rdfa_attributes($variables['comment']->rdf_mapping['created'], $variables['comment']->timestamp);
+ $variables['date'] = '' . $variables['date'] . '';
+ }
+}
+
+/**
+ * Returns the default RDFa mapping for the given entity type.
+ *
+ * @param $type
+ * An entity type.
+ * @return array
+ * The RDFa mappings or an empty array.
+ */
+function _rdf_get_default_mapping($type) {
+ $default_mappings = array();
+ $function = "{$type}_rdf_mapping_defaults";
+
+ if (function_exists($function)) {
+ $default_mappings = call_user_func($function);
+ }
+
+ return $default_mappings;
+}
=== added file 'modules/rdf/rdf.test'
--- modules/rdf/rdf.test 1970-01-01 00:00:00 +0000
+++ modules/rdf/rdf.test 2009-10-02 19:22:55 +0000
@@ -0,0 +1,328 @@
+ t('RDF mappings'),
+ 'description' => t('Test RDF mapping hooks.'),
+ 'group' => t('RDF'),
+ );
+ }
+
+ function setUp() {
+ // Enable RDF and RDF test in the test environment.
+ 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('property' => array('dc:title')), t('Mapping for title is dc:title.'));
+ $this->assertIdentical($mapping['created'], array('property' => array('dc:created')), t('Mapping for created is dc:created.'));
+ $this->assertTrue(in_array('sioc:has_creator', $mapping['uid']['property']), t('Mapping for uid contains sioc:has_creator'));
+ $this->assertTrue(in_array('dc:creator', $mapping['uid']['property']), 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']['property']), t('Mapping for title contains dc:title'));
+ $this->assertTrue(in_array('sioc:title', $mapping['title']['property']), t('Mapping for title contains sioc:title'));
+ $this->assertTrue(in_array('sioc:has_creator', $mapping['uid']['property']), t('Mapping for uid contains sioc:has_creator'));
+ $this->assertTrue(in_array('foo:bar', $mapping['uid']['property']), t('Mapping for uid contains foo:bar'));
+ $this->assertFalse(in_array('dc:creator', $mapping['uid']['property']), t('Mapping for uid does not contain dc:creator'));
+ $this->assertTrue(in_array('foaf:name', $mapping['name']['property']), t('Mapping for name contains foaf:name'));
+ $this->assertFalse(in_array('dc:creator', $mapping['name']['property']), 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.'));
+ }
+
+}
+
+/**
+ * RDFa markup generation tests.
+ */
+class RdfMarkupTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => t('RDFa markup'),
+ 'description' => t('Test RDFa markup generation.'),
+ 'group' => t('RDF'),
+ );
+ }
+
+ function setUp() {
+ // Enable RDF and RDF test in the test environment.
+ parent::setUp('rdf', 'field_test', 'rdf_test');
+ rdf_modules_installed(array('field_test', 'rdf_test'));
+ }
+
+ /**
+ * Test drupal_rdfa_attributes().
+ */
+ function testDrupalRdfaAtributes() {
+ $date = 1252750327;
+ $isoDate = date(DATE_ISO8601, $date);
+
+ $expected_type = 'xsd:dateTime';
+ $expected_property = array('dc:created');
+ $expected_value = $isoDate;
+
+ $mapping = rdf_get_mapping('test_entity', 'test_bundle');
+ $attributes = drupal_rdfa_attributes($mapping['created'], $date);
+
+ $this->assertEqual($expected_type, $attributes['datatype']);
+ $this->assertEqual($expected_property, $attributes['property']);
+ $this->assertEqual($expected_value, $attributes['content']);
+ }
+
+}
+
+class RdfBlogTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => t('RDFa blog markup'),
+ 'description' => t('Test overridden RDFa node markup for blogs.'),
+ 'group' => t('RDF'),
+ );
+ }
+
+ function setUp() {
+ parent::setUp('rdf', 'blog');
+ // HACK! simpletest does not seem to trigger hook_modules_installed().
+ rdf_modules_installed(array('blog'));
+ cache_clear_all('entity_info', 'cache');
+ }
+
+ function testAttributesInMarkup() {
+ $node = $this->drupalCreateNode(array('type' => 'blog'));
+ $this->drupalGet('node/' . $node->nid);
+
+ $this->assertRaw('sioct:Weblog');
+ }
+}
+
+class RdfFieldTestCase extends DrupalWebTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => t('RDFa field markup'),
+ 'description' => t('Test RDFa markup in fields.'),
+ 'group' => t('RDF'),
+ );
+ }
+
+ function setUp() {
+ parent::setUp('field_test', 'rdf');
+
+ $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
+ $this->field = array('field_name' => $this->field_name, 'type' => 'test_field', 'cardinality' => 4);
+ $this->field = field_create_field($this->field);
+ $this->field_id = $this->field['id'];
+ $this->instance = array(
+ 'field_name' => $this->field_name,
+ 'bundle' => 'test_bundle',
+ 'label' => $this->randomName() . '_label',
+ 'description' => $this->randomName() . '_description',
+ 'weight' => mt_rand(0, 127),
+ 'settings' => array(
+ 'test_instance_setting' => $this->randomName(),
+ ),
+ 'widget' => array(
+ 'type' => 'test_field_widget',
+ 'label' => 'Test Field',
+ 'settings' => array(
+ 'test_widget_setting' => $this->randomName(),
+ )
+ ),
+ 'rdf_mapping' => array(
+ 'property' => array('dc:created'),
+ 'datatype' => 'xsd:dateTime',
+ 'callback' => 'date_iso8601',
+ )
+ );
+ field_create_instance($this->instance);
+ }
+
+ function testAttributesInMarkup() {
+ $entity_type = 'test_entity';
+ $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
+ $langcode = FIELD_LANGUAGE_NONE;
+
+ // Populate values to be displayed.
+ $date = 1252750327;
+ $values = array(0 => array('value' => $date));
+ $entity->{$this->field_name}[$langcode] = $values;
+
+ // Simple formatter, label displayed.
+ $formatter_setting = $this->randomName();
+ $this->field['display'] = array(
+ 'full' => array(
+ 'label' => 'above',
+ 'type' => 'field_test_default',
+ 'settings' => array(
+ 'test_formatter_setting' => $formatter_setting,
+ )
+ ),
+ );
+
+ field_update_instance($this->instance);
+ $this->content = drupal_render(field_attach_view($entity_type, $entity));
+ $this->assertPattern('/property="dc:created"/');
+ $this->assertPattern('/datatype="xsd:dateTime"/');
+ $date_iso8601 = preg_quote(date(DATE_ISO8601, $date));
+ $this->assertPattern("/content=\"$date_iso8601\"/");
+ $this->pass($this->content);
+ }
+
+}
+
+class RdfaCommentTestCase extends CommentHelperCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => t('RDFa comment markup'),
+ 'description' => t('Test RDFa markup in comments.'),
+ 'group' => t('RDF'),
+ );
+ }
+
+ function setUp() {
+ parent::setUp('comment', 'rdf');
+
+ $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer permissions', 'administer blocks'));
+ $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content'));
+
+ $this->drupalLogin($this->web_user);
+ $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
+ $this->drupalLogout();
+ }
+
+ function testAttributesInMarkup() {
+ // Set comments to not have subject.
+ $this->drupalLogin($this->admin_user);
+ $this->setCommentPreview(FALSE);
+ $this->setCommentForm(TRUE);
+ $this->setCommentSubject(TRUE);
+ $this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
+ $this->drupalLogout();
+
+ // Post comment without subject.
+ $this->drupalLogin($this->web_user);
+ $subject_text = 'foo';
+ $comment_text = 'bar';
+ $comment = $this->postComment($this->node, $subject_text, $comment_text, FALSE);
+ $this->drupalGet('node/' . $this->node->nid);
+
+ $comment_container = $this->xpath("//div[contains(@class, 'comment') and @typeof='sioct:Post']");
+ $this->assertFalse(empty($comment_container));
+ $comment_title = $this->xpath("//h3[@property='dc:title']");
+ $this->assertEqual((string)$comment_title[0]->a, 'foo');
+ $comment_date = $this->xpath("//div[@typeof='sioct:Post']//*[contains(@property, 'dc:date') and contains(@property, 'dc:created')]");
+ $this->assertFalse(empty($comment_date));
+ $comment_author = $this->xpath("//div[@typeof='sioct:Post']//*[contains(@property, 'dc:creator')]");
+ $this->assertEqual((string)$comment_author[0], $this->web_user->name);
+ }
+
+}
+
+/**
+ * Test the generation of the user RDF URI.
+ */
+class RdfUserLoadUnitTest extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'User RDF URI generation',
+ 'description' => 'Test the loading of a user and a node and make sure the user RDF URI is added to the respective object.',
+ 'group' => 'RDF',
+ );
+ }
+
+ function setUp() {
+ // Enable RDF in the test environment.
+ parent::setUp('rdf');
+ $web_user = $this->drupalCreateUser(array('create article content'));
+ $this->drupalLogin($web_user);
+ }
+
+ /**
+ * Create a user and ensure it has an RDF URI.
+ */
+ function testUserLoad() {
+ // Create a user.
+ $account = $this->drupalCreateUser(array());
+ // Load real user object.
+ $account = user_load($account->uid, TRUE);
+ $this->assertIdentical($account->rdf, array('uri' => base_path() . 'user/' . $account->uid . '#user'), t('The user RDF URI is present in the user object.'));
+ }
+
+ /**
+ * Create a node and ensure it has an RDF URI for the author of the node.
+ */
+ function testNodeLoad() {
+ $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
+ $node = node_load($node->nid);
+ $this->assertIdentical($node->rdf['user'], array('uri' => base_path() . 'user/' . $node->uid . '#user'), t('The user RDF URI is present in the node object.'));
+ }
+}
+
+class RdfCrudTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'RDF crud functions',
+ 'description' => 'Test RDF crud functions for mappings.',
+ 'group' => 'RDF',
+ );
+ }
+
+ function setUp() {
+ // Enable RDF in the test environment.
+ parent::setUp('rdf', 'rdf_test');
+ }
+
+ function testCreateReadUpdateWrite() {
+ $test_mapping = rdf_test_rdf_mapping();
+
+ $this->assertFalse(rdf_read_mapping('test_type', 'test_bundle'));
+ $this->assertEqual(
+ rdf_create_mapping('test_type', 'test_bundle', $test_mapping[0]['mapping']),
+ $test_mapping[0]['mapping']
+ );
+
+ try {
+ rdf_create_mapping('test_type', 'test_bundle', $test_mapping[0]['mapping']);
+ $this->fail('No Exception thrown when attempting to insert the same mapping another time.');
+ }
+ catch (Exception $e) {
+ $this->pass('Exception thrown when attempting to insert the same mapping another time.');
+ }
+
+ $this->assertEqual($test_mapping[0]['mapping'],
+ rdf_read_mapping('test_type', 'test_bundle'));
+ $this->assertTrue(rdf_update_mapping('test_type', 'test_bundle',
+ $test_mapping[1]['mapping']));
+ $this->assertEqual($test_mapping[1]['mapping'],
+ rdf_read_mapping('test_type', 'test_bundle'));
+ $this->assertTrue(rdf_delete_mapping('test_type', 'test_bundle'));
+ $this->assertFalse(rdf_read_mapping('test_type', 'test_bundle'));
+ }
+
+ function testSaveMapping() {
+ $test_mapping = rdf_test_rdf_mapping();
+ rdf_save_mapping($test_mapping[0]);
+
+ $this->assertEqual($test_mapping[0]['mapping'],
+ rdf_read_mapping('test_type', 'test_bundle'));
+ }
+
+}
=== 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:28 +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-10-01 16:48:28 +0000
@@ -0,0 +1,111 @@
+ array(
+ 'type' => 'test_type',
+ 'bundle' => 'test_bundle',
+ 'mapping' => array(
+ 'rdftype' => array('sioc:Post'),
+ 'title' => array(
+ 'property' => array('dc:title'),
+ ),
+ 'created' => array(
+ 'property' => array('dc:created'),
+ 'datatype' => 'xsd:dateTime',
+ 'callback' => 'date_iso8601',
+ ),
+ 'uid' => array(
+ 'property' => array('sioc:has_creator', 'dc:creator'),
+ ),
+ 'foobar' => array(
+ 'property' => array('foo:bar'),
+ ),
+ ),
+ ),
+ 1 => array(
+ 'type' => 'another_test_type',
+ 'bundle' => 'another_test_bundle',
+ 'mapping' => array(
+ 'rdftype' => array('sioc:User'),
+ 'title' => array('property' => array('dc:title')),
+ 'name' => array('property' => array('dc:creator')),
+ 'uid' => array('property' => array('sioc:has_creator', 'dc:creator')),
+ 'foobar' => array('property' => array('foo:bar')),
+ ),
+ ),
+ 2 => array(
+ 'type' => 'test_entity',
+ 'bundle' => 'test_bundle',
+ 'mapping' => array(
+ 'rdftype' => array('sioc:Post'),
+ 'title' => array(
+ 'property' => array('dc:title'),
+ ),
+ 'created' => array(
+ 'property' => array('dc:created'),
+ 'datatype' => 'xsd:dateTime',
+ 'callback' => 'date_iso8601',
+ ),
+ 'uid' => array(
+ 'property' => array('sioc:has_creator', 'dc:creator'),
+ ),
+ 'foobar' => array(
+ 'property' => array('foo:bar'),
+ ),
+ ),
+ ),
+ );
+}
+
+/**
+ * Implementation of hook_rdf_mapping_alter().
+ */
+function rdf_test_rdf_mapping_alter(&$mapping) {
+ /*
+ // Add a single mapping without overriding anything.
+ $mapping['another_test_type']['another_test_bundle']['name']['property'][] = 'foaf:name';
+
+ // Add a multi-value mapping without overwriting anything.
+ $mapping_addition = array(
+ 'another_test_type' => array(
+ 'another_test_bundle' => array(
+ 'title' => array(
+ 'property' => array('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']['property'] = array_diff($mapping['rdf_test_another']['uid']['property'], array('dc:creator'));
+ $mapping['rdf_test_another']['uid']['property'][] = 'foo:bar';
+ }
+
+ // Delete a specific property.
+ $mapping['rdf_test_another']['name']['property'] = array_diff($mapping['rdf_test_another']['name']['property'], 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');
+ */
+}
=== modified file 'modules/system/system.module'
--- modules/system/system.module 2009-09-30 18:36:01 +0000
+++ modules/system/system.module 2009-09-30 21:23:49 +0000
@@ -257,8 +257,10 @@ function system_rdf_namespaces() {
'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#',
- 'xsd' => 'http://www.w3.org/2001/XMLSchema',
+ 'skos' => 'http://www.w3.org/2004/02/skos/core#',
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema#',
);
}
=== modified file 'profiles/default/default.info'
--- profiles/default/default.info 2009-08-30 06:02:08 +0000
+++ profiles/default/default.info 2009-09-13 07:26:50 +0000
@@ -16,4 +16,5 @@ dependencies[] = search
dependencies[] = toolbar
dependencies[] = field_ui
dependencies[] = file
+dependencies[] = rdf
files[] = default.profile
=== modified file 'profiles/default/default.install'
--- profiles/default/default.install 2009-10-01 13:22:43 +0000
+++ profiles/default/default.install 2009-10-01 14:10:07 +0000
@@ -146,6 +146,28 @@ function default_install() {
node_type_save($type);
}
+ // Insert default user-defined RDF mapping into the database.
+ $rdf_mappings = array(
+ array(
+ 'type' => 'node',
+ 'bundle' => 'page',
+ 'mapping' => array(
+ 'rdftype' => array('foaf:Document'),
+ ),
+ ),
+ array(
+ 'type' => 'node',
+ 'bundle' => 'article',
+ 'mapping' => array(
+ 'rdftype' => array('sioc:Item', 'foaf:Document'),
+ ),
+ ),
+ );
+
+ foreach ($rdf_mappings as $rdf_mapping) {
+ rdf_save_mapping($rdf_mapping);
+ }
+
// Default page to not be promoted and have comments disabled.
variable_set('node_options_page', array('status'));
variable_set('comment_page', COMMENT_NODE_HIDDEN);