Commit 58ed8c89 authored by webchick's avatar webchick
Browse files

Issue #1811510 by linclark: Added Enable JSON-LD entity serialization.

parent 99bef1de
name = JSON-LD
description = Serializes entities using JSON-LD format.
package = Core
core = 8.x
<?php
/**
* @file
* Enables entity serialization in JSON-LD.
*/
/**
* Implements hook_help().
*/
function jsonld_help($path, $args) {
switch ($path) {
case 'admin/help#jsonld':
$output = '';
$output .= '<p>' . t('The JSON-LD module serializes entities to the <a href="@jsonld_org">JSON-LD</a> data format. To request JSON-LD instead of HTML, a client should add an Accept header to the request. This module will respond with JSON-LD if the Accept header value is one of the following: application/ld_json, which returns an easy-to-use data structure which is compatible with many external schemas, and application/vnd.drupal.ld+json, which is more expressive and is appropriate for content staging.', array(
'@jsonld_org' => 'http://json-ld.org/',
)) . '</p>';
return $output;
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\DrupalJsonldEncoder.
*/
namespace Drupal\jsonld;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
/**
* Encodes JSON-LD data.
*
* Simply respond to JSON-LD requests using the JSON encoder.
*/
class DrupalJsonldEncoder extends JsonldEncoder implements EncoderInterface {
/**
* The format that this Encoder supports.
*
* @var string
*/
static protected $format = 'drupal_jsonld';
}
<?php
/**
* @file
* Definition of Drupal\jsonld\DrupalJsonldEntityWrapper.
*/
namespace Drupal\jsonld;
/**
* Provide an interface for DrupalJsonldNormalizer to get required properties.
*/
class DrupalJsonldEntityWrapper extends JsonldEntityWrapper {
/**
* Get properties, excluding JSON-LD specific properties.
*
* Format Entity properties for consumption by other Drupal sites. In
* Drupal's vendor specific JSON-LD, fields which correspond to primitives
* have an intermediary data structure between the entity and the value.
*/
public function getProperties() {
// Properties to skip.
$skip = array('id');
// Create language map property structure.
foreach ($this->entity->getTranslationLanguages() as $langcode => $language) {
foreach ($this->entity->getTranslation($langcode) as $name => $field) {
$definition = $this->entity->getPropertyDefinition($name);
$langKey = empty($definition['translatable']) ? 'und' : $langcode;
if (!$field->isEmpty()) {
$properties[$name][$langKey] = $field->getValue();
}
}
}
// Only return properties which are not in the $skip array.
return array_diff_key($properties, array_fill_keys($skip, ''));
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\DrupalJsonldNormalizer.
*/
namespace Drupal\jsonld;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
* Converts the Drupal entity object structure to JSON-LD array structure.
*/
class DrupalJsonldNormalizer extends JsonldNormalizer implements NormalizerInterface {
/**
* The format that this Normalizer supports.
*
* @var string
*/
static protected $format = 'drupal_jsonld';
/**
* The class to use for the entity wrapper object.
*
* @var string
*/
protected $entityWrapperClass = 'Drupal\jsonld\DrupalJsonldEntityWrapper';
}
<?php
/**
* @file
* Definition of Drupal\jsonld\JsonldBundle.
*/
namespace Drupal\jsonld;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\Serializer\Serializer;
/**
* Jsonld dependency injection container.
*/
class JsonldBundle extends Bundle {
/**
* Overrides Symfony\Component\HttpKernel\Bundle\Bundle::build().
*/
public function build(ContainerBuilder $container) {
$priority = 5;
$container->register('serializer.normalizer.jsonld', 'Drupal\jsonld\JsonldNormalizer')->addTag('normalizer', array('priority' => $priority));
$container->register('serializer.encoder.jsonld', 'Drupal\jsonld\JsonldEncoder')->addTag('encoder', array('priority' => $priority));
$container->register('serializer.normalizer.drupal_jsonld', 'Drupal\jsonld\DrupalJsonldNormalizer')->addTag('normalizer', array('priority' => $priority));
$container->register('serializer.encoder.drupal_jsonld', 'Drupal\jsonld\DrupalJsonldEncoder')->addTag('encoder', array('priority' => $priority));
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\JsonldEncoder.
*/
namespace Drupal\jsonld;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
/**
* Encodes JSON-LD data.
*
* Simply respond to JSON-LD requests using the JSON encoder.
*/
class JsonldEncoder extends JsonEncoder implements EncoderInterface {
/**
* The format that this Encoder supports.
*
* @var string
*/
static protected $format = 'jsonld';
/**
* Check whether the request is for JSON-LD.
*
* @param string $format
* The short name of the format returned by ContentNegotiation.
*
* @return bool
* Returns TRUE if the encoder can handle the request.
*/
public function supportsEncoding($format) {
return static::$format === $format;
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\JsonldEntityWrapper.
*/
namespace Drupal\jsonld;
use Drupal\Core\Entity\EntityNG;
/**
* Provide an interface for JsonldNormalizer to get required properties.
*/
class JsonldEntityWrapper {
/**
* The entity that this object wraps.
*
* @var Drupal\Core\Entity\EntityNG
*/
protected $entity;
/**
* Constructor.
*
* @param string $entity
* The Entity API entity
*/
public function __construct(EntityNG $entity) {
$this->entity = $entity;
}
/**
* Get the Entity's URI for the @id attribute.
*/
public function getId() {
$uri_info = $this->entity->uri();
return url($uri_info['path'], array('absolute' => TRUE));
}
/**
* Get properties, excluding JSON-LD specific properties.
*
* Formats Entity properties in the JSON-LD array structure and removes
* unwanted values.
*/
public function getProperties() {
// @todo Add property handling based on http://drupal.org/node/1813328.
return array();
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\JsonldNormalizer.
*/
namespace Drupal\jsonld;
use Drupal\Core\Entity\EntityNG;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
* Converts the Drupal entity object structure to JSON-LD array structure.
*/
class JsonldNormalizer implements NormalizerInterface {
/**
* The format that this Normalizer supports.
*
* @var string
*/
static protected $format = 'jsonld';
/**
* The class to use for the entity wrapper object.
*
* @var string
*/
protected $entityWrapperClass = 'Drupal\jsonld\JsonldEntityWrapper';
/**
* Normalizes an object into a set of arrays/scalars.
*
* @param object $object
* Object to normalize.
* @param string $format
* Format the normalization result will be encoded as.
*
* @return array
* An array containing the properties of the entity and JSON-LD specific
* attributes such as '@context' and '@id'.
*/
public function normalize($object, $format = NULL) {
$entityWrapper = new $this->entityWrapperClass($object);
$attributes = $entityWrapper->getProperties();
$attributes = array('@id' => $entityWrapper->getId()) + $attributes;
return $attributes;
}
/**
* Checks whether the data and format are supported by this normalizer.
*
* @param mixed $data
* Data to normalize.
* @param string $format
* Format the normalization result will be encoded as.
*
* @return bool
* Returns TRUE if the normalizer can handle the request.
*/
public function supportsNormalization($data, $format = NULL) {
// If this is an Entity object and the request is for JSON-LD.
return is_object($data) && ($data instanceof EntityNG) && static::$format === $format;
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\Tests\DrupalJsonldNormalizerTest.
*/
namespace Drupal\jsonld\Tests;
use Drupal\config\Tests\ConfigEntityTest;
use Drupal\Core\Language\Language;
use Drupal\jsonld\DrupalJsonldNormalizer;
use Drupal\jsonld\Tests\JsonldNormalizerTestBase;
/**
* Test the vendor specific JSON-LD normalizer.
*/
class DrupalJsonldNormalizerTest extends JsonldNormalizerTestBase {
/**
* The normalizer to be tested.
*/
protected $normalizer;
public static function getInfo() {
return array(
'name' => 'Drupal JSON-LD Normalizer',
'description' => "Test Drupal's vendor specific JSON-LD normalizer.",
'group' => 'JSON-LD',
);
}
/**
* Add the normalizer to be tested.
*/
function setUp() {
parent::setUp();
$this->normalizer = new DrupalJsonldNormalizer();
}
/**
* Tests the supportsNormalization function.
*/
public function testSupportsNormalization() {
$function = 'DrupalJsonldNormalizer::supportsNormlization';
$supportedFormat = 'drupal_jsonld';
$unsupportedFormat = 'jsonld';
$supportedEntity = entity_create('entity_test', array());
$unsupportedEntity = new ConfigEntityTest();
// Supported entity, supported format.
$this->assertTrue($this->normalizer->supportsNormalization($supportedEntity, $supportedFormat), "$function returns TRUE for supported format.");
// Supported entity, unsupported format.
$this->assertFalse($this->normalizer->supportsNormalization($supportedEntity, $unsupportedFormat), "$function returns FALSE for unsupported format.");
// Unsupported entity, supported format.
$this->assertFalse($this->normalizer->supportsNormalization($unsupportedEntity, $supportedFormat), "$function returns FALSE for unsupported entity type.");
}
/**
* Tests the normalize function.
*/
public function testNormalize() {
// Add German as a language.
$language = new Language(array(
'langcode' => 'de',
'name' => 'Deutsch',
));
language_save($language);
// Create a German entity.
$values = array(
'langcode' => 'de',
'name' => $this->randomName(),
'user_id' => $GLOBALS['user']->uid,
'field_test_text' => array(
'value' => $this->randomName(),
'format' => 'full_html',
),
);
// Array of translated values.
$translationValues = array(
'name' => $this->randomName(),
);
$entity = entity_create('entity_test', $values);
$entity->save();
// Add an English value for name property.
$entity->getTranslation('en')->set('name', array(0 => array('value' => $translationValues['name'])));
$expectedArray = array(
'@id' => $this->getEntityId($entity),
'uuid' => array(
'und' => array(
array(
'value' => $entity->uuid()
),
),
),
'user_id' => array(
'de' => array(
array(
'value' => 1,
),
),
),
'name' => array(
'de' => array(
array(
'value' => $values['name'],
),
),
'en' => array(
array(
'value' => $translationValues['name'],
),
),
),
'field_test_text' => array(
'und' => array(
array(
'value' => $values['field_test_text']['value'],
'format' => $values['field_test_text']['format'],
),
),
),
);
$normalized = $this->normalizer->normalize($entity);
// Test ordering. The @context and @id properties should always be first.
$keys = array_keys($normalized);
$this->assertEqual($keys[0], '@id', '@id and @context attributes placed correctly.');
// Test @id value.
$this->assertEqual($normalized['@id'], $expectedArray['@id'], '@id uses correct value.');
// Test non-translatable field.
$this->assertEqual($normalized['uuid'], $expectedArray['uuid'], 'Non-translatable fields are nested correctly.');
// Test single-language translatable.
$this->assertEqual($normalized['user_id'], $expectedArray['user_id'], 'Translatable field with single language value is nested correctly.');
// Test multi-language translatable.
$this->assertEqual($normalized['name'], $expectedArray['name'], 'Translatable field with multiple language values is nested correctly.');
// Test multi-property untranslatable field.
$this->assertEqual($normalized['field_test_text'], $expectedArray['field_test_text'], 'Field with properties is nested correctly.');
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\Tests\JsonldNormalizerTest.
*/
namespace Drupal\jsonld\Tests;
use Drupal\config\Tests\ConfigEntityTest;
use Drupal\jsonld\JsonldNormalizer;
use Drupal\jsonld\Tests\JsonldNormalizerTestBase;
/**
* Test the default JSON-LD normalizer.
*/
class JsonldNormalizerTest extends JsonldNormalizerTestBase {
/**
* The normalizer to be tested.
*/
protected $normalizer;
public static function getInfo() {
return array(
'name' => 'JSON-LD Normalizer',
'description' => "Test the JSON-LD normalizer.",
'group' => 'JSON-LD',
);
}
/**
* Add the normalizer to be tested.
*/
function setUp() {
parent::setUp();
$this->normalizer = new JsonldNormalizer();
}
/**
* Tests the supportsNormalization function.
*/
public function testSupportsNormalization() {
$function = 'JsonldNormalizer::supportsNormlization';
$supportedFormat = 'jsonld';
$unsupportedFormat = 'drupal_jsonld';
$supportedEntity = entity_create('entity_test', array());
$unsupportedEntity = new ConfigEntityTest();
// Supported entity, supported format.
$this->assertTrue($this->normalizer->supportsNormalization($supportedEntity, $supportedFormat), "$function returns TRUE for supported format.");
// Supported entity, unsupported format.
$this->assertFalse($this->normalizer->supportsNormalization($supportedEntity, $unsupportedFormat), "$function returns FALSE for unsupported format.");
// Unsupported entity, supported format.
$this->assertFalse($this->normalizer->supportsNormalization($unsupportedEntity, $supportedFormat), "$function returns FALSE for unsupported entity type.");
}
}
<?php
/**
* @file
* Definition of Drupal\jsonld\Tests\JsonldTestBase.
*/
namespace Drupal\jsonld\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\config\Tests\ConfigEntityTest;
/**
* Parent class for JSON-LD tests.
*/
abstract class JsonldNormalizerTestBase extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('language', 'entity_test');
/**
* Get the Entity ID.
*
* @param Drupal\Core\Entity\EntityNG $entity
* Entity to get URI for.
*
* @return string
* Return the entity URI.
*/
protected function getEntityId($entity) {
global $base_url;
$uriInfo = $entity->uri();
return $base_url . '/' . $uriInfo['path'];
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment