Skip to content

Instantly share code, notes, and snippets.

@imcbride
Last active September 15, 2022 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imcbride/ad84cb06e6a76983ba1a6b69d940a17e to your computer and use it in GitHub Desktop.
Save imcbride/ad84cb06e6a76983ba1a6b69d940a17e to your computer and use it in GitHub Desktop.
diff --git a/config/schema/jsonapi_reference.schema.yml b/config/schema/jsonapi_reference.schema.yml
index 98a8eca..5a18a2c 100644
--- a/config/schema/jsonapi_reference.schema.yml
+++ b/config/schema/jsonapi_reference.schema.yml
@@ -2,13 +2,19 @@ field.storage_settings.typed_resource_object:
type: mapping
label: 'Typed resource object storage settings'
mapping:
+ jsonapi_reference_entity:
+ type: string
+ label: 'Reference entrypoint'
resource_object_type:
type: string
label: 'Resource Object Type'
-jsonapi_reference.settings:
- type: config_object
- label: 'JSON:API reference settings'
+jsonapi_reference.settings.*:
+ type: config_entity
+ label: 'JSON:API reference configuration'
mapping:
+ id:
+ type: string
+ label: 'ID'
endpoint:
type: string
label: 'Entrypoint containing JSON:API objects to which we refer'
diff --git a/jsonapi_reference.info.yml b/jsonapi_reference.info.yml
index 64ce2ea4e9..81c5596bb7 100644
--- a/jsonapi_reference.info.yml
+++ b/jsonapi_reference.info.yml
@@ -3,7 +3,10 @@ type: module
description: 'Provides a field for referencing remote data elements via JSON:API'
core_version_requirement: ^8 || ^9 || ^10
package: 'Field types'
-configure: jsonapi_reference.json_api_reference_config_form
+configure: entity.jsonapi_reference.collection
+
+test_dependencies:
+ - drupal:jsonapi
# Information added by Drupal.org packaging script on 2022-09-13
version: '8.x-1.0-alpha3'
diff --git a/jsonapi_reference.install b/jsonapi_reference.install
new file mode 100644
index 0000000..6afc14a
--- /dev/null
+++ b/jsonapi_reference.install
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * jsonapi_reference.install
+ */
+
+use Drupal\jsonapi_reference\Entity\JsonApiReference;
+use Drupal\field\Entity\FieldStorageConfig;
+
+/**
+ * Migrate the existing jsonapi_reference configuration to the new format.
+ */
+function jsonapi_reference_update_8101() {
+ // Calling to flush all caches feels like hammering a nail with a tank.
+ // Perhaps this could be more specific to the cache we need to clear for the
+ // new entity to be picked up?
+ drupal_flush_all_caches();
+
+ /** @var \Drupal\Core\Config\CacheConfig $config_storage */
+ $config_storage = \Drupal::service('config.storage');
+
+ $existing_config = $config_storage->read('jsonapi_reference.settings');
+
+ if ($existing_config['endpoint']) {
+ // Create the new config entity.
+ JsonApiReference::create([
+ 'id' => 'original_reference',
+ 'entrypoint' => $existing_config['endpoint'],
+ 'username' => $existing_config['username'],
+ 'password' => $existing_config['password'],
+ ])->save();
+
+ // Remove the no-longer-used stored configuration.
+ $config_storage->delete('jsonapi_reference.settings');
+
+ if (!$field_storage_configs = \Drupal::service('entity_type.manager')
+ ->getStorage('field_storage_config')
+ ->loadByProperties(['type' => 'typed_resource_object'])
+ ) {
+ return;
+ }
+
+ foreach ($field_storage_configs as $field_storage) {
+ $new_field_storage = $field_storage->toArray();
+ $new_field_storage['settings']['jsonapi_reference_entity'] = 'original_reference';
+ $new_field_storage = FieldStorageConfig::create($new_field_storage);
+ $new_field_storage->original = $new_field_storage;
+ $new_field_storage->enforceIsNew(FALSE);
+ $new_field_storage->save();
+ }
+ }
+}
\ No newline at end of file
diff --git a/jsonapi_reference.links.action.yml b/jsonapi_reference.links.action.yml
new file mode 100644
index 0000000..53dac50
--- /dev/null
+++ b/jsonapi_reference.links.action.yml
@@ -0,0 +1,5 @@
+jsonapi_reference.json_api_reference_add_form:
+ route_name: 'entity.jsonapi_reference.add_form'
+ title: 'Add JSON:API Reference'
+ appears_on:
+ - 'entity.jsonapi_reference.collection'
diff --git a/jsonapi_reference.links.menu.yml b/jsonapi_reference.links.menu.yml
index d623e3c..b0c69f5 100644
--- a/jsonapi_reference.links.menu.yml
+++ b/jsonapi_reference.links.menu.yml
@@ -1,6 +1,6 @@
-jsonapi_reference.json_api_reference_config_form:
+entity.jsonapi_reference.collection:
title: 'JSON:API Reference'
- route_name: jsonapi_reference.json_api_reference_config_form
- description: 'Configure access to the remote JSON:API system for referencing in Typed Resource Object fields.'
+ route_name: entity.jsonapi_reference.collection
+ description: 'Configure access to remote JSON:API systems for referencing in Typed Resource Object fields.'
parent: system.admin_config_services
weight: 99
diff --git a/jsonapi_reference.routing.yml b/jsonapi_reference.routing.yml
index 29f30ce..4179b6d 100644
--- a/jsonapi_reference.routing.yml
+++ b/jsonapi_reference.routing.yml
@@ -1,5 +1,5 @@
jsonapi_reference.typed_resource_controller_autocomplete:
- path: '/jsonapi-reference/typed-resource-autocomplete/{resource_object_type}/{autocomplete_attribute}'
+ path: '/jsonapi-reference/typed-resource-autocomplete/{resource_object_type}/{jsonapi_reference}/{autocomplete_attribute}'
defaults:
_controller: '\Drupal\jsonapi_reference\Controller\TypedResourceController::autocomplete'
_format: json
@@ -7,7 +7,7 @@ jsonapi_reference.typed_resource_controller_autocomplete:
_permission: 'access jsonapi autocomplete'
jsonapi_reference.json_api_reference_config_form:
- path: '/admin/config/jsonapi_reference'
+ path: '/admin/config/services/jsonapi-reference'
defaults:
_form: '\Drupal\jsonapi_reference\Form\JsonApiReferenceConfigForm'
_title: 'JSON:API Reference'
@@ -15,3 +15,35 @@ jsonapi_reference.json_api_reference_config_form:
_permission: 'configure jsonapi reference'
options:
_admin_route: TRUE
+
+entity.jsonapi_reference.collection:
+ path: '/admin/config/services/jsonapi-reference'
+ defaults:
+ _entity_list: 'jsonapi_reference'
+ _title: 'JSON:API Reference'
+ requirements:
+ _permission: 'configure jsonapi reference'
+
+entity.jsonapi_reference.add_form:
+ path: '/admin/config/services/jsonapi-reference/add'
+ defaults:
+ _entity_form: 'jsonapi_reference.add'
+ _title: 'Add JSON:API Reference'
+ requirements:
+ _permission: 'configure jsonapi reference'
+
+entity.jsonapi_reference.edit_form:
+ path: '/admin/config/services/jsonapi-reference/{jsonapi_reference}/edit'
+ defaults:
+ _entity_form: 'jsonapi_reference.edit'
+ _title: 'Edit JSON:API Reference'
+ requirements:
+ _permission: 'configure jsonapi reference'
+
+entity.jsonapi_reference.delete_form:
+ path: '/admin/config/services/jsonapi-reference/{jsonapi_reference}/delete'
+ defaults:
+ _entity_form: 'jsonapi_reference.delete'
+ _title: 'Delete JSON:API Reference'
+ requirements:
+ _permission: 'configure jsonapi reference'
diff --git a/jsonapi_reference.services.yml b/jsonapi_reference.services.yml
index 955090f..67e6e4a 100644
--- a/jsonapi_reference.services.yml
+++ b/jsonapi_reference.services.yml
@@ -4,4 +4,4 @@ services:
arguments: ['JSON:API Reference']
jsonapi_reference.jsonapi_client:
class: Drupal\jsonapi_reference\JsonApiClient
- arguments: ['@http_client', '@jsonapi_reference.logger_channel', '@config.factory']
+ arguments: ['@http_client', '@jsonapi_reference.logger_channel']
diff --git a/src/Controller/JsonApiReferenceListBuilder.php b/src/Controller/JsonApiReferenceListBuilder.php
new file mode 100644
index 0000000..1fe89f6
--- /dev/null
+++ b/src/Controller/JsonApiReferenceListBuilder.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\jsonapi_reference\Controller;
+
+use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * List builder for the 'jsonapi_reference' entity.
+ */
+class JsonApiReferenceListBuilder extends ConfigEntityListBuilder {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildHeader() {
+ $header['label'] = $this->t('Entrypoint');
+ $header['id'] = $this->t('Machine name');
+ $header['reachable'] = $this->t('Reachable');
+
+ return $header + parent::buildHeader();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildRow(EntityInterface $entity) {
+ $row['label'] = $entity->label();
+ $row['id'] = $entity->id();
+ $row['reachable'] = $entity->isReachable() ? $this->t('Yes') : $this->t('No');
+
+ return $row + parent::buildRow($entity);
+ }
+
+}
diff --git a/src/Controller/TypedResourceController.php b/src/Controller/TypedResourceController.php
index 3f764dd..6f08e5a 100644
--- a/src/Controller/TypedResourceController.php
+++ b/src/Controller/TypedResourceController.php
@@ -4,6 +4,7 @@ namespace Drupal\jsonapi_reference\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\jsonapi_reference\JsonApiClientInterface;
+use Drupal\jsonapi_reference\JsonApiReferenceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -46,6 +47,8 @@ class TypedResourceController extends ControllerBase {
* Incoming HTTP request.
* @param string $resource_object_type
* JSON:API Object type for which we are searching, EG node--article.
+ * @param \Drupal\jsonapi_reference\JsonApiReferenceInterface $jsonapi_reference
+ * The jsonapi_reference config entity.
* @param string $autocomplete_attribute
* Attribute on the JSON:API objects against which we are searching.
*
@@ -55,9 +58,10 @@ class TypedResourceController extends ControllerBase {
* values of the autocomplete attribute, and the corresponding objects
* JSON:API ID.
*/
- public function autocomplete(Request $request, $resource_object_type, $autocomplete_attribute) {
+ public function autocomplete(Request $request, $resource_object_type, JsonApiReferenceInterface $jsonapi_reference, $autocomplete_attribute) {
$response = [];
$query = $request->query->get('q');
+ $this->client->setConfig($jsonapi_reference);
$search_results = $this->client->search($resource_object_type, $autocomplete_attribute, $query);
foreach ($search_results as $attribute => $id) {
$response[] = [
diff --git a/src/Entity/JsonApiReference.php b/src/Entity/JsonApiReference.php
new file mode 100644
index 0000000..6f796ed
--- /dev/null
+++ b/src/Entity/JsonApiReference.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Drupal\jsonapi_reference\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\jsonapi_reference\JsonApiReferenceInterface;
+
+/**
+ * Defines the JsonApiReference entity.
+ *
+ * @ConfigEntityType(
+ * id = "jsonapi_reference",
+ * label = @Translation("JSON:API Reference"),
+ * handlers = {
+ * "list_builder" = "Drupal\jsonapi_reference\Controller\JsonApiReferenceListBuilder",
+ * "form" = {
+ * "add" = "Drupal\jsonapi_reference\Form\JsonApiReferenceForm",
+ * "edit" = "Drupal\jsonapi_reference\Form\JsonApiReferenceForm",
+ * "delete" = "Drupal\jsonapi_reference\Form\JsonApiReferenceDeleteForm",
+ * }
+ * },
+ * config_prefix = "settings",
+ * admin_permission = "configure jsonapi reference",
+ * entity_keys = {
+ * "id" = "id",
+ * "label" = "entrypoint",
+ * },
+ * config_export = {
+ * "id",
+ * "entrypoint",
+ * "username",
+ * "password",
+ * },
+ * links = {
+ * "edit-form" = "/admin/config/services/jsonapi-reference/{jsonapi_reference}",
+ * "delete-form" = "/admin/config/services/jsonapi-reference/{jsonapi_reference}/delete",
+ * }
+ * )
+ */
+class JsonApiReference extends ConfigEntityBase implements JsonApiReferenceInterface {
+
+ /**
+ * A unique identifier for the jsonapi_reference config entity.
+ *
+ * @var string
+ */
+ public $id;
+
+ /**
+ * The entrypoint to access the JSON:API reference.
+ *
+ * @var string
+ */
+ public $entrypoint;
+
+ /**
+ * The username to authenticate with the entrypoint.
+ *
+ * @var string
+ */
+ public $username;
+
+ /**
+ * The password to authenticate with the entrypoint.
+ *
+ * @var string
+ */
+ public $password;
+
+ /**
+ * The 'jsonapi_reference.jsonapi_client' service.
+ *
+ * @var \Drupal\jsonapi_reference\JsonApiClientInterface
+ */
+ protected $jsonapiClient;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct(array $values, $entity_type) {
+ parent::__construct($values, $entity_type);
+
+ $this->jsonapiClient = \Drupal::service('jsonapi_reference.jsonapi_client');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isReachable() {
+ $result = $this->jsonapiClient->setConfig($this)->listResourceObjectTypes();
+
+ if (!empty($result)) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+
+}
diff --git a/src/Form/JsonApiReferenceConfigForm.php b/src/Form/JsonApiReferenceConfigForm.php
deleted file mode 100644
index ae0f3b6..0000000
--- a/src/Form/JsonApiReferenceConfigForm.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi_reference\Form;
-
-use Drupal\Core\Form\ConfigFormBase;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Class JsonApiReferenceConfigForm.
- */
-class JsonApiReferenceConfigForm extends ConfigFormBase {
-
- /**
- * {@inheritdoc}
- */
- protected function getEditableConfigNames() {
- return [
- 'jsonapi_reference.settings',
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFormId() {
- return 'json_api_reference_config_form';
- }
-
- /**
- * {@inheritdoc}
- */
- public function buildForm(array $form, FormStateInterface $form_state) {
- $config = $this->config('jsonapi_reference.settings');
- $form['entrypoint'] = [
- '#type' => 'textfield',
- '#title' => $this->t('Entrypoint'),
- '#description' => $this->t('The root JSON:API entrypoint, for example, https://example.com/jsonapi'),
- '#maxlength' => 2048,
- '#size' => 64,
- '#default_value' => $config->get('endpoint'),
- ];
- $form['username'] = [
- '#type' => 'textfield',
- '#title' => $this->t('Username'),
- '#description' => $this->t('Username for authenticating on the JSON:API entrypoint'),
- '#maxlength' => 128,
- '#size' => 64,
- '#default_value' => $config->get('username'),
- ];
- $form['password'] = [
- '#type' => 'password',
- '#title' => $this->t('Password'),
- '#description' => $this->t('Password for authenticating on the JSON:API entrypoint'),
- '#maxlength' => 128,
- '#size' => 64,
- '#default_value' => $config->get('password'),
- ];
- return parent::buildForm($form, $form_state);
- }
-
- /**
- * {@inheritdoc}
- */
- public function submitForm(array &$form, FormStateInterface $form_state) {
- parent::submitForm($form, $form_state);
-
- $config = $this->config('jsonapi_reference.settings');
- $config->set('endpoint', $form_state->getValue('entrypoint'))
- ->set('username', $form_state->getValue('username'));
- if ($password = $form_state->getValue('password')) {
- $config->set('password', $password);
- }
- $config->save();
- }
-
-}
diff --git a/src/Form/JsonApiReferenceDeleteForm.php b/src/Form/JsonApiReferenceDeleteForm.php
new file mode 100644
index 0000000..939eb22
--- /dev/null
+++ b/src/Form/JsonApiReferenceDeleteForm.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\jsonapi_reference\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Entity\EntityConfirmFormBase;
+use Drupal\Core\Url;
+
+/**
+ * Form handler for the jsonapi_reference delete form.
+ *
+ * @see \Drupal\jsonapi_reference\Entity\JsonApiReference
+ * @see \Drupal\jsonapi_reference\Form\JsonApiReferenceDeleteForm
+ */
+class JsonApiReferenceDeleteForm extends EntityConfirmFormBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQuestion() {
+ return $this->t('Are you sure you want to delete %name?', ['%name' => $this->entity->label()]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCancelUrl() {
+ return new Url('entity.jsonapi_reference.collection');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfirmText() {
+ return $this->t('Delete');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ parent::validateForm($form, $form_state);
+
+ // Check if there is any typed_resource_object fields using the entity
+ // the user is trying to delete.
+ $entity_field_manager = \Drupal::service('entity_field.manager');
+ $field_map = $entity_field_manager->getFieldMapByFieldType('typed_resource_object');
+
+ foreach ($field_map as $entity_type => $field) {
+
+ foreach ($field as $field_name => $info) {
+ if (isset($info['bundles'])) {
+ foreach ($info['bundles'] as $bundle) {
+ $field_definitions = $entity_field_manager->getFieldDefinitions($entity_type, $bundle);
+
+ if (isset($field_definitions[$field_name]) && $field_definitions[$field_name]->getSettings()['jsonapi_reference_entity'] === $this->entity->id()) {
+ $form_state->setError($form['actions']['submit'], $this->t('JSON:API reference %label could not be deleted as it is being used in a field (%field)', [
+ '%label' => $this->entity->label(),
+ '%field' => $field_name,
+ ]));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $this->entity->delete();
+ $this->messenger()->addMEssage($this->t('JSON:API reference %label has been deleted.', ['%label' => $this->entity->label()]));
+
+ $form_state->setRedirectUrl($this->getCancelUrl());
+ }
+
+}
diff --git a/src/Form/JsonApiReferenceForm.php b/src/Form/JsonApiReferenceForm.php
new file mode 100644
index 0000000..29c5d2d
--- /dev/null
+++ b/src/Form/JsonApiReferenceForm.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace Drupal\jsonapi_reference\Form;
+
+use Drupal\Core\Entity\EntityForm;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Messenger\MessengerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Form handler for the jsonapi_reference add and edit form.
+ *
+ * @see \Drupal\jsonapi_reference\Entity\JsonApiReference
+ * @see \Drupal\jsonapi_reference\Form\JsonApiReferenceDeleteForm
+ */
+class JsonApiReferenceForm extends EntityForm {
+
+ /**
+ * The entity type manager.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManager
+ */
+ protected $entityTypeManager;
+
+ /**
+ * Constructs a new JsonApiReferenceForm object.
+ *
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
+ * The entity type manager service.
+ */
+ public function __construct(EntityTypeManagerInterface $entityTypeManager) {
+ $this->entityTypeManager = $entityTypeManager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('entity_type.manager')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function form(array $form, FormStateInterface $form_state) {
+ $form = parent::form($form, $form_state);
+
+ $form['id'] = [
+ '#type' => 'machine_name',
+ '#title' => 'JSON:API Reference ID',
+ '#description' => $this->t('A machine-readable unique identifier for the JSON:API reference'),
+ '#default_value' => $this->entity->id,
+ '#disabled' => !$this->entity->isNew(),
+ '#machine_name' => [
+ 'exists' => [
+ $this, 'exists',
+ ],
+ ],
+ ];
+ $form['entrypoint'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Entrypoint'),
+ '#description' => $this->t('The root JSON:API entrypoint, for example: https://example.com/jsonapi'),
+ '#maxlength' => 2048,
+ '#size' => 64,
+ '#default_value' => $this->entity->entrypoint,
+ ];
+ $form['username'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Username'),
+ '#description' => $this->t('Username for authenticating on the JSON:API entrypoint'),
+ '#maxlength' => 128,
+ '#size' => 64,
+ '#default_value' => $this->entity->username,
+ ];
+ $form['password'] = [
+ '#type' => 'password',
+ '#title' => $this->t('Password'),
+ '#description' => $this->t('Password for authenticating on the JSON:API entrypoint'),
+ '#maxlength' => 128,
+ '#size' => 64,
+ '#default_value' => $this->entity->password,
+ ];
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save(array $form, FormStateInterface $form_state) {
+ $this->entity->entrypoint = $form_state->getValue('entrypoint');
+ $this->entity->username = $form_state->getValue('username');
+ $this->entity->password = $form_state->getValue('password');
+
+ if ($this->entity->isNew()) {
+ $this->entity->id = $form_state->getValue('id');
+ }
+
+ $status = $this->entity->save();
+
+ if ($status) {
+ $this->messenger()->addMessage($this->t('Saved the %label reference', [
+ '%label' => $this->entity->entrypoint,
+ ]));
+ }
+ else {
+ $this->messenger()->addMessage($this->t('The %label reference was not saved', [
+ '%label' => $this->entity->entrypoint,
+ ]), MessengerInterface::TYPE_ERROR);
+ }
+
+ $form_state->setRedirect('entity.jsonapi_reference.collection');
+ }
+
+ /**
+ * Helper function to check whether an Example configuration entity exists.
+ */
+ public function exists($id) {
+ $entity = $this->entityTypeManager->getStorage('jsonapi_reference')->getQuery()
+ ->condition('id', $id)
+ ->execute();
+ return (bool) $entity;
+ }
+
+}
diff --git a/src/JsonApiClient.php b/src/JsonApiClient.php
index 7b8d6df..a43d891 100644
--- a/src/JsonApiClient.php
+++ b/src/JsonApiClient.php
@@ -2,7 +2,6 @@
namespace Drupal\jsonapi_reference;
-use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
@@ -16,32 +15,18 @@ use GuzzleHttp\RequestOptions;
class JsonApiClient implements JsonApiClientInterface {
/**
- * Client for querying the JSON:API entrypoint.
+ * Client for querying the JSON:API endpoint.
*
* @var \GuzzleHttp\ClientInterface
*/
protected $httpClient;
/**
- * Entrypoint to call to retrieve JSONAPI objects.
+ * An array of jsonapi_reference config entities.
*
- * @var string
+ * @var \Drupal\jsonapi_reference\JsonApiReferenceInterface
*/
- protected $entrypoint;
-
- /**
- * Username to use when authenticating to the entrypoint.
- *
- * @var string
- */
- protected $username;
-
- /**
- * Password to use when authenticating to the entrypoint.
- *
- * @var string
- */
- protected $password;
+ protected $configEntity;
/**
* Logger channel.
@@ -54,17 +39,12 @@ class JsonApiClient implements JsonApiClientInterface {
* JsonApiClient constructor.
*
* @param \GuzzleHttp\ClientInterface $httpClient
- * Client for querying the JSON:API entrypoint.
+ * Client for querying JSON:API endpoints.
* @param \Drupal\Core\Logger\LoggerChannelInterface $loggerChannel
* Channel for logging.
- * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
- * Config factory.
*/
- public function __construct(ClientInterface $httpClient, LoggerChannelInterface $loggerChannel, ConfigFactoryInterface $configFactory) {
+ public function __construct(ClientInterface $httpClient, LoggerChannelInterface $loggerChannel) {
$this->httpClient = $httpClient;
- $this->entrypoint = $configFactory->get('jsonapi_reference.settings')->get('endpoint');
- $this->username = $configFactory->get('jsonapi_reference.settings')->get('username');
- $this->password = $configFactory->get('jsonapi_reference.settings')->get('password');
$this->loggerChannel = $loggerChannel;
}
@@ -76,16 +56,24 @@ class JsonApiClient implements JsonApiClientInterface {
}
/**
- * Gets the resource object type information from the entrypoint.
+ * {@inheritdoc}
+ */
+ public function setConfig(JsonApiReferenceInterface $config_entity) {
+ $this->configEntity = $config_entity;
+ return $this;
+ }
+
+ /**
+ * Gets the resource object type information from the endpoint.
*
* @return object[]
* Array of objects, keyed by type name (EG node--article).
- * Each object contains a href element pointing to the JSON:API entrypoint
+ * Each object contains a href element pointing to the JSON:API endpoint
* for that specific type.
*/
protected function getResourceObjectTypes() {
try {
- $response = $this->httpClient->request('get', $this->entrypoint, $this->getRequestOptions());
+ $response = $this->httpClient->request('get', $this->configEntity->entrypoint, $this->getRequestOptions());
}
catch (GuzzleException $e) {
$this->loggerChannel->error($e->getMessage());
@@ -93,7 +81,7 @@ class JsonApiClient implements JsonApiClientInterface {
}
$response = json_decode($response->getBody()->getContents());
if (!isset($response->links)) {
- $this->loggerChannel->error('JSON:API entrypoint @entrypoint returned no type information.', ['@entrypoint' => $this->entrypoint]);
+ $this->loggerChannel->error('JSON:API endpoint @endpoint returned no type information.', ['@endpoint' => $this->configEntity->entrypoint]);
return [];
}
return (array) $response->links;
@@ -105,9 +93,9 @@ class JsonApiClient implements JsonApiClientInterface {
public function search($resource_object_type, $search_attribute, $query) {
$path = $this->getPathForResourceObjectType($resource_object_type);
if (!$path) {
- $this->loggerChannel->error('No path for resource object type @type found at JSON:API entrypoint @entrypoint.', [
+ $this->loggerChannel->error('No path for resource object type @type found at JSON:API endpoint @endpoint.', [
'@type' => $resource_object_type,
- '@entrypoint' => $this->entrypoint,
+ '@endpoint' => $this->configEntity->entrypoint,
]);
return [];
}
@@ -136,8 +124,8 @@ class JsonApiClient implements JsonApiClientInterface {
foreach ($response->data as $result) {
$results[$result->attributes->$search_attribute] = $result->id;
}
- $this->loggerChannel->error('JSON:API entrypoint @entrypoint returned no data for path @path when searching for objects where the @search_attribute attribute matched "@query".', [
- '@entrypoint' => $this->entrypoint,
+ $this->loggerChannel->error('JSON:API endpoint @endpoint returned no data for path @path when searching for objects where the @search_attribute attribute matched "@query".', [
+ '@endpoint' => $this->configEntity->endpoint,
'@path' => $path,
'@search_attribute' => $search_attribute,
'@query' => $query,
@@ -182,10 +170,10 @@ class JsonApiClient implements JsonApiClientInterface {
'Accept' => 'application/json',
],
];
- if ($this->username && $this->password) {
+ if ($this->configEntity->username && $this->configEntity->password) {
$options[RequestOptions::AUTH] = [
- $this->username,
- $this->password,
+ $this->configEntity->username,
+ $this->configEntity->password,
];
}
diff --git a/src/JsonApiClientInterface.php b/src/JsonApiClientInterface.php
index fb97fcd..8b5f375 100644
--- a/src/JsonApiClientInterface.php
+++ b/src/JsonApiClientInterface.php
@@ -60,4 +60,12 @@ interface JsonApiClientInterface {
*/
public function searchById($resource_object_type, $id);
+ /**
+ * Set the configuration objects to use for the client.
+ *
+ * @param \Drupal\jsonapi_reference\JsonApiReferenceInterface $config_entity
+ * The jsonapi_reference entity to use.
+ */
+ public function setConfig(JsonApiReferenceInterface $config_entity);
+
}
diff --git a/src/JsonApiReferenceInterface.php b/src/JsonApiReferenceInterface.php
new file mode 100644
index 0000000..75b2cf6
--- /dev/null
+++ b/src/JsonApiReferenceInterface.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Drupal\jsonapi_reference;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+
+/**
+ * Provides an interface defining the JsonApiReference config entity.
+ */
+interface JsonApiReferenceInterface extends ConfigEntityInterface {
+
+ /**
+ * Checks if the JSON:API entrypoint is reachable and returns a boolean value.
+ *
+ * @return bool
+ * Is the JSON:API entrypoint reachable?
+ */
+ public function isReachable();
+
+}
diff --git a/src/Plugin/Field/FieldType/TypedResourceObjectItem.php b/src/Plugin/Field/FieldType/TypedResourceObjectItem.php
index c9855a9..3fb3a5d 100644
--- a/src/Plugin/Field/FieldType/TypedResourceObjectItem.php
+++ b/src/Plugin/Field/FieldType/TypedResourceObjectItem.php
@@ -29,6 +29,7 @@ class TypedResourceObjectItem extends FieldItemBase {
public static function defaultStorageSettings() {
return [
'resource_object_type' => '',
+ 'jsonapi_reference_entity' => '',
] + parent::defaultStorageSettings();
}
@@ -89,23 +90,89 @@ class TypedResourceObjectItem extends FieldItemBase {
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$elements = [];
- /* @var $client \Drupal\jsonapi_reference\JsonApiClientInterface */
- $client = \Drupal::service('jsonapi_reference.jsonapi_client');
- $types = $client->listResourceObjectTypes();
+ // Load all of the jsonapi_reference config entities to populate the select
+ // list.
+ $jsonapi_references = \Drupal::service('entity_type.manager')
+ ->getStorage('jsonapi_reference')
+ ->loadMultiple();
+
+ // Format the array of jsonapi_reference entities in to a format that is
+ // usable by the form api.
+ $formatted_references = $this->formatJsonapiReferences($jsonapi_references);
+
+ if ($form_state->getValue(['settings', 'jsonapi_reference_entity'])) {
+ $resource_object_type_options = $this->getResourceObjectTypes($form_state->getValue(['settings', 'jsonapi_reference_entity']));
+ }
+ elseif ($this->getSetting('jsonapi_reference_entity')) {
+ $resource_object_type_options = $this->getResourceObjectTypes($this->getSetting('jsonapi_reference_entity'));
+ }
+ else {
+ $resource_object_type_options = $this->getResourceObjectTypes(key($formatted_references));
+ }
+
+ $elements['jsonapi_reference_entity'] = [
+ '#type' => 'select',
+ '#title' => $this->t('Reference entrypoint'),
+ '#default_value' => $this->getSetting('jsonapi_reference_entity'),
+ '#required' => TRUE,
+ '#description' => $this->t('The source JSON:API to use for the content of the field.'),
+ '#disabled' => $has_data || count($formatted_references) === 1,
+ '#options' => $formatted_references,
+ '#ajax' => [
+ 'callback' => [$this, 'populateObjectTypes'],
+ 'method' => 'replace',
+ 'wrapper' => 'object-type-container',
+ ],
+ ];
$elements['resource_object_type'] = [
'#type' => 'select',
'#title' => $this->t('Type'),
'#default_value' => $this->getSetting('resource_object_type'),
- '#required' => TRUE,
'#description' => $this->t('The type of resource object.'),
- '#disabled' => $has_data,
- '#options' => array_combine($types, $types),
+ '#disabled' => $has_data || count($resource_object_type_options) == 0,
+ '#options' => $resource_object_type_options,
+ '#required' => TRUE,
+ '#prefix' => '<div id="object-type-container">',
+ '#suffix' => '</div>',
];
return $elements;
}
+ /**
+ * Callback for populating the resource_object_types field with object types.
+ *
+ * @param array $form
+ * The form array.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ * The form state.
+ */
+ public function populateObjectTypes(array &$form, FormStateInterface $form_state) {
+ return $form['settings']['resource_object_type'];
+ }
+
+ /**
+ * Returns the list of available object types from the specified resource.
+ *
+ * @param string $id
+ * The ID of the jsonapi_reference entity.
+ *
+ * @return array
+ * The resource's object types.
+ */
+ public function getResourceObjectTypes(string $id) {
+ $jsonapi_reference = \Drupal::service('entity_type.manager')
+ ->getStorage('jsonapi_reference')
+ ->load($id);
+
+ /** @var \Drupal\jsonapi_reference\JsonApiClientInterface $client */
+ $client = \Drupal::service('jsonapi_reference.jsonapi_client');
+ $client->setConfig($jsonapi_reference);
+ $object_types = $client->listResourceObjectTypes();
+ return array_combine($object_types, $object_types);
+ }
+
/**
* {@inheritdoc}
*/
@@ -128,4 +195,22 @@ class TypedResourceObjectItem extends FieldItemBase {
return $this->get('value')->getValue();
}
+ /**
+ * Format an array of jsonapi_reference config entities.
+ *
+ * @param array[\Drupal\jsonapi_reference\JsonapiReferenceInterface] $entities
+ * The array of JsonapiReference entities.
+ *
+ * @return array
+ * An array suitable for use within the #options of a select form element.
+ */
+ protected function formatJsonapiReferences(array $entities) {
+ $references = [];
+ foreach ($entities as $entity) {
+ $references[$entity->id()] = $entity->label();
+ }
+
+ return $references;
+ }
+
}
diff --git a/src/Plugin/Field/FieldWidget/TypedResourceObjectAutocompleteWidget.php b/src/Plugin/Field/FieldWidget/TypedResourceObjectAutocompleteWidget.php
index 3cb1d47..385aa7e 100644
--- a/src/Plugin/Field/FieldWidget/TypedResourceObjectAutocompleteWidget.php
+++ b/src/Plugin/Field/FieldWidget/TypedResourceObjectAutocompleteWidget.php
@@ -4,7 +4,12 @@ namespace Drupal\jsonapi_reference\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\jsonapi_reference\JsonApiClientInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin implementation of the 'typed_resource_object_autocomplete' widget.
@@ -18,7 +23,61 @@ use Drupal\Core\Form\FormStateInterface;
* }
* )
*/
-class TypedResourceObjectAutocompleteWidget extends WidgetBase {
+class TypedResourceObjectAutocompleteWidget extends WidgetBase implements ContainerFactoryPluginInterface {
+
+ /**
+ * The entity_type.manager service.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+ */
+ protected $entityTypeManager;
+
+ /**
+ * The jsonapi_reference.jsonapi_client service.
+ *
+ * @var \Drupal\jsonapi_reference\JsonApiClientInterface
+ */
+ protected $jsonapiClient;
+
+ /**
+ * Constructs a new TypedResourceObjectAutocompleteWidget object.
+ *
+ * @param string $plugin_id
+ * The plugin ID.
+ * @param mixed $plugin_definition
+ * The plugin definition.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+ * The field definition.
+ * @param array $settings
+ * The widget settings.
+ * @param array $third_party_settings
+ * The third party widget settings.
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+ * The entity_type.manager service.
+ * @param \Drupal\jsonapi_reference\JsonApiClientInterface $jsonapi_client
+ * The jsonapi_reference.jsonapi_client service.
+ */
+ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, JsonApiClientInterface $jsonapi_client) {
+ parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+
+ $this->entityTypeManager = $entity_type_manager;
+ $this->jsonapiClient = $jsonapi_client;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+ return new static(
+ $plugin_id,
+ $plugin_definition,
+ $configuration['field_definition'],
+ $configuration['settings'],
+ $configuration['third_party_settings'],
+ $container->get('entity_type.manager'),
+ $container->get('jsonapi_reference.jsonapi_client')
+ );
+ }
/**
* {@inheritdoc}
@@ -63,10 +122,12 @@ class TypedResourceObjectAutocompleteWidget extends WidgetBase {
'#autocomplete_route_name' => 'jsonapi_reference.typed_resource_controller_autocomplete',
'#autocomplete_route_parameters' => [
'resource_object_type' => $field_settings['resource_object_type'],
+ 'jsonapi_reference' => $field_settings['jsonapi_reference_entity'],
'autocomplete_attribute' => $this->getSetting('autocomplete_attribute'),
],
- '#value_callback' => [get_class($this), 'valueCallback'],
+ '#value_callback' => [$this, 'valueCallback'],
'#resource_object_type' => $field_settings['resource_object_type'],
+ '#jsonapi_reference_entity' => $field_settings['jsonapi_reference_entity'],
'#autocomplete_attribute' => $this->getSetting('autocomplete_attribute'),
];
@@ -87,7 +148,7 @@ class TypedResourceObjectAutocompleteWidget extends WidgetBase {
* @return mixed
* The value to assign to the element.
*/
- public static function valueCallback(array $element, $input, FormStateInterface $form_state) {
+ public function valueCallback(array $element, $input, FormStateInterface $form_state) {
$value = '';
// If we're rebuilding the form due to AJAX (eg adding another item to the
@@ -115,10 +176,15 @@ class TypedResourceObjectAutocompleteWidget extends WidgetBase {
// Otherwise we need to convert the other way - for the given id..
if ($element['#default_value']) {
- // ..look it up via jsonapi and format with the title.
- /* @var $client \Drupal\jsonapi_reference\JsonApiClientInterface */
- $client = \Drupal::service('jsonapi_reference.jsonapi_client');
- $jsonapi_object = $client->searchById($element['#resource_object_type'], $element['#default_value']);
+ /** @var \Drupal\jsonapi_reference\JsonApiReferenceInterface $config */
+ $config = $this->entityTypeManager
+ ->getStorage('jsonapi_reference')
+ ->load($element['#jsonapi_reference_entity']);
+
+ /** @var \Drupal\jsonapi_reference\JsonApiClientInterface $client */
+ $this->jsonapiClient->setConfig($config);
+ $jsonapi_object = $this->jsonapiClient->searchById($element['#resource_object_type'], $element['#default_value']);
+
if ($jsonapi_object) {
$value = $jsonapi_object->data->attributes->{$element['#autocomplete_attribute']} . ' (' . $element['#default_value'] . ')';
}
diff --git a/tests/src/Functional/JsonApiReferenceTest.php b/tests/src/Functional/JsonApiReferenceTest.php
index 5624686..752166b 100644
--- a/tests/src/Functional/JsonApiReferenceTest.php
+++ b/tests/src/Functional/JsonApiReferenceTest.php
@@ -4,6 +4,9 @@ namespace Drupal\Tests\jsonapi_reference\Functional;
use Drupal\KernelTests\AssertConfigTrait;
use Drupal\Tests\BrowserTestBase;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\jsonapi_reference\Entity\JsonApiReference;
+use Drupal\Core\Url;
/**
* Class JsonApiReferenceTest.
@@ -11,7 +14,26 @@ use Drupal\Tests\BrowserTestBase;
* @group jsonapi_reference
*/
class JsonApiReferenceTest extends BrowserTestBase {
- use AssertConfigTrait;
+ use AssertConfigTrait, StringTranslationTrait;
+
+ /**
+ * A user with no significant control.
+ *
+ * @var \Drupal\user\UserInterface
+ */
+ protected $personOfNoSignificance;
+
+ /**
+ * A user with appropriate permissions to administer jsonapi_reference config.
+ *
+ * @var \Drupal\user\UserInterface
+ */
+ protected $personOfSignificance;
+
+ /**
+ * {@inheritdoc}
+ */
+ static protected $modules = ['jsonapi_reference', 'jsonapi'];
/**
* {@inheritdoc}
@@ -21,7 +43,39 @@ class JsonApiReferenceTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
- static protected $modules = ['jsonapi_reference'];
+ protected function setUp() {
+ parent::setUp();
+
+ // Create a user with no significant administrative capabilities and a user
+ // with permissions to configure the jsonapi_reference module.
+ $this->personOfNoSignificance = $this->createUser();
+ $this->personOfSignificance = $this->createUser(['configure jsonapi reference']);
+ }
+
+ /**
+ * Test the entity list is protected by permissions.
+ */
+ public function testEntityListProtected() {
+ // Test anonymous users can't access the config.
+ $this->drupalGet('admin/config/services/jsonapi-reference');
+ $this->assertSession()->statusCodeEquals(403);
+
+ // Test a logged-in user with a no specific permissions can't access the
+ // configuration screen.
+ $this->drupalLogin($this->personOfNoSignificance);
+ $this->drupalGet('admin/config/services/jsonapi-reference');
+ $this->assertSession()->statusCodeEquals(403);
+
+ $this->drupalLogout();
+
+ // Test a logged-in user with the appropriate permissions can access the
+ // configuration screen.
+ $this->drupalLogin($this->personOfSignificance);
+ $this->drupalGet('admin/config/services/jsonapi-reference');
+ $this->assertSession()->statusCodeEquals(200);
+
+ $this->drupalLogout();
+ }
/**
* Test configuration form protected by permissions.
@@ -31,26 +85,142 @@ class JsonApiReferenceTest extends BrowserTestBase {
*/
public function testConfigFormProtected() {
// Test anonymous users can't access the configuration screen.
- $this->drupalGet('admin/config/jsonapi_reference');
+ $this->drupalGet('admin/config/services/jsonapi-reference/add');
$this->assertSession()->statusCodeEquals(403);
- // Test a logged in user with no specific permissions can't access the
+ // Test a logged-in user with no specific permissions can't access the
// configuration screen.
- $person_of_no_significance = $this->createUser();
- $this->drupalLogin($person_of_no_significance);
- $this->drupalGet('admin/config/jsonapi_reference');
+ $this->drupalLogin($this->personOfNoSignificance);
+ $this->drupalGet('admin/config/services/jsonapi-reference/add');
$this->assertSession()->statusCodeEquals(403);
$this->drupalLogout();
- // Test a logged in user with the appropriate permission can access the
+ // Test a logged-in user with the appropriate permission can access the
// configuration screen.
- $person_of_appropriate_significance = $this->createUser(['configure jsonapi reference']);
- $this->drupalLogin($person_of_appropriate_significance);
- $this->drupalGet('admin/config/jsonapi_reference');
+ $this->drupalLogin($this->personOfSignificance);
+ $this->drupalGet('admin/config/services/jsonapi-reference/add');
$this->assertSession()->statusCodeEquals(200);
$this->drupalLogout();
}
+ /**
+ * Test submitting the 'add' configuration form.
+ */
+ public function testAddFormSubmit() {
+ // Login as a user with the appropriate permission to submit the form.
+ $this->drupalLogin($this->personOfSignificance);
+ $this->drupalPostForm('admin/config/services/jsonapi-reference/add', [
+ 'id' => 'testing',
+ 'entrypoint' => 'http://localhost/jsonapi',
+ 'username' => '',
+ 'password' => '',
+ ], $this->t('Save'));
+
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Verify the config entity exists.
+ /** @var \Drupal\jsonapi_reference\JsonApiReferenceInterface $entity */
+ $entity = JsonApiReference::load('testing');
+
+ $this->assert($entity->label() == 'http://localhost/jsonapi');
+
+ $this->drupalLogout();
+ }
+
+ /**
+ * Test submitting the 'delete' form for the jsonapi_reference entity type.
+ */
+ public function testDeleteFormSubmit() {
+ // Login as a user with the appropriate permission to submit the form.
+ $this->drupalLogin($this->personOfSignificance);
+
+ // Create a jsonapi_reference entity.
+ $state = JsonApiReference::create([
+ 'id' => 'testing',
+ 'entrypoint' => 'http://localhost/jsonapi',
+ 'username' => '',
+ 'password' => '',
+ ])->save();
+ $this->assert($state == SAVED_NEW);
+
+ $this->drupalPostForm('admin/config/services/jsonapi-reference/testing/delete', [], $this->t('Delete'));
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Verify the entity no longer exists.
+ $this->assert(is_null(JsonApiReference::load('testing')));
+
+ $this->drupalLogout();
+ }
+
+ /**
+ * Test submitting the 'edit' form for the jsonapi_reference entity type.
+ */
+ public function testEditFormSubmit() {
+ // Login as a user with the appropriate permission to submit the form.
+ $this->drupalLogin($this->personOfSignificance);
+
+ // Create a jsonapi_reference entity that will be edited.
+ $state = JsonApiReference::create([
+ 'id' => 'edit_me',
+ 'entrypoint' => 'http://localhost/jsonapi',
+ 'username' => '',
+ 'password' => '',
+ ])->save();
+ $this->assert($state == SAVED_NEW);
+
+ $this->drupalPostForm('admin/config/services/jsonapi-reference/edit_me/edit', [
+ 'entrypoint' => 'http://localhost/jsonapitest',
+ ], $this->t('Save'));
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Verify the entity has been changed.
+ /** @var \Drupal\jsonapi_reference\JsonApiReferenceInterface $entity */
+ $entity = JsonApiReference::load('edit_me');
+
+ $this->assert($entity->entrypoint == 'http://localhost/jsonapitest');
+
+ $this->drupalLogout();
+ }
+
+ /**
+ * Test the reachable method on the jsonapi_reference entity.
+ */
+ public function testReachable() {
+ // Login as a user with the appropriate permission to submit the form.
+ $this->drupalLogin($this->personOfSignificance);
+
+ // Create a new jsonapi_reference entity that is expected to be reachable.
+ $state = JsonApiReference::create([
+ 'id' => 'reachable',
+ 'entrypoint' => Url::fromUri('base:/jsonapi')->setAbsolute()->toString(TRUE)->getGeneratedUrl(),
+ 'username' => '',
+ 'password' => '',
+ ])->save();
+ $this->assert($state == SAVED_NEW);
+
+ /** @var \Drupal\jsonapi_reference\JsonApiReferenceInterfae $reachable */
+ $reachable = JsonApiReference::load('reachable');
+
+ $this->assert($reachable->isReachable());
+
+ // Create a new jsonapi_reference entity that should not be reachable.
+ $state = JsonApiReference::create([
+ 'id' => 'unreachable',
+ 'entrypoint' => Url::fromUri('base:/jsonapiunreachable')->setAbsolute()->toString(TRUE)->getGeneratedUrl(),
+ 'username' => '',
+ 'password' => '',
+ ])->save();
+ $this->assert($state == SAVED_NEW);
+
+ /** @var \Drupal\jsonapi_reference\JsonApiReferenceInterface $unreachable */
+ $unreachable = JsonApiReference::load('unreachable');
+
+ $this->assert(!$unreachable->isReachable());
+
+
+ $this->drupalLogout();
+ }
+
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment