config/install/jsonapi.settings.yml | 4 +++- config/schema/jsonapi.schema.yml | 7 +++++++ jsonapi.install | 19 +++++++++++++++++ jsonapi.module | 6 +----- tests/src/Functional/FileTest.php | 41 +++++++++++++++++++++++++++++++++++-- 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/config/install/jsonapi.settings.yml b/config/install/jsonapi.settings.yml index c0eec09..2b8c70a 100644 --- a/config/install/jsonapi.settings.yml +++ b/config/install/jsonapi.settings.yml @@ -1,2 +1,4 @@ -# +# Before Drupal 8.5, the File entity type did not expose the file URL as a +# computed property on the 'uri' base field. Sites built with JSON API +# before Drupal 8.5 will have JSON API's added computed field. bc_file_download_url: false diff --git a/config/schema/jsonapi.schema.yml b/config/schema/jsonapi.schema.yml new file mode 100644 index 0000000..3bee798 --- /dev/null +++ b/config/schema/jsonapi.schema.yml @@ -0,0 +1,7 @@ +jsonapi.settings: + type: config_object + label: 'JSON API settings' + mapping: + bc_file_download_url: + type: boolean + label: 'Whether to retain the JSON API work-around for the missing file URL field on File entities before Drupal 8.5.' diff --git a/jsonapi.install b/jsonapi.install index 1193d7a..4e5ddf0 100644 --- a/jsonapi.install +++ b/jsonapi.install @@ -6,7 +6,26 @@ */ /** + * Implements hook_install(). + */ +function jsonapi_install() { + // For new sites, also still enable JSON API's custom base field, if it's a + // new site starting on Drupal <8.5. Because only in Drupal >=8.5, core ships + // with an alternative. + // @todo Remove this when JSON API requires Drupal 8.5. + if (floatval(\Drupal::VERSION) < 8.5) { + $config_factory = \Drupal::configFactory(); + $config_factory->getEditable('jsonapi.settings') + ->set('bc_file_download_url', TRUE) + ->save(TRUE); + } +} + +/** * Add jsonapi.settings::bc_file_download_url configuration. + * + * All existing JSON API sites are using JSON API's custom base field, so enable + * the BC layer for them. */ function jsonapi_update_8101() { $config_factory = \Drupal::configFactory(); diff --git a/jsonapi.module b/jsonapi.module index 48e27c6..613cb15 100644 --- a/jsonapi.module +++ b/jsonapi.module @@ -33,11 +33,7 @@ function jsonapi_help($route_name, RouteMatchInterface $route_match) { /** * Implements hook_entity_base_field_info(). * - * @todo Remove this in a future version of the JSON API module. This was a - * work-around until it was fixed in Drupal core, we must continue to support - * existing API consumers. - * - * @see https://www.drupal.org/node/2825487 + * @todo Remove this when JSON API requires Drupal 8.5 or newer. */ function jsonapi_entity_base_field_info(EntityTypeInterface $entity_type) { $jsonapi_settings = \Drupal::config('jsonapi.settings'); diff --git a/tests/src/Functional/FileTest.php b/tests/src/Functional/FileTest.php index 3266f1d..a437833 100644 --- a/tests/src/Functional/FileTest.php +++ b/tests/src/Functional/FileTest.php @@ -2,10 +2,14 @@ namespace Drupal\Tests\jsonapi\Functional; +use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Cache\Cache; use Drupal\Core\Url; use Drupal\file\Entity\File; use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait; use Drupal\user\Entity\User; +use GuzzleHttp\RequestOptions; /** * JSON API integration test for the "File" content entity type. @@ -141,8 +145,6 @@ class FileTest extends ResourceTestBase { 'filesize' => (int) $this->entity->getSize(), 'langcode' => 'en', 'status' => TRUE, - // @todo Decide what to do with this in https://www.drupal.org/project/jsonapi/issues/2926463 - 'url' => base_path() . $this->siteDirectory . '/files/drupal.txt', 'uri' => [ 'url' => base_path() . $this->siteDirectory . '/files/drupal.txt', 'value' => 'public://drupal.txt', @@ -167,6 +169,9 @@ class FileTest extends ResourceTestBase { if (floatval(\Drupal::VERSION) < 8.5) { $normalization['data']['attributes']['uri'] = $normalization['data']['attributes']['uri']['url']; } + if ($this->config('jsonapi.settings')->get('bc_file_download_url') == TRUE) { + $normalization['data']['attributes']['url'] = base_path() . $this->siteDirectory . '/files/drupal.txt'; + } return $normalization; } @@ -226,4 +231,36 @@ class FileTest extends ResourceTestBase { return parent::testGetIndividual(); } + /** + * Tests the BC layer for the pre-8.5 JSON API work-around for File entities. + */ + public function testGetIndividualBc() { + if (floatval(\Drupal::VERSION) < 8.5) { + $this->markTestSkipped('The "url" property on the "uri" field on File entities is only available for normalization in Drupal 8.5 and later.'); + return; + } + + // Enable the BC layer. + // @see jsonapi_entity_base_field_info() + $config_factory = \Drupal::configFactory(); + $config_factory->getEditable('jsonapi.settings') + ->set('bc_file_download_url', TRUE) + ->save(TRUE); + Cache::invalidateTags(['entity_field_info']); + + // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463. + $url = Url::fromRoute(sprintf('jsonapi.file--file.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]); + /* $url = $this->entity->toUrl('jsonapi'); */ + $request_options = []; + $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; + $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); + $this->setUpAuthorization('GET'); + $response = $this->request('GET', $url, $request_options); + $expected = $this->getExpectedDocument(); + static::recursiveKSort($expected); + $actual = Json::decode((string) $response->getBody()); + static::recursiveKSort($actual); + $this->assertSame($expected, $actual); + } + }