diff --git a/core/modules/jsonld/jsonld.info b/core/modules/jsonld/jsonld.info new file mode 100644 index 0000000..70d5d40 --- /dev/null +++ b/core/modules/jsonld/jsonld.info @@ -0,0 +1,4 @@ +name = JSON-LD +description = Serializes entities using JSON-LD format. +package = Core +core = 8.x diff --git a/core/modules/jsonld/jsonld.module b/core/modules/jsonld/jsonld.module new file mode 100644 index 0000000..43410fd --- /dev/null +++ b/core/modules/jsonld/jsonld.module @@ -0,0 +1,20 @@ +' . t('The JSON-LD module serializes entities to the JSON-LD 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/', + )) . '

'; + return $output; + } +} diff --git a/core/modules/jsonld/lib/Drupal/jsonld/DrupalJsonldEncoder.php b/core/modules/jsonld/lib/Drupal/jsonld/DrupalJsonldEncoder.php new file mode 100644 index 0000000..33dab76 --- /dev/null +++ b/core/modules/jsonld/lib/Drupal/jsonld/DrupalJsonldEncoder.php @@ -0,0 +1,27 @@ +entity->language()->langcode !== 'und') { + $defaultLangcode = $this->entity->language(); + } + else { + $language = variable_get('language_default'); + $defaultLangcode = $language['langcode']; + } + + // Process all the field values from the default translation. + foreach ($this->entity as $name => $field) { + $definition = $this->entity->getPropertyDefinition($name); + // Add non-translatable values. + if ($definition['translatable'] == FALSE) { + $properties[$name] = $field->getValue(); + } + // Add values in the default language. + else { + $properties[$name][$defaultLangcode] = $field->getValue(); + } + } + // Add translation values. + foreach ($this->entity->getTranslationLanguages(FALSE) as $langcode => $language) { + foreach ($this->entity->getTranslation($langcode) as $name => $field) { + $properties[$name][$langcode] = $field->getValue(); + } + } + + // Only return properties which are not in the $skip array. + return array_diff_key($properties, array_fill_keys($skip, '')); + } + +} diff --git a/core/modules/jsonld/lib/Drupal/jsonld/DrupalJsonldNormalizer.php b/core/modules/jsonld/lib/Drupal/jsonld/DrupalJsonldNormalizer.php new file mode 100644 index 0000000..fec373b --- /dev/null +++ b/core/modules/jsonld/lib/Drupal/jsonld/DrupalJsonldNormalizer.php @@ -0,0 +1,32 @@ +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(); + } +} diff --git a/core/modules/jsonld/lib/Drupal/jsonld/JsonldNormalizer.php b/core/modules/jsonld/lib/Drupal/jsonld/JsonldNormalizer.php new file mode 100644 index 0000000..6bd6db9 --- /dev/null +++ b/core/modules/jsonld/lib/Drupal/jsonld/JsonldNormalizer.php @@ -0,0 +1,68 @@ +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) && is_subclass_of($data, 'Drupal\Core\Entity\EntityNG') && static::$format === $format; + } + +} diff --git a/core/modules/jsonld/lib/Drupal/jsonld/Tests/DrupalJsonldNormalizerTest.php b/core/modules/jsonld/lib/Drupal/jsonld/Tests/DrupalJsonldNormalizerTest.php new file mode 100644 index 0000000..08e3844 --- /dev/null +++ b/core/modules/jsonld/lib/Drupal/jsonld/Tests/DrupalJsonldNormalizerTest.php @@ -0,0 +1,132 @@ + '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('jsonld_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() { + // 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', + ), + ); + + $langSpecificValues = array( + 'name' => $this->randomName(), + ); + + $entity = entity_create('jsonld_test', $values); + $entity->save(); + // Add an English value for name property. + $entity->getTranslation('en')->set('name', array(0 => array('value' => $langSpecificValues['name']))); + + $expectedArray = array( + '@id' => $this->getEntityId($entity), + 'uuid' => 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' => $langSpecificValues['name'], + ), + ), + ), + 'field_test_text' => 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.'); + } + +} diff --git a/core/modules/jsonld/lib/Drupal/jsonld/Tests/JsonldNormalizerTest.php b/core/modules/jsonld/lib/Drupal/jsonld/Tests/JsonldNormalizerTest.php new file mode 100644 index 0000000..6d3a2fc --- /dev/null +++ b/core/modules/jsonld/lib/Drupal/jsonld/Tests/JsonldNormalizerTest.php @@ -0,0 +1,58 @@ + '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('jsonld_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."); + } + +} diff --git a/core/modules/jsonld/lib/Drupal/jsonld/Tests/JsonldNormalizerTestBase.php b/core/modules/jsonld/lib/Drupal/jsonld/Tests/JsonldNormalizerTestBase.php new file mode 100644 index 0000000..dd3ea0d --- /dev/null +++ b/core/modules/jsonld/lib/Drupal/jsonld/Tests/JsonldNormalizerTestBase.php @@ -0,0 +1,39 @@ +uri(); + return $base_url . '/' . $uriInfo['path']; + } + +} diff --git a/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.info b/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.info new file mode 100644 index 0000000..7436c09 --- /dev/null +++ b/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.info @@ -0,0 +1,6 @@ +name = JSON-LD test module +description = Provides entity types for testing JSON-LD. +package = Testing +core = 8.x +dependencies[] = field +hidden = TRUE diff --git a/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.install b/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.install new file mode 100644 index 0000000..9496d0e --- /dev/null +++ b/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.install @@ -0,0 +1,112 @@ + 'field_test_text', + 'type' => 'text', + 'cardinality' => 1, + 'translatable' => FALSE, + ); + field_create_field($field); + + $instance = array( + 'entity_type' => 'jsonld_test', + 'field_name' => 'field_test_text', + 'bundle' => 'jsonld_test', + 'label' => 'Test text-field', + 'widget' => array( + 'type' => 'text_textfield', + 'weight' => 0, + ), + ); + field_create_instance($instance); +} + +/** + * Implements hook_schema(). + */ +function jsonld_test_schema() { + $schema['jsonld_test'] = array( + 'description' => 'Stores jsonld_test items.', + 'fields' => array( + 'id' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'Primary Key: Unique entity-test item ID.', + ), + 'uuid' => array( + 'description' => 'Unique Key: Universally unique identifier for this entity.', + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ), + 'langcode' => array( + 'description' => 'The {language}.langcode of the original variant of this test entity.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => '', + ), + ), + 'primary key' => array('id'), + 'unique keys' => array( + 'uuid' => array('uuid'), + ), + ); + $schema['jsonld_test_property_data'] = array( + 'description' => 'Stores jsonld_test item properties.', + 'fields' => array( + 'id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => 'The {jsonld_test}.id of the test entity.', + ), + 'langcode' => array( + 'description' => 'The {language}.langcode of this variant of this test entity.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => '', + ), + 'default_langcode' => array( + 'description' => 'Boolean indicating whether the current variant is in the original entity language.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 1, + ), + 'name' => array( + 'description' => 'The name of the test entity.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'user_id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + 'default' => NULL, + 'description' => "The {users}.uid of the associated user.", + ), + ), + 'indexes' => array( + 'user_id' => array('user_id'), + ), + 'foreign keys' => array( + 'user_id' => array('users' => 'uid'), + 'id' => array('jsonld_test' => 'id'), + ), + 'primary key' => array('id', 'langcode'), + ); + return $schema; +} diff --git a/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.module b/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.module new file mode 100644 index 0000000..7f9997b --- /dev/null +++ b/core/modules/jsonld/tests/modules/jsonld_test/jsonld_test.module @@ -0,0 +1,25 @@ + t('Test entity'), + 'entity class' => 'Drupal\jsonld_test\JsonldTest', + 'controller class' => 'Drupal\jsonld_test\JsonldTestStorageController', + 'base table' => 'jsonld_test', + 'data table' => 'jsonld_test_property_data', + 'fieldable' => TRUE, + 'entity keys' => array( + 'id' => 'id', + 'uuid' => 'uuid', + ), + ); + return $items; +} diff --git a/core/modules/jsonld/tests/modules/jsonld_test/lib/Drupal/jsonld_test/JsonldTest.php b/core/modules/jsonld/tests/modules/jsonld_test/lib/Drupal/jsonld_test/JsonldTest.php new file mode 100644 index 0000000..3155b8a --- /dev/null +++ b/core/modules/jsonld/tests/modules/jsonld_test/lib/Drupal/jsonld_test/JsonldTest.php @@ -0,0 +1,58 @@ +id); + unset($this->langcode); + unset($this->uuid); + unset($this->name); + unset($this->user_id); + } +} diff --git a/core/modules/jsonld/tests/modules/jsonld_test/lib/Drupal/jsonld_test/JsonldTestStorageController.php b/core/modules/jsonld/tests/modules/jsonld_test/lib/Drupal/jsonld_test/JsonldTestStorageController.php new file mode 100644 index 0000000..016ca69 --- /dev/null +++ b/core/modules/jsonld/tests/modules/jsonld_test/lib/Drupal/jsonld_test/JsonldTestStorageController.php @@ -0,0 +1,55 @@ + t('ID'), + 'description' => t('The ID of the test entity.'), + 'type' => 'integer_field', + 'read-only' => TRUE, + ); + $fields['uuid'] = array( + 'label' => t('UUID'), + 'description' => t('The UUID of the test entity.'), + 'type' => 'string_field', + ); + $fields['langcode'] = array( + 'label' => t('Language code'), + 'description' => t('The language code of the test entity.'), + 'type' => 'language_field', + ); + $fields['name'] = array( + 'label' => t('Name'), + 'description' => t('The name of the test entity.'), + 'type' => 'string_field', + 'translatable' => TRUE, + ); + $fields['user_id'] = array( + 'label' => t('User ID'), + 'description' => t('The ID of the associated user.'), + 'type' => 'entityreference_field', + 'settings' => array('entity type' => 'user'), + 'translatable' => TRUE, + ); + return $fields; + } +}