Skip to content
This repository has been archived by the owner on Aug 25, 2022. It is now read-only.

Graph refactoring #13

Merged
merged 30 commits into from
Jan 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d088448
RDF Entity module requires PHP >=7.1.
claudiu-cristea Jan 9, 2018
5a05af6
Fix docs in src/RdfGraphHandler.
claudiu-cristea Jan 9, 2018
e404205
Add schema for 'rdf_entity_graph' and 'rdf_entity_mapping' entities.
claudiu-cristea Jan 9, 2018
3532abe
Move mapping config from bundle 3rd party settings to dedicated confi…
claudiu-cristea Jan 9, 2018
05be3d9
Use the mapping stored in the dedicated config entity.
claudiu-cristea Jan 9, 2018
a946220
Add the rdf_entity_graph config entity.
claudiu-cristea Jan 9, 2018
1ea6809
Additional checks for field existence in base fields mapping.
claudiu-cristea Jan 9, 2018
edfdde7
Update path: move mapping configs in their dedicated storage.
claudiu-cristea Jan 9, 2018
d5dc9b1
Add an interface to RdfEntityGraph class.
claudiu-cristea Jan 10, 2018
4d703dc
Expand the RdfEntityMapping with setters and getters.
claudiu-cristea Jan 10, 2018
28ec21f
Fix the return type.
claudiu-cristea Jan 10, 2018
d30b89d
YAML standards on rdf_draft.info.yml.
claudiu-cristea Jan 10, 2018
885d3e4
::getGraph() was renamed to ::getGraphUri().
claudiu-cristea Jan 10, 2018
ae40916
Add setters/getters and a new property 'entity_types' to RdfEntityGraph.
claudiu-cristea Jan 10, 2018
5b62742
Refactor \Drupal\rdf_entity\RdfGraphHandler::getGraphDefinitions().
claudiu-cristea Jan 10, 2018
7fa3c20
Add the 'draft' graph.
claudiu-cristea Jan 10, 2018
d19927b
Change the label of 'default' graph to 'Published' when rdf_draft mod…
claudiu-cristea Jan 10, 2018
2f7a793
Completely modernize RdfGraphHandler & RdfEntitySparqlStorage
claudiu-cristea Jan 10, 2018
5181d63
Additional fixes.
claudiu-cristea Jan 19, 2018
39f4366
Add reference to #15 follow-up.
claudiu-cristea Jan 22, 2018
4d00706
Rename rdf_entity_get_third_party_property() to rdf_entity_get_mappin…
claudiu-cristea Jan 22, 2018
4f369a0
Allow the exception to propagate when saving a mapping in the UI.
claudiu-cristea Jan 22, 2018
322d6d8
Remove stale @todo.
claudiu-cristea Jan 22, 2018
ccc59d8
Throw exception when invalid graphs are passed to storage loaders.
claudiu-cristea Jan 22, 2018
0ae10cd
Missing strict type declaration.
claudiu-cristea Jan 22, 2018
0d15115
Typo in RdfEntityGraphToggle docs.
claudiu-cristea Jan 22, 2018
11b92c7
Improve wording in API.md.
claudiu-cristea Jan 22, 2018
de7fb03
Use the RdfGraphHandlerInterface instead of class on type hinting.
claudiu-cristea Jan 23, 2018
31828f7
Unmute some exceptions.
claudiu-cristea Jan 23, 2018
477f582
Add followups to some @todos.
claudiu-cristea Jan 23, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# RDF Entity API

@todo This document is under development.

## RDF Graphs

Entities using the SPARQL storage can be stored in different graphs. Graphs can
be used to store different versions or states of the same entity. Depending on
the use case you can use graphs to store a draft version of the entity.

### RDF graphs storage

Graphs are handled by the `RdfGraphHandler` service which is injected in the
`Query` and the `RdfEntitySparqlStorage` classes. There are a number of methods
offered to handle the graphs.

### Graphs CRUD

Graphs are config entities of type `rdf_entity_graph` and are supported by the
Drupal API. You can add, edit, delete graphs also by using the UI provided at
`/admin/config/rdf_entity/graph`. The `default` graph, shipped with `rdf_entity`
module cannot be deleted or restricted to specific entity types. However, you
can still edit its name and description. Only enabled graphs are taken into
account by the SPARQL backend.

The order of graph entities is important. You can configure a priority by
settings the `weight` property. Also this could be done in the UI.

### Handling entities and graphs

#### Entity creation

Set a specific graph to a new entity:

```php
$storage = \Drupal::entityTypeManager()->getStorage('food');
$entity = $storage->create([
'id' => 'http://example.com',
'type' => 'fruit',
'graph' => 'draft',
]);
$entity->save();
```

If no `'graph'` is set, the entity will be saved in the topmost graph. The
topmost graph is the graph witch has the lowest `weight` property.

#### Reading the graph of an entity

```php
$graph_id = $entity->get('graph')->value;
// or...
$graph_id = $entity->graph->value;

```

#### Loading an entity from a specific graph

```php
$storage = \Drupal::entityTypeManager()->getStorage('food');

// Load from the default graph (the tompost graph in the list).
$entity = $storage->load($id);

// Load from the 'draft' graph.
$entity = $storage->load($id, ['draft']);

// Load from the first graph where the entity exists. First, the storage will
// attempt to load the entity from the 'draft' graph. If this entity doesn't
// exist in the 'draft' graph, will fallback to the next one which is 'sync' and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking to be commented: I haven't looked into all the changes yet, but last time I checked, all triples were returned from the database from all available graphs. The triples were the processed by the RdfEntitySparqlStorage class and the appropriate entity was returned instead.

To be checked later on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

he triples were the processed by the RdfEntitySparqlStorage

Yes. this ($storage) is actually a RdfEntitySparqlStorage class. So, it returns a single entity, not all.

// so on. If the entity is not found in any of the graphs, normal behaviour is
// in place: will return NULL.
$entity = $storage->load($id, ['draft', 'sync', 'obsolete', ...]);

// Load multiple entities using a graph candidate list.
$entities = $storage->loadMultiple($ids, ['draft', 'sync', 'obsolete', ...]);
```

**Note**: When the list of graph candidates is not specified (first example),
the candidates are all enabled graph entities, ordered by the weight property.

#### Saving in a different graph

```php
$storage = \Drupal::entityTypeManager()->getStorage('food');
$entity = $storage->load($id, ['draft']);
$entity->set('graph', 'default')->save();
```

#### Using graphs with entity query

```php
$storage = \Drupal::entityTypeManager()->getStorage('food');
$query = $storage->getQuery;
$ids = $query
->condition('type', 'fruit')
->setGraphType(['default', 'draft'])
->execute();
```
7 changes: 7 additions & 0 deletions config/install/rdf_entity.graph.default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
langcode: en
status: true
id: default
weight: 0
name: Default
description: 'Default graph. This is available for all entity types and bundles.'
entity_types: null
95 changes: 64 additions & 31 deletions config/schema/rdf_entity.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,6 @@ rdf_entity.rdfentity.*:
type: text
label: 'Explanation or submission guidelines'

rdf_entity.rdfentity.*.third_party.rdf_entity:
type: mapping
label: 'Third party settings'
mapping:
rdf_type:
type: string
label: 'Rdf type mapping'
graph:
type: sequence
sequence:
type: string
label: 'The mapping of a graph definition to a graph uri.'
mapping:
type: sequence
label: 'Property'
sequence:
type: sequence
label: 'Column'
sequence:
type: mapping
mapping:
predicate:
type: string
label: 'Predicate'
format:
type: string
label: 'Value format'
entity_id_plugin:
type: string
label: 'The plugin that generates the entity ID'

field.storage.*.*.third_party.rdf_entity:
type: mapping
mapping:
Expand Down Expand Up @@ -86,3 +55,67 @@ field.formatter.third_party.joinup:
mapping:
template_suggestion:
type: string

rdf_entity.graph.*:
type: config_entity
label: 'RDF entity graph'
mapping:
id:
type: string
label: ID
weight:
type: integer
label: Weight
name:
type: label
label: Name
description:
type: text
label: Description
entity_types:
type: sequence
nullable: true
label: 'Entity types'
sequence:
type: string
label: 'Entity type'

rdf_entity.mapping.*:
type: config_entity
label: 'Stores the mapping between Drupal bundle settings and RDF representation'
mapping:
id:
type: string
label: ID
entity_type_id:
type: string
label: 'Referred entity type'
bundle:
type: string
label: 'Referred bundle'
rdf_type:
type: string
label: 'RDF type mapping'
graph:
type: sequence
sequence:
type: string
label: 'The mapping of a graph definition to a graph URI.'
base_fields_mapping:
type: sequence
label: 'The base fields mapping'
sequence:
type: sequence
label: 'Column'
sequence:
type: mapping
mapping:
predicate:
type: string
label: 'Predicate'
format:
type: string
label: 'Value format'
entity_id_plugin:
type: string
label: 'The plugin that generates the entity ID'
7 changes: 7 additions & 0 deletions modules/rdf_draft/config/install/rdf_entity.graph.draft.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
langcode: en
status: true
id: draft
weight: 10
name: Draft
description: 'Draft graph.'
entity_types: null
16 changes: 0 additions & 16 deletions modules/rdf_draft/config/schema/rdf_draft.schema.yml

This file was deleted.

6 changes: 3 additions & 3 deletions modules/rdf_draft/rdf_draft.info.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: RDF draft
name: 'RDF draft'
type: module
description: Brings the notion of a draft graph to RDF entities.
description: 'Brings the notion of a draft graph to RDF entities.'
core: 8.x
package: Joinup
package: Custom
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could have our own name since all of these modules are related to RDF data. 'RDF Entity' could do for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right but I expanded too much the initial scope of this issue. Opened #14 to do this change.

dependencies:
- rdf_entity
32 changes: 32 additions & 0 deletions modules/rdf_draft/rdf_draft.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* @file
* Includes installation functions for the rdf_draft module.
*/

use Drupal\Core\Serialization\Yaml;
use Drupal\rdf_entity\Entity\RdfEntityGraph;
use Drupal\rdf_entity\RdfEntityGraphInterface;

/**
* Implements hook_install().
*/
function rdf_draft_install() {
// Change the label of the 'default' graph to 'Published'.
if ($default = RdfEntityGraph::load(RdfEntityGraphInterface::DEFAULT)) {
$default->setName('Published')->save();
}
}

/**
* Install the 'draft' config entity.
*/
function rdf_draft_update_8001() {
// Update or post-update scripts might need this config entity available when
// they run. We don't wait on configuration synchronization, because that runs
// usually after the database update, so we make this entity available in an
// early stage of updates.
$values = Yaml::decode(file_get_contents(__DIR__ . '/config/install/rdf_entity.graph.draft.yml'));
RdfEntityGraph::create($values)->save();
}
5 changes: 0 additions & 5 deletions modules/rdf_draft/rdf_draft.links.menu.yml

This file was deleted.

77 changes: 24 additions & 53 deletions modules/rdf_draft/rdf_draft.module
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,8 @@
*/

use Drupal\Core\Entity\EntityInterface;
use Drupal\rdf_entity\Entity\RdfEntitySparqlStorage;

/**
* Implements hook_rdf_graph_definition_alter().
*/
function rdf_draft_rdf_graph_definition_alter($entity_type_id, &$definitions) {
// @todo Replace this hard-coded setting with a settings form
// where you can enable entity types.
if (!(\Drupal::entityManager()->getStorage($entity_type_id) instanceof RdfEntitySparqlStorage)) {
return;
}

$definitions['default']['title'] = t('Published');
$definitions['draft'] = [
'title' => t('Draft'),
'description' => t('The draft graph used to store entities of this type.'),
];
}
use Drupal\rdf_entity\RdfEntitySparqlStorageInterface;
use Drupal\rdf_entity\RdfEntityGraphInterface;

/**
* Implements hook_entity_type_alter().
Expand All @@ -35,29 +19,20 @@ function rdf_draft_entity_type_alter(array &$entity_types) {
return;
}

$config = \Drupal::config('rdf_draft.settings');
foreach ($entity_types as $entity_type_id => $entity_type) {
if (
// This entity type is not eligible for RDF Draft.
!($bundles = $config->get("revision_bundle_{$entity_type_id}"))
// Or doesn't have any 'draft' enabled bundle.
|| !array_filter($bundles)
// Or doesn't have a view builder class.
|| !$entity_type->hasViewBuilderClass()
// Or is missing a canonical link template.
|| !$entity_type->hasLinkTemplate('canonical')
) {
continue;
}
/** @var \Drupal\rdf_entity\RdfGraphHandlerInterface $graph_handler */
$graph_handler = \Drupal::service('sparql.graph_handler');

$recurse = TRUE;
$storage = \Drupal::entityTypeManager()->getStorage($entity_type_id);
$recurse = FALSE;
$definitions = $storage->getGraphDefinitions();
unset($definitions['default']);
// Set the link templates for each graph type.
foreach ($definitions as $name => $definition) {
$entity_type->setLinkTemplate('rdf-draft-' . $name, "/$entity_type_id/{{$entity_type_id}}/graph/$name");
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
foreach ($entity_types as $entity_type_id => $entity_type) {
if ($entity_type->hasViewBuilderClass() && $entity_type->hasLinkTemplate('canonical')) {
$recurse = TRUE;
$graphs = $graph_handler->getGraphDefinitions($entity_type_id);
$recurse = FALSE;
foreach ($graphs as $graph_id => $graph) {
if ($graph_id !== RdfEntityGraphInterface::DEFAULT) {
$entity_type->setLinkTemplate("rdf-draft-$graph_id", "/$entity_type_id/{{$entity_type_id}}/graph/$graph_id");
}
}
}
}
}
Expand All @@ -67,25 +42,21 @@ function rdf_draft_entity_type_alter(array &$entity_types) {
*/
function rdf_draft_entity_operation(EntityInterface $entity) {
$operations = [];
$storage = \Drupal::service('entity.manager')->getStorage($entity->getEntityTypeId());
if ($storage instanceof RdfEntitySparqlStorage) {
$definitions = $storage->getGraphDefinitions();
foreach ($definitions as $name => $definition) {
if ($entity->hasLinkTemplate('rdf-draft-' . $name) && $entity->hasGraph($name)) {

/** @var \Drupal\rdf_entity\RdfEntitySparqlStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId());

if ($storage instanceof RdfEntitySparqlStorageInterface) {
foreach ($storage->getGraphDefinitions() as $name => $definition) {
$link_template = "rdf-draft-$name";
if ($entity->hasLinkTemplate($link_template) && $storage->hasGraph($entity, $name)) {
$operations[$name] = [
'title' => t('View @graph', ['@graph' => $name]),
'weight' => 100,
'url' => $entity->toUrl('rdf-draft-' . $name),
'url' => $entity->toUrl($link_template),
];
}
}
}
return $operations;
}

/**
* Implements hook_rdf_default_active_graph_alter().
*/
function rdf_draft_rdf_default_active_graph_alter($entity_type, &$graph) {
$graph[] = 'draft';
}
Loading