Issue #1869600 by linclark, scor, jesse.d: Refactor RDF mappings to be inline with the new Entity Field API.

8.0.x
Dries 2013-06-24 18:21:37 -04:00
parent 36df8e8784
commit b4655c58f6
60 changed files with 1594 additions and 2144 deletions

View File

@ -1196,8 +1196,6 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
/** /**
* Returns an ISO8601 formatted date based on the given date. * Returns an ISO8601 formatted date based on the given date.
* *
* Callback for use within hook_rdf_mapping() implementations.
*
* @param $date * @param $date
* A UNIX timestamp. * A UNIX timestamp.
* *

View File

@ -1797,48 +1797,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(). * Implements hook_file_download_access().
*/ */

View File

@ -0,0 +1,11 @@
id: node.forum
targetEntityType: node
bundle: forum
types:
- 'sioc:Post'
- 'sioct:BoardPost'
fieldMappings:
taxonomy_forums:
properties:
- 'sioc:has_container'
mapping_type: 'rel'

View File

@ -0,0 +1,6 @@
id: taxonomy_term.forums
targetEntityType: taxonomy_term
bundle: forums
types:
- 'sioc:Container'
- 'sioc:Forum'

View File

@ -1312,29 +1312,3 @@ function _forum_update_forum_index($nid) {
->execute(); ->execute();
} }
} }
/**
* Implements hook_rdf_mapping().
*/
function forum_rdf_mapping() {
return array(
array(
'type' => 'node',
'bundle' => 'forum',
'mapping' => array(
'rdftype' => array('sioc:Post', 'sioct:BoardPost'),
'taxonomy_forums' => array(
'predicates' => array('sioc:has_container'),
'type' => 'rel',
),
),
),
array(
'type' => 'taxonomy_term',
'bundle' => 'forums',
'mapping' => array(
'rdftype' => array('sioc:Container', 'sioc:Forum'),
),
),
);
}

View File

@ -1,45 +0,0 @@
<?php
/**
* @file
* Contains MappingSubscriber.
*/
namespace Drupal\rdf\EventSubscriber;
use Drupal\rdf\RdfMappingEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Default RDF mapping handling.
*/
class MappingSubscriber implements EventSubscriberInterface {
/**
* Stops event if incoming URI is a site schema URI.
*
* If the incoming URI is one of the site's own registered types, then
* mapping is unnecessary. Mapping is only necessary if the incoming type URI
* is from an external vocabulary.
*
* @param \Drupal\rdf\MapTypesFromInputEvent $event
* The mapping event.
*/
public function mapTypesFromInput(\Drupal\rdf\MapTypesFromInputEvent $event) {
$input_uris = $event->getInputUris();
$site_schema_types = $event->getSiteSchemaTypes();
foreach ($input_uris as $input_uri) {
if (isset($site_schema_types[$input_uri])) {
$event->setSiteSchemaUri($input_uri);
$event->stopPropagation();
}
}
}
/**
* Implements EventSubscriberInterface::getSubscribedEvents().
*/
static function getSubscribedEvents() {
$events[RdfMappingEvents::MAP_TYPES_FROM_INPUT] = 'mapTypesFromInput';
return $events;
}
}

View File

@ -1,91 +0,0 @@
<?php
/**
* @file
* Contains MapInputTypesEvent.
*/
namespace Drupal\rdf;
use Symfony\Component\EventDispatcher\Event;
/**
* Represents type mapping as event.
*/
class MapTypesFromInputEvent extends Event {
/**
* An array of incoming RDF type URIs.
*
* @var array
*/
protected $inputUris;
/**
* An array of entity_type/bundles, keyed by site schema type URI
*
* @var array
*/
protected $siteSchemaTypes;
/**
* The site schema type URI.
*
* @var string
*/
protected $siteSchemaUri;
/**
* Constructor.
*
* @param $input_uris
* An array of incoming RDF type URIs.
* @param $site_schema_types
* An array of entity_type/bundles, keyed by site schema type URI.
*/
public function __construct($input_uris, $site_schema_types) {
$this->inputUris = $input_uris;
$this->siteSchemaTypes = $site_schema_types;
$this->siteSchemaUri = FALSE;
}
/**
* Gets the input URI.
*
* @return array
* The array of incoming RDF type URIs.
*/
public function getInputUris() {
return $this->inputUris;
}
/**
* Gets the cache of internal site schema types.
*
* @return array
* The cached site schema type array.
*/
public function getSiteSchemaTypes() {
return $this->siteSchemaTypes;
}
/**
* Gets the site schema URI.
*
* @return string|bool
* The site schema type URI if set, FALSE if otherwise.
*/
public function getSiteSchemaUri() {
return $this->siteSchemaUri;
}
/**
* Sets the site schema URI.
*
* @param string $uri
* The site schema type URI.
*/
public function setSiteSchemaUri($uri) {
$this->siteSchemaUri = $uri;
}
}

View File

@ -0,0 +1,179 @@
<?php
/**
* @file
* Contains \Drupal\rdf\Plugin\Core\Entity\RdfMapping.
*/
namespace Drupal\rdf\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\Annotation\EntityType;
use Drupal\Core\Annotation\Translation;
use Drupal\rdf\RdfMappingInterface;
/**
* Config entity for working with RDF mappings.
*
* @EntityType(
* id = "rdf_mapping",
* label = @Translation("RDF mapping"),
* module = "rdf",
* controllers = {
* "storage" = "Drupal\Core\Config\Entity\ConfigStorageController"
* },
* config_prefix = "rdf.mapping",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid"
* }
* )
*/
class RdfMapping extends ConfigEntityBase implements RdfMappingInterface {
/**
* Unique ID for the config entity.
*
* @var string
*/
public $id;
/**
* UUID for the config entity.
*
* @var string
*/
public $uuid;
/**
* Entity type to be mapped.
*
* @var string
*/
public $targetEntityType;
/**
* Bundle to be mapped.
*
* @var string
*/
public $bundle;
/**
* The RDF type mapping for this bundle.
*
* @var array
*/
protected $types;
/**
* The mappings for fields on this bundle.
*
* @var array
*/
protected $fieldMappings;
/**
* {@inheritdoc}
*/
public function getPreparedBundleMapping() {
$types = array();
if (isset($this->types)) {
$types = $this->types;
}
return array('types' => $types);
}
/**
* {@inheritdoc}
*/
public function getBundleMapping() {
if (isset($this->types)) {
return array('types' => $this->types);
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function setBundleMapping(array $mapping) {
if (isset($mapping['types'])) {
$this->types = $mapping['types'];
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getPreparedFieldMapping($field_name) {
$field_mapping = array(
'properties' => NULL,
'datatype' => NULL,
'datatype_callback' => NULL,
'mapping_type' => NULL,
);
if (isset($this->fieldMappings[$field_name])) {
$field_mapping = array_merge($field_mapping, $this->fieldMappings[$field_name]);
}
return $field_mapping;
}
/**
* {@inheritdoc}
*/
public function getFieldMapping($field_name) {
if (isset($this->fieldMappings[$field_name])) {
return $this->fieldMappings[$field_name];
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function setFieldMapping($field_name, array $mapping = array()) {
$this->fieldMappings[$field_name] = $mapping;
return $this;
}
/**
* {@inheritdoc}
*/
public function id() {
return $this->targetEntityType . '.' . $this->bundle;
}
/**
* {@inheritdoc}
*/
public function save() {
// Build an ID if none is set.
if (empty($this->id)) {
$this->id = $this->id();
}
return parent::save();
}
/**
* {@inheritdoc}
*/
public function getExportProperties() {
$names = array(
'id',
'uuid',
'targetEntityType',
'bundle',
'types',
'fieldMappings',
);
$properties = array();
foreach ($names as $name) {
$properties[$name] = $this->get($name);
}
return $properties;
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @file
* Contains RdfConstants.
*/
namespace Drupal\rdf;
/**
* Defines constants for RDF terms.
*/
abstract class RdfConstants {
const RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
// RDF Schema terms.
const RDFS_CLASS = 'http://www.w3.org/2000/01/rdf-schema#class';
const RDFS_DOMAIN = 'http://www.w3.org/2000/01/rdf-schema#domain';
const RDFS_IS_DEFINED_BY = 'http://www.w3.org/2000/01/rdf-schema#isDefinedBy';
const RDFS_RANGE = 'http://www.w3.org/2000/01/rdf-schema#range';
const RDFS_SUB_CLASS_OF = 'http://www.w3.org/2000/01/rdf-schema#subClassOf';
// XSD datatypes.
const XSD_INTEGER = 'http://www.w3.org/2001/XMLSchema#integer';
const XSD_DOUBLE = 'http://www.w3.org/2001/XMLSchema#double';
const XSD_BOOLEAN = 'http://www.w3.org/2001/XMLSchema#boolean';
const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string';
}

View File

@ -1,29 +0,0 @@
<?php
/**
* @file
* Contains RdfMappingEvents.
*/
namespace Drupal\rdf;
/**
* Contains all events for mapping site schemas to external vocabularies.
*/
final class RdfMappingEvents {
/**
* Maps an array of incoming type URIs to a site schema URI.
*
* Modules can use this event to convert an RDF type from an externally
* defined vocabulary to a URI defined in the site's schema. From the site
* schema URI, the site can derive the Typed Data API ids, which can be used
* to create an entity.
*
* @see \Drupal\rdf\RdfMappingManager
*
* @var string
*/
const MAP_TYPES_FROM_INPUT = 'rdf.map_types_from_input';
}

View File

@ -1,13 +0,0 @@
<?php
/**
* @file
* Contains RdfMappingException.
*/
namespace Drupal\rdf;
/**
* Exception to use when no RDF mapping is found.
*/
class RdfMappingException extends \Exception { }

View File

@ -0,0 +1,110 @@
<?php
/**
* @file
* Contains \Drupal\rdf\RdfMappingInterface
*/
namespace Drupal\rdf;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
/**
* Provides an interface defining an RDF mapping entity.
*/
interface RdfMappingInterface extends ConfigEntityInterface {
/**
* Gets the mapping for the bundle-level data.
*
* The prepared bundle mapping should be used when outputting data in RDF
* serializations such as RDFa. In the prepared mapping, the mapping
* configuration's CURIE arrays are processed into CURIE strings suitable for
* output.
*
* @return array
* The bundle mapping.
*/
public function getPreparedBundleMapping();
/**
* Gets the mapping config for the bundle-level data.
*
* This function returns the bundle mapping as stored in config, which may
* contain CURIE arrays. If the mapping is needed for output in a
* serialization format, such as RDFa, then getPreparedBundleMapping() should
* be used instead.
*
* @return array|null
* The bundle mapping, or NULL if there is no mapping.
*/
public function getBundleMapping();
/**
* Sets the mapping config for the bundle-level data.
*
* This only sets bundle-level mappings, such as the RDF type. Mappings for
* a bundle's fields should be handled with setFieldMapping.
*
* Example usage:
* -Map the 'article' bundle to 'sioc:Post'.
* @code
* rdf_get_mapping('node', 'article')
* ->setBundleMapping(array(
* 'types' => array('sioc:Post'),
* ))
* ->save();
* @endcode
*
* @param array $mapping
* The bundle mapping.
*
* @return \Drupal\rdf\Plugin\Core\Entity\RdfMapping
* The RdfMapping object.
*/
public function setBundleMapping(array $mapping);
/**
* Gets the prepared mapping for a field.
*
* The prepared field mapping should be used when outputting data in RDF
* serializations such as RDFa. In the prepared mapping, the mapping
* configuration's CURIE arrays are processed into CURIE strings suitable for
* output.
*
* @param string $field_name
* The name of the field.
*
* @return array
* The prepared field mapping.
*/
public function getPreparedFieldMapping($field_name);
/**
* Gets the mapping config for a field.
*
* This function returns the field mapping as stored in config, which may
* contain CURIE arrays. If the mapping is needed for output in a
* serialization format, such as RDFa, then getPreparedFieldMapping() should
* be used instead.
*
* @param string $field_name
* The name of the field.
*
* @return array|null
* The field mapping config array, or NULL if there is no mapping.
*/
public function getFieldMapping($field_name);
/**
* Sets the mapping config for a field.
*
* @param string $field_name
* The name of the field.
* @param array $mapping
* The field mapping.
*
* @return \Drupal\rdf\Plugin\Core\Entity\RdfMapping
* The RdfMapping object.
*/
public function setFieldMapping($field_name, array $mapping = array());
}

View File

@ -1,101 +0,0 @@
<?php
/**
* @file
* Contains RdfMappingManager.
*/
namespace Drupal\rdf;
use ReflectionClass;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\rdf\MapTypesFromInputEvent;
use Drupal\rdf\RdfMappingEvents;
use Drupal\rdf\SiteSchema\BundleSchema;
use Drupal\rdf\SiteSchema\SiteSchema;
use Drupal\rdf\SiteSchema\SiteSchemaManager;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Manager for mapping internal and external schema terms.
*/
class RdfMappingManager {
/**
* The event dispatcher.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $dispatcher;
/**
* The site schema manager.
*
* @var \Drupal\rdf\SiteSchema\SiteSchemaManager
*/
protected $siteSchemaManager;
/**
* Constructor.
*
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
* The event dispatcher.
* @param \Drupal\rdf\SiteSchema\SiteSchemaManager $site_schema_manager
* The site schema manager.
*/
public function __construct(EventDispatcherInterface $dispatcher, SiteSchemaManager $site_schema_manager) {
$this->dispatcher = $dispatcher;
$this->siteSchemaManager = $site_schema_manager;
}
/**
* Convert an array of RDF type URIs to the corresponding TypedData IDs.
*
* @param array $input_rdf_types
* An array of URIs for the type.
*
* @return array
* An array containing entity_type and bundle.
*
* @throws \Drupal\rdf\RdfMappingException
*/
public function getTypedDataIdsFromTypeUris($input_rdf_types) {
// Get the cache of site schema types.
$site_schema_types = $this->siteSchemaManager->getTypes();
// Map the RDF type from the incoming data to an RDF type defined in the
// internal site schema.
$type_uri = $this->mapTypesFromInput($input_rdf_types);
// If no site schema URI has been determined, then it's impossible to know
// what entity type to create. Throw an exception.
if ($type_uri == FALSE) {
throw new RdfMappingException(sprintf('No mapping to a site schema type URI found for incoming types (%s).', implode(',', $input_rdf_types)));
}
// Use the mapped RDF type URI to get the TypedData API ids the rest of the
// system uses (entity type and bundle).
return $site_schema_types[$type_uri];
}
/**
* Map an array of incoming URIs to an internal site schema URI.
*
* @param array $input_rdf_types
* An array of RDF type URIs.
*
* @return string
* The corresponding site schema type URI.
*/
protected function mapTypesFromInput($input_rdf_types) {
// Create the event using the array of incoming RDF type URIs and the cache
// of internal site schema URIs.
$site_schema_types = $this->siteSchemaManager->getTypes();
$mapping_event = new MapTypesFromInputEvent($input_rdf_types, $site_schema_types);
// Allow other modules to map the incoming type URIs to an internal site
// schema type URI. For example, a content deployment module could take
// URIs from the staging site's schema and map them to the corresponding
// URI in the live site's schema.
$this->dispatcher->dispatch(RdfMappingEvents::MAP_TYPES_FROM_INPUT, $mapping_event);
return $mapping_event->getSiteSchemaUri();
}
}

View File

@ -1,64 +0,0 @@
<?php
/**
* @file
* Contains BundleSchema.
*/
namespace Drupal\rdf\SiteSchema;
use Drupal\rdf\RdfConstants;
use Drupal\rdf\SiteSchema\EntitySchema;
/**
* Defines RDF terms corresponding to Drupal bundles.
*/
class BundleSchema extends EntitySchema {
/**
* The URI pattern for bundle site schema terms.
*
* @var string
*/
public static $uriPattern = '{entity_type}/{bundle}';
/**
* The bundle that this term identifies.
*
* @var string
*/
protected $bundle;
/**
* Constructor.
*
* @param \Drupal\rdf\SiteSchema\SiteSchema $site_schema
* The schema the term is defined in.
* @param string $entity_type
* The entity type.
* @param string $bundle
* The bundle.
*/
public function __construct($site_schema, $entity_type, $bundle) {
parent::__construct($site_schema, $entity_type);
$this->bundle = $bundle;
}
/**
* Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getUri().
*/
public function getUri() {
$path = str_replace(array('{entity_type}', '{bundle}'), array($this->entityType, $this->bundle), static::$uriPattern);
return $this->siteSchema->getUri() . '/' . $path;
}
/**
* Overrides \Drupal\rdf\SiteSchema\SchemaTermBase::getProperties().
*/
public function getProperties() {
$properties = parent::getProperties();
$properties[RdfConstants::RDFS_SUB_CLASS_OF] = $this->siteSchema->entity($this->entityType)->getUri();
return $properties;
}
}

View File

@ -1,73 +0,0 @@
<?php
/**
* @file
* Contains EntitySchema.
*/
namespace Drupal\rdf\SiteSchema;
use Drupal\rdf\RdfConstants;
use Drupal\rdf\SiteSchema\SchemaTermBase;
/**
* Defines RDF terms corresponding to Drupal entity types.
*/
class EntitySchema extends SchemaTermBase {
/**
* The URI pattern for entity site schema terms.
*
* @var string
*/
public static $uriPattern = '{entity_type}';
/**
* The entity type that this term identifies.
*
* @var string
*/
protected $entityType;
/**
* Constructor.
*
* @param \Drupal\rdf\SiteSchema\SiteSchema $site_schema
* The schema the term is defined in.
* @param string $entity_type
* The entity type.
*/
public function __construct($site_schema, $entity_type) {
parent::__construct($site_schema);
$this->entityType = $entity_type;
}
/**
* Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getGraph().
*
* @todo Loop through all fields and add their RDF descriptions.
*/
public function getGraph() {
$graph = array();
$graph[$this->getUri()] = $this->getProperties();
return $graph;
}
/**
* Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getUri().
*/
public function getUri() {
$path = str_replace('{entity_type}', $this->entityType , static::$uriPattern);
return $this->siteSchema->getUri() . '/' . $path;
}
/**
* Overrides \Drupal\rdf\SiteSchema\SchemaTermBase::getProperties().
*/
public function getProperties() {
$properties = parent::getProperties();
$properties[RdfConstants::RDF_TYPE] = RdfConstants::RDFS_CLASS;
return $properties;
}
}

View File

@ -1,50 +0,0 @@
<?php
/**
* @file
* Contains SchemaTermBase.
*/
namespace Drupal\rdf\SiteSchema;
use Drupal\rdf\RdfConstants;
/**
* Base class to define an RDF term in a schema.
*/
abstract class SchemaTermBase implements SchemaTermInterface {
/**
* The URI pattern for this type of site schema term.
*
* @var string
*/
public static $uriPattern;
/**
* The schema in which this term is defined.
*
* @var \Drupal\rdf\SiteSchema\SiteSchema
*/
protected $siteSchema;
/**
* Constructor.
*
* @param \Drupal\rdf\SiteSchema\SiteSchema $site_schema
* The namespace.
*/
public function __construct($site_schema) {
$this->siteSchema = $site_schema;
}
/**
* Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getProperties().
*/
public function getProperties() {
return array(
RdfConstants::RDFS_IS_DEFINED_BY => $this->siteSchema->getUri(),
);
}
}

View File

@ -1,44 +0,0 @@
<?php
/**
* @file
* Contains SchemaTermInterface.
*/
namespace Drupal\rdf\SiteSchema;
interface SchemaTermInterface {
/**
* Get the full graph of terms and properties to display.
*
* When an RDF term URI is dereferenced, it usually contains a description of
* the term in RDF. To make it easier to use this description, include
* information about all related terms. For example, when viewing the RDF
* description for the RDF class which corresponds to a Drupal bundle, data
* about its fields would also be included.
*
* @return array
* An array of terms and their properties, keyed by term URI.
*/
public function getGraph();
/**
* Get the term properties.
*
* @return array
* An array of properties for this term, keyed by URI.
*/
public function getProperties();
/**
* Get the URI of the term.
*
* Implementations of this method will use the URI patterns defined in
* $uriPattern static variables and replace placeholders with actual values.
*
* @return string
* The URI of the term.
*/
public function getUri();
}

View File

@ -1,90 +0,0 @@
<?php
/**
* @file
* Contains SiteSchema.
*/
namespace Drupal\rdf\SiteSchema;
use Drupal\rdf\SiteSchema\BundleSchema;
use Drupal\rdf\SiteSchema\EntitySchema;
/**
* Defines a site-generated schema.
*/
class SiteSchema {
// Site schema paths. There are only two site schemas provided by core, which
// are not intended to be extensible. If a site wants to use external
// vocabulary terms, the appropriate way to do this is to use the RDF mapping
// system.
const CONTENT_DEPLOYMENT = 'site-schema/content-deployment/';
const SYNDICATION = 'site-schema/syndication/';
/**
* The relative base path of the instantiated schema.
*
* @var string
*/
protected $schemaPath;
/**
* Constructor.
*
* @param string $schema_path
* The schema path constant, used to determine which schema to instantiate.
*
* @throws \UnexpectedValueException
*/
public function __construct($schema_path) {
$valid_paths = array(self::CONTENT_DEPLOYMENT, self::SYNDICATION);
if (!in_array($schema_path, $valid_paths)) {
throw new \UnexpectedValueException(sprintf('%s is not a valid site schema path. Schema path must be one of %s.'), $schema_path, implode(', ', $valid_paths));
}
$this->schemaPath = $schema_path;
}
/**
* Get an entity's term definition in this vocabulary.
*/
public function entity($entity_type) {
return new EntitySchema($this, $entity_type);
}
/**
* Get a bundle's term definition in this vocabulary.
*/
public function bundle($entity_type, $bundle) {
return new BundleSchema($this, $entity_type, $bundle);
}
/**
* Get the URI of the schema.
*
* @return string
* The URI of the schema.
*/
public function getUri() {
return url($this->schemaPath, array('absolute' => TRUE));
}
/**
* Get the relative base path of the schema.
*/
public function getPath() {
return $this->schemaPath;
}
/**
* Get the routes for the types of terms defined in this schema.
*
* @return array
* An array of route patterns, keyed by controller method name.
*/
public function getRoutes() {
return array(
'bundle' => $this->schemaPath . BundleSchema::$uriPattern,
);
}
}

View File

@ -1,91 +0,0 @@
<?php
/**
* @file
* Contains SiteSchemaManager.
*/
namespace Drupal\rdf\SiteSchema;
use ReflectionClass;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\rdf\SiteSchema\SiteSchema;
use Drupal\rdf\SiteSchema\BundleSchema;
class SiteSchemaManager {
/**
* @var \Drupal\Core\Cache\CacheBackendInterface;
*/
protected $cache;
/**
* Constructor.
*/
public function __construct(CacheBackendInterface $cache) {
$this->cache = $cache;
$this->siteSchemas = array(
SiteSchema::CONTENT_DEPLOYMENT => new SiteSchema(SiteSchema::CONTENT_DEPLOYMENT),
SiteSchema::SYNDICATION => new SiteSchema(SiteSchema::SYNDICATION),
);
}
/**
* Writes the cache of site schema types.
*/
public function writeCache() {
$data = array();
// Type URIs correspond to bundles. Iterate through the bundles to get the
// URI and data for them.
$entity_info = entity_get_info();
foreach (entity_get_bundles() as $entity_type => $bundles) {
// Only content entities are supported currently.
// @todo Consider supporting config entities.
$entity_type_info = $entity_info[$entity_type];
$reflection = new ReflectionClass($entity_type_info['class']);
if ($reflection->implementsInterface('\Drupal\Core\Config\Entity\ConfigEntityInterface')) {
continue;
}
foreach ($bundles as $bundle => $bundle_info) {
// Get a type URI for the bundle in each of the defined schemas.
foreach ($this->siteSchemas as $schema) {
$bundle_uri = $schema->bundle($entity_type, $bundle)->getUri();
$data[$bundle_uri] = array(
'entity_type' => $entity_type,
'bundle' => $bundle,
);
}
}
}
// These URIs only change when entity info changes, so cache it permanently
// and only clear it when entity_info is cleared.
$this->cache->set('rdf:site_schema:types', $data, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
}
public function getSchemas() {
return $this->siteSchemas;
}
public function getSchema($schema_path) {
return $this->siteSchemas[$schema_path];
}
/**
* Get the array of site schema types.
*
* @return array
* An array of typed data ids (entity_type and bundle) keyed by
* corresponding site schema URI.
*/
public function getTypes() {
$cid = 'rdf:site_schema:types';
$cache = $this->cache->get($cid);
if (!$cache) {
$this->writeCache();
$cache = $this->cache->get($cid);
}
return $cache->data;
}
}

View File

@ -2,7 +2,7 @@
/** /**
* @file * @file
* Contains Drupal\rdf\Tests\CommentAttributesTest. * Contains \Drupal\rdf\Tests\CommentAttributesTest.
*/ */
namespace Drupal\rdf\Tests; namespace Drupal\rdf\Tests;
@ -48,6 +48,59 @@ class CommentAttributesTest extends CommentTestBase {
// Prepares commonly used URIs. // Prepares commonly used URIs.
$this->base_uri = url('<front>', array('absolute' => TRUE)); $this->base_uri = url('<front>', array('absolute' => TRUE));
$this->node_uri = url('node/' . $this->node->nid, array('absolute' => TRUE)); $this->node_uri = url('node/' . $this->node->nid, array('absolute' => TRUE));
// Set relation between node and comment.
$article_mapping = rdf_get_mapping('node', 'article');
$comment_count_mapping = array(
'properties' => array('sioc:num_replies'),
'datatype' => 'xsd:integer',
);
$article_mapping->setFieldMapping('comment_count', $comment_count_mapping)->save();
// Save user mapping.
$user_mapping = rdf_get_mapping('user', 'user');
$username_mapping = array(
'properties' => array('foaf:name'),
);
$user_mapping->setFieldMapping('name', $username_mapping)->save();
$user_mapping->setFieldMapping('homepage', array('properties' => array('foaf:page'), 'mapping_type' => 'rel'))->save();
// Save comment mapping.
$mapping = rdf_get_mapping('comment', 'comment_node_article');
$mapping->setBundleMapping(array('types' => array('sioc:Post', 'sioct:Comment')))->save();
$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 ($field_mappings as $field_name => $field_mapping) {
$mapping->setFieldMapping($field_name, $field_mapping)->save();
}
} }
/** /**
@ -274,6 +327,9 @@ class CommentAttributesTest extends CommentTestBase {
* array of values to set contact info. * array of values to set contact info.
* @param $pid * @param $pid
* Comment id of the parent comment in a thread. * Comment id of the parent comment in a thread.
*
* @return \Drupal\comment\Plugin\Core\Entity\Comment
* The saved comment.
*/ */
function saveComment($nid, $uid, $contact = NULL, $pid = 0) { function saveComment($nid, $uid, $contact = NULL, $pid = 0) {
$values = array( $values = array(
@ -292,5 +348,5 @@ class CommentAttributesTest extends CommentTestBase {
$comment = entity_create('comment', $values); $comment = entity_create('comment', $values);
$comment->save(); $comment->save();
return $comment; return $comment;
} }
} }

View File

@ -7,19 +7,19 @@
namespace Drupal\rdf\Tests; namespace Drupal\rdf\Tests;
use Drupal\simpletest\WebTestBase; use Drupal\simpletest\DrupalUnitTestBase;
/** /**
* Tests the RDF mapping CRUD functions. * Tests the RDF mapping CRUD functions.
*/ */
class CrudTest extends WebTestBase { class CrudTest extends DrupalUnitTestBase {
/** /**
* Modules to enable. * Modules to enable.
* *
* @var array * @var array
*/ */
public static $modules = array('rdf', 'rdf_test'); public static $modules = array('entity_test', 'rdf', 'system');
public static function getInfo() { public static function getInfo() {
return array( return array(
@ -29,57 +29,78 @@ class CrudTest extends WebTestBase {
); );
} }
public function setUp() {
parent::setUp();
$this->prefix = 'rdf.mapping';
$this->entity_type = $this->bundle = 'entity_test';
}
/** /**
* Tests inserting, loading, updating, and deleting RDF mappings. * Tests creation of RDF mapping.
*/ */
function testCRUD() { function testMappingCreation() {
// Verify loading of a default mapping. $mapping_config_name = "{$this->prefix}.{$this->entity_type}.{$this->bundle}";
$mapping = _rdf_mapping_load('entity_test', 'entity_test');
$this->assertTrue(count($mapping), 'Default mapping was found.');
// Verify saving a mapping. // Save bundle mapping config.
rdf_get_mapping($this->entity_type, $this->bundle)->save();
// Test that config file was saved.
$mapping_config = config_get_storage_names_with_prefix('rdf.mapping');
$this->assertTrue(in_array($mapping_config_name, $mapping_config), 'Rdf mapping config saved.');
}
/**
* Test the handling of bundle mappings.
*/
function testBundleMapping() {
// Test that the bundle mapping can be saved.
$types = array('sioc:Post', 'foaf:Document');
rdf_get_mapping($this->entity_type, $this->bundle)
->setBundleMapping(array('types' => $types))
->save();
$bundle_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
->getBundleMapping();
$this->assertEqual($types, $bundle_mapping['types'], 'Bundle mapping saved.');
// Test that the bundle mapping can be edited.
$types = array('schema:BlogPosting');
rdf_get_mapping($this->entity_type, $this->bundle)
->setBundleMapping(array('types' => $types))
->save();
$bundle_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
->getBundleMapping();
$this->assertEqual($types, $bundle_mapping['types'], 'Bundle mapping updated.');
}
/**
* Test the handling of field mappings.
*/
function testFieldMapping() {
$field_name = 'created';
// Test that the field mapping can be saved.
$mapping = array( $mapping = array(
'type' => 'crud_test_entity', 'properties' => array('dc:created'),
'bundle' => 'crud_test_bundle', 'datatype' => 'xsd:dateTime',
'mapping' => array( 'datatype_callback' => 'date_iso8601',
'rdftype' => array('sioc:Post'),
'title' => array(
'predicates' => array('dc:title'),
),
'uid' => array(
'predicates' => array('sioc:has_creator', 'dc:creator'),
'type' => 'rel',
),
),
); );
$this->assertTrue(rdf_mapping_save($mapping) === SAVED_NEW, 'Mapping was saved.'); rdf_get_mapping($this->entity_type, $this->bundle)
->setFieldMapping($field_name, $mapping)
->save();
$field_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
->getFieldMapping($field_name);
$this->assertEqual($mapping, $field_mapping, 'Field mapping saved.');
// Read the raw record from the {rdf_mapping} table. // Test that the field mapping can be edited.
$result = db_query('SELECT * FROM {rdf_mapping} WHERE type = :type AND bundle = :bundle', array(':type' => $mapping['type'], ':bundle' => $mapping['bundle'])); $mapping = array(
$stored_mapping = $result->fetchAssoc(); 'properties' => array('dc:date'),
$stored_mapping['mapping'] = unserialize($stored_mapping['mapping']); 'datatype' => 'foo:bar',
$this->assertEqual($mapping, $stored_mapping, 'Mapping was stored properly in the {rdf_mapping} table.'); 'datatype_callback' => 'date_iso8601',
// Verify loading of saved mapping.
$this->assertEqual($mapping['mapping'], _rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Saved mapping loaded successfully.');
// Verify updating of mapping.
$mapping['mapping']['title'] = array(
'predicates' => array('dc2:bar2'),
); );
$this->assertTrue(rdf_mapping_save($mapping) === SAVED_UPDATED, 'Mapping was updated.'); rdf_get_mapping($this->entity_type, $this->bundle)
->setFieldMapping($field_name, $mapping)
// Read the raw record from the {rdf_mapping} table. ->save();
$result = db_query('SELECT * FROM {rdf_mapping} WHERE type = :type AND bundle = :bundle', array(':type' => $mapping['type'], ':bundle' => $mapping['bundle'])); $field_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
$stored_mapping = $result->fetchAssoc(); ->getFieldMapping($field_name);
$stored_mapping['mapping'] = unserialize($stored_mapping['mapping']); $this->assertEqual($mapping, $field_mapping, 'Field mapping updated.');
$this->assertEqual($mapping, $stored_mapping, 'Updated mapping was stored properly in the {rdf_mapping} table.');
// Verify loading of saved mapping.
$this->assertEqual($mapping['mapping'], _rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Saved mapping loaded successfully.');
// Verify deleting of mapping.
$this->assertTrue(rdf_mapping_delete($mapping['type'], $mapping['bundle']), 'Mapping was deleted.');
$this->assertFalse(_rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Deleted mapping is no longer found in the database.');
} }
} }

View File

@ -0,0 +1,90 @@
<?php
/**
* @file
* Contains \Drupal\rdf\Tests\FileFieldAttributesTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\Core\Language\Language;
use Drupal\file\Tests\FileFieldTestBase;
/**
* Tests RDFa markup generation for File fields.
*/
class FileFieldAttributesTest extends FileFieldTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'file');
public static function getInfo() {
return array(
'name' => 'RDFa markup for files',
'description' => 'Tests the RDFa markup of filefields.',
'group' => 'RDF',
);
}
public function setUp() {
parent::setUp();
$this->fieldName = strtolower($this->randomName());
$type_name = 'article';
$this->createFileField($this->fieldName, $type_name);
// Set the teaser display to show this field.
entity_get_display('node', 'article', 'teaser')
->setComponent($this->fieldName, array('type' => 'file_default'))
->save();
// Set the RDF mapping for the new field.
$mapping = rdf_get_mapping('node', 'article');
$mapping->setFieldMapping($this->fieldName, array('properties' => array('rdfs:seeAlso'), 'mapping_type' => 'rel'))->save();
$test_file = $this->getTestFile('text');
// Create a new node with the uploaded file.
$nid = $this->uploadNodeFile($test_file, $this->fieldName, $type_name);
$this->node = node_load($nid, TRUE);
$this->file = file_load($this->node->{$this->fieldName}[Language::LANGCODE_NOT_SPECIFIED][0]['fid']);
}
/**
* Tests if file fields in teasers have correct resources.
*
* Ensure that file fields have the correct resource as the object in RDFa
* when displayed as a teaser.
*/
function testNodeTeaser() {
$node = $this->node;
$node_file = $this->file;
// Render the teaser.
$node_render_array = entity_view_multiple(array($node), 'teaser');
$html = drupal_render($node_render_array);
// Parses front page where the node is displayed in its teaser form.
$parser = new \EasyRdf_Parser_Rdfa();
$graph = new \EasyRdf_Graph();
$base_uri = url('<front>', array('absolute' => TRUE));
$parser->parse($graph, $html, 'rdfa', $base_uri);
$node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
$file_uri = file_create_url($node_file->getFileUri());
// Node relation to attached file.
$expected_value = array(
'type' => 'uri',
'value' => $file_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://www.w3.org/2000/01/rdf-schema#seeAlso', $expected_value), 'Node to file relation found in RDF output (rdfs:seeAlso).');
$this->drupalGet('node');
}
}

View File

@ -19,7 +19,7 @@ class GetNamespacesTest extends WebTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('rdf', 'rdf_test'); public static $modules = array('rdf', 'rdf_test_namespaces');
public static function getInfo() { public static function getInfo() {
return array( return array(

View File

@ -19,7 +19,7 @@ class GetRdfNamespacesTest extends WebTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('rdf', 'rdf_test'); public static $modules = array('rdf', 'rdf_test_namespaces');
public static function getInfo() { public static function getInfo() {
return array( return array(

View File

@ -0,0 +1,104 @@
<?php
/**
* @file
* Contains \Drupal\rdf\Tests\ImageFieldAttributesTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\Core\Language\Language;
use Drupal\image\Tests\ImageFieldTestBase;
use Drupal\rdf\Tests\RdfTestHelper;
/**
* Tests RDFa markup generation for image fields.
*/
class ImageFieldAttributesTest extends ImageFieldTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'image');
public static function getInfo() {
return array(
'name' => 'RDFa markup for imagefield',
'description' => 'Tests the RDFa markup of imagefields.',
'group' => 'RDF',
);
}
public function setUp() {
parent::setUp();
$this->fieldName = 'field_image';
// Create the image field.
$this->createImageField($this->fieldName, 'article');
// Set the RDF mapping for the new field.
rdf_get_mapping('node', 'article')
->setFieldMapping($this->fieldName, array(
'properties' => array('og:image'),
'mapping_type' => 'rel',
))
->save();
// Get the test image that simpletest provides.
$image = current($this->drupalGetTestFiles('image'));
// Save a node with the image.
$nid = $this->uploadNodeImage($image, $this->fieldName, 'article');
$this->node = node_load($nid);
$this->file = file_load($this->node->{$this->fieldName}[Language::LANGCODE_NOT_SPECIFIED][0]['fid']);
}
/**
* Tests that image fields in teasers have correct resources.
*/
function testNodeTeaser() {
$node = $this->node;
$node_file = $this->file;
// Set the display options for the teaser.
$display_options = array(
'type' => 'image',
'settings' => array('image_style' => 'medium', 'image_link' => 'content'),
);
$display = entity_get_display('node', 'article', 'teaser');
$display->setComponent($this->fieldName, $display_options)
->save();
// Render the teaser.
$node_render_array = node_view($node, 'teaser');
$html = drupal_render($node_render_array);
// Parse the teaser.
$parser = new \EasyRdf_Parser_Rdfa();
$graph = new \EasyRdf_Graph();
$base_uri = url('<front>', array('absolute' => TRUE));
$parser->parse($graph, $html, 'rdfa', $base_uri);
// Construct the node and image URIs for testing.
$node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
$image_uri = image_style_url('medium', $node_file->getFileUri());
// Test relations from node to image.
$expected_value = array(
'type' => 'uri',
'value' => $image_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://ogp.me/ns#image', $expected_value), 'Node to file relation found in RDF output (og:image).');
// Test image type.
$expected_value = array(
'type' => 'uri',
'value' => 'http://xmlns.com/foaf/0.1/Image',
);
$this->assertTrue($graph->hasProperty($image_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Image type found in RDF output (foaf:Image).');
}
}

View File

@ -1,135 +0,0 @@
<?php
/**
* @file
* Contains Drupal\rdf\Tests\MappingDefinitionTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\node\Tests\NodeTestBase;
/**
* Tests the RDF mapping definition functionality.
*/
class MappingDefinitionTest extends NodeTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'rdf_test');
public static function getInfo() {
return array(
'name' => 'RDF mapping definition functionality',
'description' => 'Tests that RDF definitions are properly attached to entities.',
'group' => 'RDF',
);
}
function setUp() {
parent::setUp();
// NodeTestBase creates page content type for us.
// Defines RDF mapping for page content type.
$page_rdf_mapping = array(
'type' => 'node',
'bundle' => 'page',
'mapping' => array(
'rdftype' => array('foaf:DocumentBar'),
'body' => array(
'predicates' => array('dc:dummy-property'),
),
'created' => array(
'predicates' => array('dc:dummy-date'),
'callback' => 'date_iso8601_foo',
'datatype' => 'xsd:dateTimeFoo',
),
),
);
rdf_mapping_save($page_rdf_mapping);
}
/**
* Creates a node of type page and tests whether the RDF mapping is
* attached to the node.
*/
function testMappingDefinitionPage() {
$node = $this->drupalCreateNode(array('type' => 'page'));
$expected_mapping = array(
'rdftype' => array('foaf:DocumentBar'),
'title' => array(
'predicates' => array('dc:title'),
),
'body' => array(
'predicates' => array('dc:dummy-property'),
),
'created' => array(
'predicates' => array('dc:dummy-date'),
'callback' => 'date_iso8601_foo',
'datatype' => 'xsd:dateTimeFoo',
),
);
$node = node_load($node->nid);
foreach ($expected_mapping as $key => $mapping) {
$this->assertEqual($node->rdf_mapping[$key], $mapping, format_string('Expected mapping found for @key.', array('@key' => $key)));
}
}
/**
* 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.
*/
function testMappingDefinitionTestBundleInstall() {
$this->drupalCreateContentType(array('type' => 'test_bundle_hook_install'));
$node = $this->drupalCreateNode(array('type' => 'test_bundle_hook_install'));
$expected_mapping = array(
'rdftype' => array('foo:mapping_install1', 'bar:mapping_install2'),
'title' => array(
'predicates' => array('dc:title'),
),
'body' => array(
'predicates' => array('content:encoded'),
),
'created' => array(
'predicates' => array('dc:date', 'dc:created'),
'callback' => 'date_iso8601',
'datatype' => 'xsd:dateTime',
),
);
$node = node_load($node->nid);
foreach ($expected_mapping as $key => $mapping) {
$this->assertEqual($node->rdf_mapping[$key], $mapping, format_string('Expected mapping found for @key.', array('@key' => $key)));
}
}
/**
* Creates a random content type and node and ensures the default mapping for
* the node is being used.
*/
function testMappingDefinitionRandomContentType() {
$type = $this->drupalCreateContentType();
$node = $this->drupalCreateNode(array('type' => $type->type));
$expected_mapping = array(
'rdftype' => array('sioc:Item', 'foaf:Document'),
'title' => array(
'predicates' => array('dc:title'),
),
'body' => array(
'predicates' => array('content:encoded'),
),
'created' => array(
'predicates' => array('dc:date', 'dc:created'),
'callback' => 'date_iso8601',
'datatype' => 'xsd:dateTime',
),
);
$node = node_load($node->nid);
foreach ($expected_mapping as $key => $mapping) {
$this->assertEqual($node->rdf_mapping[$key], $mapping, format_string('Expected mapping found for @key.', array('@key' => $key)));
}
}
}

View File

@ -1,50 +0,0 @@
<?php
/**
* @file
* Definition of Drupal\rdf\Tests\MappingHookTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests the RDF mapping hook.
*/
class MappingHookTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'rdf_test', 'entity_test');
public static function getInfo() {
return array(
'name' => 'RDF mapping hook',
'description' => 'Test hook_rdf_mapping().',
'group' => 'RDF',
);
}
/**
* Tests that hook_rdf_mapping() correctly returns and processes mapping.
*/
function testMapping() {
// Test that the mapping is returned correctly by the hook.
$mapping = rdf_mapping_load('entity_test', 'entity_test');
$this->assertIdentical($mapping['rdftype'], array('sioc:Post'), 'Mapping for rdftype is sioc:Post.');
$this->assertIdentical($mapping['title'], array('predicates' => array('dc:title')), 'Mapping for title is dc:title.');
$this->assertIdentical($mapping['created'], array(
'predicates' => array('dc:created'),
'datatype' => 'xsd:dateTime',
'callback' => 'date_iso8601',
), 'Mapping for created is dc:created with datatype xsd:dateTime and callback date_iso8601.');
$this->assertIdentical($mapping['uid'], array('predicates' => array('sioc:has_creator', 'dc:creator'), 'type' => 'rel'), 'Mapping for uid is sioc:has_creator and dc:creator, and type is rel.');
$mapping = rdf_mapping_load('entity_test', 'test_bundle_no_mapping');
$this->assertEqual($mapping, array(), 'Empty array returned when an entity type, bundle pair has no mapping.');
}
}

View File

@ -2,7 +2,7 @@
/** /**
* @file * @file
* Contains Drupal\rdf\Tests\NodeAttributesTest. * Contains \Drupal\rdf\Tests\NodeAttributesTest.
*/ */
namespace Drupal\rdf\Tests; namespace Drupal\rdf\Tests;
@ -29,6 +29,24 @@ class NodeAttributesTest extends NodeTestBase {
); );
} }
public function setUp() {
parent::setUp();
rdf_get_mapping('node', 'article')
->setBundleMapping(array(
'types' => array('sioc:Item', 'foaf:Document'),
))
->setFieldMapping('title', array(
'properties' => array('dc:title'),
))
->setFieldMapping('created', array(
'properties' => array('dc:date', 'dc:created'),
'datatype' => 'xsd:dateTime',
'datatype_callback' => 'date_iso8601',
))
->save();
}
/** /**
* Creates a node of type article and tests its RDFa markup. * Creates a node of type article and tests its RDFa markup.
*/ */

View File

@ -1,63 +0,0 @@
<?php
/**
* @file
* Contains RdfMappingEventTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\rdf\RdfMappingManager;
use Drupal\rdf\EventSubscriber\MappingSubscriber;
use Drupal\rdf_test_mapping\EventSubscriber\TestMappingSubscriber;
use Drupal\rdf\SiteSchema\BundleSchema;
use Drupal\rdf\SiteSchema\SiteSchema;
use Drupal\rdf\SiteSchema\SiteSchemaManager;
use Drupal\simpletest\WebTestBase;
use Symfony\Component\EventDispatcher\EventDispatcher;
/**
* Test the RDF mapping events.
*
* This is implemented as a WebTest because it depends on entity info.
*/
class RdfMappingEventTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'rdf_test_mapping', 'entity_test');
public static function getInfo() {
return array(
'name' => 'RDF mapping tests',
'description' => 'Tests the event-based RDF mapping system.',
'group' => 'RDF',
);
}
/**
* Test that other modules can define incoming type mappings.
*/
public function testMapInputType() {
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new MappingSubscriber());
$dispatcher->addSubscriber(new TestMappingSubscriber());
$site_schema_manager = new SiteSchemaManager($this->container->get('cache.cache'));
$mapping_manager = new RdfMappingManager($dispatcher, $site_schema_manager);
// Test that a site schema URI is mapped to itself. This is the default
// behavior.
$schema = new SiteSchema(SiteSchema::CONTENT_DEPLOYMENT);
$bundle_schema = $schema->bundle('entity_test', 'entity_test');
$site_schema_type = $bundle_schema->getUri();
$typed_data_ids = $mapping_manager->getTypedDataIdsFromTypeUris(array($site_schema_type));
$this->assertTrue($typed_data_ids['bundle'] == 'entity_test', 'An internal site schema type URI is properly handled.');
// Test that a module can map an external URI to a site schema URI.
$typed_data_ids = $mapping_manager->getTypedDataIdsFromTypeUris(array(TestMappingSubscriber::STAGING_SITE_TYPE_URI));
$this->assertTrue($typed_data_ids['bundle'] == 'entity_test', 'Modules can map external type URIs to a site schema type.');
}
}

View File

@ -0,0 +1,122 @@
<?php
/**
* @file
* Contains \Drupal\rdf\Tests\RdfMappingUpgradePathTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\system\Tests\Upgrade\UpgradePathTestBase;
/**
* Tests the upgrade path of RDF mappings.
*/
class RdfMappingUpgradePathTest extends UpgradePathTestBase {
public static function getInfo() {
return array(
'name' => 'RDF mapping upgrade test',
'description' => 'Upgrade tests with RDF mapping data.',
'group' => 'RDF',
);
}
public function setUp() {
// Path to the database dump files.
$this->databaseDumpFiles = array(
drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz',
drupal_get_path('module', 'rdf') . '/tests/drupal-7.rdf.database.php',
);
parent::setUp();
}
/**
* Tests to see if RDF mappings were upgraded.
*/
public function testRdfMappingUpgrade() {
$this->assertTrue(db_table_exists('rdf_mapping'), 'RDF mapping table exists.');
$this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
$this->_testUnalteredMappingUpgrade();
$this->_testAlteredMappingUpgrade();
$this->_testReverseRelationUpgrade();
}
/**
* Helper function to test upgrade of unaltered mappings.
*/
protected function _testUnalteredMappingUpgrade() {
$config = rdf_get_mapping('node', 'page');
// Test bundle mapping.
$mapping = $config->getBundleMapping();
$expected_mapping = array(
'types' => array('foaf:Document'),
);
$this->assertEqual($mapping, $expected_mapping, 'Unaltered bundle mapping upgraded correctly.');
// Test field mapping - property.
$mapping = $config->getFieldMapping('title');
$expected_mapping = array(
'properties' => array('dc:title'),
);
$this->assertEqual($mapping, $expected_mapping, 'Unaltered field mapping upgraded correctly.');
// Test field mapping - property with datatype and callback.
$mapping = $config->getFieldMapping('created');
$expected_mapping = array(
'properties' => array('dc:date', 'dc:created'),
'datatype' => 'xsd:dateTime',
'datatype_callback' => 'date_iso8601',
);
$this->assertEqual($mapping, $expected_mapping, 'Unaltered field mapping with datatype and datatype callback upgraded correctly.');
// Test field mapping - rel.
$mapping = $config->getFieldMapping('uid');
$expected_mapping = array(
'properties' => array('sioc:has_creator'),
'mapping_type' => 'rel',
);
$this->assertEqual($mapping, $expected_mapping, 'Unaltered field mapping with rel mapping type upgraded correctly.');
}
/**
* Helper function to test upgrade of altered mappings.
*/
protected function _testAlteredMappingUpgrade() {
$config = rdf_get_mapping('node', 'article');
// Test bundle mapping.
$mapping = $config->getBundleMapping();
$expected_mapping = array(
'types' => array('foo:Type'),
);
$this->assertEqual($mapping, $expected_mapping, 'Overriden bundle mapping upgraded correctly.');
// Test field mapping.
$mapping = $config->getFieldMapping('field_image');
$expected_mapping = array(
'properties' => array('foo:image'),
);
$this->assertEqual($expected_mapping, $mapping, 'Overriden field mapping is upgraded correctly.');
// Test field mapping.
$mapping = $config->getFieldMapping('changed');
$expected_mapping = array();
$this->assertEqual($expected_mapping, $mapping, 'Empty field mapping from overriden mapping is upgraded correctly.');
}
/**
* Helper function to test handling of deprecated reverse relation mappings.
*/
protected function _testReverseRelationUpgrade() {
// Test field mapping - rev.
$config = rdf_get_mapping('node', 'rev_test');
$mapping = $config->getFieldMapping('field_rev');
$expected_mapping = array();
$this->assertEqual($mapping, $expected_mapping, 'Reverse relation mapping has been dropped.');
}
}

View File

@ -0,0 +1,134 @@
<?php
/**
* @file
* Contains \Drupal\rdf\Tests\RdfaAttributesTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\simpletest\DrupalUnitTestBase;
/**
* Tests RDFa attribute generation.
*/
class RdfaAttributesTest extends DrupalUnitTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf');
public static function getInfo() {
return array(
'name' => 'RDFa attributes',
'description' => 'Test RDFa attribute generation from RDF mapping.',
'group' => 'RDF',
);
}
/**
* Test attribute creation for mappings which use 'property'.
*/
function testProperty() {
$properties = array('dc:title');
$mapping = array('properties' => $properties);
$expected_attributes = array('property' => $properties);
$this->_testAttributes($expected_attributes, $mapping);
}
/**
* Test attribute creation for mappings which use 'datatype'.
*/
function testDatatype() {
$properties = array('foo:bar1');
$datatype = 'foo:bar1type';
$mapping = array(
'datatype' => $datatype,
'properties' => $properties,
);
$expected_attributes = array(
'datatype' => $datatype,
'property' => $properties,
);
$this->_testAttributes($expected_attributes, $mapping);
}
/**
* Test attribute creation for mappings which override human-readable content.
*/
function testDatatypeCallback() {
$properties = array('dc:created');
$datatype = 'xsd:dateTime';
$date = 1252750327;
$iso_date = date('c', $date);
$mapping = array(
'datatype' => $datatype,
'properties' => $properties,
'datatype_callback' => 'date_iso8601',
);
$expected_attributes = array(
'datatype' => $datatype,
'property' => $properties,
'content' => $iso_date,
);
$this->_testAttributes($expected_attributes, $mapping, $date);
}
/**
* Test attribute creation for mappings which use 'rel'.
*/
function testRel() {
$properties = array('sioc:has_creator', 'dc:creator');
$mapping = array(
'properties' => $properties,
'mapping_type' => 'rel',
);
$expected_attributes = array('rel' => $properties);
$this->_testAttributes($expected_attributes, $mapping);
}
/**
* Helper function to test attribute generation.
*
* @param array $expected_attributes
* The expected return of rdf_rdfa_attributes.
* @param array $field_mapping
* The field mapping to merge into the RDF mapping config.
* @param mixed $data
* The data to pass into the datatype callback, if specified.
*/
protected function _testAttributes($expected_attributes, $field_mapping, $data = NULL) {
$this->saveMapping($field_mapping);
$mapping = rdf_get_mapping('node', 'article')
->getPreparedFieldMapping('field_test');
$attributes = rdf_rdfa_attributes($mapping, $data);
ksort($expected_attributes);
ksort($attributes);
$this->assertEqual($expected_attributes, $attributes);
}
/**
* Helper function to save mapping using config system.
*
* @param array $field_mapping
* The field mapping.
*/
protected function saveMapping($field_mapping) {
rdf_get_mapping('node', 'article')
->setFieldMapping('field_test', $field_mapping)
->save();
}
}

View File

@ -1,254 +0,0 @@
<?php
/**
* @file
* Definition of Drupal\rdf\Tests\RdfaMarkupTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\Core\Language\Language;
use Drupal\simpletest\WebTestBase;
/**
* Tests RDFa markup generation.
*/
class RdfaMarkupTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'entity_test', 'rdf_test');
protected $profile = 'standard';
public static function getInfo() {
return array(
'name' => 'RDFa markup',
'description' => 'Test RDFa markup generation.',
'group' => 'RDF',
);
}
/**
* Tests rdf_rdfa_attributes().
*/
function testDrupalRdfaAttributes() {
// Same value as the one in the HTML tag (no callback function).
$expected_attributes = array(
'property' => array('dc:title'),
);
$mapping = rdf_mapping_load('entity_test', 'entity_test');
$attributes = rdf_rdfa_attributes($mapping['title']);
ksort($expected_attributes);
ksort($attributes);
$this->assertEqual($expected_attributes, $attributes);
// Value different from the one in the HTML tag (callback function).
$date = 1252750327;
$isoDate = date('c', $date);
$expected_attributes = array(
'datatype' => 'xsd:dateTime',
'property' => array('dc:created'),
'content' => $isoDate,
);
$mapping = rdf_mapping_load('entity_test', 'entity_test');
$attributes = rdf_rdfa_attributes($mapping['created'], $date);
ksort($expected_attributes);
ksort($attributes);
$this->assertEqual($expected_attributes, $attributes);
// Same value as the one in the HTML tag with datatype.
$expected_attributes = array(
'datatype' => 'foo:bar1type',
'property' => array('foo:bar1'),
);
$mapping = rdf_mapping_load('entity_test', 'entity_test');
$attributes = rdf_rdfa_attributes($mapping['foobar1']);
ksort($expected_attributes);
ksort($attributes);
$this->assertEqual($expected_attributes, $attributes);
// ObjectProperty mapping (rel).
$expected_attributes = array(
'rel' => array('sioc:has_creator', 'dc:creator'),
);
$mapping = rdf_mapping_load('entity_test', 'entity_test');
$attributes = rdf_rdfa_attributes($mapping['foobar_objproperty1']);
ksort($expected_attributes);
ksort($attributes);
$this->assertEqual($expected_attributes, $attributes);
// Inverse ObjectProperty mapping (rev).
$expected_attributes = array(
'rev' => array('sioc:reply_of'),
);
$mapping = rdf_mapping_load('entity_test', 'entity_test');
$attributes = rdf_rdfa_attributes($mapping['foobar_objproperty2']);
ksort($expected_attributes);
ksort($attributes);
$this->assertEqual($expected_attributes, $attributes);
}
/**
* Tests if file fields in teasers have correct resources.
*
* Ensure that file fields have the correct resource as the object in RDFa
* when displayed as a teaser.
*/
function testAttributesInMarkupFile() {
// Create a user to post the image.
$admin_user = $this->drupalCreateUser(array('edit own article content', 'revert article revisions', 'administer content types'));
$this->drupalLogin($admin_user);
$langcode = Language::LANGCODE_NOT_SPECIFIED;
$bundle_name = "article";
$field_name = 'file_test';
entity_create('field_entity', array(
'field_name' => $field_name,
'type' => 'file',
))->save();
entity_create('field_instance', array(
'field_name' => $field_name,
'entity_type' => 'node',
'bundle' => $bundle_name,
))->save();
entity_get_form_display('node', $bundle_name, 'default')
->setComponent($field_name, array(
'type' => 'file_generic',
))
->save();
entity_get_display('node', $bundle_name, 'teaser')
->setComponent($field_name, array(
'type' => 'file_default',
))
->save();
// Set the RDF mapping for the new field.
$rdf_mapping = rdf_mapping_load('node', $bundle_name);
$rdf_mapping += array($field_name => array('predicates' => array('rdfs:seeAlso'), 'type' => 'rel'));
$rdf_mapping_save = array('mapping' => $rdf_mapping, 'type' => 'node', 'bundle' => $bundle_name);
rdf_mapping_save($rdf_mapping_save);
// Get the test file that simpletest provides.
$file = current($this->drupalGetTestFiles('text'));
// Prepare image variables.
$image_field = "field_image";
// Get the test image that simpletest provides.
$image = current($this->drupalGetTestFiles('image'));
// Create an array for drupalPost with the field names as the keys and
// the URIs for the test files as the values.
$edit = array("files[" . $field_name . "_" . $langcode . "_0]" => drupal_realpath($file->uri),
"files[" . $image_field . "_" . $langcode . "_0]" => drupal_realpath($image->uri));
// Create node and save, then edit node to upload files.
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
// Prepares filenames for lookup in RDF graph.
$node = node_load($node->nid);
$node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
$file_uri = file_create_url(file_load($node->file_test['und'][0]['fid'])->getFileUri());
$image_uri = image_style_url('medium', file_load($node->field_image['und'][0]['fid'])->getFileUri());
$base_uri = url('<front>', array('absolute' => TRUE));
// Edits the node to add tags.
$tag1 = $this->randomName(8);
$tag2 = $this->randomName(8);
$edit = array();
$edit['field_tags[' . Language::LANGCODE_NOT_SPECIFIED . ']'] = "$tag1, $tag2";
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
$term_1_id = key(taxonomy_term_load_multiple_by_name($tag1));
$taxonomy_term_1_uri = url('taxonomy/term/' . $term_1_id, array('absolute' => TRUE));
$term_2_id = key(taxonomy_term_load_multiple_by_name($tag2));
$taxonomy_term_2_uri = url('taxonomy/term/' . $term_2_id, array('absolute' => TRUE));
// Parses front page where the node is displayed in its teaser form.
$parser = new \EasyRdf_Parser_Rdfa();
$graph = new \EasyRdf_Graph();
$parser->parse($graph, $this->drupalGet('node'), 'rdfa', $base_uri);
$rdf_output = $graph->toArray();
// Inspects RDF graph output.
// Node relations to attached file.
$expected_value = array(
'type' => 'uri',
'value' => $file_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://www.w3.org/2000/01/rdf-schema#seeAlso', $expected_value), 'Node to file relation found in RDF output (rdfs:seeAlso).');
// Node relations to attached image.
$expected_value = array(
'type' => 'uri',
'value' => $image_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://www.w3.org/2000/01/rdf-schema#seeAlso', $expected_value), 'Node to file relation found in RDF output (rdfs:seeAlso).');
$expected_value = array(
'type' => 'uri',
'value' => $image_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://ogp.me/ns#image', $expected_value), 'Node to file relation found in RDF output (og:image).');
// Image type.
$expected_value = array(
'type' => 'uri',
'value' => 'http://xmlns.com/foaf/0.1/Image',
);
$this->assertTrue($graph->hasProperty($image_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Image type found in RDF output (foaf:Image).');
// Node relations to taxonomy terms.
$expected_value = array(
'type' => 'uri',
'value' => $taxonomy_term_1_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
$expected_value = array(
'type' => 'uri',
'value' => $taxonomy_term_2_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
// Taxonomy terms triples.
// Term 1.
$expected_value = array(
'type' => 'uri',
'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
$expected_value = array(
'type' => 'literal',
'value' => $tag1,
'lang' => 'en',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
$expected_value = array(
'type' => 'literal',
'value' => $tag1,
'lang' => 'en',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/2004/02/skos/core#prefLabel', $expected_value), 'Taxonomy term name found in RDF output (skos:prefLabel).');
// Term 2.
$expected_value = array(
'type' => 'uri',
'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
$expected_value = array(
'type' => 'literal',
'value' => $tag2,
'lang' => 'en',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
$expected_value = array(
'type' => 'literal',
'value' => $tag2,
'lang' => 'en',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2004/02/skos/core#prefLabel', $expected_value), 'Taxonomy term name found in RDF output (skos:prefLabel).');
}
}

View File

@ -1,54 +0,0 @@
<?php
/**
* @file
* Contains SiteSchemaTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\rdf\SiteSchema\BundleSchema;
use Drupal\rdf\SiteSchema\SiteSchema;
use Drupal\simpletest\WebTestBase;
/**
* Tests for RDF namespaces XML serialization.
*/
class SiteSchemaTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'entity_test');
public static function getInfo() {
return array(
'name' => 'RDF site schema test',
'description' => 'Confirm that site-generated schemas are created for entity, bundle, field, and field property.',
'group' => 'RDF',
);
}
/**
* Tests site-generated schema.
*/
function testSiteSchema() {
$entity_type = $bundle = 'entity_test';
$schema = new SiteSchema(SiteSchema::SYNDICATION);
$schema_path = 'site-schema/syndication/';
// Bundle.
$bundle_schema = $schema->bundle($entity_type, $bundle);
$bundle_uri = url("$schema_path$entity_type/$bundle", array('absolute' => TRUE));
$bundle_properties = array(
'http://www.w3.org/2000/01/rdf-schema#isDefinedBy' => url($schema_path, array('absolute' => TRUE)),
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' => 'http://www.w3.org/2000/01/rdf-schema#class',
'http://www.w3.org/2000/01/rdf-schema#subClassOf' => url("$schema_path$entity_type", array('absolute' => TRUE)),
);
$this->assertEqual($bundle_schema->getUri(), $bundle_uri, 'Bundle term URI is generated correctly.');
$this->assertEqual($bundle_schema->getProperties(), $bundle_properties, 'Bundle term properties are generated correctly.');
}
}

View File

@ -2,7 +2,7 @@
/** /**
* @file * @file
* Contains Drupal\rdf\Tests\TaxonomyAttributesTest. * Contains \Drupal\rdf\Tests\TaxonomyAttributesTest.
*/ */
namespace Drupal\rdf\Tests; namespace Drupal\rdf\Tests;
@ -29,12 +29,25 @@ class TaxonomyAttributesTest extends TaxonomyTestBase {
); );
} }
function setUp() {
parent::setUp();
$this->vocabulary = $this->createVocabulary();
// RDF mapping - term bundle.
rdf_get_mapping('taxonomy_term', $this->vocabulary->id())
->setBundleMapping(array('types' => array('skos:Concept')))
->setFieldMapping('name', array(
'properties' => array('rdfs:label', 'skos:prefLabel'),
))
->save();
}
/** /**
* Creates a random term and ensures the RDF output is correct. * Creates a random term and ensures the RDF output is correct.
*/ */
function testTaxonomyTermRdfaAttributes() { function testTaxonomyTermRdfaAttributes() {
$vocabulary = $this->createVocabulary(); $term = $this->createTerm($this->vocabulary);
$term = $this->createTerm($vocabulary);
$term_uri = url('taxonomy/term/' . $term->id(), array('absolute' => TRUE)); $term_uri = url('taxonomy/term/' . $term->id(), array('absolute' => TRUE));
// Parses the term's page and checks that the RDF output is correct. // Parses the term's page and checks that the RDF output is correct.

View File

@ -0,0 +1,171 @@
<?php
/**
* @file
* Contains \Drupal\rdf\Tests\TaxonomyTermFieldAttributesTest.
*/
namespace Drupal\rdf\Tests;
use Drupal\Core\Language\Language;
use Drupal\rdf\Tests\RdfTestHelper;
use Drupal\taxonomy\Tests\TaxonomyTestBase;
/**
* Tests RDFa markup generation for taxonomy term fields.
*/
class TaxonomyTermFieldAttributesTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('rdf', 'field_test', 'file', 'image');
public static function getInfo() {
return array(
'name' => 'RDFa markup for taxonomy term fields',
'description' => 'Tests the RDFa markup of taxonomy term fields.',
'group' => 'RDF',
);
}
public function setUp() {
parent::setUp();
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer taxonomy'));
$this->drupalLogin($web_user);
$this->vocabulary = $this->createVocabulary();
// Setup a field and instance.
$this->fieldName = 'field_taxonomy_test';
// Create the field.
$this->createTaxonomyTermReferenceField($this->fieldName, $this->vocabulary);
// Set the RDF mapping for the new field.
rdf_get_mapping('node', 'article')
->setFieldMapping($this->fieldName, array(
'properties' => array('dc:subject'),
'mapping_type' => 'rel',
))
->save();
rdf_get_mapping('taxonomy_term', $this->vocabulary->id())
->setBundleMapping(array('types' => array('skos:Concept')))
->setFieldMapping('name', array('properties' => array('rdfs:label')))
->save();
}
/**
* Tests if file fields in teasers have correct resources.
*
* Ensure that file fields have the correct resource as the object in RDFa
* when displayed as a teaser.
*/
function testNodeTeaser() {
// Set the teaser display to show this field.
entity_get_display('node', 'article', 'teaser')
->setComponent($this->fieldName, array('type' => 'taxonomy_term_reference_link'))
->save();
// Create a term in each vocabulary.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
$taxonomy_term_1_uri = url('taxonomy/term/' . $term1->id(), array('absolute' => TRUE));
$taxonomy_term_2_uri = url('taxonomy/term/' . $term2->id(), array('absolute' => TRUE));
// Create the node.
$node = $this->drupalCreateNode(array('type' => 'article'));
$node->set($this->fieldName, array(
array('target_id' => $term1->id()),
array('target_id' => $term2->id()),
));
// Render the node.
$node_render_array = entity_view_multiple(array($node), 'teaser');
$html = drupal_render($node_render_array);
// Parse the teaser.
$parser = new \EasyRdf_Parser_Rdfa();
$graph = new \EasyRdf_Graph();
$base_uri = url('<front>', array('absolute' => TRUE));
$parser->parse($graph, $html, 'rdfa', $base_uri);
// Node relations to taxonomy terms.
$node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
$expected_value = array(
'type' => 'uri',
'value' => $taxonomy_term_1_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
$expected_value = array(
'type' => 'uri',
'value' => $taxonomy_term_2_uri,
);
$this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
// Taxonomy terms triples.
// Term 1.
$expected_value = array(
'type' => 'uri',
'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
$expected_value = array(
'type' => 'literal',
'value' => $term1->label(),
);
$this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
// Term 2.
$expected_value = array(
'type' => 'uri',
'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
);
$this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
$expected_value = array(
'type' => 'literal',
'value' => $term2->label(),
);
$this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
}
/**
* Create the taxonomy term reference field for testing.
*
* @param string $field_name
* The name of the field to create.
* @param \Drupal\taxonomy\Plugin\Core\Entity\Vocabulary $vocabulary
* The vocabulary that the field should use.
*
* @todo Move this to TaxonomyTestBase, like the other field modules.
*/
protected function createTaxonomyTermReferenceField($field_name, $vocabulary) {
$field = array(
'field_name' => $field_name,
'type' => 'taxonomy_term_reference',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'settings' => array(
'allowed_values' => array(
array(
'vocabulary' => $vocabulary->id(),
'parent' => '0',
),
),
),
);
field_create_field($field);
$instance = array(
'field_name' => $field_name,
'entity_type' => 'node',
'bundle' => 'article',
);
field_create_instance($instance);
entity_get_form_display('node', 'article', 'default')
->setComponent($field_name, array('type' => 'options_select'))
->save();
entity_get_display('node', 'article', 'full')
->setComponent($field_name, array('type' => 'taxonomy_term_reference_link'))
->save();
}
}

View File

@ -2,7 +2,7 @@
/** /**
* @file * @file
* Contains Drupal\rdf\Tests\TrackerAttributesTest. * Contains \Drupal\rdf\Tests\TrackerAttributesTest.
*/ */
namespace Drupal\rdf\Tests; namespace Drupal\rdf\Tests;
@ -37,6 +37,48 @@ class TrackerAttributesTest extends WebTestBase {
// Creates article content type. // Creates article content type.
$this->drupalCreateContentType(array('type' => 'article', 'name' => t('Article'))); $this->drupalCreateContentType(array('type' => 'article', 'name' => t('Article')));
// Set bundle RDF mapping config for article.
$mapping = rdf_get_mapping('node', 'article');
// 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) {
$mapping->setFieldMapping($field_name, $field_mapping)->save();
}
// Enables anonymous posting of content. // Enables anonymous posting of content.
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array( user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
'create article content' => TRUE, 'create article content' => TRUE,

View File

@ -19,7 +19,7 @@ class UserAttributesTest extends WebTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('rdf', 'rdf_test'); public static $modules = array('rdf');
public static function getInfo() { public static function getInfo() {
return array( return array(
@ -29,6 +29,18 @@ class UserAttributesTest extends WebTestBase {
); );
} }
public function setUp() {
parent::setUp();
rdf_get_mapping('user', 'user')
->setBundleMapping(array(
'types' => array('sioc:UserAccount'),
))
->setFieldMapping('name', array(
'properties' => array('foaf:name'),
))
->save();
}
/** /**
* Tests if default mapping for user is being used. * Tests if default mapping for user is being used.
* *
@ -39,7 +51,6 @@ class UserAttributesTest extends WebTestBase {
// Creates two users, one with access to user profiles. // Creates two users, one with access to user profiles.
$user1 = $this->drupalCreateUser(array('access user profiles')); $user1 = $this->drupalCreateUser(array('access user profiles'));
$user2 = $this->drupalCreateUser(); $user2 = $this->drupalCreateUser();
$username = $user2->name;
$this->drupalLogin($user1); $this->drupalLogin($user1);
$account_uri = url('user/' . $user2->uid, array('absolute' => TRUE)); $account_uri = url('user/' . $user2->uid, array('absolute' => TRUE));

View File

@ -10,78 +10,6 @@
* @{ * @{
*/ */
/**
* Allow modules to define RDF mappings for field bundles.
*
* Modules defining their own field bundles can specify which RDF semantics
* should be used to annotate these bundles. These mappings are then used for
* automatic RDFa output in the HTML code.
*
* @return
* A list of mapping structures, where each mapping is an associative array:
* - type: The name of an entity type (e.g., 'node', 'comment', and so on.)
* - bundle: The name of the bundle (e.g., 'page', 'article', or
* RDF_DEFAULT_BUNDLE for default mappings.)
* - mapping: The mapping structure which applies to the entity type and
* bundle. A mapping structure is an array with keys corresponding to
* existing field instances in the bundle. Each field is then described in
* terms of the RDF mapping:
* - predicates: An array of RDF predicates which describe the relation
* between the bundle (RDF subject) and the value of the field (RDF
* object). This value is either some text, another bundle, or a URI in
* general.
* - datatype: Is used along with 'callback' to format data so that it is
* readable by machines. A typical example is a date which can be written
* in many different formats but should be translated into a uniform
* format for machine consumption.
* - callback: A function name to invoke for 'datatype'.
* - type: A string used to determine the type of RDFa markup which will be
* used in the final HTML output, depending on whether the RDF object is a
* literal text or another RDF resource.
* - rdftype: A special property used to define the type of the instance.
* Its value should be an array of RDF classes.
*
* @ingroup rdf
*/
function hook_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'),
),
),
),
);
}
/** /**
* Allow modules to define namespaces for RDF mappings. * Allow modules to define namespaces for RDF mappings.
* *

View File

@ -5,45 +5,56 @@
* Install, update and uninstall functions for the rdf module. * Install, update and uninstall functions for the rdf module.
*/ */
/** use Drupal\Component\Uuid\Uuid;
* Implements hook_schema().
*/
function rdf_schema() {
$schema['rdf_mapping'] = array(
'description' => 'Stores custom RDF mappings for user defined content types or overriden module-defined mappings',
'fields' => array(
'type' => array(
'type' => 'varchar',
'length' => 128,
'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' => 'blob',
'not null' => FALSE,
'size' => 'big',
'serialize' => TRUE,
),
),
'primary key' => array('type', 'bundle'),
);
return $schema;
}
/** /**
* Implements hook_install(). * Convert RDF mappings to configuration.
*
* @ingroup config_upgrade
*/ */
function rdf_install() { function rdf_update_8000() {
// Collect any RDF mappings that were declared by modules installed before $uuid = new Uuid();
// this one. $query = db_query("SELECT * FROM {rdf_mapping}");
$modules = module_implements('rdf_mapping');
rdf_modules_installed($modules); // Iterate through all the stored mappings.
while ($row = $query->fetchAssoc()) {
$mapping = unserialize($row['mapping']);
$entity_type = $row['type'];
$bundle = $row['bundle'];
// Create a config object for the mapping.
$config = config("rdf.mapping.$entity_type.$bundle")
->set('id', "$entity_type.$bundle")
->set('uuid', $uuid->generate())
->set('targetEntityType', $entity_type)
->set('bundle', $bundle);
// Add the bundle and field mappings.
$field_mappings = array();
foreach ($mapping as $key => $value) {
// If this is the rdftype entry, add the types to the config object.
if ($key == 'rdftype') {
$config->set('types', $value);
}
// Otherwise, this key is a field. Process the field mapping into the new
// structure.
else {
// Since reverse relations are not supported in D8, drop any mappings
// which use the 'rev' type.
if (!empty($value['type'])) {
if ($value['type'] == 'rev') {
continue;
}
$field_mappings[$key]['mapping_type'] = $value['type'];
}
!empty($value['predicates']) ? $field_mappings[$key]['properties'] = $value['predicates'] : NULL;
!empty($value['datatype']) ? $field_mappings[$key]['datatype'] = $value['datatype'] : NULL;
!empty($value['callback']) ? $field_mappings[$key]['datatype_callback'] = $value['callback'] : NULL;
}
}
$config->set('fieldMappings', $field_mappings);
// Save the mapping config object.
$config->save();
}
} }

View File

@ -36,45 +36,51 @@ function rdf_help($path, $arg) {
* classes and properties. This module takes care of injecting these mappings * classes and properties. This module takes care of injecting these mappings
* into variables available to theme functions and templates. All Drupal core * into variables available to theme functions and templates. All Drupal core
* themes are coded to be RDFa compatible. * themes are coded to be RDFa compatible.
*
* Example mapping from node.module:
* @code
* array(
* 'type' => 'node',
* 'bundle' => RDF_DEFAULT_BUNDLE,
* 'mapping' => array(
* 'rdftype' => array('sioc:Item', 'foaf:Document'),
* 'title' => array(
* 'predicates' => array('dc:title'),
* ),
* 'created' => array(
* 'predicates' => array('dc:date', 'dc:created'),
* 'datatype' => 'xsd:dateTime',
* 'callback' => 'date_iso8601',
* ),
* 'body' => array(
* 'predicates' => array('content:encoded'),
* ),
* 'uid' => array(
* 'predicates' => array('sioc:has_creator'),
* ),
* 'name' => array(
* 'predicates' => array('foaf:name'),
* ),
* ),
* );
* @endcode
*/ */
/** /**
* RDF bundle flag: Default bundle. * Returns the RDF mapping object associated to a bundle.
* *
* Implementations of hook_rdf_mapping() should use this constant for the * The function reads the rdf_mapping object from the current configuration,
* 'bundle' key when defining a default set of RDF mappings for an entity type. * or returns a ready-to-use empty one if no configuration entry exists yet for
* Each bundle will inherit the default mappings defined for the entity type * this bundle. This streamlines the manipulation of mapping objects by always
* unless the bundle defines its own specific mappings. * returning a consistent object that reflects the current state of the
* configuration.
*
* Example usage:
* -Map the 'article' bundle to 'sioc:Post' and the 'title' field to 'dc:title'.
* @code
* rdf_get_mapping('node', 'article')
* ->setBundleMapping(array(
* 'types' => array('sioc:Post'),
* ))
* ->setFieldMapping('title', array(
* 'properties' => array('dc:title')
* ))
* ->save();
* @endcode
*
* @param string $entity_type
* The entity type.
* @param string $bundle
* The bundle.
*
* @return \Drupal\rdf\Plugin\Core\Entity\RdfMapping
* The RdfMapping object.
*/ */
const RDF_DEFAULT_BUNDLE = ''; function rdf_get_mapping($entity_type, $bundle) {
// Try loading the mapping from configuration.
$mapping = entity_load('rdf_mapping', $entity_type . '.' . $bundle);
// If not found, create a fresh mapping object.
if (!$mapping) {
$mapping = entity_create('rdf_mapping', array(
'targetEntityType' => $entity_type,
'bundle' => $bundle,
));
}
return $mapping;
}
/** /**
* Implements hook_rdf_namespaces(). * Implements hook_rdf_namespaces().
@ -112,167 +118,15 @@ function rdf_get_namespaces() {
return $namespaces; return $namespaces;
} }
/**
* Returns the mapping for attributes of a given entity type/bundle pair.
*
* @param $type
* An entity type.
* @param $bundle
* (optional) A bundle name.
*
* @return
* The mapping corresponding to the requested entity type/bundle pair or an
* empty array.
*/
function rdf_mapping_load($type, $bundle = RDF_DEFAULT_BUNDLE) {
// Retrieves the bundle-specific mapping from the entity info.
$bundles = entity_get_bundles($type);
if (!empty($bundles[$bundle]['rdf_mapping'])) {
return $bundles[$bundle]['rdf_mapping'];
}
// If there is no mapping defined for this bundle, we return the default
// mapping that is defined for this entity type.
else {
return _rdf_get_default_mapping($type);
}
}
/** /**
* @} End of "defgroup rdf". * @} End of "defgroup rdf".
*/ */
/**
* Gets the default RDF mapping for a given entity type.
*
* @param $type
* An entity type, e.g. 'node' or 'comment'.
*
* @return
* The RDF mapping or an empty array if no mapping is defined for this entity
* type.
*/
function _rdf_get_default_mapping($type) {
$default_mappings = &drupal_static(__FUNCTION__);
if (!isset($default_mappings)) {
// Get all of the modules that implement hook_rdf_mapping().
$modules = module_implements('rdf_mapping');
// Only consider the default entity mapping definitions.
foreach ($modules as $module) {
$mappings = module_invoke($module, 'rdf_mapping');
foreach ($mappings as $mapping) {
if ($mapping['bundle'] === RDF_DEFAULT_BUNDLE) {
$default_mappings[$mapping['type']] = $mapping['mapping'];
}
}
}
}
return isset($default_mappings[$type]) ? $default_mappings[$type] : array();
}
/**
* Retrieves an RDF mapping from the database.
*
* @param $type
* The entity type the mapping refers to.
* @param $bundle
* The bundle the mapping refers to.
*
* @return
* An RDF mapping structure or, FALSE if the mapping does not exist.
*/
function _rdf_mapping_load($type, $bundle) {
$mappings = _rdf_mapping_load_multiple($type, array($bundle));
return $mappings ? reset($mappings) : FALSE;
}
/**
* Helper function to retrieve a set of RDF mappings from the database.
*
* @param $type
* The entity type of the mappings.
* @param $bundles
* The bundles the mappings refer to.
*
* @return
* An array of RDF mapping structures, or an empty array.
*/
function _rdf_mapping_load_multiple($type, array $bundles) {
$mappings = db_select('rdf_mapping')
->fields(NULL, array('bundle', 'mapping'))
->condition('type', $type)
->condition('bundle', $bundles)
->execute()
->fetchAllKeyed();
foreach ($mappings as $bundle => $mapping) {
$mappings[$bundle] = unserialize($mapping);
}
return $mappings;
}
/** /**
* @addtogroup rdf * @addtogroup rdf
* @{ * @{
*/ */
/**
* 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 entity
* type/bundle pair. If available, adds default values for non-existent mapping
* keys.
*
* @param $mapping
* The RDF mapping to save.
*
* @return
* MergeQuery object that indicates the outcome of the operation.
*/
function rdf_mapping_save($mapping) {
// In the case where a field has a mapping defined in the default entity
// mapping, but a mapping is not specified in the bundle-specific mapping,
// then use the default mapping for that field.
$mapping['mapping'] += _rdf_get_default_mapping($mapping['type']);
$status = db_merge('rdf_mapping')
->key(array(
'type' => $mapping['type'],
'bundle' => $mapping['bundle'],
))
->fields(array(
'mapping' => serialize($mapping['mapping']),
))
->execute();
entity_info_cache_clear();
return $status;
}
/**
* Deletes the mapping for the given bundle from the database.
*
* @param $type
* The entity type the mapping refers to.
* @param $bundle
* The bundle the mapping refers to.
*
* @return
* TRUE if the mapping is deleted, FALSE if not.
*/
function rdf_mapping_delete($type, $bundle) {
$num_rows = db_delete('rdf_mapping')
->condition('type', $type)
->condition('bundle', $bundle)
->execute();
return (bool) ($num_rows > 0);
}
/** /**
* Builds an array of RDFa attributes for a given mapping. * Builds an array of RDFa attributes for a given mapping.
* *
@ -281,50 +135,54 @@ function rdf_mapping_delete($type, $bundle) {
* These include $attributes, $title_attributes, $content_attributes and the * These include $attributes, $title_attributes, $content_attributes and the
* field-specific $item_attributes variables. * field-specific $item_attributes variables.
* *
* @param $mapping * @param array $mapping
* An array containing a mandatory 'predicates' key and optional 'datatype', * An array containing a mandatory 'properties' key and optional 'datatype',
* 'callback' and 'type' keys. For example: * 'datatype_callback' and 'type' keys. For example:
* @code * @code
* array( * array(
* 'predicates' => array('dc:created'), * 'properties' => array('dc:created'),
* 'datatype' => 'xsd:dateTime', * 'datatype' => 'xsd:dateTime',
* 'callback' => 'date_iso8601', * 'datatype_callback' => 'date_iso8601',
* ), * ),
* ); * );
* @endcode * @endcode
* @param $data * @param mixed $data
* (optional) A value that needs to be converted by the provided callback * (optional) A value that needs to be converted by the provided callback
* function. * function.
* *
* @return * @return array
* RDFa attributes suitable for Drupal\Core\Template\Attribute. * RDFa attributes suitable for Drupal\Core\Template\Attribute.
* *
* @see theme_rdf_template_variable_wrapper() * @see theme_rdf_template_variable_wrapper()
*/ */
function rdf_rdfa_attributes($mapping, $data = NULL) { function rdf_rdfa_attributes($mapping, $data = NULL) {
$attributes = array();
// The type of mapping defaults to 'property'. // 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) { switch ($type) {
// The mapping expresses the relationship between two resources. // The mapping expresses the relationship between two resources.
case 'rel': case 'rel':
case 'rev': case 'rev':
$attributes[$type] = $mapping['predicates']; $attributes[$type] = $mapping['properties'];
break; break;
// The mapping expresses the relationship between a resource and some // The mapping expresses the relationship between a resource and some
// literal text. // literal text.
case 'property': case 'property':
$attributes['property'] = $mapping['predicates']; if (!empty($mapping['properties'])) {
// Convert $data to a specific format as per the callback function. $attributes['property'] = $mapping['properties'];
if (isset($data) && isset($mapping['callback'])) { // Convert $data to a specific format as per the callback function.
$callback = $mapping['callback']; if (isset($data) && !empty($mapping['datatype_callback'])) {
$attributes['content'] = $callback($data); $callback = $mapping['datatype_callback'];
$attributes['content'] = $callback($data);
}
if (isset($mapping['datatype'])) {
$attributes['datatype'] = $mapping['datatype'];
}
break;
} }
if (isset($mapping['datatype'])) {
$attributes['datatype'] = $mapping['datatype'];
}
break;
} }
return $attributes; return $attributes;
@ -334,80 +192,6 @@ function rdf_rdfa_attributes($mapping, $data = NULL) {
* @} End of "addtogroup rdf". * @} End of "addtogroup rdf".
*/ */
/**
* Implements hook_modules_installed().
*
* Checks if the installed modules have any RDF mapping definitions to declare
* and stores them in the rdf_mapping table.
*
* While both default entity mappings and specific bundle mappings can be
* defined in hook_rdf_mapping(), default entity mappings are not stored in the
* database. Only overridden mappings are stored in the database. The default
* entity mappings can be overriden by specific bundle mappings which are
* stored in the database and can be altered via the RDF CRUD mapping API.
*/
function rdf_modules_installed($modules) {
foreach ($modules as $module) {
$function = $module . '_rdf_mapping';
if (function_exists($function)) {
foreach ($function() as $mapping) {
// Only the bundle mappings are saved in the database.
if ($mapping['bundle'] !== RDF_DEFAULT_BUNDLE) {
rdf_mapping_save($mapping);
}
}
}
}
}
/**
* Implements hook_modules_uninstalled().
*/
function rdf_modules_uninstalled($modules) {
// @todo Remove RDF mappings of uninstalled modules.
}
/**
* Implements hook_entity_bundle_info_alter().
*
* Adds the proper RDF mapping to each entity type/bundle pair.
*
* @todo May need to move the comment below to another place.
* This hook should not be used by modules to alter the bundle mappings. The UI
* should always be authoritative. UI mappings are stored in the database and
* if hook_entity_info_alter() was used to override module defined mappings, it
* would override the user defined mapping as well.
*
*/
function rdf_entity_bundle_info_alter(&$bundles) {
// Loop through each entity type and its bundles.
foreach ($bundles as $entity_type => $bundle_info) {
$bundle_names = array_keys($bundle_info);
$mappings = _rdf_mapping_load_multiple($entity_type, $bundle_names);
foreach ($bundle_names as $bundle) {
if (isset($mappings[$bundle])) {
$bundles[$entity_type][$bundle]['rdf_mapping'] = $mappings[$bundle];
}
else {
// If no mapping was found in the database, assign the default RDF
// mapping for this entity type.
$bundles[$entity_type][$bundle]['rdf_mapping'] = _rdf_get_default_mapping($entity_type);
}
}
}
}
/**
* Implements hook_entity_load().
*/
function rdf_entity_load($entities, $type) {
foreach ($entities as $entity) {
// Extracts the bundle of the entity being loaded.
$entity->rdf_mapping = rdf_mapping_load($type, $entity->bundle());
}
}
/** /**
* Implements hook_comment_load(). * Implements hook_comment_load().
*/ */
@ -416,7 +200,9 @@ function rdf_comment_load($comments) {
// Pages with many comments can show poor performance. This information // Pages with many comments can show poor performance. This information
// isn't needed until rdf_preprocess_comment() is called, but set it here // isn't needed until rdf_preprocess_comment() is called, but set it here
// to optimize performance for websites that implement an entity cache. // to optimize performance for websites that implement an entity cache.
$comment->rdf_data['date'] = rdf_rdfa_attributes($comment->rdf_mapping['created'], $comment->created->value); $created_mapping = rdf_get_mapping('comment', $comment->bundle())
->getPreparedFieldMapping('created');
$comment->rdf_data['date'] = rdf_rdfa_attributes($created_mapping, $comment->created->value);
$comment->rdf_data['nid_uri'] = url('node/' . $comment->nid->target_id); $comment->rdf_data['nid_uri'] = url('node/' . $comment->nid->target_id);
if ($comment->pid->target_id) { if ($comment->pid->target_id) {
$comment->rdf_data['pid_uri'] = url('comment/' . $comment->pid->target_id); $comment->rdf_data['pid_uri'] = url('comment/' . $comment->pid->target_id);
@ -509,14 +295,18 @@ function rdf_preprocess_node(&$variables) {
// URI of the resource described within the HTML element, while the @typeof // URI of the resource described within the HTML element, while the @typeof
// attribute indicates its RDF type (e.g., foaf:Document, sioc:Person, and so // attribute indicates its RDF type (e.g., foaf:Document, sioc:Person, and so
// on.) // on.)
$bundle = $variables['node']->bundle();
$mapping = rdf_get_mapping('node', $bundle);
$bundle_mapping = $mapping->getPreparedBundleMapping('node', $bundle);
$variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url']; $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
$variables['attributes']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_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 // Adds 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 // 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 // datatype to ensure the value of the title read by the RDFa parsers is a
// literal. // literal.
$variables['title_attributes']['property'] = empty($variables['node']->rdf_mapping['title']['predicates']) ? NULL : $variables['node']->rdf_mapping['title']['predicates']; $title_mapping = $mapping->getPreparedFieldMapping('title');
$variables['title_attributes']['property'] = empty($title_mapping['properties']) ? NULL : $title_mapping['properties'];
$variables['title_attributes']['datatype'] = ''; $variables['title_attributes']['datatype'] = '';
// In full node mode, the title is not displayed by node.html.twig so it is // In full node mode, the title is not displayed by node.html.twig so it is
@ -529,35 +319,40 @@ function rdf_preprocess_node(&$variables) {
'about' => $variables['node_url'], 'about' => $variables['node_url'],
), ),
); );
if (!empty($variables['node']->rdf_mapping['title']['predicates'])) { if (!empty($title_mapping['properties'])) {
$element['#attributes']['property'] = $variables['node']->rdf_mapping['title']['predicates']; $element['#attributes']['property'] = $title_mapping['properties'];
} }
drupal_add_html_head($element, 'rdf_node_title'); drupal_add_html_head($element, 'rdf_node_title');
} }
// Adds RDFa markup for the date. // Adds RDFa markup for the date.
if (!empty($variables['node']->rdf_mapping['created'])) { $created_mapping = $mapping->getPreparedFieldMapping('created');
$date_attributes = rdf_rdfa_attributes($variables['node']->rdf_mapping['created'], $variables['node']->created); if (!empty($created_mapping)) {
$date_attributes = rdf_rdfa_attributes($created_mapping, $variables['node']->created);
$variables['rdf_template_variable_attributes']['date'] = $date_attributes; $variables['rdf_template_variable_attributes']['date'] = $date_attributes;
if ($variables['submitted']) { if ($variables['submitted']) {
$variables['rdf_template_variable_attributes']['submitted'] = $date_attributes; $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes;
} }
} }
// Adds RDFa markup for the relation between the node and its author. // Adds RDFa markup for the relation between the node and its author.
if (!empty($variables['node']->rdf_mapping['uid'])) { $uid_mapping = $mapping->getPreparedFieldMapping('uid');
$variables['rdf_template_variable_attributes']['name']['rel'] = $variables['node']->rdf_mapping['uid']['predicates']; if (!empty($uid_mapping)) {
$variables['rdf_template_variable_attributes']['name']['rel'] = $uid_mapping['properties'];
if ($variables['submitted']) { if ($variables['submitted']) {
$variables['rdf_template_variable_attributes']['submitted']['rel'] = $variables['node']->rdf_mapping['uid']['predicates']; $variables['rdf_template_variable_attributes']['submitted']['rel'] = $uid_mapping['properties'];
} }
} }
// Adds RDFa markup annotating the number of comments a node has. // Adds RDFa markup annotating the number of comments a node has.
if (isset($variables['node']->comment_count) && !empty($variables['node']->rdf_mapping['comment_count']['predicates'])) { $comment_count_mapping = $mapping->getPreparedFieldMapping('comment_count');
if (isset($variables['node']->comment_count) && !empty($comment_count_mapping['properties'])) {
// Annotates the 'x comments' link in teaser view. // Annotates the 'x comments' link in teaser view.
if (isset($variables['content']['links']['comment']['#links']['comment-comments'])) { if (isset($variables['content']['links']['comment']['#links']['comment-comments'])) {
$comment_count_attributes['property'] = $variables['node']->rdf_mapping['comment_count']['predicates']; $comment_count_attributes['property'] = $comment_count_mapping['properties'];
$comment_count_attributes['content'] = $variables['node']->comment_count; $comment_count_attributes['content'] = $variables['node']->comment_count;
$comment_count_attributes['datatype'] = $variables['node']->rdf_mapping['comment_count']['datatype']; if (isset($comment_count_mapping['datatype'])) {
$comment_count_attributes['datatype'] = $comment_count_mapping['datatype'];
}
// According to RDFa parsing rule number 4, a new subject URI is created // According to RDFa parsing rule number 4, a new subject URI is created
// from the href attribute if no rel/rev attribute is present. To get the // from the href attribute if no rel/rev attribute is present. To get the
// original node URL from the about attribute of the parent container we // original node URL from the about attribute of the parent container we
@ -574,9 +369,9 @@ function rdf_preprocess_node(&$variables) {
'#tag' => 'meta', '#tag' => 'meta',
'#attributes' => array( '#attributes' => array(
'about' => $variables['node_url'], 'about' => $variables['node_url'],
'property' => $variables['node']->rdf_mapping['comment_count']['predicates'], 'property' => $comment_count_mapping['properties'],
'content' => $variables['node']->comment_count, 'content' => $variables['node']->comment_count,
'datatype' => $variables['node']->rdf_mapping['comment_count']['datatype'], 'datatype' => $comment_count_mapping['datatype'],
), ),
); );
drupal_add_html_head($element, 'rdf_node_comment_count'); drupal_add_html_head($element, 'rdf_node_comment_count');
@ -589,12 +384,15 @@ function rdf_preprocess_node(&$variables) {
*/ */
function rdf_preprocess_field(&$variables) { function rdf_preprocess_field(&$variables) {
$element = $variables['element']; $element = $variables['element'];
$mapping = rdf_mapping_load($element['#entity_type'], $element['#bundle']); $entity_type = $element['#entity_type'];
$bundle = $element['#bundle'];
$field_name = $element['#field_name']; $field_name = $element['#field_name'];
$field_mapping = rdf_get_mapping($entity_type, $bundle)
->getPreparedFieldMapping($field_name);
if (!empty($mapping) && !empty($mapping[$field_name])) { if (!empty($field_mapping)) {
foreach ($element['#items'] as $delta => $item) { foreach ($element['#items'] as $delta => $item) {
$variables['item_attributes'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item); $variables['item_attributes'][$delta] = rdf_rdfa_attributes($field_mapping, $item);
// If this field is an image, RDFa will not output correctly when the // If this field is an image, RDFa will not output correctly when the
// image is in a containing <a> tag. If the field is a file, RDFa will // image is in a containing <a> tag. If the field is a file, RDFa will
// not output correctly if the filetype icon comes before the link to the // not output correctly if the filetype icon comes before the link to the
@ -618,11 +416,13 @@ function rdf_preprocess_field(&$variables) {
function rdf_preprocess_user(&$variables) { function rdf_preprocess_user(&$variables) {
$account = $variables['elements']['#user']; $account = $variables['elements']['#user'];
$uri = $account->uri(); $uri = $account->uri();
$mapping = rdf_get_mapping('user', 'user');
$bundle_mapping = $mapping->getPreparedBundleMapping();
// Adds RDFa markup to the user profile page. Fields displayed in this page // Adds RDFa markup to the user profile page. Fields displayed in this page
// will automatically describe the user. // will automatically describe the user.
if (!empty($account->rdf_mapping['rdftype'])) { if (!empty($bundle_mapping['types'])) {
$variables['attributes']['typeof'] = $account->rdf_mapping['rdftype']; $variables['attributes']['typeof'] = $bundle_mapping['types'];
$variables['attributes']['about'] = url($uri['path'], $uri['options']); $variables['attributes']['about'] = url($uri['path'], $uri['options']);
} }
// If we are on the user account page, add the relationship between the // If we are on the user account page, add the relationship between the
@ -639,17 +439,20 @@ function rdf_preprocess_user(&$variables) {
); );
// Adds the markup for username as language neutral literal, see // Adds the markup for username as language neutral literal, see
// rdf_preprocess_username(). // rdf_preprocess_username().
$username_meta = array( $name_mapping = $mapping->getPreparedFieldMapping('name');
'#tag' => 'meta', if (!empty($name_mapping['properties'])) {
'#attributes' => array( $username_meta = array(
'about' => url($uri['path'], $uri['options']), '#tag' => 'meta',
'property' => $account->rdf_mapping['name']['predicates'], '#attributes' => array(
'content' => $account->name, 'about' => url($uri['path'], $uri['options']),
'lang' => '', 'property' => $name_mapping['properties'],
) 'content' => $account->name,
); 'lang' => '',
),
);
drupal_add_html_head($username_meta, 'rdf_user_username');
}
drupal_add_html_head($account_holder_meta, 'rdf_user_account_holder'); drupal_add_html_head($account_holder_meta, 'rdf_user_account_holder');
drupal_add_html_head($username_meta, 'rdf_user_username');
} }
} }
@ -667,16 +470,8 @@ function rdf_preprocess_username(&$variables) {
$attributes['lang'] = ''; $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 // 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 // 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. // 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 // We do not use this attribute for the anonymous user because we do not have
@ -686,21 +481,24 @@ function rdf_preprocess_username(&$variables) {
$attributes['about'] = url('user/' . $variables['uid']); $attributes['about'] = url('user/' . $variables['uid']);
} }
// The typeof attribute specifies the RDF type(s) of this resource. They // Add RDF type of user.
// are defined in the 'rdftype' property of the user RDF mapping. $mapping = rdf_get_mapping('user', 'user');
if (!empty($rdf_mapping['rdftype'])) { $bundle_mapping = $mapping->getPreparedBundleMapping();
$attributes['typeof'] = $rdf_mapping['rdftype']; if (!empty($bundle_mapping['types'])) {
$attributes['typeof'] = $bundle_mapping['types'];
} }
// Annotate the username in RDFa. A property attribute is used with an empty // 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 // datatype attribute to ensure the username is parsed as a plain literal
// in RDFa 1.0 and 1.1. // in RDFa 1.0 and 1.1.
if (!empty($rdf_mapping['name'])) { $name_mapping = $mapping->getPreparedFieldMapping('name');
$attributes['property'] = $rdf_mapping['name']['predicates']; if (!empty($name_mapping)) {
$attributes['property'] = $name_mapping['properties'];
$attributes['datatype'] = ''; $attributes['datatype'] = '';
} }
// Add the homepage RDFa markup if present. // Add the homepage RDFa markup if present.
if (!empty($variables['homepage']) && !empty($rdf_mapping['homepage'])) { $homepage_mapping = $mapping->getPreparedFieldMapping('homepage');
$attributes['rel'] = $rdf_mapping['homepage']['predicates']; if (!empty($variables['homepage']) && !empty($homepage_mapping)) {
$attributes['rel'] = $homepage_mapping['properties'];
} }
// The remaining attributes can have multiple values listed, with whitespace // The remaining attributes can have multiple values listed, with whitespace
// separating the values in the RDFa attributes // separating the values in the RDFa attributes
@ -721,18 +519,22 @@ function rdf_preprocess_username(&$variables) {
*/ */
function rdf_preprocess_comment(&$variables) { function rdf_preprocess_comment(&$variables) {
$comment = $variables['comment']; $comment = $variables['comment'];
if (!empty($comment->rdf_mapping['rdftype'])) { $mapping = rdf_get_mapping('comment', $comment->bundle());
$bundle_mapping = $mapping->getPreparedBundleMapping();
if (!empty($bundle_mapping['types'])) {
// Adds RDFa markup to the comment container. The about attribute specifies // Adds RDFa markup to the comment container. The about attribute specifies
// the URI of the resource described within the HTML element, while the // the URI of the resource described within the HTML element, while the
// typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document, // typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document,
// and so on.) // and so on.)
$uri = $comment->uri(); $uri = $comment->uri();
$variables['attributes']['about'] = url($uri['path'], $uri['options']); $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. // Adds RDFa markup for the date of the comment.
if (!empty($comment->rdf_mapping['created'])) { $created_mapping = $mapping->getPreparedFieldMapping('created');
if (!empty($created_mapping)) {
// The comment date is precomputed as part of the rdf_data so that it can be // The comment date is precomputed as part of the rdf_data so that it can be
// cached as part of the entity. // cached as part of the entity.
$date_attributes = $comment->rdf_data['date']; $date_attributes = $comment->rdf_data['date'];
@ -740,24 +542,27 @@ function rdf_preprocess_comment(&$variables) {
$variables['rdf_template_variable_attributes']['submitted'] = $date_attributes; $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes;
} }
// Adds RDFa markup for the relation between the comment and its author. // Adds RDFa markup for the relation between the comment and its author.
if (!empty($comment->rdf_mapping['uid'])) { $uid_mapping = $mapping->getPreparedFieldMapping('uid');
$variables['rdf_template_variable_attributes']['author']['rel'] = $comment->rdf_mapping['uid']['predicates']; if (!empty($uid_mapping)) {
$variables['rdf_template_variable_attributes']['submitted']['rel'] = $comment->rdf_mapping['uid']['predicates']; $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->getPreparedFieldMapping('title');
if (!empty($title_mapping)) {
// Adds RDFa markup to the subject of the comment. Because the RDFa markup // Adds RDFa markup to the subject of the comment. Because the RDFa markup
// is added to an <h3> tag which might contain HTML code, we specify an // is added to an <h3> tag which might contain HTML code, we specify an
// empty datatype to ensure the value of the title read by the RDFa parsers // empty datatype to ensure the value of the title read by the RDFa parsers
// is a literal. // is a literal.
$variables['title_attributes']['property'] = $comment->rdf_mapping['title']['predicates']; $variables['title_attributes']['property'] = $title_mapping['properties'];
$variables['title_attributes']['datatype'] = ''; $variables['title_attributes']['datatype'] = '';
} }
// Annotates the parent relationship between the current comment and the node // Annotates the parent relationship between the current comment and the node
// it belongs to. If available, the parent comment is also annotated. // it belongs to. If available, the parent comment is also annotated.
if (!empty($comment->rdf_mapping['pid'])) { $pid_mapping = $mapping->getPreparedFieldMapping('pid');
if (!empty($pid_mapping)) {
// Adds the relation to the parent node. // Adds the relation to the parent node.
$parent_node_attributes['rel'] = $comment->rdf_mapping['pid']['predicates']; $parent_node_attributes['rel'] = $pid_mapping['properties'];
// The parent node URI is precomputed as part of the rdf_data so that it can // The parent node URI is precomputed as part of the rdf_data so that it can
// be cached as part of the entity. // be cached as part of the entity.
$parent_node_attributes['resource'] = $comment->rdf_data['nid_uri']; $parent_node_attributes['resource'] = $comment->rdf_data['nid_uri'];
@ -765,7 +570,7 @@ function rdf_preprocess_comment(&$variables) {
// Adds the relation to parent comment, if it exists. // Adds the relation to parent comment, if it exists.
if ($comment->pid->target_id != 0) { 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 // The parent comment URI is precomputed as part of the rdf_data so that
// it can be cached as part of the entity. // it can be cached as part of the entity.
$parent_comment_attributes['resource'] = $comment->rdf_data['pid_uri']; $parent_comment_attributes['resource'] = $comment->rdf_data['pid_uri'];
@ -778,17 +583,20 @@ function rdf_preprocess_comment(&$variables) {
* Implements hook_preprocess_HOOK() for taxonomy-term.tpl.php. * Implements hook_preprocess_HOOK() for taxonomy-term.tpl.php.
*/ */
function rdf_preprocess_taxonomy_term(&$variables) { function rdf_preprocess_taxonomy_term(&$variables) {
// Adds the RDF type of the term and the term name in a <meta> tag.
$term = $variables['term']; $term = $variables['term'];
$mapping = rdf_get_mapping('taxonomy_term', $term->bundle());
$bundle_mapping = $mapping->getPreparedBundleMapping();
$name_field_mapping = $mapping->getPreparedFieldMapping('name');
// Adds the RDF type of the term and the term name in a <meta> tag.
$term_label_meta = array( $term_label_meta = array(
'#tag' => 'meta', '#tag' => 'meta',
'#attributes' => array( '#attributes' => array(
'about' => url('taxonomy/term/' . $term->id()), 'about' => url('taxonomy/term/' . $term->id()),
'typeof' => $term->rdf_mapping['rdftype'], 'typeof' => $bundle_mapping['types'],
'property' => $term->rdf_mapping['name']['predicates'], 'property' => $name_field_mapping['properties'],
'content' => $term->label(), 'content' => $term->label(),
), ),
); );
drupal_add_html_head($term_label_meta, 'rdf_term_label'); drupal_add_html_head($term_label_meta, 'rdf_term_label');
} }
@ -806,13 +614,16 @@ function rdf_field_attach_view_alter(&$output, $context) {
// yet and thus have no $item['entity']. // yet and thus have no $item['entity'].
if (isset($item['entity'])) { if (isset($item['entity'])) {
$term = $item['entity']; $term = $item['entity'];
if (!empty($term->rdf_mapping['rdftype'])) { $mapping = rdf_get_mapping('taxonomy_term', $term->bundle());
$element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype']; $bundle_mapping = $mapping->getPreparedBundleMapping();
if (!empty($bundle_mapping['types'])) {
$element[$delta]['#options']['attributes']['typeof'] = $bundle_mapping['types'];
} }
if (!empty($term->rdf_mapping['name']['predicates'])) { $name_field_mapping = $mapping->getPreparedFieldMapping('name');
if (!empty($name_field_mapping['properties'])) {
// A property attribute is used with an empty datatype attribute so // A property attribute is used with an empty datatype attribute so
// the term name is parsed as a plain literal in RDFa 1.0 and 1.1. // the term name is parsed as a plain literal in RDFa 1.0 and 1.1.
$element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates']; $element[$delta]['#options']['attributes']['property'] = $name_field_mapping['properties'];
$element[$delta]['#options']['attributes']['datatype'] = ''; $element[$delta]['#options']['attributes']['datatype'] = '';
} }
} }

View File

@ -1,11 +0,0 @@
services:
rdf.site_schema_manager:
class: Drupal\rdf\SiteSchema\SiteSchemaManager
arguments: ['@cache.cache']
rdf.mapping_manager:
class: Drupal\rdf\RdfMappingManager
arguments: ['@event_dispatcher', '@rdf.site_schema_manager']
rdf.mapping:
class: Drupal\rdf\EventSubscriber\MappingSubscriber
tags:
- { name: event_subscriber }

View File

@ -0,0 +1,51 @@
<?php
/**
* @file
* Database additions for Drupal\rdf\Tests\RdfMappingUpgradePathTest.
*
* This dump only contains data for the RDF module. The
* drupal-7.bare.standard_all.database.php file is imported before this dump,
* so the combination of the two forms the database structure expected in tests.
*/
// Create a new mapping to test reverse relations.
$rev_mapping = array(
'field_rev' => array(
'predicates' => array('foo:rev'),
'type' => 'rev',
),
'field_notrev' => array(
'predicates' => array('foo:rel'),
'type' => 'rel',
),
);
db_insert('rdf_mapping')
->fields(array(
'type',
'bundle',
'mapping',
))
->values(array(
'type' => 'node',
'bundle'=> 'rev_test',
'mapping' => serialize($rev_mapping),
))
->execute();
// Alter the stored mapping for articles.
$altered_mapping = array(
'rdftype' => array('foo:Type'),
'field_image' => array(
'predicates' => array('foo:image'),
),
);
db_update('rdf_mapping')
->fields(array(
'type' => 'node',
'bundle'=> 'article',
'mapping' => serialize($altered_mapping),
))
->condition('type', 'node')
->condition('bundle', 'article')
->execute();

View File

@ -1,9 +0,0 @@
name: 'RDF module tests'
type: module
description: 'Support module for RDF module testing.'
package: Testing
version: VERSION
core: 8.x
hidden: true
dependencies:
- rdf

View File

@ -1,25 +0,0 @@
<?php
/**
* @file
* Install, update and uninstall functions for the rdf module.
*/
/**
* 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'),
),
),
);
foreach ($rdf_mappings as $rdf_mapping) {
rdf_mapping_save($rdf_mapping);
}
}

View File

@ -1,59 +0,0 @@
<?php
/**
* @file
* Tests API interaction with the RDF module.
*/
/**
* Implements hook_rdf_mapping().
*/
function rdf_test_rdf_mapping() {
return array(
array(
'type' => 'entity_test',
'bundle' => 'entity_test',
'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',
),
),
),
);
}
/**
* Implements hook_rdf_namespaces().
*/
function rdf_test_rdf_namespaces() {
return array(
'dc' => 'http://purl.org/conflicting/namespace',
'foaf' => 'http://xmlns.com/foaf/0.1/',
'foaf1' => 'http://xmlns.com/foaf/0.1/',
);
}

View File

@ -1,58 +0,0 @@
<?php
/**
* @file
* Contains TestMappingSubscriber.
*/
namespace Drupal\rdf_test_mapping\EventSubscriber;
use Drupal\rdf\RdfMappingEvents;
use Drupal\rdf\SiteSchema\BundleSchema;
use Drupal\rdf\SiteSchema\SiteSchema;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class TestMappingSubscriber implements EventSubscriberInterface {
const STAGING_SITE_TYPE_URI = 'http://staging.com/entity_test_bundle';
/**
* Demonstrate mapping between external type and site schema type.
*
* @param \Drupal\rdf\MapTypesFromInputEvent $event
* The mapping event.
*/
public function mapTypesFromInput($event) {
$input_uris = $event->getInputUris();
$site_schema_types = $event->getSiteSchemaTypes();
// This mapping between an external type and a site schema type would be
// managed by something in the implementing module, such as a database
// table. For the test, manually map a fake external URI to the site schema
// URI for the test entity.
$schema = new SiteSchema(SiteSchema::CONTENT_DEPLOYMENT);
$bundle_schema = $schema->bundle('entity_test', 'entity_test');
$site_schema_type = $bundle_schema->getUri();
$mapping = array(
self::STAGING_SITE_TYPE_URI => $site_schema_type,
);
foreach ($input_uris as $input_uri) {
// If the incoming URI is mapped in the mapping array, and the value of
// that mapping is found in the cache of site schema types, then set the
// site schema URI.
if (isset($mapping[$input_uri]) && isset($site_schema_types[$mapping[$input_uri]])) {
$event->setSiteSchemaUri($mapping[$input_uri]);
}
}
}
/**
* Implements EventSubscriberInterface::getSubscribedEvents().
*/
static function getSubscribedEvents() {
$events[RdfMappingEvents::MAP_TYPES_FROM_INPUT] = 'mapTypesFromInput';
return $events;
}
}

View File

@ -1,8 +0,0 @@
name: 'RDF module mapping test'
type: module
description: 'Test mapping subscriber for RDF mapping tests.'
package: Testing
core: 8.x
hidden: true
dependencies:
- rdf

View File

@ -1,5 +0,0 @@
services:
rdf_test_mapping.mapping:
class: Drupal\rdf_test_mapping\EventSubscriber\TestMappingSubscriber
tags:
- { name: event_subscriber }

View File

@ -0,0 +1,8 @@
name: 'RDF module namespaces test'
type: module
description: 'Test namespace declaration.'
package: Testing
core: 8.x
hidden: true
dependencies:
- rdf

View File

@ -0,0 +1,17 @@
<?php
/**
* @file
* Test the namespace registration functionality.
*/
/**
* Implements hook_rdf_namespaces().
*/
function rdf_test_namespaces_rdf_namespaces() {
return array(
'dc' => 'http://purl.org/conflicting/namespace',
'foaf' => 'http://xmlns.com/foaf/0.1/',
'foaf1' => 'http://xmlns.com/foaf/0.1/',
);
}

View File

@ -1083,51 +1083,6 @@ function taxonomy_field_settings_form($field, $instance) {
return $form; return $form;
} }
/**
* 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'),
),
'description' => array(
'predicates' => array('skos:definition'),
),
'vid' => array(
'predicates' => array('skos:inScheme'),
'type' => 'rel',
),
'parent' => array(
'predicates' => array('skos:broader'),
'type' => 'rel',
),
),
),
array(
'type' => 'taxonomy_vocabulary',
'bundle' => RDF_DEFAULT_BUNDLE,
'mapping' => array(
'rdftype' => array('skos:ConceptScheme'),
'name' => array(
'predicates' => array('dc:title'),
),
'description' => array(
'predicates' => array('rdfs:comment'),
),
),
),
);
}
/** /**
* @defgroup taxonomy_index Taxonomy indexing * @defgroup taxonomy_index Taxonomy indexing
* @{ * @{

View File

@ -89,34 +89,37 @@ function tracker_page($account = NULL, $set_title = FALSE) {
); );
// Adds extra RDFa markup to the $row array if the RDF module is enabled. // Adds extra RDFa markup to the $row array if the RDF module is enabled.
if (function_exists('rdf_mapping_load')) { if (module_exists('rdf')) {
// Each node is not loaded for performance reasons, as a result we need $mapping = rdf_get_mapping('node', $node->type);
// to retrieve the RDF mapping for each node type.
$mapping = rdf_mapping_load('node', $node->type);
// Adds RDFa markup to the title of the node. Because the RDFa markup is // 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 // 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 // empty datatype to ensure the value of the title read by the RDFa
// parsers is a plain literal. // parsers is a plain literal.
$row['title'] += rdf_rdfa_attributes($mapping['title']) + array('datatype' => ''); $title_mapping = $mapping->getPreparedFieldMapping('title');
$row['title'] += rdf_rdfa_attributes($title_mapping) + array('datatype' => '');
// Annotates the td tag containing the author of the node. // Annotates the td tag containing the author of the node.
$row['author'] += rdf_rdfa_attributes($mapping['uid']); $uid_mapping = $mapping->getPreparedFieldMapping('uid');
$row['author'] += rdf_rdfa_attributes($uid_mapping);
// Annotates the td tag containing the number of replies. We add the // Annotates the td tag containing the number of replies. We add the
// content attribute to ensure that only the comment count is used as // content attribute to ensure that only the comment count is used as
// the value for 'num_replies'. Otherwise, other text such as a link // 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' // to the number of new comments could be included in the 'num_replies'
// value. // value.
$row['replies'] += rdf_rdfa_attributes($mapping['comment_count']); $comment_count_mapping = $mapping->getPreparedFieldMapping('comment_count');
$row['replies'] += rdf_rdfa_attributes($comment_count_mapping);
$row['replies'] += array('content' => $node->comment_count); $row['replies'] += array('content' => $node->comment_count);
// If the node has no comments, we assume the node itself was modified // If the node has no comments, we assume the node itself was modified
// and apply 'changed' in addition to 'last_activity'. If there are // and apply 'changed' in addition to 'last_activity'. If there are
// comments present, we cannot infer whether the node itself was // comments present, we cannot infer whether the node itself was
// modified or a comment was posted, so we use only 'last_activity'. // 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->getPreparedFieldMapping('last_activity');
$last_activity_attributes = rdf_rdfa_attributes($last_activity_mapping, $node->last_activity);
if ($node->comment_count == 0) { if ($node->comment_count == 0) {
$mapping_changed = rdf_rdfa_attributes($mapping['changed'], $node->last_activity); $changed_mapping = $mapping->getPreparedFieldMapping('changed');
$mapping_last_activity['property'] = array_merge($mapping_last_activity['property'], $mapping_changed['property']); $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 // 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 // node the RDFa annotations above apply to. We move the content of

View File

@ -2453,28 +2453,6 @@ function user_cookie_delete($cookie_name) {
setrawcookie('Drupal.visitor.' . $cookie_name, '', REQUEST_TIME - 3600, '/'); setrawcookie('Drupal.visitor.' . $cookie_name, '', REQUEST_TIME - 3600, '/');
} }
/**
* Implements hook_rdf_mapping().
*/
function user_rdf_mapping() {
return array(
array(
'type' => 'user',
'bundle' => RDF_DEFAULT_BUNDLE,
'mapping' => array(
'rdftype' => array('sioc:UserAccount'),
'name' => array(
'predicates' => array('foaf:name'),
),
'homepage' => array(
'predicates' => array('foaf:page'),
'type' => 'rel',
),
),
),
);
}
/** /**
* Implements hook_file_download_access(). * Implements hook_file_download_access().
*/ */

View File

@ -0,0 +1,35 @@
id: comment.comment_node_article
targetEntityType: comment
bundle: comment_node_article
types:
- 'sioc:Post'
- 'sioct:Comment'
fieldMappings:
title:
properties:
- 'dc:title'
created:
properties:
- 'dc:date'
- 'dc:created'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
changed:
properties:
- 'dc:modified'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
comment_body:
properties:
- 'content:encoded'
uid:
properties:
- 'sioc:has_creator'
mapping_type: 'rel'
name:
properties:
- 'foaf:name'
pid:
properties:
- 'sioc:reply_of'
mapping_type: 'rel'

View File

@ -0,0 +1,49 @@
id: node.article
targetEntityType: node
bundle: article
types:
- 'foaf:Document'
- 'sioc:Item'
fieldMappings:
title:
properties:
- 'dc:title'
created:
properties:
- 'dc:date'
- 'dc:created'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
changed:
properties:
- 'dc:modified'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
body:
properties:
- 'content:encoded'
uid:
properties:
- 'sioc:has_creator'
mapping_type: 'rel'
name:
properties:
- 'foaf:name'
comment_count:
properties:
- 'sioc:num_replies'
datatype: 'xsd:integer'
last_activity:
properties:
- 'sioc:last_activity_date'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
field_image:
properties:
- 'og:image'
- 'rdfs:seeAlso'
mapping_type: 'rel'
field_tags:
properties:
- 'dc:subject'
mapping_type: 'rel'

View File

@ -0,0 +1,40 @@
id: node.page
targetEntityType: node
bundle: page
types:
- 'foaf:Document'
- 'sioc:Item'
fieldMappings:
title:
properties:
- 'dc:title'
created:
properties:
- 'dc:date'
- 'dc:created'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
changed:
properties:
- 'dc:modified'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'
body:
properties:
- 'content:encoded'
uid:
properties:
- 'sioc:has_creator'
mapping_type: 'rel'
name:
properties:
- 'foaf:name'
comment_count:
properties:
- 'sioc:num_replies'
datatype: 'xsd:integer'
last_activity:
properties:
- 'sioc:last_activity_date'
datatype: 'xsd:dateTime'
datatype_callback: 'date_iso8601'

View File

@ -0,0 +1,10 @@
id: taxonomy_term.tags
targetEntityType: taxonomy_term
bundle: tags
types:
- 'skos:Concept'
fieldMappings:
name:
properties:
- 'rdfs:label'
- 'skos:prefLabel'

View File

@ -0,0 +1,13 @@
id: user.user
targetEntityType: user
bundle: user
types:
- 'sioc:UserAccount'
fieldMappings:
name:
properties:
- 'foaf:name'
homepage:
properties:
- 'foaf:page'
mapping_type: 'rel'

View File

@ -54,34 +54,6 @@ function standard_install() {
node_add_body_field($type); node_add_body_field($type);
} }
// Insert default pre-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(
'field_image' => array(
'predicates' => array('og:image', 'rdfs:seeAlso'),
'type' => 'rel',
),
'field_tags' => array(
'predicates' => array('dc:subject'),
'type' => 'rel',
),
),
),
);
foreach ($rdf_mappings as $rdf_mapping) {
rdf_mapping_save($rdf_mapping);
}
// Default "Basic page" to not be promoted and have comments disabled. // Default "Basic page" to not be promoted and have comments disabled.
variable_set('node_options_page', array('status')); variable_set('node_options_page', array('status'));
variable_set('comment_page', COMMENT_NODE_HIDDEN); variable_set('comment_page', COMMENT_NODE_HIDDEN);