Browse Source
* Use Context to allow altering the normalized JSON-LD * Implement jsonld hook and do context work in islandora * Add functional test * Namespace ContextReaction ID * Fix reaction id in testpull/756/head
Jared Whiklo
7 years ago
committed by
dannylamb
4 changed files with 321 additions and 0 deletions
@ -0,0 +1,29 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Drupal\islandora\ContextReaction; |
||||||
|
|
||||||
|
use Drupal\context\ContextReactionPluginBase; |
||||||
|
use Drupal\Core\Entity\EntityInterface; |
||||||
|
|
||||||
|
/** |
||||||
|
* Base class to alter the normalizes Json-ld. |
||||||
|
* |
||||||
|
* Plugins must extend this class to be considered for execution. |
||||||
|
* |
||||||
|
* @package Drupal\islandora\ContextReaction |
||||||
|
*/ |
||||||
|
abstract class NormalizerAlterReaction extends ContextReactionPluginBase { |
||||||
|
|
||||||
|
/** |
||||||
|
* This reaction takes can alter the array of json-ld built from the entity. |
||||||
|
* |
||||||
|
* @param \Drupal\Core\Entity\EntityInterface|null $entity |
||||||
|
* The entity we are normalizing. |
||||||
|
* @param array|null $normalized |
||||||
|
* The normalized json-ld before encoding. |
||||||
|
* @param array|null $context |
||||||
|
* The context used in the normalizer. |
||||||
|
*/ |
||||||
|
abstract public function execute(EntityInterface $entity = NULL, array &$normalized = NULL, array $context = NULL); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,126 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Drupal\islandora\Plugin\ContextReaction; |
||||||
|
|
||||||
|
use Drupal\Core\Entity\EntityInterface; |
||||||
|
use Drupal\Core\Form\FormStateInterface; |
||||||
|
use Drupal\islandora\ContextReaction\NormalizerAlterReaction; |
||||||
|
use Drupal\jsonld\Normalizer\NormalizerBase; |
||||||
|
|
||||||
|
/** |
||||||
|
* Map URI to predicate context reaction. |
||||||
|
* |
||||||
|
* @ContextReaction( |
||||||
|
* id = "islandora_map_uri_predicate", |
||||||
|
* label = @Translation("Map URI to predicate") |
||||||
|
* ) |
||||||
|
*/ |
||||||
|
class MappingUriPredicateReaction extends NormalizerAlterReaction { |
||||||
|
|
||||||
|
const URI_PREDICATE = 'drupal_uri_predicate'; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function summary() { |
||||||
|
return $this->t('Map Drupal URI to configured predicate.'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function execute(EntityInterface $entity = NULL, array &$normalized = NULL, array $context = NULL) { |
||||||
|
$config = $this->getConfiguration(); |
||||||
|
$drupal_predicate = $config[self::URI_PREDICATE]; |
||||||
|
if (!is_null($drupal_predicate) && !empty($drupal_predicate)) { |
||||||
|
$url = $entity |
||||||
|
->toUrl('canonical', ['absolute' => TRUE]) |
||||||
|
->setRouteParameter('_format', 'jsonld') |
||||||
|
->toString(); |
||||||
|
if ($context['needs_jsonldcontext'] === FALSE) { |
||||||
|
$drupal_predicate = NormalizerBase::escapePrefix($drupal_predicate, $context['namespaces']); |
||||||
|
} |
||||||
|
if (isset($normalized['@graph']) && is_array($normalized['@graph'])) { |
||||||
|
foreach ($normalized['@graph'] as &$graph) { |
||||||
|
if (isset($graph['@id']) && $graph['@id'] == $url) { |
||||||
|
if (isset($graph[$drupal_predicate])) { |
||||||
|
if (!is_array($graph[$drupal_predicate])) { |
||||||
|
if ($graph[$drupal_predicate] == $url) { |
||||||
|
// Don't add it if it already exists. |
||||||
|
return; |
||||||
|
} |
||||||
|
$tmp = $graph[$drupal_predicate]; |
||||||
|
$graph[$drupal_predicate] = [$tmp]; |
||||||
|
} |
||||||
|
elseif (array_search($url, array_column($graph[$drupal_predicate], '@value'))) { |
||||||
|
// Don't add it if it already exists. |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
$graph[$drupal_predicate] = []; |
||||||
|
} |
||||||
|
$graph[$drupal_predicate][] = ["@value" => $url]; |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { |
||||||
|
$config = $this->getConfiguration(); |
||||||
|
$form[self::URI_PREDICATE] = [ |
||||||
|
'#type' => 'textfield', |
||||||
|
'#title' => $this->t('Drupal URI predicate'), |
||||||
|
'#description' => $this->t("The Drupal object's URI will be added to the resource with this predicate. Must use a defined prefix."), |
||||||
|
'#default_value' => isset($config[self::URI_PREDICATE]) ? $config[self::URI_PREDICATE] : '', |
||||||
|
'#size' => 35, |
||||||
|
]; |
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { |
||||||
|
$drupal_predicate = $form_state->getValue(self::URI_PREDICATE); |
||||||
|
if (!is_null($drupal_predicate) and !empty($drupal_predicate)) { |
||||||
|
if (preg_match('/^https?:\/\//', $drupal_predicate)) { |
||||||
|
// Can't validate all URIs so we have to trust them. |
||||||
|
return; |
||||||
|
} |
||||||
|
elseif (preg_match('/^([^\s:]+):/', $drupal_predicate, $matches)) { |
||||||
|
$predicate_prefix = $matches[1]; |
||||||
|
$rdf = rdf_get_namespaces(); |
||||||
|
$rdf_prefixes = array_keys($rdf); |
||||||
|
if (!in_array($predicate_prefix, $rdf_prefixes)) { |
||||||
|
$form_state->setErrorByName( |
||||||
|
self::URI_PREDICATE, |
||||||
|
$this->t('Namespace prefix @prefix is not registered.', |
||||||
|
['@prefix' => $predicate_prefix] |
||||||
|
) |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
$form_state->setErrorByName( |
||||||
|
self::URI_PREDICATE, |
||||||
|
$this->t('Predicate must use a defined prefix or be a full URI') |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
parent::validateConfigurationForm($form, $form_state); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { |
||||||
|
$this->setConfiguration([self::URI_PREDICATE => $form_state->getValue(self::URI_PREDICATE)]); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,156 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Drupal\Tests\islandora\Functional; |
||||||
|
|
||||||
|
/** |
||||||
|
* Class MappingUriPredicateReactionTest. |
||||||
|
* |
||||||
|
* @package Drupal\Tests\islandora\Functional |
||||||
|
* @group islandora |
||||||
|
*/ |
||||||
|
class MappingUriPredicateReactionTest extends IslandoraFunctionalTestBase { |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function setUp() { |
||||||
|
parent::setUp(); |
||||||
|
|
||||||
|
$types = ['schema:Thing']; |
||||||
|
$created_mapping = [ |
||||||
|
'properties' => ['schema:dateCreated'], |
||||||
|
'datatype' => 'xsd:dateTime', |
||||||
|
'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], |
||||||
|
]; |
||||||
|
|
||||||
|
// Save bundle mapping config. |
||||||
|
$this->rdfMapping = rdf_get_mapping('node', 'test_type') |
||||||
|
->setBundleMapping(['types' => $types]) |
||||||
|
->setFieldMapping('created', $created_mapping) |
||||||
|
->setFieldMapping('title', [ |
||||||
|
'properties' => ['dc:title'], |
||||||
|
'datatype' => 'xsd:string', |
||||||
|
]) |
||||||
|
->save(); |
||||||
|
|
||||||
|
$resourceConfigStorage = $this->container |
||||||
|
->get('entity_type.manager') |
||||||
|
->getStorage('rest_resource_config'); |
||||||
|
// There is already a setting for entity.node, so delete it. |
||||||
|
$resourceConfigStorage |
||||||
|
->delete($resourceConfigStorage |
||||||
|
->loadMultiple(['entity.node'])); |
||||||
|
// Create it new. |
||||||
|
$resourceConfigStorage->create([ |
||||||
|
'id' => 'entity.node', |
||||||
|
'granularity' => 'resource', |
||||||
|
'configuration' => [ |
||||||
|
'methods' => ['GET'], |
||||||
|
'authentication' => ['basic_auth', 'cookie'], |
||||||
|
'formats' => ['jsonld'], |
||||||
|
], |
||||||
|
'status' => TRUE, |
||||||
|
])->save(TRUE); |
||||||
|
|
||||||
|
$this->container->get('router.builder')->rebuildIfNeeded(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @covers \Drupal\islandora\Plugin\ContextReaction\MappingUriPredicateReaction |
||||||
|
*/ |
||||||
|
public function testMappingReaction() { |
||||||
|
$account = $this->drupalCreateUser([ |
||||||
|
'bypass node access', |
||||||
|
'administer contexts', |
||||||
|
]); |
||||||
|
$this->drupalLogin($account); |
||||||
|
|
||||||
|
$context_name = 'test'; |
||||||
|
$reaction_id = 'islandora_map_uri_predicate'; |
||||||
|
|
||||||
|
$this->postNodeAddForm('test_type', |
||||||
|
['title[0][value]' => 'Test Node'], |
||||||
|
t('Save')); |
||||||
|
$this->assertSession()->pageTextContains("Test Node"); |
||||||
|
$url = $this->getUrl(); |
||||||
|
|
||||||
|
// Make sure the node exists. |
||||||
|
$this->drupalGet($url); |
||||||
|
$this->assertSession()->statusCodeEquals(200); |
||||||
|
|
||||||
|
$contents = $this->drupalGet($url . '?_format=jsonld'); |
||||||
|
$this->assertSession()->statusCodeEquals(200); |
||||||
|
$json = \GuzzleHttp\json_decode($contents, TRUE); |
||||||
|
$this->assertArrayHasKey('http://purl.org/dc/terms/title', |
||||||
|
$json['@graph'][0], 'Missing dcterms:title key'); |
||||||
|
$this->assertEquals( |
||||||
|
'Test Node', |
||||||
|
$json['@graph'][0]['http://purl.org/dc/terms/title'][0]['@value'], |
||||||
|
'Missing title value' |
||||||
|
); |
||||||
|
$this->assertArrayNotHasKey('http://www.w3.org/2002/07/owl#sameAs', |
||||||
|
$json['@graph'][0], 'Has predicate when not configured'); |
||||||
|
|
||||||
|
$this->createContext('Test', $context_name); |
||||||
|
$this->drupalGet("admin/structure/context/$context_name/reaction/add/$reaction_id"); |
||||||
|
$this->assertSession()->statusCodeEquals(200); |
||||||
|
|
||||||
|
$this->drupalGet("admin/structure/context/$context_name"); |
||||||
|
// Can't use an undefined prefix. |
||||||
|
$this->getSession()->getPage() |
||||||
|
->fillField("Drupal URI predicate", "bob:smith"); |
||||||
|
$this->getSession()->getPage()->pressButton("Save and continue"); |
||||||
|
$this->assertSession() |
||||||
|
->pageTextContains("Namespace prefix bob is not registered"); |
||||||
|
|
||||||
|
// Can't use a straight string. |
||||||
|
$this->getSession()->getPage() |
||||||
|
->fillField("Drupal URI predicate", "woohoo"); |
||||||
|
$this->getSession()->getPage()->pressButton("Save and continue"); |
||||||
|
$this->assertSession() |
||||||
|
->pageTextContains("Predicate must use a defined prefix or be a full URI"); |
||||||
|
|
||||||
|
// Use an existing prefix. |
||||||
|
$this->getSession()->getPage() |
||||||
|
->fillField("Drupal URI predicate", "owl:sameAs"); |
||||||
|
$this->getSession()->getPage()->pressButton("Save and continue"); |
||||||
|
$this->assertSession() |
||||||
|
->pageTextContains("The context $context_name has been saved"); |
||||||
|
|
||||||
|
$new_contents = $this->drupalGet($url . '?_format=jsonld'); |
||||||
|
$json = \GuzzleHttp\json_decode($new_contents, TRUE); |
||||||
|
$this->assertEquals( |
||||||
|
'Test Node', |
||||||
|
$json['@graph'][0]['http://purl.org/dc/terms/title'][0]['@value'], |
||||||
|
'Missing title value' |
||||||
|
); |
||||||
|
$this->assertEquals( |
||||||
|
"$url?_format=jsonld", |
||||||
|
$json['@graph'][0]['http://www.w3.org/2002/07/owl#sameAs'][0]['@value'], |
||||||
|
'Missing alter added predicate.' |
||||||
|
); |
||||||
|
|
||||||
|
$this->drupalGet("admin/structure/context/$context_name"); |
||||||
|
// Change to a random URL. |
||||||
|
$this->getSession()->getPage() |
||||||
|
->fillField("Drupal URI predicate", "http://example.org/first/second"); |
||||||
|
$this->getSession()->getPage()->pressButton("Save and continue"); |
||||||
|
$this->assertSession() |
||||||
|
->pageTextContains("The context $context_name has been saved"); |
||||||
|
$new_contents = $this->drupalGet($url . '?_format=jsonld'); |
||||||
|
$json = \GuzzleHttp\json_decode($new_contents, TRUE); |
||||||
|
$this->assertEquals( |
||||||
|
'Test Node', |
||||||
|
$json['@graph'][0]['http://purl.org/dc/terms/title'][0]['@value'], |
||||||
|
'Missing title value' |
||||||
|
); |
||||||
|
$this->assertArrayNotHasKey('http://www.w3.org/2002/07/owl#sameAs', |
||||||
|
$json['@graph'][0], 'Still has old predicate'); |
||||||
|
$this->assertEquals( |
||||||
|
"$url?_format=jsonld", |
||||||
|
$json['@graph'][0]['http://example.org/first/second'][0]['@value'], |
||||||
|
'Missing alter added predicate.' |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue