diff --git a/core/includes/common.inc b/core/includes/common.inc index 97b73f4..d5c9e5b 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1904,8 +1904,6 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL /** * Returns an ISO8601 formatted date based on the given date. * - * Callback for use within hook_rdf_mapping() implementations. - * * @param $date * A UNIX timestamp. * diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 6f2795a..45834df 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -2016,48 +2016,6 @@ function comment_ranking() { } /** - * Implements hook_rdf_mapping(). - */ -function comment_rdf_mapping() { - return array( - array( - 'type' => 'comment', - 'bundle' => RDF_DEFAULT_BUNDLE, - 'mapping' => array( - 'rdftype' => array('sioc:Post', 'sioct:Comment'), - 'title' => array( - 'predicates' => array('dc:title'), - ), - 'created' => array( - 'predicates' => array('dc:date', 'dc:created'), - 'datatype' => 'xsd:dateTime', - 'callback' => 'date_iso8601', - ), - 'changed' => array( - 'predicates' => array('dc:modified'), - 'datatype' => 'xsd:dateTime', - 'callback' => 'date_iso8601', - ), - 'comment_body' => array( - 'predicates' => array('content:encoded'), - ), - 'pid' => array( - 'predicates' => array('sioc:reply_of'), - 'type' => 'rel', - ), - 'uid' => array( - 'predicates' => array('sioc:has_creator'), - 'type' => 'rel', - ), - 'name' => array( - 'predicates' => array('foaf:name'), - ), - ), - ), - ); -} - -/** * Implements hook_file_download_access(). */ function comment_file_download_access($field, EntityInterface $entity, File $file) { diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 872eb95..85b9c66 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -1306,7 +1306,7 @@ function forum_rdf_mapping() { 'rdftype' => array('sioc:Post', 'sioct:BoardPost'), 'taxonomy_forums' => array( 'predicates' => array('sioc:has_container'), - 'type' => 'rel', + 'mapping_type' => 'rel', ), ), ), diff --git a/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php b/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php index cc0104e..f168fa0 100644 --- a/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php +++ b/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php @@ -62,6 +62,7 @@ public function mapFieldForOutput(\Drupal\rdf\Mapping\MapFieldForOutputEvent $ev $event->addPredicates($properties); $datatype = $config->get('datatype'); $datatype_callback = $config->get('datatype_callback'); + $mapping_type = $config->get('mapping_type'); if (isset($datatype)) { $event->setDatatype($datatype); @@ -69,6 +70,9 @@ public function mapFieldForOutput(\Drupal\rdf\Mapping\MapFieldForOutputEvent $ev if (isset($datatype_callback)) { $event->setDatatypeCallback($datatype_callback); } + if (isset($mapping_type)) { + $event->setMappingType($mapping_type); + } } } diff --git a/core/modules/rdf/lib/Drupal/rdf/Mapping/MapFieldForOutputEvent.php b/core/modules/rdf/lib/Drupal/rdf/Mapping/MapFieldForOutputEvent.php index 682c67f..ce4869a 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Mapping/MapFieldForOutputEvent.php +++ b/core/modules/rdf/lib/Drupal/rdf/Mapping/MapFieldForOutputEvent.php @@ -29,6 +29,8 @@ class MapFieldForOutputEvent extends Event { protected $datatypeCallback; + protected $mappingType; + /** * Constructor. * @@ -76,6 +78,15 @@ public function setDatatypeCallback($callable) { $this->datatypeCallback = $callable; } + /** + * Set the mapping type. + * + * @param string $mapping_type + */ + public function setMappingType($mapping_type) { + $this->mappingType = $mapping_type; + } + public function getPredicates() { return $this->predicates; } @@ -87,4 +98,8 @@ public function getDatatype() { public function getDatatypeCallback() { return $this->datatypeCallback; } + + public function getMappingType() { + return $this->mappingType; + } } diff --git a/core/modules/rdf/lib/Drupal/rdf/Mapping/RdfMappingManager.php b/core/modules/rdf/lib/Drupal/rdf/Mapping/RdfMappingManager.php index d9c5c73..70a0cf6 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Mapping/RdfMappingManager.php +++ b/core/modules/rdf/lib/Drupal/rdf/Mapping/RdfMappingManager.php @@ -235,6 +235,7 @@ protected function mapFieldForOutput($term_schema) { $mapping['properties'] = $predicates; $mapping['datatype'] = $map_event->getDatatype(); $mapping['datatype_callback'] = $map_event->getDatatypeCallback(); + $mapping['mapping_type'] = $map_event->getMappingType(); } return array_filter($mapping); } diff --git a/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/FieldRdfMapping.php b/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/FieldRdfMapping.php index 89f7aae..a38eee3 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/FieldRdfMapping.php +++ b/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/FieldRdfMapping.php @@ -84,6 +84,15 @@ class FieldRdfMapping extends ConfigEntityBase { public $datatype_callback; /** + * The type of mapping indicating if the target is a string or a resource. + * + * @todo deprecate in favor of EntityNG. + * + * @var string + */ + public $mapping_type; + + /** * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php index bce0f35..e78e1ba 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php @@ -19,7 +19,7 @@ class CommentAttributesTest extends CommentTestBase { * * @var array */ - public static $modules = array('comment', 'rdf'); + public static $modules = array('comment', 'rdf', 'rdf_test'); public static function getInfo() { return array( diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php index 52bcc7e..c77887a 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php @@ -43,7 +43,7 @@ function testAttributesInMarkup1() { // Ensure the default bundle mapping for node is used. These attributes come // from the node default bundle definition. - $node_title = $this->xpath("//meta[@property='dc:title' and @content='$node->title']"); + $node_title = $this->xpath("//meta[contains(@property, 'dc:title') and @content='$node->title']"); $node_meta = $this->xpath("//article[(@about='$url')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']"); $this->assertTrue(!empty($node_title), 'Property dc:title is present in meta tag.'); $this->assertTrue(!empty($node_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.'); @@ -53,44 +53,72 @@ function testAttributesInMarkup1() { * Tests if RDF mapping defined in rdf_test.install is used. * * Creates a content type and a node of type test_bundle_hook_install and - * tests whether the RDF mapping defined in rdf_test.install is used. + * tests whether the RDF mappings from the RDF mapping manager are used. */ function testAttributesInMarkup2() { $type = $this->drupalCreateContentType(array('type' => 'test_bundle_hook_install')); $node = $this->drupalCreateNode(array('type' => 'test_bundle_hook_install')); + + // Set bundle mapping config for test_bundle_hook_install. + $rdf_mapping_manager = drupal_container()->get('rdf.mapping_manager'); + $config = $rdf_mapping_manager->getBundleMappingConfig('node', 'test_bundle_hook_install'); + $bundle_mapping = array_merge($config->get(), array('types' => array('foo:mapping_install1', 'bar:mapping_install2'))); + $config->setData($bundle_mapping)->save(); + + // Set fields mapping config for test_bundle_hook_install. + $node_shared_field_mappings = array( + 'title' => array( + 'properties' => array('dc:title'), + ), + 'created' => array( + 'properties' => array('dc:date', 'dc:created'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'changed' => array( + 'properties' => array('dc:modified'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'body' => array( + 'properties' => array('content:encoded'), + ), + 'uid' => array( + 'properties' => array('sioc:has_creator'), + 'mapping_type' => 'rel', + ), + 'name' => array( + 'properties' => array('foaf:name'), + ), + 'comment_count' => array( + 'properties' => array('sioc:num_replies'), + 'datatype' => 'xsd:integer', + ), + 'last_activity' => array( + 'properties' => array('sioc:last_activity_date'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + ); + // Iterate over field mappings and save. + foreach ($node_shared_field_mappings as $field_name => $field_mapping) { + $config = $rdf_mapping_manager->getFieldMappingConfig('node', 'test_bundle_hook_install', $field_name); + $field_mapping = array_merge($config->get(), $field_mapping); + $config->setData($field_mapping)->save(); + } + $isoDate = date('c', $node->changed); $url = url('node/' . $node->nid); $this->drupalGet('node/' . $node->nid); // Ensure the mapping defined in rdf_module.test is used. - $test_bundle_title = $this->xpath("//meta[@property='dc:title' and @content='$node->title']"); + $test_bundle_title = $this->xpath("//meta[contains(@property, 'dc:title') and @content='$node->title']"); $test_bundle_meta = $this->xpath("//article[(@about='$url') and contains(@typeof, 'foo:mapping_install1') and contains(@typeof, 'bar:mapping_install2')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']"); $this->assertTrue(!empty($test_bundle_title), 'Property dc:title is present in meta tag.'); $this->assertTrue(!empty($test_bundle_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.'); } /** - * Tests if the default mapping for a node is being used. - * - * Creates a random content type and node and ensures the default mapping for - * the node is being used. - */ - function testAttributesInMarkup3() { - $type = $this->drupalCreateContentType(); - $node = $this->drupalCreateNode(array('type' => $type->type)); - $isoDate = date('c', $node->changed); - $url = url('node/' . $node->nid); - $this->drupalGet('node/' . $node->nid); - - // Ensure the default bundle mapping for node is used. These attributes come - // from the node default bundle definition. - $random_bundle_title = $this->xpath("//meta[@property='dc:title' and @content='$node->title']"); - $random_bundle_meta = $this->xpath("//article[(@about='$url') and contains(@typeof, 'sioc:Item') and contains(@typeof, 'foaf:Document')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']"); - $this->assertTrue(!empty($random_bundle_title), 'Property dc:title is present in meta tag.'); - $this->assertTrue(!empty($random_bundle_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.'); - } - - /** * Tests if default mapping for user is being used. * * Creates a random user and ensures the default mapping for the user is @@ -109,7 +137,7 @@ function testUserAttributesInMarkup() { $account_uri = url('user/' . $user2->uid); $person_uri = url('user/' . $user2->uid, array('fragment' => 'me')); - $user2_profile_about = $this->xpath('//article[@class="profile" and @typeof="sioc:UserAccount" and @about=:account-uri]', array( + $user2_profile_about = $this->xpath('//article[@class="profile" and contains(@typeof, "sioc:UserAccount") and @about=:account-uri]', array( ':account-uri' => $account_uri, )); $this->assertTrue(!empty($user2_profile_about), 'RDFa markup found on user profile page'); @@ -133,7 +161,7 @@ function testUserAttributesInMarkup() { $this->drupalGet('node/' . $node->nid); // Ensures the default bundle mapping for user is used on the Authored By // information on the node. - $author_about = $this->xpath('//a[@typeof="sioc:UserAccount" and @about=:account-uri and @property="foaf:name" and @datatype="" and contains(@lang, "")]', array( + $author_about = $this->xpath('//a[contains(@typeof, "sioc:UserAccount") and @about=:account-uri and contains(@property, "foaf:name") and @datatype="" and contains(@lang, "")]', array( ':account-uri' => $account_uri, )); $this->assertTrue(!empty($author_about), 'RDFa markup found on author information on post. The lang attribute on username is set to empty string.'); @@ -143,14 +171,13 @@ function testUserAttributesInMarkup() { * Creates a random term and ensures the right RDFa markup is used. */ function testTaxonomyTermRdfaAttributes() { - $vocabulary = $this->createVocabulary(); - $term = $this->createTerm($vocabulary); + $term = $this->createTerm(taxonomy_vocabulary_load('tags')); // Views the term and checks that the RDFa markup is correct. $this->drupalGet('taxonomy/term/' . $term->tid); $term_url = url('taxonomy/term/' . $term->tid); $term_label = $term->label(); - $term_rdfa_meta = $this->xpath('//meta[@typeof="skos:Concept" and @about=:term-url and contains(@property, "rdfs:label") and contains(@property, "skos:prefLabel") and @content=:term-label]', array( + $term_rdfa_meta = $this->xpath('//meta[contains(@typeof, "skos:Concept") and @about=:term-url and contains(@property, "rdfs:label") and contains(@property, "skos:prefLabel") and @content=:term-label]', array( ':term-url' => $term_url, ':term-label' => $term_label, )); diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php index 92362ee..78707e5 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php @@ -81,7 +81,7 @@ function testAttributesInMarkupFile() { // Set the RDF mapping for the new field. $config = $this->mappingManager->getFieldMappingConfig('node', 'article', $field_name); - $field_mapping = array_merge($config->get(), array('properties' => array('rdfs:seeAlso'), 'type' => 'rel')); + $field_mapping = array_merge($config->get(), array('properties' => array('rdfs:seeAlso'), 'mapping_type' => 'rel')); $config->setData($field_mapping)->save(); // Get the test file that simpletest provides. diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php index 45488bd..dd67950 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php @@ -36,6 +36,54 @@ function setUp() { // Creates article content type. $this->drupalCreateContentType(array('type' => 'article', 'name' => t('Article'))); + // Set bundle RDF mapping config for article. + $rdf_mapping_manager = drupal_container()->get('rdf.mapping_manager'); + $config = $rdf_mapping_manager->getBundleMappingConfig('node', 'article'); + $bundle_mapping = array_merge($config->get(), array('types' => array('foaf:Document', 'sioc:Item'))); + $config->setData($bundle_mapping)->save(); + + // Set fields RDF mapping config for article. + $node_shared_field_mappings = array( + 'title' => array( + 'properties' => array('dc:title'), + ), + 'created' => array( + 'properties' => array('dc:date', 'dc:created'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'changed' => array( + 'properties' => array('dc:modified'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'body' => array( + 'properties' => array('content:encoded'), + ), + 'uid' => array( + 'properties' => array('sioc:has_creator'), + 'mapping_type' => 'rel', + ), + 'name' => array( + 'properties' => array('foaf:name'), + ), + 'comment_count' => array( + 'properties' => array('sioc:num_replies'), + 'datatype' => 'xsd:integer', + ), + 'last_activity' => array( + 'properties' => array('sioc:last_activity_date'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + ); + // Iterate over field mappings and save. + foreach ($node_shared_field_mappings as $field_name => $field_mapping) { + $config = $rdf_mapping_manager->getFieldMappingConfig('node', 'article', $field_name); + $field_mapping = array_merge($config->get(), $field_mapping); + $config->setData($field_mapping)->save(); + } + // Enables anonymous posting of content. user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array( 'create article content' => TRUE, diff --git a/core/modules/rdf/rdf.api.php b/core/modules/rdf/rdf.api.php index b3f95ba..a1a7c18 100644 --- a/core/modules/rdf/rdf.api.php +++ b/core/modules/rdf/rdf.api.php @@ -68,11 +68,11 @@ function hook_rdf_mapping() { ), 'pid' => array( 'predicates' => array('sioc:reply_of'), - 'type' => 'rel', + 'mapping_type' => 'rel', ), 'uid' => array( 'predicates' => array('sioc:has_creator'), - 'type' => 'rel', + 'mapping_type' => 'rel', ), 'name' => array( 'predicates' => array('foaf:name'), diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module index 3e4bf08..f149123 100644 --- a/core/modules/rdf/rdf.module +++ b/core/modules/rdf/rdf.module @@ -43,23 +43,23 @@ function rdf_help($path, $arg) { * 'type' => 'node', * 'bundle' => RDF_DEFAULT_BUNDLE, * 'mapping' => array( - * 'rdftype' => array('sioc:Item', 'foaf:Document'), + * 'types' => array('sioc:Item', 'foaf:Document'), * 'title' => array( - * 'predicates' => array('dc:title'), + * 'properties' => array('dc:title'), * ), * 'created' => array( - * 'predicates' => array('dc:date', 'dc:created'), + * 'properties' => array('dc:date', 'dc:created'), * 'datatype' => 'xsd:dateTime', - * 'callback' => 'date_iso8601', + * 'datatype_callback' => 'date_iso8601', * ), * 'body' => array( - * 'predicates' => array('content:encoded'), + * 'properties' => array('content:encoded'), * ), * 'uid' => array( - * 'predicates' => array('sioc:has_creator'), + * 'properties' => array('sioc:has_creator'), * ), * 'name' => array( - * 'predicates' => array('foaf:name'), + * 'properties' => array('foaf:name'), * ), * ), * ); @@ -103,37 +103,6 @@ function rdf_get_namespaces() { } /** - * Returns the mapping for attributes of a given entity type/bundle pair. - * - * @param $type - * An entity type. - * @param $bundle - * A bundle name. - * - * @return - * The mapping corresponding to the requested entity type/bundle pair or an - * empty array. - */ -function rdf_mapping_load($type, $bundle) { - $mapping_manager = drupal_container()->get('rdf.mapping_manager'); - $mapping = array( - 'rdftypes' => $mapping_manager->getBundleMapping($type, $bundle), - ); - $entity = entity_create($type, array('type' => $bundle)); - - $properties = $entity->getPropertyDefinitions(); - if (!empty($properties)) { - foreach ($properties as $field_name => $field_info) { - $field_mapping = $mapping_manager->getFieldMapping($type, $bundle, $field_name); - if (!empty($field_mapping)) { - $mapping[$field_name] = $field_mapping; - } - } - } - return $mapping; -} - -/** * @} End of "defgroup rdf". */ @@ -151,13 +120,13 @@ function rdf_mapping_load($type, $bundle) { * field-specific $item_attributes variables. * * @param $mapping - * An array containing a mandatory 'predicates' key and optional 'datatype', - * 'callback' and 'type' keys. For example: + * An array containing a mandatory 'properties' key and optional 'datatype', + * 'datatype_callback' and 'type' keys. For example: * @code * array( - * 'predicates' => array('dc:created'), + * 'properties' => array('dc:created'), * 'datatype' => 'xsd:dateTime', - * 'callback' => 'date_iso8601', + * 'datatype_callback' => 'date_iso8601', * ), * ); * @endcode @@ -172,7 +141,7 @@ function rdf_mapping_load($type, $bundle) { */ function rdf_rdfa_attributes($mapping, $data = NULL) { // The type of mapping defaults to 'property'. - $type = isset($mapping['type']) ? $mapping['type'] : 'property'; + $type = isset($mapping['mapping_type']) ? $mapping['mapping_type'] : 'property'; switch ($type) { // The mapping expresses the relationship between two resources. @@ -186,8 +155,8 @@ function rdf_rdfa_attributes($mapping, $data = NULL) { case 'property': $attributes['property'] = $mapping['properties']; // Convert $data to a specific format as per the callback function. - if (isset($data) && isset($mapping['callback'])) { - $callback = $mapping['callback']; + if (isset($data) && isset($mapping['datatype_callback'])) { + $callback = $mapping['datatype_callback']; $attributes['content'] = $callback($data); } if (isset($mapping['datatype'])) { @@ -204,6 +173,26 @@ function rdf_rdfa_attributes($mapping, $data = NULL) { */ /** + * Implements hook_comment_load(). + * + * @todo refactor to take advantage of the new Drupal 8 APIs. + */ +function rdf_comment_load($comments) { + foreach ($comments as $comment) { + // Pages with many comments can show poor performance. This information + // isn't needed until rdf_preprocess_comment() is called, but set it here + // to optimize performance for websites that implement an entity cache. + $mapping_manager = drupal_container()->get('rdf.mapping_manager'); + $created_mapping = $mapping_manager->getFieldMapping('comment', $comment->bundle(), 'created'); + $comment->rdf_data['date'] = rdf_rdfa_attributes($created_mapping, $comment->created->value); + $comment->rdf_data['nid_uri'] = url('node/' . $comment->nid->target_id); + if ($comment->pid->target_id) { + $comment->rdf_data['pid_uri'] = url('comment/' . $comment->pid->target_id, array('fragment' => 'comment-' . $comment->pid->target_id)); + } + } +} + +/** * Implements hook_theme(). */ function rdf_theme() { @@ -281,7 +270,7 @@ function rdf_preprocess_node(&$variables) { $mapping_manager = drupal_container()->get('rdf.mapping_manager'); $bundle_mapping = $mapping_manager->getBundleMapping('node', $variables['type']); $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url']; - $variables['attributes']['typeof'] = empty($bundle_mapping['rdftype']) ? NULL : $bundle_mapping['rdftype']; + $variables['attributes']['typeof'] = empty($bundle_mapping['types']) ? NULL : $bundle_mapping['types']; // Adds RDFa markup to the title of the node. Because the RDFa markup is // added to the

tag which might contain HTML code, we specify an empty @@ -368,7 +357,7 @@ function rdf_preprocess_field(&$variables) { $entity_type = $element['#entity_type']; $bundle = $element['#bundle']; $field_name = $element['#field_name']; - $field_mapping = $mapping_manager->getFieldMappingConfig($entity_type, $bundle, $field_name)->get(); + $field_mapping = $mapping_manager->getFieldMapping($entity_type, $bundle, $field_name); if (!empty($field_mapping)) { foreach ($element['#items'] as $delta => $item) { @@ -443,16 +432,8 @@ function rdf_preprocess_username(&$variables) { $variables['attributes']['lang'] = ''; } - // $variables['account'] is a pseudo account object, and as such, does not - // contain the RDF mappings for the user. In the case of nodes and comments, - // it contains the mappings for the node or comment object instead. However, - // while the RDF mappings are available from a full user_load(), this should - // be avoided for performance reasons. Since the type and bundle for users is - // already known, call rdf_mapping_load() directly. - $rdf_mapping = rdf_mapping_load('user', 'user'); - // The profile URI is used to identify the user account. The about attribute - // is used to set the URI as the default subject of the predicates embedded + // is used to set the URI as the default subject of the properties embedded // as RDFa in the child elements. Even if the user profile is not accessible // to the current user, we use its URI in order to identify the user in RDF. // We do not use this attribute for the anonymous user because we do not have @@ -463,21 +444,24 @@ function rdf_preprocess_username(&$variables) { } $attributes = array(); - // The typeof attribute specifies the RDF type(s) of this resource. They - // are defined in the 'rdftype' property of the user RDF mapping. - if (!empty($rdf_mapping['rdftype'])) { - $attributes['typeof'] = $rdf_mapping['rdftype']; + // Add RDF type of user. + $mapping_manager = drupal_container()->get('rdf.mapping_manager'); + $bundle_mapping = $mapping_manager->getBundleMapping('user', 'user'); + if (!empty($bundle_mapping['types'])) { + $attributes['typeof'] = $bundle_mapping['types']; } // Annotate the username in RDFa. A property attribute is used with an empty // datatype attribute to ensure the username is parsed as a plain literal // in RDFa 1.0 and 1.1. - if (!empty($rdf_mapping['name'])) { - $attributes['property'] = $rdf_mapping['name']['properties']; + $name_mapping = $mapping_manager->getFieldMapping('user', 'user', 'name'); + if (!empty($name_mapping)) { + $attributes['property'] = $name_mapping['properties']; $attributes['datatype'] = ''; } // Add the homepage RDFa markup if present. - if (!empty($variables['homepage']) && !empty($rdf_mapping['homepage'])) { - $attributes['rel'] = $rdf_mapping['homepage']['properties']; + $homepage_mapping = $mapping_manager->getFieldMapping('user', 'user', 'homepage'); + if (!empty($variables['homepage']) && !empty($homepage_mapping)) { + $attributes['rel'] = $homepage_mapping['properties']; } // The remaining attributes can have multiple values listed, with whitespace // separating the values in the RDFa attributes @@ -492,18 +476,22 @@ function rdf_preprocess_username(&$variables) { */ function rdf_preprocess_comment(&$variables) { $comment = $variables['comment']; - if (!empty($comment->rdf_mapping['rdftype'])) { + $mapping_manager = drupal_container()->get('rdf.mapping_manager'); + $bundle_mapping = $mapping_manager->getBundleMapping('comment', $comment->bundle()); + + if (!empty($bundle_mapping['types'])) { // Adds RDFa markup to the comment container. The about attribute specifies // the URI of the resource described within the HTML element, while the // typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document, // and so on.) $uri = $comment->uri(); $variables['attributes']['about'] = url($uri['path'], $uri['options']); - $variables['attributes']['typeof'] = $comment->rdf_mapping['rdftype']; + $variables['attributes']['typeof'] = $bundle_mapping['types']; } // Adds RDFa markup for the date of the comment. - if (!empty($comment->rdf_mapping['created'])) { + $created_mapping = $mapping_manager->getFieldMapping('comment', $comment->bundle(), 'created'); + if (!empty($created_mapping)) { // The comment date is precomputed as part of the rdf_data so that it can be // cached as part of the entity. $date_attributes = $comment->rdf_data['date']; @@ -511,24 +499,27 @@ function rdf_preprocess_comment(&$variables) { $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes; } // Adds RDFa markup for the relation between the comment and its author. - if (!empty($comment->rdf_mapping['uid'])) { - $variables['rdf_template_variable_attributes']['author']['rel'] = $comment->rdf_mapping['uid']['properties']; - $variables['rdf_template_variable_attributes']['submitted']['rel'] = $comment->rdf_mapping['uid']['properties']; + $uid_mapping = $mapping_manager->getFieldMapping('comment', $comment->bundle(), 'uid'); + if (!empty($uid_mapping)) { + $variables['rdf_template_variable_attributes']['author']['rel'] = $uid_mapping['properties']; + $variables['rdf_template_variable_attributes']['submitted']['rel'] = $uid_mapping['properties']; } - if (!empty($comment->rdf_mapping['title'])) { + $title_mapping = $mapping_manager->getFieldMapping('comment', $comment->bundle(), 'title'); + if (!empty($title_mapping)) { // Adds RDFa markup to the subject of the comment. Because the RDFa markup // is added to an

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']['property'] = $comment->rdf_mapping['title']['properties']; + $variables['title_attributes']['property'] = $title_mapping['properties']; $variables['title_attributes']['datatype'] = ''; } // Annotates the parent relationship between the current comment and the node // it belongs to. If available, the parent comment is also annotated. - if (!empty($comment->rdf_mapping['pid'])) { + $pid_mapping = $mapping_manager->getFieldMapping('comment', $comment->bundle(), 'pid'); + if (!empty($pid_mapping)) { // Adds the relation to the parent node. - $parent_node_attributes['rel'] = $comment->rdf_mapping['pid']['properties']; + $parent_node_attributes['rel'] = $pid_mapping['properties']; // The parent node URI is precomputed as part of the rdf_data so that it can // be cached as part of the entity. $parent_node_attributes['resource'] = $comment->rdf_data['nid_uri']; @@ -536,7 +527,7 @@ function rdf_preprocess_comment(&$variables) { // Adds the relation to parent comment, if it exists. if ($comment->pid->target_id != 0) { - $parent_comment_attributes['rel'] = $comment->rdf_mapping['pid']['predicates']; + $parent_comment_attributes['rel'] = $pid_mapping['properties']; // The parent comment URI is precomputed as part of the rdf_data so that // it can be cached as part of the entity. $parent_comment_attributes['resource'] = $comment->rdf_data['pid_uri']; diff --git a/core/modules/rdf/tests/rdf_test.install b/core/modules/rdf/tests/rdf_test.install index 91a3392..9a4d76a 100644 --- a/core/modules/rdf/tests/rdf_test.install +++ b/core/modules/rdf/tests/rdf_test.install @@ -9,17 +9,108 @@ * Implements hook_install(). */ function rdf_test_install() { - $rdf_mappings = array( - array( - 'type' => 'node', - 'bundle' => 'test_bundle_hook_install', - 'mapping' => array( - 'rdftype' => array('foo:mapping_install1', 'bar:mapping_install2'), - ), + // Set bundle mapping config. + $rdf_mapping_manager = drupal_container()->get('rdf.mapping_manager'); + $config = $rdf_mapping_manager->getBundleMappingConfig('node', 'article'); + $bundle_mapping = array_merge($config->get(), array('types' => array('foaf:Document', 'sioc:Item'))); + $config->setData($bundle_mapping)->save(); + + // Set fields mapping config. + $node_shared_field_mappings = array( + 'title' => array( + 'properties' => array('dc:title'), + ), + 'created' => array( + 'properties' => array('dc:date', 'dc:created'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'changed' => array( + 'properties' => array('dc:modified'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'body' => array( + 'properties' => array('content:encoded'), + ), + 'uid' => array( + 'properties' => array('sioc:has_creator'), + 'mapping_type' => 'rel', + ), + 'name' => array( + 'properties' => array('foaf:name'), + ), + 'comment_count' => array( + 'properties' => array('sioc:num_replies'), + 'datatype' => 'xsd:integer', + ), + 'last_activity' => array( + 'properties' => array('sioc:last_activity_date'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', ), ); + // Iterate over field mappings and save. + foreach ($node_shared_field_mappings as $field_name => $field_mapping) { + $config = $rdf_mapping_manager->getFieldMappingConfig('node', 'article', $field_name); + $field_mapping = array_merge($config->get(), $field_mapping); + $config->setData($field_mapping)->save(); + } - foreach ($rdf_mappings as $rdf_mapping) { - rdf_mapping_save($rdf_mapping); + // Save comment RDF mapping configuration for article. + $rdf_mapping_manager = drupal_container()->get('rdf.mapping_manager'); + // Save bundle mapping config. + $config = $rdf_mapping_manager->getBundleMappingConfig('comment', 'comment_node_article'); + $bundle_mapping = array_merge($config->get(), array('types' => array('sioc:Post', 'sioct:Comment'))); + $config->setData($bundle_mapping)->save(); + $comment_shared_field_mappings = array( + 'title' => array( + 'properties' => array('dc:title'), + ), + 'created' => array( + 'properties' => array('dc:date', 'dc:created'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'changed' => array( + 'properties' => array('dc:modified'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'comment_body' => array( + 'properties' => array('content:encoded'), + ), + 'pid' => array( + 'properties' => array('sioc:reply_of'), + 'mapping_type' => 'rel', + ), + 'uid' => array( + 'properties' => array('sioc:has_creator'), + 'mapping_type' => 'rel', + ), + 'name' => array( + 'properties' => array('foaf:name'), + ), + ); + // Iterate over shared field mappings and save. + foreach ($comment_shared_field_mappings as $field_name => $field_mapping) { + $config = $rdf_mapping_manager->getFieldMappingConfig('comment', 'comment_node_article', $field_name); + $field_mapping = array_merge($config->get(), $field_mapping); + $config->setData($field_mapping)->save(); } + + // Configure RDF mapping for User bundle. + $config = $rdf_mapping_manager->getBundleMappingConfig('user', 'user'); + $bundle_mapping = array_merge($config->get(), array('types' => array('sioc:UserAccount'))); + $config->setData($bundle_mapping)->save(); + // @todo Change to reflect field names once User uses real fields. + // Configure RDF mapping for name field on User bundle. + $config = $rdf_mapping_manager->getFieldMappingConfig('user', 'user', 'name'); + $field_mapping = array_merge($config->get(), array('properties' => array('foaf:name'))); + $config->setData($field_mapping)->save(); + // Configure RDF mapping for homepage field on User bundle. + $config = $rdf_mapping_manager->getFieldMappingConfig('user', 'user', 'homepage'); + $field_mapping = array_merge($config->get(), array('properties' => array('foaf:page'), 'mapping_type' => 'rel')); + $config->setData($field_mapping)->save(); + } diff --git a/core/modules/rdf/tests/rdf_test.module b/core/modules/rdf/tests/rdf_test.module index 27e4382..b3d9bbc 100644 --- a/core/modules/rdf/tests/rdf_test.module +++ b/core/modules/rdf/tests/rdf_test.module @@ -1,48 +1 @@ 'test_entity', - 'bundle' => 'test_bundle', - 'mapping' => array( - 'rdftype' => array('sioc:Post'), - 'title' => array( - 'predicates' => array('dc:title'), - ), - 'created' => array( - 'predicates' => array('dc:created'), - 'datatype' => 'xsd:dateTime', - 'callback' => 'date_iso8601', - ), - 'uid' => array( - 'predicates' => array('sioc:has_creator', 'dc:creator'), - 'type' => 'rel', - ), - 'foobar' => array( - 'predicates' => array('foo:bar'), - ), - 'foobar1' => array( - 'datatype' => 'foo:bar1type', - 'predicates' => array('foo:bar1'), - ), - 'foobar_objproperty1' => array( - 'predicates' => array('sioc:has_creator', 'dc:creator'), - 'type' => 'rel', - ), - 'foobar_objproperty2' => array( - 'predicates' => array('sioc:reply_of'), - 'type' => 'rev', - ), - ), - ), - ); -} diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 054c451..c13a263 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -1293,27 +1293,6 @@ function taxonomy_field_settings_form($field, $instance, $has_data) { } /** - * Implements hook_rdf_mapping(). - * - * @return array - * The rdf mapping for vocabularies and terms. - */ -function taxonomy_rdf_mapping() { - return array( - array( - 'type' => 'taxonomy_term', - 'bundle' => RDF_DEFAULT_BUNDLE, - 'mapping' => array( - 'rdftype' => array('skos:Concept'), - 'name' => array( - 'predicates' => array('rdfs:label', 'skos:prefLabel'), - ), - ), - ), - ); -} - -/** * @defgroup taxonomy_index Taxonomy indexing * @{ * Functions to maintain taxonomy indexing. diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc index 853f50d..8695321 100644 --- a/core/modules/tracker/tracker.pages.inc +++ b/core/modules/tracker/tracker.pages.inc @@ -79,34 +79,37 @@ function tracker_page($account = NULL, $set_title = FALSE) { ); // Adds extra RDFa markup to the $row array if the RDF module is enabled. - if (function_exists('rdf_mapping_load')) { - // Each node is not loaded for performance reasons, as a result we need - // to retrieve the RDF mapping for each node type. - $mapping = rdf_mapping_load('node', $node->type); + if (module_exists('rdf')) { + $mapping_manager = drupal_container()->get('rdf.mapping_manager'); // Adds RDFa markup to the title of the node. Because the RDFa markup is // added to the td 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 plain literal. - $row['title'] += rdf_rdfa_attributes($mapping['title']) + array('datatype' => ''); + $title_mapping = $mapping_manager->getFieldMapping('node', $node->type, 'title'); + $row['title'] += rdf_rdfa_attributes($title_mapping) + array('datatype' => ''); // Annotates the td tag containing the author of the node. - $row['author'] += rdf_rdfa_attributes($mapping['uid']); + $uid_mapping = $mapping_manager->getFieldMapping('node', $node->type, 'uid'); + $row['author'] += rdf_rdfa_attributes($uid_mapping); // Annotates the td tag containing the number of replies. We add the // content attribute to ensure that only the comment count is used as // the value for 'num_replies'. Otherwise, other text such as a link // to the number of new comments could be included in the 'num_replies' // value. - $row['replies'] += rdf_rdfa_attributes($mapping['comment_count']); + $comment_count_mapping = $mapping_manager->getFieldMapping('node', $node->type, 'comment_count'); + $row['replies'] += rdf_rdfa_attributes($comment_count_mapping); $row['replies'] += array('content' => $node->comment_count); // If the node has no comments, we assume the node itself was modified // and apply 'changed' in addition to 'last_activity'. If there are // comments present, we cannot infer whether the node itself was // modified or a comment was posted, so we use only 'last_activity'. - $mapping_last_activity = rdf_rdfa_attributes($mapping['last_activity'], $node->last_activity); + $last_activity_mapping = $mapping_manager->getFieldMapping('node', $node->type, 'last_activity'); + $last_activity_attributes = rdf_rdfa_attributes($last_activity_mapping, $node->last_activity); if ($node->comment_count == 0) { - $mapping_changed = rdf_rdfa_attributes($mapping['changed'], $node->last_activity); - $mapping_last_activity['property'] = array_merge($mapping_last_activity['property'], $mapping_changed['property']); + $changed_mapping = $mapping_manager->getFieldMapping('node', $node->type, 'changed'); + $changed_attributes = rdf_rdfa_attributes($changed_mapping, $node->last_activity); + $last_activity_attributes['property'] = array_merge($last_activity_attributes['property'], $changed_attributes['property']); } - $row['last updated'] += $mapping_last_activity; + $row['last updated'] += $last_activity_attributes; // We need to add the about attribute on the tr tag to specify which // node the RDFa annotations above apply to. We move the content of diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install index ea89719..97dd542 100644 --- a/core/profiles/standard/standard.install +++ b/core/profiles/standard/standard.install @@ -266,7 +266,7 @@ function standard_install() { ), 'uid' => array( 'properties' => array('sioc:has_creator'), - 'type' => 'rel', + 'mapping_type' => 'rel', ), 'name' => array( 'properties' => array('foaf:name'), @@ -298,11 +298,11 @@ function standard_install() { // Save the RDF mappings for fields which are unique to articles. $field_image_mapping = array( 'properties' => array('og:image', 'rdfs:seeAlso'), - 'type' => 'rel', + 'mapping_type' => 'rel', ); $field_tags_mapping = array( 'properties' => array('dc:subject'), - 'type' => 'rel', + 'mapping_type' => 'rel', ); // Configure RDF mapping for field_image on Article bundle. $config = $rdf_mapping_manager->getFieldMappingConfig('node', 'article', 'field_image'); @@ -313,6 +313,48 @@ function standard_install() { $field_mapping = array_merge($config->get(), $field_tags_mapping); $config->setData($field_mapping)->save(); + // Save comment RDF mapping configuration for article. + $rdf_mapping_manager = drupal_container()->get('rdf.mapping_manager'); + // Save bundle mapping config. + $config = $rdf_mapping_manager->getBundleMappingConfig('comment', 'comment_node_article'); + $bundle_mapping = array_merge($config->get(), array('types' => array('sioc:Post', 'sioct:Comment'))); + $config->setData($bundle_mapping)->save(); + $comment_shared_field_mappings = array( + 'title' => array( + 'properties' => array('dc:title'), + ), + 'created' => array( + 'properties' => array('dc:date', 'dc:created'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'changed' => array( + 'properties' => array('dc:modified'), + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => 'date_iso8601', + ), + 'comment_body' => array( + 'properties' => array('content:encoded'), + ), + 'pid' => array( + 'properties' => array('sioc:reply_of'), + 'mapping_type' => 'rel', + ), + 'uid' => array( + 'properties' => array('sioc:has_creator'), + 'mapping_type' => 'rel', + ), + 'name' => array( + 'properties' => array('foaf:name'), + ), + ); + // Iterate over shared field mappings and save. + foreach ($comment_shared_field_mappings as $field_name => $field_mapping) { + $config = $rdf_mapping_manager->getFieldMappingConfig('comment', 'comment_node_article', $field_name); + $field_mapping = array_merge($config->get(), $field_mapping); + $config->setData($field_mapping)->save(); + } + // Configure RDF mapping for User bundle. $config = $rdf_mapping_manager->getBundleMappingConfig('user', 'user'); $bundle_mapping = array_merge($config->get(), array('types' => array('sioc:UserAccount'))); @@ -324,7 +366,7 @@ function standard_install() { $config->setData($field_mapping)->save(); // Configure RDF mapping for homepage field on User bundle. $config = $rdf_mapping_manager->getFieldMappingConfig('user', 'user', 'homepage'); - $field_mapping = array_merge($config->get(), array('properties' => array('foaf:page'), 'type' => 'rel')); + $field_mapping = array_merge($config->get(), array('properties' => array('foaf:page'), 'mapping_type' => 'rel')); $config->setData($field_mapping)->save(); // Configure RDF mapping for Tags bundle.